169 lines
5.1 KiB
TypeScript
169 lines
5.1 KiB
TypeScript
"use client";
|
||
|
||
import { addWeeks, subWeeks, addDays, format } from "date-fns";
|
||
import {
|
||
Select,
|
||
SelectContent,
|
||
SelectItem,
|
||
SelectTrigger,
|
||
SelectValue,
|
||
} from "@/components/ui/select";
|
||
import { Button } from "@/components/ui/button";
|
||
import { ChevronLeft, ChevronRight, CalendarDays } from "lucide-react";
|
||
import { ScheduleArtist } from "@/app/(dashboard)/schedule/SchedulePageClient";
|
||
|
||
const STATUS_OPTIONS = [
|
||
{ value: "TODO", label: "To Do" },
|
||
{ value: "IN_PROGRESS", label: "In Progress" },
|
||
{ value: "INTERNAL_REVIEW", label: "Internal Review" },
|
||
{ value: "CLIENT_REVIEW", label: "Client Review" },
|
||
{ value: "CHANGES", label: "Changes" },
|
||
];
|
||
|
||
interface ScheduleFiltersProps {
|
||
projects: { id: string; name: string; code: string }[];
|
||
artists: ScheduleArtist[];
|
||
filterProject: string;
|
||
filterArtist: string;
|
||
filterStatus: string;
|
||
viewStart: Date;
|
||
onProjectChange: (v: string) => void;
|
||
onArtistChange: (v: string) => void;
|
||
onStatusChange: (v: string) => void;
|
||
onViewStartChange: (d: Date) => void;
|
||
}
|
||
|
||
export function ScheduleFilters({
|
||
projects,
|
||
artists,
|
||
filterProject,
|
||
filterArtist,
|
||
filterStatus,
|
||
viewStart,
|
||
onProjectChange,
|
||
onArtistChange,
|
||
onStatusChange,
|
||
onViewStartChange,
|
||
}: ScheduleFiltersProps) {
|
||
const goPrev = () => onViewStartChange(subWeeks(viewStart, 1));
|
||
const goNext = () => onViewStartChange(addWeeks(viewStart, 1));
|
||
const goToday = () => {
|
||
const today = new Date();
|
||
const monday = addDays(today, -((today.getDay() + 6) % 7));
|
||
onViewStartChange(monday);
|
||
};
|
||
|
||
return (
|
||
<div className="flex items-center gap-3 px-4 py-2 border-b border-zinc-800 bg-zinc-950 shrink-0 flex-wrap">
|
||
{/* Week navigation */}
|
||
<div className="flex items-center gap-1">
|
||
<Button
|
||
variant="ghost"
|
||
size="icon"
|
||
className="h-7 w-7 text-zinc-400 hover:text-white"
|
||
onClick={goPrev}
|
||
>
|
||
<ChevronLeft className="h-4 w-4" />
|
||
</Button>
|
||
<Button
|
||
variant="ghost"
|
||
size="sm"
|
||
className="h-7 px-2 text-xs text-zinc-400 hover:text-white gap-1.5"
|
||
onClick={goToday}
|
||
>
|
||
<CalendarDays className="h-3 w-3" />
|
||
Today
|
||
</Button>
|
||
<Button
|
||
variant="ghost"
|
||
size="icon"
|
||
className="h-7 w-7 text-zinc-400 hover:text-white"
|
||
onClick={goNext}
|
||
>
|
||
<ChevronRight className="h-4 w-4" />
|
||
</Button>
|
||
<span className="text-xs text-zinc-500 ml-1">
|
||
{format(viewStart, "MMM d")} – {format(addDays(viewStart, 34), "MMM d, yyyy")}
|
||
</span>
|
||
</div>
|
||
|
||
<div className="h-4 w-px bg-zinc-800" />
|
||
|
||
{/* Project filter */}
|
||
<Select
|
||
value={filterProject || "__all__"}
|
||
onValueChange={(v) => onProjectChange(v === "__all__" ? "" : v)}
|
||
>
|
||
<SelectTrigger className="h-7 text-xs w-36 bg-zinc-900 border-zinc-700">
|
||
<SelectValue placeholder="All projects" />
|
||
</SelectTrigger>
|
||
<SelectContent className="bg-zinc-900 border-zinc-700">
|
||
<SelectItem value="__all__" className="text-xs">
|
||
All projects
|
||
</SelectItem>
|
||
{projects.map((p) => (
|
||
<SelectItem key={p.id} value={p.id} className="text-xs">
|
||
[{p.code}] {p.name}
|
||
</SelectItem>
|
||
))}
|
||
</SelectContent>
|
||
</Select>
|
||
|
||
{/* Artist filter */}
|
||
<Select
|
||
value={filterArtist || "__all__"}
|
||
onValueChange={(v) => onArtistChange(v === "__all__" ? "" : v)}
|
||
>
|
||
<SelectTrigger className="h-7 text-xs w-36 bg-zinc-900 border-zinc-700">
|
||
<SelectValue placeholder="All artists" />
|
||
</SelectTrigger>
|
||
<SelectContent className="bg-zinc-900 border-zinc-700">
|
||
<SelectItem value="__all__" className="text-xs">
|
||
All artists
|
||
</SelectItem>
|
||
{artists.map((a) => (
|
||
<SelectItem key={a.id} value={a.id} className="text-xs">
|
||
{a.name ?? a.email.split("@")[0]}
|
||
</SelectItem>
|
||
))}
|
||
</SelectContent>
|
||
</Select>
|
||
|
||
{/* Status filter */}
|
||
<Select
|
||
value={filterStatus || "__all__"}
|
||
onValueChange={(v) => onStatusChange(v === "__all__" ? "" : v)}
|
||
>
|
||
<SelectTrigger className="h-7 text-xs w-36 bg-zinc-900 border-zinc-700">
|
||
<SelectValue placeholder="All statuses" />
|
||
</SelectTrigger>
|
||
<SelectContent className="bg-zinc-900 border-zinc-700">
|
||
<SelectItem value="__all__" className="text-xs">
|
||
All statuses
|
||
</SelectItem>
|
||
{STATUS_OPTIONS.map((s) => (
|
||
<SelectItem key={s.value} value={s.value} className="text-xs">
|
||
{s.label}
|
||
</SelectItem>
|
||
))}
|
||
</SelectContent>
|
||
</Select>
|
||
|
||
{(filterProject || filterArtist || filterStatus) && (
|
||
<Button
|
||
variant="ghost"
|
||
size="sm"
|
||
className="h-7 px-2 text-xs text-zinc-500 hover:text-white"
|
||
onClick={() => {
|
||
onProjectChange("");
|
||
onArtistChange("");
|
||
onStatusChange("");
|
||
}}
|
||
>
|
||
Clear filters
|
||
</Button>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|