Positioning, sizing and sorting of the gadgets improved.
This commit is contained in:
@@ -22,8 +22,6 @@ interface TodayUpcomingAppointmentsProps {
|
||||
isInitialLoad?: boolean;
|
||||
}
|
||||
|
||||
const MAX_VISIBLE = 3;
|
||||
|
||||
export function TodayUpcomingAppointments({
|
||||
actions,
|
||||
loading = false,
|
||||
@@ -48,11 +46,11 @@ export function TodayUpcomingAppointments({
|
||||
return null;
|
||||
}
|
||||
|
||||
const appointments = (actions.upcomingAppointmentsToday ?? []).slice(0, MAX_VISIBLE);
|
||||
const appointments = actions.upcomingAppointmentsToday ?? [];
|
||||
|
||||
if (isInitialLoad) {
|
||||
return (
|
||||
<Card className="min-h-[140px] p-3">
|
||||
<Card className="flex h-full min-h-0 flex-col p-3">
|
||||
<div className="mb-2 space-y-1.5">
|
||||
<div className="h-3.5 w-32 animate-pulse rounded bg-background-secondary/60" />
|
||||
<div className="h-3 w-44 animate-pulse rounded bg-background-secondary/60" />
|
||||
@@ -67,7 +65,7 @@ export function TodayUpcomingAppointments({
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="min-h-[140px] p-3">
|
||||
<Card className="flex h-full min-h-0 flex-col p-3">
|
||||
<div className="mb-2 flex flex-col gap-1 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold text-card-foreground">
|
||||
@@ -88,44 +86,48 @@ export function TodayUpcomingAppointments({
|
||||
<p className="text-xs text-text-muted text-center">{t('noUpcomingAppointments')}</p>
|
||||
</div>
|
||||
) : (
|
||||
<ul className="divide-y divide-border/40">
|
||||
{appointments.map((appointment) => {
|
||||
const start = new Date(appointment.startAt);
|
||||
const end = new Date(appointment.endAt);
|
||||
const timeLabel = `${formatTimeForInput(start)} – ${formatTimeForInput(end)}`;
|
||||
const purposeIndex = treatmentCatalog.findIndex((entry) => entry.code === appointment.purpose);
|
||||
const purposeTextColor = treatmentTypeColor(
|
||||
appointment.purpose,
|
||||
purposeIndex < 0 ? 0 : purposeIndex,
|
||||
);
|
||||
const purposeDisplay = purposeLabel(appointment.purpose, treatmentCatalog);
|
||||
<div className="min-h-0 flex-1 overflow-x-hidden overflow-y-auto">
|
||||
<ul className="divide-y divide-border/40">
|
||||
{appointments.map((appointment) => {
|
||||
const start = new Date(appointment.startAt);
|
||||
const end = new Date(appointment.endAt);
|
||||
const timeLabel = `${formatTimeForInput(start)} – ${formatTimeForInput(end)}`;
|
||||
const purposeIndex = treatmentCatalog.findIndex(
|
||||
(entry) => entry.code === appointment.purpose,
|
||||
);
|
||||
const purposeTextColor = treatmentTypeColor(
|
||||
appointment.purpose,
|
||||
purposeIndex < 0 ? 0 : purposeIndex,
|
||||
);
|
||||
const purposeDisplay = purposeLabel(appointment.purpose, treatmentCatalog);
|
||||
|
||||
return (
|
||||
<li key={appointment.id}>
|
||||
<Link
|
||||
href={treatmentAppointmentHref(appointment.id)}
|
||||
className="group -mx-1 flex items-center justify-between gap-2 rounded-[var(--radius-md)] px-1 py-2 transition-colors hover:bg-background-secondary/45"
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<p className="truncate text-xs font-medium text-text-primary">
|
||||
{appointment.patientName}
|
||||
</p>
|
||||
<p className="mt-0.5 truncate text-[11px] text-text-muted">
|
||||
{timeLabel}
|
||||
{appointment.purpose ? (
|
||||
<span style={{ color: purposeTextColor }}> · {purposeDisplay}</span>
|
||||
) : null}
|
||||
</p>
|
||||
</div>
|
||||
<ChevronRight
|
||||
className="h-3.5 w-3.5 shrink-0 text-text-muted opacity-0 transition-opacity group-hover:opacity-100"
|
||||
aria-hidden
|
||||
/>
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
return (
|
||||
<li key={appointment.id}>
|
||||
<Link
|
||||
href={treatmentAppointmentHref(appointment.id)}
|
||||
className="group -mx-1 flex items-center justify-between gap-2 rounded-[var(--radius-md)] px-1 py-2 transition-colors hover:bg-background-secondary/45"
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<p className="truncate text-xs font-medium text-text-primary">
|
||||
{appointment.patientName}
|
||||
</p>
|
||||
<p className="mt-0.5 truncate text-[11px] text-text-muted">
|
||||
{timeLabel}
|
||||
{appointment.purpose ? (
|
||||
<span style={{ color: purposeTextColor }}> · {purposeDisplay}</span>
|
||||
) : null}
|
||||
</p>
|
||||
</div>
|
||||
<ChevronRight
|
||||
className="h-3.5 w-3.5 shrink-0 text-text-muted opacity-0 transition-opacity group-hover:opacity-100"
|
||||
aria-hidden
|
||||
/>
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user