Initial commit

This commit is contained in:
twotalesanimation
2026-05-19 22:20:29 +02:00
commit 0fbe856dce
173 changed files with 38316 additions and 0 deletions
+168
View File
@@ -0,0 +1,168 @@
"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>
);
}