feat: flexible group management in schedule editor

- Group = trainer + type (time-independent)
- Edit modal shows per-day time fields (Mon 12:00, Fri 18:00)
- Calendar blocks colored by group, not class type
- Color picker for site dots moved to classes editor
- New class: single time + multi-day selector
- Edit class: per-day times, add/remove days from group
- Delete removes group from all days

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 21:31:05 +03:00
parent b5262b4adc
commit bfa59a8d18
2 changed files with 209 additions and 227 deletions

View File

@@ -9,6 +9,25 @@ const ICON_OPTIONS = [
"heart", "music", "dumbbell", "trophy",
];
const COLOR_SWATCHES: { value: string; bg: string }[] = [
{ value: "rose", bg: "bg-rose-500" },
{ value: "orange", bg: "bg-orange-500" },
{ value: "amber", bg: "bg-amber-500" },
{ value: "yellow", bg: "bg-yellow-400" },
{ value: "lime", bg: "bg-lime-500" },
{ value: "emerald", bg: "bg-emerald-500" },
{ value: "teal", bg: "bg-teal-500" },
{ value: "cyan", bg: "bg-cyan-500" },
{ value: "sky", bg: "bg-sky-500" },
{ value: "blue", bg: "bg-blue-500" },
{ value: "indigo", bg: "bg-indigo-500" },
{ value: "violet", bg: "bg-violet-500" },
{ value: "purple", bg: "bg-purple-500" },
{ value: "fuchsia", bg: "bg-fuchsia-500" },
{ value: "pink", bg: "bg-pink-500" },
{ value: "red", bg: "bg-red-500" },
];
interface ClassesData {
title: string;
items: {
@@ -63,6 +82,31 @@ export default function ClassesEditorPage() {
</select>
</div>
</div>
<div>
<label className="block text-sm text-neutral-400 mb-1.5">
Цвет в расписании
</label>
<div className="flex flex-wrap gap-1.5">
{COLOR_SWATCHES.map((c) => {
const isUsed = data.items.some(
(other) => other !== item && other.color === c.value
);
if (isUsed) return null;
return (
<button
key={c.value}
type="button"
onClick={() => updateItem({ ...item, color: c.value })}
className={`h-6 w-6 rounded-full ${c.bg} transition-all ${
item.color === c.value
? "ring-2 ring-white ring-offset-1 ring-offset-neutral-900 scale-110"
: "opacity-50 hover:opacity-100"
}`}
/>
);
})}
</div>
</div>
<TextareaField
label="Краткое описание"
value={item.description}