Files
Krow-workspace/frontend-web-free/src/components/events/EventHoverCard.jsx
2025-12-04 18:02:28 -05:00

135 lines
5.4 KiB
JavaScript

import React from "react";
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card";
import { Badge } from "@/components/ui/badge";
import { Calendar, MapPin, Users, FileText } from "lucide-react";
import { format, parseISO, isValid } from "date-fns";
const statusColors = {
Draft: "bg-slate-100 text-slate-700 border border-slate-300",
Active: "bg-emerald-50 text-emerald-700 border border-emerald-200",
Pending: "bg-purple-50 text-purple-700 border border-purple-200",
Confirmed: "bg-[#0A39DF]/10 text-[#0A39DF] border border-[#0A39DF]/30",
Assigned: "bg-amber-50 text-amber-700 border border-amber-200",
Completed: "bg-slate-100 text-slate-600 border border-slate-300",
Canceled: "bg-red-50 text-red-700 border border-red-200",
Cancelled: "bg-red-50 text-red-700 border border-red-200"
};
// Helper function to safely format dates
const safeFormatDate = (dateString, formatStr) => {
if (!dateString) return "-";
try {
const date = typeof dateString === 'string' ? parseISO(dateString) : new Date(dateString);
if (!isValid(date)) return "-";
return format(date, formatStr);
} catch {
return "-";
}
};
export default function EventHoverCard({ event, children }) {
const assignedCount = event.assigned_staff?.length || event.assigned || 0;
const requestedCount = event.requested || 0;
const remainingSlots = requestedCount - assignedCount;
return (
<HoverCard openDelay={200}>
<HoverCardTrigger asChild>
{children}
</HoverCardTrigger>
<HoverCardContent className="w-96 p-0" side="right" align="start">
<div className="bg-gradient-to-br from-slate-50 to-white p-4 border-b border-slate-200">
<div className="flex items-start justify-between mb-3">
<div>
<h3 className="font-bold text-lg text-[#1C323E]">{event.event_name}</h3>
<p className="text-sm text-slate-600">{event.business_name || "Company Name"}</p>
</div>
<Badge className={`${statusColors[event.status]} font-medium`}>
{event.status}
</Badge>
</div>
<div className="space-y-2 text-sm">
<div className="flex items-center gap-2 text-slate-700">
<Calendar className="w-4 h-4 text-[#0A39DF]" />
<span className="font-semibold">{safeFormatDate(event.date, "MMMM dd, yyyy")}</span>
</div>
{event.event_location && (
<div className="flex items-center gap-2 text-slate-700">
<MapPin className="w-4 h-4 text-[#0A39DF]" />
<span className="truncate">{event.event_location}</span>
</div>
)}
{event.po && (
<div className="flex items-center gap-2 text-slate-700">
<FileText className="w-4 h-4 text-[#0A39DF]" />
<span>PO: {event.po}</span>
</div>
)}
</div>
</div>
<div className="p-4 space-y-3">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Users className="w-4 h-4 text-slate-600" />
<span className="text-sm font-medium text-slate-700">Staff Assignment</span>
</div>
<Badge variant="outline" className="border-[#0A39DF] text-[#0A39DF]">
{assignedCount} / {requestedCount}
</Badge>
</div>
{remainingSlots > 0 && (
<div className="bg-amber-50 border border-amber-200 rounded-lg p-2 text-xs text-amber-800">
<strong>{remainingSlots}</strong> staff member{remainingSlots !== 1 ? 's' : ''} still needed
</div>
)}
{remainingSlots === 0 && requestedCount > 0 && (
<div className="bg-emerald-50 border border-emerald-200 rounded-lg p-2 text-xs text-emerald-800">
Fully staffed
</div>
)}
{event.assigned_staff && event.assigned_staff.length > 0 && (
<div className="space-y-2 max-h-40 overflow-y-auto">
<p className="text-xs font-semibold text-slate-600 uppercase">Assigned Staff:</p>
{event.assigned_staff.map((staff, idx) => (
<div key={idx} className="flex items-center gap-2 text-sm">
<div className="w-6 h-6 bg-[#0A39DF] rounded flex items-center justify-center text-white text-xs font-bold">
{staff.staff_name?.charAt(0) || '?'}
</div>
<div className="flex-1 min-w-0">
<p className="font-medium text-slate-900 truncate">{staff.staff_name}</p>
{staff.position && <p className="text-xs text-slate-500 truncate">{staff.position}</p>}
</div>
{staff.confirmed && (
<Badge variant="outline" className="text-xs border-emerald-500 text-emerald-700">
Confirmed
</Badge>
)}
</div>
))}
</div>
)}
{event.notes && (
<div className="pt-2 border-t border-slate-200">
<p className="text-xs font-semibold text-slate-600 uppercase mb-1">Notes:</p>
<p className="text-xs text-slate-600">{event.notes}</p>
</div>
)}
</div>
</HoverCardContent>
</HoverCard>
);
}