Compare commits
No commits in common. "da8ee7244b4be4e18b5837c7c225eddadc1c2e44" and "dce7b485e2a66fc8f2cde0fab8e053dc3a1f8709" have entirely different histories.
da8ee7244b
...
dce7b485e2
@ -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,33 +865,17 @@ 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
|
||||||
// Prefer PATCH to mark appointment as cancelled (safer under RLS)
|
await deletarAgendamento(consulta.id)
|
||||||
try {
|
// Mark as deleted in cache so it won't appear again
|
||||||
await atualizarAgendamento(consulta.id, {
|
addDeletedAppointmentId(consulta.id)
|
||||||
cancelled_at: new Date().toISOString(),
|
// remove from local list
|
||||||
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)
|
||||||
@ -1576,7 +1560,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,32 +60,9 @@ 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>
|
||||||
|
|
||||||
@ -117,9 +94,11 @@ 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) => {
|
||||||
@ -131,7 +110,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