mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
chore(medications): remove unused IntakeTimeline component
The component was exported but never imported anywhere — only the file itself contained the three references (the props interface, the function declaration, and the type annotation). Likely an early scaffold for the v1.4 medication-intake redesign that was superseded by the intake-card layout before any caller wired it in. No tests existed for this component, so the delete is single-file.
This commit is contained in:
1 parent
1149ae5021
commit
784105d3bb
1 file changed
-159
@@ -1,159 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { invalidateKeys, medicationDependentKeys } from "@/lib/query-keys";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Check, SkipForward, Loader2, X } from "lucide-react";
|
||||
import { formatDateWithWeekday, formatTime } from "@/lib/format";
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
|
||||
interface IntakeEvent {
|
||||
id: string;
|
||||
medicationId: string;
|
||||
scheduledFor: string;
|
||||
takenAt: string | null;
|
||||
skipped: boolean;
|
||||
source: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
interface IntakeTimelineProps {
|
||||
medicationId: string;
|
||||
medicationName: string;
|
||||
}
|
||||
|
||||
export function IntakeTimeline({
|
||||
medicationId,
|
||||
medicationName,
|
||||
}: IntakeTimelineProps) {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslations();
|
||||
|
||||
const { data: events, isLoading } = useQuery({
|
||||
queryKey: ["medications", medicationId, "intake"],
|
||||
queryFn: async () => {
|
||||
const res = await fetch(
|
||||
`/api/medications/${medicationId}/intake?limit=50`,
|
||||
);
|
||||
if (!res.ok) throw new Error("Failed to fetch");
|
||||
const json = await res.json();
|
||||
return json.data.events as IntakeEvent[];
|
||||
},
|
||||
});
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: async (eventId: string) => {
|
||||
const res = await fetch(
|
||||
`/api/medications/${medicationId}/intake/${eventId}`,
|
||||
{ method: "DELETE" },
|
||||
);
|
||||
if (!res.ok) throw new Error("Delete failed");
|
||||
},
|
||||
onSuccess: () => {
|
||||
void invalidateKeys(queryClient, medicationDependentKeys);
|
||||
},
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex h-20 items-center justify-center">
|
||||
<Loader2 className="text-muted-foreground h-4 w-4 animate-spin" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!events?.length) {
|
||||
return (
|
||||
<p className="text-muted-foreground py-4 text-center text-sm">
|
||||
{`${t("medications.noIntakesForMedication")} ${medicationName}`}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
// Group by day
|
||||
const grouped = new Map<string, IntakeEvent[]>();
|
||||
for (const event of events) {
|
||||
const day = formatDateWithWeekday(event.scheduledFor);
|
||||
const list = grouped.get(day) ?? [];
|
||||
list.push(event);
|
||||
grouped.set(day, list);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-2.5">
|
||||
{[...grouped.entries()].map(([day, dayEvents]) => (
|
||||
<div key={day} className="space-y-1.5">
|
||||
<p className="text-muted-foreground text-xs font-medium">{day}</p>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{dayEvents.map((event) => (
|
||||
<div key={event.id} className="group relative inline-flex">
|
||||
<Badge
|
||||
variant={event.skipped ? "outline" : "secondary"}
|
||||
className={
|
||||
event.skipped
|
||||
? "text-muted-foreground gap-1 pr-6"
|
||||
: "gap-1 bg-green-500/20 pr-6 text-green-400"
|
||||
}
|
||||
>
|
||||
{event.skipped ? (
|
||||
<SkipForward className="h-3 w-3" />
|
||||
) : (
|
||||
<Check className="h-3 w-3" />
|
||||
)}
|
||||
{formatTime(event.scheduledFor)}
|
||||
{event.source !== "WEB" && (
|
||||
<span className="text-[10px] opacity-60">
|
||||
{event.source}
|
||||
</span>
|
||||
)}
|
||||
</Badge>
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<button
|
||||
className="text-destructive absolute top-1/2 right-1 -translate-y-1/2 opacity-0 transition-opacity group-hover:opacity-100"
|
||||
aria-label={t("medications.deleteIntakeAriaLabel")}
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
</button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
{t("medications.intakeDeleteConfirm")}
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
{t("medications.intakeDeleteDescription")}
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>
|
||||
{t("common.cancel")}
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
||||
onClick={() => deleteMutation.mutate(event.id)}
|
||||
>
|
||||
{t("common.delete")}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user