import { useMemo, useState } from 'react' import { Link, useParams } from 'react-router-dom' import { toast } from 'sonner' import { Check, ClipboardCopy, HelpCircle, X } from 'lucide-react' import { DetailPageLayout } from '@/layouts/DetailPageLayout' import { ActivityTimeline, DetailSection } from '@/components/detail/ActivityTimeline' import { ApprovalStepper, type ApprovalStep } from '@/components/detail/ApprovalStepper' import { KeyValueGrid } from '@/components/detail/KeyValueGrid' import { RowActions, type RowAction } from '@/components/table/RowActions' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { StatusBadge, statusLabel } from '@/components/ui/status-badge' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table' import { branches, doctors, prescriptions } from '@/mocks/data' import { useAuthStore } from '@/zustand/authStore' import { formatDoseTimes, formatFrequencyLabel } from '@/lib/dosingSchedule' import { formatDateTime } from '@/lib/utils' import type { Prescription } from '@/types' const OPEN_STATUSES: Prescription['status'][] = ['submitted', 'under_review', 'queried'] export function PrescriptionDetailPage() { const { id } = useParams() const user = useAuthStore((s) => s.user) const seed = prescriptions.find((p) => p.id === id) const [rx, setRx] = useState(seed ? { ...seed, items: [...seed.items] } : undefined) if (!rx) { return ( ) } const branch = branches.find((b) => b.id === rx.branchId) const doctor = rx.doctorId ? doctors.find((d) => d.id === rx.doctorId) : undefined const controlled = rx.items.some((i) => i.controlled) const isOpen = OPEN_STATUSES.includes(rx.status) const act = (next: Prescription['status']) => { const patch = { status: next, reviewedBy: user?.name ?? 'Pharmacist', reviewedAt: new Date().toISOString(), } setRx((prev) => (prev ? { ...prev, ...patch } : prev)) const target = prescriptions.find((p) => p.id === rx.id) if (target) Object.assign(target, patch) toast.success(`Prescription ${next}`) } const copyId = () => { void navigator.clipboard?.writeText(rx.id) toast.message(`${rx.id} copied to clipboard`) } const overflow: RowAction[] = [ ...(isOpen ? [ { label: 'Reject prescription', icon: , variant: 'destructive' as const, onClick: () => act('rejected'), }, ] : []), { label: 'Copy Rx ID', icon: , onClick: copyId }, ] const steps = useMemo(() => { const decided = rx.status === 'approved' || rx.status === 'rejected' const reviewSeen = decided || rx.status === 'queried' return [ { key: 'submitted', label: 'Submitted', state: 'done', actor: rx.customerName, at: rx.submittedAt, }, { key: 'review', label: 'Pharmacist review', state: reviewSeen ? 'done' : 'current', actor: reviewSeen ? rx.reviewedBy : rx.reviewStartedAt ? 'Review in progress' : undefined, at: rx.reviewStartedAt, hint: rx.status === 'submitted' ? 'Waiting to be picked up from the queue' : undefined, }, { key: 'decision', label: rx.status === 'approved' ? 'Approved for dispensing' : rx.status === 'rejected' ? 'Rejected' : rx.status === 'queried' ? 'Queried with customer' : 'Decision', state: rx.status === 'approved' ? 'done' : rx.status === 'rejected' ? 'failed' : rx.status === 'queried' ? 'current' : 'upcoming', actor: rx.status === 'queried' || rx.status === 'approved' || rx.status === 'rejected' ? rx.reviewedBy : undefined, at: rx.status === 'submitted' || rx.status === 'under_review' ? undefined : rx.reviewedAt, hint: rx.status === 'queried' ? 'Awaiting a clearer scan from the customer' : undefined, }, ] }, [rx]) const decisionCluster = (
{isOpen ? ( <> ) : ( )}
) return ( {controlled ? Controlled : null} } actions={ <> {isOpen ? ( <> ) : null} } sidebar={ } >

{rx.status === 'approved' ? 'Approved and ready to dispense' : rx.status === 'rejected' ? 'Rejected — nothing will be dispensed' : rx.status === 'queried' ? 'Waiting on the customer' : rx.status === 'under_review' ? 'Open with a pharmacist' : 'Waiting for a pharmacist'}

{rx.reviewedBy && rx.reviewedAt ? `${statusLabel('prescription', rx.status)} by ${rx.reviewedBy} · ${formatDateTime(rx.reviewedAt)}` : `Submitted ${formatDateTime(rx.submittedAt)} · no decision recorded yet`}

{rx.decisionNote ? (

{rx.decisionNote}

) : null}
{doctor.name} ) : ( rx.prescriber ?? '—' ), }, { label: 'Hospital', value: doctor?.orgName ?? '—' }, { label: 'License', value: doctor?.licenseNumber ?? '—' }, { label: 'Submitted', value: formatDateTime(rx.submittedAt) }, { label: 'Items', value: String(rx.items.length) }, { label: 'Controlled items', value: controlled ? 'Yes — stamp required' : 'None' }, { label: 'Reviewed by', value: rx.reviewedBy ?? 'Not reviewed yet' }, ]} /> Medication Qty Interval Dose times Flags {rx.items.map((item) => ( {item.name} {item.qty} {formatFrequencyLabel(item.frequency, item.intervalHours)} {item.frequency ? ( {item.frequency} {item.frequency === 'QXH' && item.intervalHours ? ` · ${item.intervalHours}h` : ''} ) : null} {formatDoseTimes(item.times)} {item.controlled ? ( Controlled ) : ( OTC/Rx )} ))}

{isOpen ? controlled ? 'Approving stamps a dispensing record and logs the controlled item against your licence.' : 'Approving stamps a dispensing record against this branch’s stock.' : `Decision recorded by ${rx.reviewedBy ?? 'a pharmacist'}.`}

{decisionCluster}
) }