/
opt
/
canhelp
/
apps
/
web
/
src
/
app
/
favorites
/
/opt/canhelp/apps/web/src/app/favorites
mkdir
upload
Name
Size
Mode
Actions
page.tsx
3559
0644
edit
dl
rm
Edit:
/opt/canhelp/apps/web/src/app/favorites/page.tsx
(3559B)
'use client' import { useState, useEffect } from 'react' import Link from 'next/link' import { useRouter } from 'next/navigation' import { useSession } from '@/lib/auth' import { useLocale } from '@/context/locale' import { getSpecialistFavorites, removeSpecialistFavorite } from '@/lib/api' import { formatShortName } from '@/lib/formatName' export default function FavoritesPage() { const { data: session, isPending } = useSession() const router = useRouter() const { t } = useLocale() const [favorites, setFavorites] = useState<any[]>([]) const [loading, setLoading] = useState(true) useEffect(() => { if (!isPending && !session) { router.push('/login') return } if (!session) return getSpecialistFavorites() .then(setFavorites) .catch(() => {}) .finally(() => setLoading(false)) }, [session, isPending]) async function handleRemove(specialistId: string) { await removeSpecialistFavorite(specialistId).catch(() => {}) setFavorites((prev) => prev.filter((r) => r.specialist?.id !== specialistId)) } if (isPending || loading) { return <div className="text-center py-20 text-white">{t('common.loading')}</div> } return ( <div className="max-w-3xl mx-auto px-4 py-10"> <h1 className="text-2xl font-bold text-white mb-6">{t('favorites.specialists.title')}</h1> {favorites.length === 0 ? ( <div className="text-center py-20 text-white/70"> <p className="text-4xl mb-4">🤍</p> <p className="text-lg">{t('favorites.specialists.empty')}</p> <Link href="/specialists" className="mt-4 inline-block text-white hover:text-white/80 text-sm"> {t('specialists.view')} → </Link> </div> ) : ( <div className="space-y-3"> {favorites.map((row) => { const u = row.specialist if (!u) return null const name = formatShortName(u.firstName, u.lastName, u.name) const initials = `${u.firstName?.[0] ?? ''}${u.lastName?.[0] ?? ''}`.toUpperCase() || u.name?.[0]?.toUpperCase() || '?' return ( <div key={row.id} className="flex items-center gap-4 bg-white rounded-xl border border-gray-200 p-4 hover:shadow-sm transition" > <Link href={`/users/${u.id}`} className="flex items-center gap-3 flex-1 min-w-0"> <div className="w-12 h-12 rounded-full bg-green-100 flex-shrink-0 flex items-center justify-center text-green-700 font-bold text-sm overflow-hidden border border-gray-100"> {u.image ? ( <img src={u.image} alt={name} className="w-full h-full object-cover" /> ) : initials} </div> <div className="min-w-0"> <p className="font-semibold text-gray-900 truncate">{name}</p> {u.bio && ( <p className="text-sm text-gray-500 line-clamp-1">{u.bio}</p> )} </div> </Link> <button onClick={() => handleRemove(u.id)} title={t('specialist.unfavorite')} className="flex-shrink-0 w-8 h-8 flex items-center justify-center text-pink-400 hover:text-pink-600 hover:bg-pink-50 rounded-full transition" > ❤️ </button> </div> ) })} </div> )} </div> ) }
Save
cmd:
run