2025-08-04 17:45:44 +02:00
|
|
|
import { add, differenceInDays } from "date-fns";
|
2025-08-28 18:27:07 +02:00
|
|
|
import { CalendarClock, CalendarDays, Clock, Hourglass } from "lucide-react";
|
2025-08-04 17:45:44 +02:00
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
Accordion,
|
|
|
|
|
AccordionContent,
|
|
|
|
|
AccordionItem,
|
|
|
|
|
AccordionTrigger,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "~/components/ui/accordion";
|
2025-08-28 18:27:07 +02:00
|
|
|
import { Card, CardContent } from "~/components/ui/card";
|
|
|
|
|
import { Progress } from "~/components/ui/progress"; // Import the Progress component
|
2025-08-04 17:45:44 +02:00
|
|
|
import { useMediaQuery } from "~/hooks/use-media-query";
|
|
|
|
|
|
|
|
|
|
export const ServizioDuration = ({
|
2025-08-28 18:27:07 +02:00
|
|
|
decorrenza,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
decorrenza: Date | null;
|
2025-08-04 17:45:44 +02:00
|
|
|
}) => {
|
2025-08-28 18:27:07 +02:00
|
|
|
const isDesktop = useMediaQuery("(min-width: 768px)");
|
|
|
|
|
if (!decorrenza) {
|
|
|
|
|
return null; // If decorrenza is null, do not render the component
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<Accordion
|
|
|
|
|
collapsible
|
|
|
|
|
defaultValue={isDesktop ? "validity" : undefined}
|
2025-08-29 16:18:32 +02:00
|
|
|
type="single"
|
2025-08-28 18:27:07 +02:00
|
|
|
>
|
|
|
|
|
<AccordionItem value="validity">
|
|
|
|
|
<AccordionTrigger>
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="flex items-center gap-2 font-medium text-base">
|
|
|
|
|
<Clock className="size-6 text-primary" />
|
2025-08-28 18:27:07 +02:00
|
|
|
Validità servizio
|
|
|
|
|
</div>
|
|
|
|
|
</AccordionTrigger>
|
|
|
|
|
<AccordionContent>
|
|
|
|
|
<ServiceDurationDisplay
|
|
|
|
|
decorrenza={decorrenza}
|
|
|
|
|
recessoDays={14}
|
2025-08-29 16:18:32 +02:00
|
|
|
scadenza={add(decorrenza, { days: 60 })}
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
|
|
|
|
</AccordionContent>
|
|
|
|
|
</AccordionItem>
|
|
|
|
|
</Accordion>
|
|
|
|
|
);
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
interface ServiceDurationDisplayProps {
|
2025-08-28 18:27:07 +02:00
|
|
|
decorrenza: Date;
|
|
|
|
|
scadenza: Date;
|
|
|
|
|
recessoDays: number;
|
2025-08-04 17:45:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A sleek, light-themed component for displaying service duration,
|
|
|
|
|
* including start date, end date, and trial period, with a progress bar.
|
|
|
|
|
*/
|
|
|
|
|
function ServiceDurationDisplay({
|
2025-08-28 18:27:07 +02:00
|
|
|
decorrenza,
|
|
|
|
|
scadenza,
|
|
|
|
|
recessoDays,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: ServiceDurationDisplayProps) {
|
2025-08-28 18:27:07 +02:00
|
|
|
// Calculate remaining days
|
|
|
|
|
const diffDays = differenceInDays(scadenza, new Date()) + 1;
|
|
|
|
|
const remainingDaysText = diffDays >= 0 ? `${diffDays} giorni` : "Concluso";
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
const progressPercentage = ((60 - diffDays) / 60) * 100; // Assuming 60 days is the full duration for 100% progress
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
return (
|
|
|
|
|
<Card className="w-full rounded-xl p-2 shadow-lg sm:py-3">
|
|
|
|
|
<CardContent className="flex flex-col gap-5 px-1">
|
|
|
|
|
<div className="flex w-full flex-col justify-between gap-4 sm:flex-row sm:items-center">
|
|
|
|
|
<div className="flex items-center gap-4">
|
2025-10-10 16:18:43 +02:00
|
|
|
<CalendarDays aria-hidden="true" className="h-6 w-6 text-primary" />
|
2025-08-28 18:27:07 +02:00
|
|
|
<div>
|
|
|
|
|
<div className="text-muted-foreground text-sm">Decorrenza</div>
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="font-semibold text-foreground text-lg">
|
2025-08-28 18:27:07 +02:00
|
|
|
{decorrenza.toLocaleDateString("it-IT", {
|
|
|
|
|
day: "2-digit",
|
|
|
|
|
month: "long",
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
<div className="flex items-center gap-4">
|
|
|
|
|
<CalendarClock
|
|
|
|
|
aria-hidden="true"
|
2025-10-10 16:18:43 +02:00
|
|
|
className="h-6 w-6 text-primary"
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
|
|
|
|
<div>
|
|
|
|
|
<div className="text-muted-foreground text-sm">Scadenza</div>
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="font-semibold text-foreground text-lg">
|
2025-08-28 18:27:07 +02:00
|
|
|
{scadenza.toLocaleDateString("it-IT", {
|
|
|
|
|
day: "2-digit",
|
|
|
|
|
month: "long",
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
<div className="flex items-center gap-4">
|
2025-10-10 16:18:43 +02:00
|
|
|
<Hourglass aria-hidden="true" className="h-6 w-6 text-primary" />
|
2025-08-28 18:27:07 +02:00
|
|
|
<div>
|
|
|
|
|
<div className="text-muted-foreground text-sm">
|
|
|
|
|
Periodo di recesso
|
|
|
|
|
</div>
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="font-semibold text-foreground text-lg">
|
2025-08-28 18:27:07 +02:00
|
|
|
{recessoDays} giorni
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
{/* Progress Bar */}
|
|
|
|
|
<div className="pt-2">
|
|
|
|
|
<Progress
|
|
|
|
|
aria-label="Service duration progress"
|
2025-08-29 16:18:32 +02:00
|
|
|
className="h-2"
|
|
|
|
|
value={progressPercentage}
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="mt-1 text-right text-muted-foreground text-sm">
|
2025-08-28 18:27:07 +02:00
|
|
|
{remainingDaysText}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
);
|
2025-08-04 17:45:44 +02:00
|
|
|
}
|