feat(aptmpt page - patient status badge added

This commit is contained in:
2025-10-30 21:54:02 +05:30
parent 54f83ab398
commit a19c246ddb
2 changed files with 72 additions and 7 deletions

View File

@@ -0,0 +1,55 @@
import * as React from "react";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { PatientStatus } from "@repo/db/types";
export function PatientStatusBadge({
status,
className = "",
size = 10,
}: {
status: PatientStatus;
className?: string;
size?: number; // px
}) {
const { bg, label } = getVisuals(status);
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<span
aria-label={`Patient status: ${label}`}
className={`inline-block rounded-full ring-2 ring-white shadow ${className}`}
style={{
width: size,
height: size,
backgroundColor: bg,
position: "absolute",
top: "-6px", // stick out above card
right: "-6px", // stick out right
}}
/>
</TooltipTrigger>
<TooltipContent side="top" className="px-2 py-1 text-xs">
{label}
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}
function getVisuals(status: PatientStatus): { label: string; bg: string } {
switch (status) {
case "ACTIVE":
return { label: "Active", bg: "#16A34A" }; // MEDICAL GREEN (not same as staff green)
case "INACTIVE":
return { label: "Inactive", bg: "#DC2626" }; // ALERT RED (distinct from card red)
default:
return { label: "Unknown", bg: "#6B7280" }; // solid gray
}
}

View File

@@ -37,6 +37,7 @@ import {
Appointment, Appointment,
InsertAppointment, InsertAppointment,
Patient, Patient,
PatientStatus,
UpdateAppointment, UpdateAppointment,
} from "@repo/db/types"; } from "@repo/db/types";
import { import {
@@ -51,6 +52,7 @@ import {
setTaskStatus, setTaskStatus,
} from "@/redux/slices/seleniumEligibilityBatchCheckTaskSlice"; } from "@/redux/slices/seleniumEligibilityBatchCheckTaskSlice";
import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner"; import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner";
import { PatientStatusBadge } from "@/components/appointments/patient-status-badge";
// Define types for scheduling // Define types for scheduling
interface TimeSlot { interface TimeSlot {
@@ -69,6 +71,7 @@ interface ScheduledAppointment {
id?: number; id?: number;
patientId: number; patientId: number;
patientName: string; patientName: string;
patientStatus: PatientStatus;
staffId: number; staffId: number;
date: string | Date; date: string | Date;
startTime: string | Date; startTime: string | Date;
@@ -163,12 +166,12 @@ export default function AppointmentsPage() {
}); });
const colors = [ const colors = [
"bg-blue-600", "bg-sky-500", // light blue
"bg-emerald-600", "bg-teal-500", // teal
"bg-purple-600", "bg-indigo-500", // soft indigo
"bg-pink-600", "bg-rose-400", // muted rose
"bg-yellow-500", "bg-amber-400", // muted amber
"bg-red-600", "bg-orange-500", // softer warm orange
]; ];
// Assign colors cycling through the list // Assign colors cycling through the list
@@ -403,6 +406,7 @@ export default function AppointmentsPage() {
const patientName = patient const patientName = patient
? `${patient.firstName} ${patient.lastName}` ? `${patient.firstName} ${patient.lastName}`
: "Unknown Patient"; : "Unknown Patient";
const patientStatus = patient?.status;
const staffId = Number(apt.staffId ?? 1); const staffId = Number(apt.staffId ?? 1);
@@ -418,6 +422,7 @@ export default function AppointmentsPage() {
const processed = { const processed = {
...apt, ...apt,
patientName, patientName,
patientStatus,
staffId, staffId,
status: apt.status ?? null, status: apt.status ?? null,
date: formatLocalDate(apt.date), date: formatLocalDate(apt.date),
@@ -615,6 +620,12 @@ export default function AppointmentsPage() {
}} }}
onContextMenu={(e) => handleContextMenu(e, appointment.id ?? 0)} onContextMenu={(e) => handleContextMenu(e, appointment.id ?? 0)}
> >
<PatientStatusBadge
status={appointment.patientStatus ?? "UNKNOWN"}
className="pointer-events-auto" // ensure tooltip works
size={30} // bump size up from 10 → 14
/>
<div className="font-bold truncate flex items-center gap-1"> <div className="font-bold truncate flex items-center gap-1">
<Move className="h-3 w-3" /> <Move className="h-3 w-3" />
{appointment.patientName} {appointment.patientName}
@@ -835,7 +846,6 @@ export default function AppointmentsPage() {
description: `Processed ${results.length} appointments — success: ${successCount}, warnings: ${warningCount}, skipped: ${skippedCount}.`, description: `Processed ${results.length} appointments — success: ${successCount}, warnings: ${warningCount}, skipped: ${skippedCount}.`,
variant: skippedCount > 0 ? "destructive" : "default", variant: skippedCount > 0 ? "destructive" : "default",
}); });
} catch (err: any) { } catch (err: any) {
console.error("[check-all-eligibilities] error", err); console.error("[check-all-eligibilities] error", err);
dispatch( dispatch(