refactor: remove avatar upload functionality and profile settings tab from Profile page

This commit is contained in:
2026-04-29 09:53:17 +01:00
parent 46ec1eddab
commit 4865121558

View File

@@ -10,7 +10,7 @@ import { Badge } from '../components/ui/badge'
import { Button } from '../components/ui/button'
import { currency } from '../lib/format'
import { useApp } from '../context/AppContext'
import { Calendar, ShoppingBag, User, Clock, Heart, Star, MapPin, CheckCircle2, Scissors, Settings, Camera, Upload } from 'lucide-react'
import { Calendar, ShoppingBag, User, Clock, Heart, Star, MapPin, CheckCircle2, Bell, Scissors } from 'lucide-react'
import { supabase } from '../lib/supabase'
import { ReviewModal } from '../components/ReviewModal'
@@ -29,7 +29,7 @@ const statusLabel: Record<string, string> = {
}
export default function Profile() {
const { user, appointments, orders, shops, favorites, submitReview, notifications, markNotificationRead } = useApp()
const { appointments, orders, shops, favorites, submitReview, notifications, markNotificationRead } = useApp()
const navigate = useNavigate()
const [authEmail, setAuthEmail] = useState<string>('')
@@ -40,8 +40,7 @@ export default function Profile() {
const [reviewedAppointments, setReviewedAppointments] = useState<Set<string>>(new Set())
const [reviewTarget, setReviewTarget] = useState<{ appointmentId: string; shopId: string; shopName: string } | null>(null)
// Avatar local
const [avatarBase64, setAvatarBase64] = useState<string | null>(null)
useEffect(() => {
let mounted = true
@@ -62,9 +61,6 @@ export default function Profile() {
if (reviews) {
setReviewedAppointments(new Set(reviews.map((r: any) => r.appointment_id).filter(Boolean)))
}
// Load local avatar
const savedAvatar = localStorage.getItem('avatar_' + data.user.id)
if (savedAvatar) setAvatarBase64(savedAvatar)
}
setLoadingAuth(false)
})()
@@ -97,43 +93,7 @@ export default function Profile() {
setReviewTarget(null)
}
const [activeTab, setActiveTab] = useState<'favoritos' | 'agenda' | 'pedidos' | 'definicoes'>('favoritos')
const [editName, setEditName] = useState('')
const [isSaving, setIsSaving] = useState(false)
useEffect(() => {
if (user?.name) {
setEditName(user.name)
} else if (authEmail) {
setEditName(authEmail.split('@')[0])
}
}, [user, authEmail])
const handleSaveProfile = async () => {
if (!authId || !editName.trim()) return
setIsSaving(true)
const { error } = await supabase.from('profiles').update({ name: editName.trim() }).eq('id', authId)
setIsSaving(false)
if (error) {
alert('Erro ao atualizar perfil: ' + error.message)
} else {
alert('Perfil atualizado com sucesso!')
window.location.reload()
}
}
const handleAvatarChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0]
if (!file || !authId) return
const reader = new FileReader()
reader.onload = (event) => {
const base64 = event.target?.result as string
setAvatarBase64(base64)
localStorage.setItem('avatar_' + authId, base64)
}
reader.readAsDataURL(file)
}
const [activeTab, setActiveTab] = useState<'favoritos' | 'agenda' | 'pedidos'>('favoritos')
if (loadingAuth) {
return (
@@ -165,7 +125,7 @@ export default function Profile() {
)
}
const displayName = user?.name || (authEmail ? authEmail.split('@')[0] : 'Utilizador')
const displayName = authEmail ? authEmail.split('@')[0] : 'Utilizador'
return (
<>
@@ -189,40 +149,20 @@ export default function Profile() {
<div className="absolute bottom-0 left-0 w-64 h-64 bg-purple-500/10 rounded-full blur-[80px] translate-y-1/2 -translate-x-1/2" />
<div className="relative z-10 p-6 sm:p-10 md:p-14 flex flex-col md:flex-row items-center gap-8 md:text-left text-center">
<label htmlFor="avatar-upload" className="relative group/avatar cursor-pointer block">
<input
type="file"
id="avatar-upload"
accept="image/*"
className="hidden"
onChange={handleAvatarChange}
/>
<div className="relative">
<div className="absolute inset-0 bg-indigo-500 rounded-[2rem] blur-2xl opacity-20 animate-pulse" />
<div className="w-20 h-20 sm:w-28 sm:h-28 bg-white/10 backdrop-blur-2xl border-2 border-white/20 rounded-[2rem] flex flex-col items-center justify-center text-indigo-400 shadow-2xl relative z-10 transition-transform duration-700 hover:scale-105 hover:rotate-3 overflow-hidden">
{avatarBase64 ? (
<img src={avatarBase64} alt="Avatar" className="w-full h-full object-cover group-hover/avatar:opacity-50 transition-opacity duration-300" />
) : (
<>
<User size={40} className="sm:hidden group-hover/avatar:opacity-0 transition-opacity duration-300" />
<User size={56} className="hidden sm:block group-hover/avatar:opacity-0 transition-opacity duration-300" />
</>
)}
{/* Overlay for upload */}
<div className="absolute inset-0 bg-indigo-900/80 flex flex-col items-center justify-center opacity-0 group-hover/avatar:opacity-100 transition-opacity duration-300">
<Camera size={24} className="text-white mb-1" />
<span className="text-[8px] font-black text-white uppercase tracking-widest text-center">Alterar<br/>Foto</span>
</div>
<div className="w-20 h-20 sm:w-28 sm:h-28 bg-white/10 backdrop-blur-2xl border-2 border-white/20 rounded-[2rem] flex items-center justify-center text-indigo-400 shadow-2xl relative z-10 transition-transform duration-700 hover:scale-105 hover:rotate-3">
<User size={40} className="sm:hidden" />
<User size={56} className="hidden sm:block" />
</div>
</label>
</div>
<div className="space-y-3 sm:space-y-4">
<div className="inline-flex items-center gap-2 px-3 py-1 bg-indigo-500/10 border border-indigo-500/20 rounded-full text-[10px] font-black uppercase tracking-[0.2em] text-indigo-400">
<div className="w-1.5 h-1.5 rounded-full bg-indigo-400 animate-ping" />
<span>Membro Verificado</span>
</div>
<div className="space-y-1 overflow-hidden">
<h1 className="text-xl sm:text-4xl md:text-5xl font-black text-white tracking-tighter uppercase italic leading-[0.9] break-all sm:break-normal flex flex-col gap-1">
<span className="text-sm sm:text-xl text-indigo-400 opacity-80 font-bold not-italic tracking-widest">Olá,</span>
<h1 className="text-xl sm:text-5xl md:text-6xl font-black text-white tracking-tighter uppercase italic leading-[0.9] break-all sm:break-normal">
{displayName}
</h1>
<p className="text-slate-400 font-bold italic tracking-wide text-xs sm:text-base truncate">{authEmail}</p>
@@ -239,7 +179,6 @@ export default function Profile() {
{ id: 'favoritos', label: 'Favoritos', icon: Heart, color: 'text-rose-500' },
{ id: 'agenda', label: 'Agenda', icon: Calendar, color: 'text-indigo-500' },
{ id: 'pedidos', label: 'Pedidos', icon: ShoppingBag, color: 'text-emerald-500' },
{ id: 'definicoes', label: 'Definições', icon: Settings, color: 'text-slate-500' },
].map((t) => (
<button
key={t.id}
@@ -435,44 +374,6 @@ export default function Profile() {
)}
</div>
)}
{activeTab === 'definicoes' && (
<div className="space-y-6 animate-in fade-in slide-in-from-bottom-8 duration-700">
<div className="flex items-center justify-between px-4">
<h2 className="text-xs font-black text-slate-400 uppercase tracking-[0.3em]">Definições de Conta</h2>
</div>
<Card className="p-6 sm:p-8 border-none bg-white rounded-[2.5rem] shadow-xl shadow-slate-200/50">
<div className="space-y-6 max-w-md">
<div className="space-y-2">
<label className="text-xs font-black uppercase tracking-widest text-slate-500">Nome de Utilizador</label>
<input
type="text"
value={editName}
onChange={(e) => setEditName(e.target.value)}
className="w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-2xl text-sm font-bold text-slate-900 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition-all"
placeholder="O teu nome"
/>
</div>
<div className="space-y-2">
<label className="text-xs font-black uppercase tracking-widest text-slate-500">E-mail</label>
<input
type="email"
value={authEmail}
disabled
className="w-full px-4 py-3 bg-slate-100/50 border border-slate-200 rounded-2xl text-sm font-bold text-slate-500 cursor-not-allowed"
/>
<p className="text-[10px] text-slate-400 font-bold italic">O e-mail não pode ser alterado.</p>
</div>
<Button
onClick={handleSaveProfile}
disabled={isSaving || !editName.trim()}
className="w-full sm:w-auto bg-slate-950 text-amber-400 hover:bg-amber-600 hover:text-white transition-colors uppercase tracking-widest font-black text-xs py-3 rounded-2xl mt-4"
>
{isSaving ? 'A guardar...' : 'Guardar Alterações'}
</Button>
</div>
</Card>
</div>
)}
</div>
</div>
</>