export with one error

This commit is contained in:
José Salazar
2025-11-26 13:05:42 -05:00
parent 46dcebd69f
commit 645fecfae9
33 changed files with 10028 additions and 1726 deletions

View File

@@ -21,9 +21,29 @@ import {
TabsList, // New import
TabsTrigger, // New import
} from "@/components/ui/tabs"; // New import
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Calendar as CalendarComponent } from "@/components/ui/calendar";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
} from "@/components/ui/command";
import {
Search, Calendar, MapPin, Users, Eye, Edit, X, Trash2, FileText, // Edit instead of Edit2
Clock, DollarSign, Package, CheckCircle, AlertTriangle, Grid, List, Zap, Plus, Building2, Bell, Edit3
Clock, DollarSign, Package, CheckCircle, AlertTriangle, Grid, List, Zap, Plus, Building2, Bell, Edit3, Filter, CalendarIcon, Check, ChevronsUpDown
} from "lucide-react";
import { useToast } from "@/components/ui/use-toast";
import { format, parseISO, isValid } from "date-fns";
@@ -92,10 +112,18 @@ export default function ClientOrders() {
const { toast } = useToast();
const [searchTerm, setSearchTerm] = useState("");
const [statusFilter, setStatusFilter] = useState("all"); // Updated values for Tabs
const [dateFilter, setDateFilter] = useState("all");
const [specificDate, setSpecificDate] = useState(null);
const [tempDate, setTempDate] = useState(null);
const [locationFilter, setLocationFilter] = useState("all");
const [managerFilter, setManagerFilter] = useState("all");
const [locationOpen, setLocationOpen] = useState(false);
const [managerOpen, setManagerOpen] = useState(false);
const [cancelDialogOpen, setCancelDialogOpen] = useState(false); // Changed from cancelDialog.open
const [orderToCancel, setOrderToCancel] = useState(null); // Changed from cancelDialog.order
const [viewOrderModal, setViewOrderModal] = useState(false);
const [selectedOrder, setSelectedOrder] = useState(null);
const [calendarOpen, setCalendarOpen] = useState(false);
const { data: user } = useQuery({
queryKey: ['current-user-client-orders'],
@@ -135,6 +163,28 @@ export default function ClientOrders() {
},
});
// Get unique locations and managers for filters
const uniqueLocations = useMemo(() => {
const locations = new Set();
clientEvents.forEach(e => {
if (e.hub) locations.add(e.hub);
if (e.event_location) locations.add(e.event_location);
});
return Array.from(locations).sort();
}, [clientEvents]);
const uniqueManagers = useMemo(() => {
const managers = new Set();
clientEvents.forEach(e => {
if (e.manager_name) managers.add(e.manager_name);
// Also check in shifts for manager names
e.shifts?.forEach(shift => {
if (shift.manager_name) managers.add(shift.manager_name);
});
});
return Array.from(managers).sort();
}, [clientEvents]);
const filteredOrders = useMemo(() => { // Renamed from filteredEvents
let filtered = clientEvents;
@@ -166,8 +216,61 @@ export default function ClientOrders() {
return true; // For "all" or other statuses
});
// Specific date filter (from calendar)
if (specificDate) {
filtered = filtered.filter(e => {
const eventDate = safeParseDate(e.date);
if (!eventDate) return false;
const selectedDateNormalized = new Date(specificDate);
selectedDateNormalized.setHours(0, 0, 0, 0);
eventDate.setHours(0, 0, 0, 0);
return eventDate.getTime() === selectedDateNormalized.getTime();
});
}
// Date range filter
else if (dateFilter !== "all") {
filtered = filtered.filter(e => {
const eventDate = safeParseDate(e.date);
if (!eventDate) return false;
const now = new Date();
now.setHours(0, 0, 0, 0);
if (dateFilter === "today") {
return eventDate.toDateString() === now.toDateString();
} else if (dateFilter === "week") {
const weekFromNow = new Date(now);
weekFromNow.setDate(now.getDate() + 7);
return eventDate >= now && eventDate <= weekFromNow;
} else if (dateFilter === "month") {
const monthFromNow = new Date(now);
monthFromNow.setMonth(now.getMonth() + 1);
return eventDate >= now && eventDate <= monthFromNow;
} else if (dateFilter === "past") {
return eventDate < now;
}
return true;
});
}
// Location filter
if (locationFilter !== "all") {
filtered = filtered.filter(e =>
e.hub === locationFilter || e.event_location === locationFilter
);
}
// Manager filter
if (managerFilter !== "all") {
filtered = filtered.filter(e => {
if (e.manager_name === managerFilter) return true;
// Check shifts for manager
return e.shifts?.some(shift => shift.manager_name === managerFilter);
});
}
return filtered;
}, [clientEvents, searchTerm, statusFilter]);
}, [clientEvents, searchTerm, statusFilter, dateFilter, specificDate, locationFilter, managerFilter]);
const activeOrders = clientEvents.filter(e =>
e.status !== "Completed" && e.status !== "Canceled"
@@ -316,23 +419,261 @@ export default function ClientOrders() {
</Card>
</div>
<div className="bg-white rounded-xl p-4 flex items-center gap-4 border shadow-sm">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-400" /> {/* Icon size updated */}
<Input
placeholder="Search orders..." // Placeholder text updated
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10 border-slate-300 h-10" // Class updated
/>
<div className="bg-white rounded-xl p-4 border shadow-sm">
<div className="flex items-center gap-4 mb-4">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-slate-400" />
<Input
placeholder="Search orders..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10 border-slate-300 h-10"
/>
</div>
<Tabs value={statusFilter} onValueChange={setStatusFilter} className="w-fit">
<TabsList>
<TabsTrigger value="all">All</TabsTrigger>
<TabsTrigger value="active">Active</TabsTrigger>
<TabsTrigger value="completed">Completed</TabsTrigger>
</TabsList>
</Tabs>
</div>
<div className="flex items-center gap-3">
<div className="flex items-center gap-2">
<Filter className="w-4 h-4 text-slate-500" />
<span className="text-sm font-medium text-slate-700">Filters:</span>
</div>
<Popover open={calendarOpen} onOpenChange={setCalendarOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
className={`h-9 w-[160px] justify-start text-left font-normal ${specificDate ? 'bg-blue-50 border-blue-300' : ''}`}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{specificDate ? format(specificDate, 'MMM dd, yyyy') : 'Pick a date'}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<div className="p-6">
<CalendarComponent
mode="single"
selected={tempDate || specificDate}
onSelect={(date) => setTempDate(date)}
numberOfMonths={2}
initialFocus
/>
<div className="mt-6 pt-6 border-t border-slate-200">
<div className="flex items-center justify-center gap-3 mb-6">
<Button
variant="ghost"
size="sm"
onClick={() => setTempDate(new Date())}
className={`px-6 h-10 font-medium ${!tempDate && !specificDate ? 'border-b-2 border-blue-600 rounded-none' : ''}`}
>
Today
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => {
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
setTempDate(yesterday);
}}
className="px-6 h-10 font-medium"
>
Yesterday
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
setTempDate(tomorrow);
}}
className="px-6 h-10 font-medium"
>
Tomorrow
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => {
setTempDate(null);
setDateFilter("week");
}}
className="px-6 h-10 font-medium"
>
This Week
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => {
setTempDate(null);
setDateFilter("month");
}}
className="px-6 h-10 font-medium"
>
This Month
</Button>
</div>
<div className="flex items-center justify-end gap-3">
<Button
variant="outline"
size="sm"
onClick={() => {
setTempDate(null);
setSpecificDate(null);
setDateFilter("all");
setCalendarOpen(false);
}}
className="px-8 h-10 text-red-600 border-red-300 hover:bg-red-50 font-medium"
>
Reset
</Button>
<Button
variant="outline"
size="sm"
onClick={() => {
setTempDate(null);
setCalendarOpen(false);
}}
className="px-8 h-10 font-medium"
>
Cancel
</Button>
<Button
size="sm"
onClick={() => {
if (tempDate) {
setSpecificDate(tempDate);
setDateFilter("all");
}
setTempDate(null);
setCalendarOpen(false);
}}
className="px-10 h-10 bg-blue-600 hover:bg-blue-700 font-medium"
>
Apply
</Button>
</div>
</div>
</div>
</PopoverContent>
</Popover>
<Popover open={locationOpen} onOpenChange={setLocationOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={locationOpen}
className="w-[200px] h-9 justify-between text-sm"
>
<span className="truncate">{locationFilter === "all" ? "All Locations" : locationFilter}</span>
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command shouldFilter={true}>
<CommandInput placeholder="Type to search..." className="h-9" />
<CommandEmpty>No location found.</CommandEmpty>
<CommandGroup className="max-h-64 overflow-auto">
<CommandItem
value="all"
onSelect={() => {
setLocationFilter("all");
setLocationOpen(false);
}}
>
<Check className={`mr-2 h-4 w-4 ${locationFilter === "all" ? "opacity-100" : "opacity-0"}`} />
All Locations
</CommandItem>
{uniqueLocations.map((location) => (
<CommandItem
key={location}
value={location}
onSelect={(currentValue) => {
setLocationFilter(currentValue);
setLocationOpen(false);
}}
>
<Check className={`mr-2 h-4 w-4 ${locationFilter === location ? "opacity-100" : "opacity-0"}`} />
{location}
</CommandItem>
))}
</CommandGroup>
</Command>
</PopoverContent>
</Popover>
<Popover open={managerOpen} onOpenChange={setManagerOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={managerOpen}
className="w-[200px] h-9 justify-between text-sm"
>
<span className="truncate">{managerFilter === "all" ? "All Managers" : managerFilter}</span>
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command shouldFilter={true}>
<CommandInput placeholder="Type to search..." className="h-9" />
<CommandEmpty>No manager found.</CommandEmpty>
<CommandGroup className="max-h-64 overflow-auto">
<CommandItem
value="all"
onSelect={() => {
setManagerFilter("all");
setManagerOpen(false);
}}
>
<Check className={`mr-2 h-4 w-4 ${managerFilter === "all" ? "opacity-100" : "opacity-0"}`} />
All Managers
</CommandItem>
{uniqueManagers.map((manager) => (
<CommandItem
key={manager}
value={manager}
onSelect={(currentValue) => {
setManagerFilter(currentValue);
setManagerOpen(false);
}}
>
<Check className={`mr-2 h-4 w-4 ${managerFilter === manager ? "opacity-100" : "opacity-0"}`} />
{manager}
</CommandItem>
))}
</CommandGroup>
</Command>
</PopoverContent>
</Popover>
{(dateFilter !== "all" || specificDate || locationFilter !== "all" || managerFilter !== "all") && (
<Button
variant="ghost"
size="sm"
onClick={() => {
setDateFilter("all");
setSpecificDate(null);
setLocationFilter("all");
setManagerFilter("all");
}}
className="text-slate-600 hover:text-slate-900"
>
Clear Filters
</Button>
)}
</div>
<Tabs value={statusFilter} onValueChange={setStatusFilter} className="w-fit"> {/* Replaced Select with Tabs */}
<TabsList>
<TabsTrigger value="all">All</TabsTrigger>
<TabsTrigger value="active">Active</TabsTrigger>
<TabsTrigger value="completed">Completed</TabsTrigger>
</TabsList>
</Tabs>
</div>
<Card className="border-slate-200 shadow-sm"> {/* Card class updated */}