Merge branch 'feature/ajusAvatar' into feature/confirm-appoiments
This commit is contained in:
commit
da8ee7244b
@ -296,7 +296,7 @@ export default function PerfilPage() {
|
|||||||
className="bg-blue-600 hover:bg-blue-700"
|
className="bg-blue-600 hover:bg-blue-700"
|
||||||
onClick={handleEditClick}
|
onClick={handleEditClick}
|
||||||
>
|
>
|
||||||
✏️ Editar Perfil
|
Editar Perfil
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
|
|||||||
@ -865,17 +865,33 @@ export default function PacientePage() {
|
|||||||
try {
|
try {
|
||||||
const ok = typeof window !== 'undefined' ? window.confirm('Deseja realmente cancelar esta consulta?') : true
|
const ok = typeof window !== 'undefined' ? window.confirm('Deseja realmente cancelar esta consulta?') : true
|
||||||
if (!ok) return
|
if (!ok) return
|
||||||
// call API to delete
|
|
||||||
await deletarAgendamento(consulta.id)
|
// Prefer PATCH to mark appointment as cancelled (safer under RLS)
|
||||||
// Mark as deleted in cache so it won't appear again
|
try {
|
||||||
addDeletedAppointmentId(consulta.id)
|
await atualizarAgendamento(consulta.id, {
|
||||||
// remove from local list
|
cancelled_at: new Date().toISOString(),
|
||||||
|
status: 'cancelled',
|
||||||
|
cancellation_reason: 'Cancelado pelo paciente'
|
||||||
|
})
|
||||||
|
} catch (patchErr) {
|
||||||
|
// Fallback: try hard delete if server allows it
|
||||||
|
try {
|
||||||
|
await deletarAgendamento(consulta.id)
|
||||||
|
} catch (delErr) {
|
||||||
|
// Re-throw original patch error if both fail
|
||||||
|
throw patchErr || delErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove from local list so UI updates immediately
|
||||||
setAppointments((prev) => {
|
setAppointments((prev) => {
|
||||||
if (!prev) return prev
|
if (!prev) return prev
|
||||||
return prev.filter((a: any) => String(a.id) !== String(consulta.id))
|
return prev.filter((a: any) => String(a.id) !== String(consulta.id))
|
||||||
})
|
})
|
||||||
// if modal open for this appointment, close it
|
// if modal open for this appointment, close it
|
||||||
if (selectedAppointment && String(selectedAppointment.id) === String(consulta.id)) setSelectedAppointment(null)
|
if (selectedAppointment && String(selectedAppointment.id) === String(consulta.id)) setSelectedAppointment(null)
|
||||||
|
// Optionally persist to deleted cache to help client-side filtering
|
||||||
|
try { addDeletedAppointmentId(consulta.id) } catch(e) {}
|
||||||
setToast({ type: 'success', msg: 'Consulta cancelada.' })
|
setToast({ type: 'success', msg: 'Consulta cancelada.' })
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error('[Consultas] falha ao cancelar agendamento', err)
|
console.error('[Consultas] falha ao cancelar agendamento', err)
|
||||||
@ -1560,7 +1576,7 @@ export default function PacientePage() {
|
|||||||
className="bg-blue-600 hover:bg-blue-700 w-full sm:w-auto whitespace-nowrap text-xs sm:text-sm"
|
className="bg-blue-600 hover:bg-blue-700 w-full sm:w-auto whitespace-nowrap text-xs sm:text-sm"
|
||||||
onClick={() => setIsEditingProfile(true)}
|
onClick={() => setIsEditingProfile(true)}
|
||||||
>
|
>
|
||||||
✏️ Editar Perfil
|
Editar Perfil
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col sm:flex-row gap-2 w-full sm:w-auto">
|
<div className="flex flex-col sm:flex-row gap-2 w-full sm:w-auto">
|
||||||
|
|||||||
@ -2780,7 +2780,7 @@ const ProfissionalPage = () => {
|
|||||||
className="bg-blue-600 hover:bg-blue-700 text-xs sm:text-sm w-full sm:w-auto"
|
className="bg-blue-600 hover:bg-blue-700 text-xs sm:text-sm w-full sm:w-auto"
|
||||||
onClick={() => setIsEditingProfile(true)}
|
onClick={() => setIsEditingProfile(true)}
|
||||||
>
|
>
|
||||||
✏️ Editar Perfil
|
Editar Perfil
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex gap-2 w-full sm:w-auto">
|
<div className="flex gap-2 w-full sm:w-auto">
|
||||||
|
|||||||
@ -60,9 +60,32 @@ export function PagesHeader({ title = "", subtitle = "" }: { title?: string, sub
|
|||||||
className="relative h-8 w-8 rounded-full border-2 border-border hover:border-primary"
|
className="relative h-8 w-8 rounded-full border-2 border-border hover:border-primary"
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
onClick={() => setDropdownOpen(!dropdownOpen)}
|
||||||
>
|
>
|
||||||
|
{/* Mostrar foto do usuário quando disponível; senão, mostrar fallback com iniciais */}
|
||||||
<Avatar className="h-8 w-8">
|
<Avatar className="h-8 w-8">
|
||||||
<AvatarImage src="/avatars/01.png" alt="@usuario" />
|
{
|
||||||
<AvatarFallback className="bg-primary text-primary-foreground font-semibold">RA</AvatarFallback>
|
(() => {
|
||||||
|
const userPhoto = (user as any)?.profile?.foto_url || (user as any)?.profile?.fotoUrl || (user as any)?.profile?.avatar_url
|
||||||
|
const alt = user?.name || user?.email || 'Usuário'
|
||||||
|
|
||||||
|
const getInitials = (name?: string, email?: string) => {
|
||||||
|
if (name) {
|
||||||
|
const parts = name.trim().split(/\s+/)
|
||||||
|
const first = parts[0]?.charAt(0) ?? ''
|
||||||
|
const second = parts[1]?.charAt(0) ?? ''
|
||||||
|
return (first + second).toUpperCase() || (email?.charAt(0) ?? 'U').toUpperCase()
|
||||||
|
}
|
||||||
|
if (email) return email.charAt(0).toUpperCase()
|
||||||
|
return 'U'
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AvatarImage src={userPhoto || undefined} alt={alt} />
|
||||||
|
<AvatarFallback className="bg-primary text-primary-foreground font-semibold">{getInitials(user?.name, user?.email)}</AvatarFallback>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
})()
|
||||||
|
}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
@ -94,11 +117,9 @@ export function PagesHeader({ title = "", subtitle = "" }: { title?: string, sub
|
|||||||
}}
|
}}
|
||||||
className="w-full text-left px-4 py-2 text-sm hover:bg-accent cursor-pointer"
|
className="w-full text-left px-4 py-2 text-sm hover:bg-accent cursor-pointer"
|
||||||
>
|
>
|
||||||
👤 Perfil
|
Perfil
|
||||||
</button>
|
|
||||||
<button className="w-full text-left px-4 py-2 text-sm hover:bg-accent cursor-pointer">
|
|
||||||
⚙️ Configurações
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div className="border-t border-border my-1"></div>
|
<div className="border-t border-border my-1"></div>
|
||||||
<button
|
<button
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@ -110,7 +131,7 @@ export function PagesHeader({ title = "", subtitle = "" }: { title?: string, sub
|
|||||||
}}
|
}}
|
||||||
className="w-full text-left px-4 py-2 text-sm text-destructive hover:bg-destructive/10 cursor-pointer"
|
className="w-full text-left px-4 py-2 text-sm text-destructive hover:bg-destructive/10 cursor-pointer"
|
||||||
>
|
>
|
||||||
🚪 Sair
|
Sair
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user