"use client"; import { useState } from "react"; import type { StaffingRequirement } from "@capakraken/shared"; import { uuid } from "~/lib/uuid.js"; const INPUT_CLS = "px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 text-sm"; const BTN_DANGER = "px-2 py-1 text-red-500 hover:text-red-700 hover:bg-red-50 rounded text-sm transition-colors"; function makeEmptyPreset(): StaffingRequirement { return { id: uuid(), role: "", requiredSkills: [], preferredSkills: [], hoursPerDay: 8, headcount: 1, }; } interface PresetRowProps { preset: StaffingRequirement; onChange: (preset: StaffingRequirement) => void; onDelete: () => void; } function PresetRow({ preset, onChange, onDelete }: PresetRowProps) { function update(key: K, value: StaffingRequirement[K]) { onChange({ ...preset, [key]: value }); } return (
{/* Role */} update("role", e.target.value)} placeholder="Role name" className={`${INPUT_CLS} flex-1 min-w-32`} aria-label="Role name" /> {/* Required Skills */}
update( "requiredSkills", e.target.value .split(",") .map((s) => s.trim()) .filter(Boolean), ) } placeholder="e.g. 3D Modeling, Lighting" className={INPUT_CLS} aria-label="Required skills" />
{/* Hours per day */}
update("hoursPerDay", parseFloat(e.target.value) || 0)} className={INPUT_CLS} aria-label="Hours per day" />
{/* Headcount */}
update("headcount", parseInt(e.target.value, 10) || 1)} className={INPUT_CLS} aria-label="Headcount" />
{/* Delete */}
{/* Preferred skills (secondary row) */}
update( "preferredSkills", e.target.value .split(",") .map((s) => s.trim()) .filter(Boolean), ) } placeholder="e.g. Compositing, Art Direction" className={`${INPUT_CLS} w-full mt-0.5`} aria-label="Preferred skills" />
); } interface RolePresetsEditorProps { initialPresets: StaffingRequirement[]; /** Called with the current presets array when the user clicks Save */ onSave: (presets: StaffingRequirement[]) => void; isSaving?: boolean; saveError?: string | null; } export function RolePresetsEditor({ initialPresets, onSave, isSaving = false, saveError = null, }: RolePresetsEditorProps) { const [presets, setPresets] = useState(initialPresets); function addPreset() { setPresets((prev) => [...prev, makeEmptyPreset()]); } function removePreset(idx: number) { setPresets((prev) => prev.filter((_, i) => i !== idx)); } function updatePreset(idx: number, updated: StaffingRequirement) { setPresets((prev) => prev.map((p, i) => (i === idx ? updated : p))); } return (
{presets.length === 0 && (

No role presets yet. Click “+ Add Role” to define default staffing.

)} {presets.map((preset, idx) => ( updatePreset(idx, updated)} onDelete={() => removePreset(idx)} /> ))}
{saveError && (
{saveError}
)}
); }