new version frontend-webpage

This commit is contained in:
José Salazar
2025-11-21 09:13:05 -05:00
parent 23dfba35cc
commit de1cc96ba0
56 changed files with 7736 additions and 3367 deletions

View File

@@ -0,0 +1,161 @@
import React from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { AlertTriangle, Clock, DollarSign, Calendar, Users } from "lucide-react";
import { format, differenceInHours } from "date-fns";
// Calculate if cancellation fee applies
export const calculateCancellationFee = (eventDate, eventStartTime, assignedCount) => {
const now = new Date();
// Combine event date and start time
const eventDateTime = new Date(`${eventDate}T${eventStartTime || '00:00'}`);
const hoursUntilEvent = differenceInHours(eventDateTime, now);
// Rule: 24+ hours = no fee, < 24 hours = 4-hour fee per worker
const feeApplies = hoursUntilEvent < 24;
const feeAmount = feeApplies ? assignedCount * 4 * 50 : 0; // Assuming $50/hour average
return {
feeApplies,
hoursUntilEvent,
feeAmount,
assignedCount
};
};
export default function CancellationFeeModal({
open,
onClose,
onConfirm,
event,
isSubmitting
}) {
if (!event) return null;
const eventStartTime = event.shifts?.[0]?.roles?.[0]?.start_time || '09:00';
const assignedCount = event.assigned_staff?.length || 0;
const feeData = calculateCancellationFee(event.date, eventStartTime, assignedCount);
return (
<Dialog open={open} onOpenChange={onClose}>
<DialogContent className="max-w-xl">
<DialogHeader>
<div className="flex items-center gap-3 mb-2">
<div className="w-12 h-12 bg-red-100 rounded-xl flex items-center justify-center">
<AlertTriangle className="w-6 h-6 text-red-600" />
</div>
<div>
<DialogTitle className="text-2xl font-bold text-red-700">
Confirm Order Cancellation
</DialogTitle>
<DialogDescription className="text-slate-600 mt-1">
{feeData.feeApplies
? "⚠️ Cancellation fee will apply"
: "✅ No cancellation fee"
}
</DialogDescription>
</div>
</div>
</DialogHeader>
<div className="space-y-4 py-4">
{/* Event Summary */}
<div className="bg-slate-50 border border-slate-200 rounded-xl p-4">
<h4 className="font-bold text-slate-900 mb-3">{event.event_name}</h4>
<div className="grid grid-cols-2 gap-3 text-sm">
<div className="flex items-center gap-2">
<Calendar className="w-4 h-4 text-blue-600" />
<span>{format(new Date(event.date), 'MMM d, yyyy')}</span>
</div>
<div className="flex items-center gap-2">
<Clock className="w-4 h-4 text-blue-600" />
<span>{eventStartTime}</span>
</div>
<div className="flex items-center gap-2">
<Users className="w-4 h-4 text-blue-600" />
<span>{assignedCount} Staff Assigned</span>
</div>
</div>
</div>
{/* Time Until Event */}
<Alert className={feeData.feeApplies ? "bg-red-50 border-red-300" : "bg-green-50 border-green-300"}>
<AlertDescription>
<div className="flex items-center gap-2 mb-2">
<Clock className={`w-5 h-5 ${feeData.feeApplies ? 'text-red-600' : 'text-green-600'}`} />
<span className="font-bold text-slate-900">
{feeData.hoursUntilEvent} hours until event
</span>
</div>
<p className="text-sm text-slate-700">
{feeData.feeApplies
? "Canceling within 24 hours triggers a 4-hour minimum fee per assigned worker."
: "You're canceling more than 24 hours in advance - no penalty applies."
}
</p>
</AlertDescription>
</Alert>
{/* Fee Breakdown */}
{feeData.feeApplies && (
<div className="bg-gradient-to-r from-red-50 to-orange-50 border-2 border-red-300 rounded-xl p-5">
<div className="flex items-center gap-2 mb-4">
<DollarSign className="w-5 h-5 text-red-600" />
<h4 className="font-bold text-red-900">Cancellation Fee Breakdown</h4>
</div>
<div className="space-y-3">
<div className="flex items-center justify-between p-3 bg-white rounded-lg">
<span className="text-sm text-slate-700">Assigned Staff</span>
<span className="font-bold text-slate-900">{assignedCount} workers</span>
</div>
<div className="flex items-center justify-between p-3 bg-white rounded-lg">
<span className="text-sm text-slate-700">Minimum Charge</span>
<span className="font-bold text-slate-900">4 hours each</span>
</div>
<div className="flex items-center justify-between p-4 bg-red-100 rounded-lg border-2 border-red-300">
<span className="font-bold text-red-900">Total Cancellation Fee</span>
<span className="text-2xl font-bold text-red-700">
${feeData.feeAmount.toLocaleString()}
</span>
</div>
</div>
</div>
)}
{/* Warning Text */}
<Alert className="bg-yellow-50 border-yellow-300">
<AlertDescription className="text-sm text-yellow-900">
<strong> This action cannot be undone.</strong> The vendor will be notified immediately,
and all assigned staff will be released from this event.
</AlertDescription>
</Alert>
</div>
<DialogFooter>
<Button variant="outline" onClick={onClose}>
Keep Order
</Button>
<Button
variant="destructive"
onClick={onConfirm}
disabled={isSubmitting}
className="bg-red-600 hover:bg-red-700"
>
{isSubmitting ? "Canceling..." : `Confirm Cancellation${feeData.feeApplies ? ` ($${feeData.feeAmount})` : ''}`}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}