feat: unique color picker for class types in schedule editor

- Add clickable color picker in schedule legend (16 distinct colors)
- Two-pass smart assignment: explicit colors first, then unused palette slots
- Hide already-used colors from the picker (both explicit and fallback)
- Colors saved to classes section and flow to public site schedule dots
- Expanded palette: rose, orange, amber, yellow, lime, emerald, teal, cyan,
  sky, blue, indigo, violet, purple, fuchsia, pink, red

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 20:16:26 +03:00
parent 85c61cfacd
commit 5c23b622f9
9 changed files with 240 additions and 40 deletions

View File

@@ -7,14 +7,16 @@ import { Reveal } from "@/components/ui/Reveal";
import { DayCard } from "./schedule/DayCard";
import { ScheduleFilters } from "./schedule/ScheduleFilters";
import { MobileSchedule } from "./schedule/MobileSchedule";
import { buildTypeDots } from "./schedule/constants";
import type { StatusFilter } from "./schedule/constants";
import type { SiteContent } from "@/types/content";
interface ScheduleProps {
data: SiteContent["schedule"];
classItems?: { name: string; color?: string }[];
}
export function Schedule({ data: schedule }: ScheduleProps) {
export function Schedule({ data: schedule, classItems }: ScheduleProps) {
const [locationIndex, setLocationIndex] = useState(0);
const [filterTrainer, setFilterTrainer] = useState<string | null>(null);
const [filterType, setFilterType] = useState<string | null>(null);
@@ -22,6 +24,8 @@ export function Schedule({ data: schedule }: ScheduleProps) {
const [showTrainers, setShowTrainers] = useState(false);
const location = schedule.locations[locationIndex];
const typeDots = useMemo(() => buildTypeDots(classItems), [classItems]);
const { trainers, types, hasAnySlots, hasAnyRecruiting } = useMemo(() => {
const trainerSet = new Set<string>();
const typeSet = new Set<string>();
@@ -108,6 +112,7 @@ export function Schedule({ data: schedule }: ScheduleProps) {
{/* Compact filters — desktop only */}
<Reveal>
<ScheduleFilters
typeDots={typeDots}
types={types}
trainers={trainers}
hasAnySlots={hasAnySlots}
@@ -129,6 +134,7 @@ export function Schedule({ data: schedule }: ScheduleProps) {
{/* Mobile: compact agenda list with tap-to-filter */}
<Reveal>
<MobileSchedule
typeDots={typeDots}
filteredDays={filteredDays}
filterType={filterType}
setFilterType={setFilterType}
@@ -151,7 +157,7 @@ export function Schedule({ data: schedule }: ScheduleProps) {
key={day.day}
className={filteredDays.length === 1 ? "w-full max-w-[340px]" : ""}
>
<DayCard day={day} />
<DayCard day={day} typeDots={typeDots} />
</div>
))}