diff --git a/app/src/features/crews/CrewColorField.tsx b/app/src/features/crews/CrewColorField.tsx new file mode 100644 index 00000000..93b5ee70 --- /dev/null +++ b/app/src/features/crews/CrewColorField.tsx @@ -0,0 +1,46 @@ +import { Check } from "lucide-react"; +import { useT } from "../../i18n"; +import { AVATAR_PALETTE } from "../../lib/protocol.gen"; + +/** Swatches for a crew's color, and a way to have none. */ +export function CrewColorField({ + value, + onChange, +}: { + value: string | null; + onChange(color: string | null): void; +}) { + const words = useT().crews.dialog; + const same = (a: string | null, b: string | null) => a?.toLowerCase() === b?.toLowerCase(); + return ( +
+ {words.color} +
+ + {AVATAR_PALETTE.map((swatch) => { + const on = same(value, swatch); + return ( + + ); + })} +
+
+ ); +} diff --git a/app/src/features/crews/CrewDialog.tsx b/app/src/features/crews/CrewDialog.tsx index a6436cfa..e572e9e7 100644 --- a/app/src/features/crews/CrewDialog.tsx +++ b/app/src/features/crews/CrewDialog.tsx @@ -9,6 +9,7 @@ import { SelectField, TextArea, TextField } from "../../ui/Field"; import { notifyError } from "../../ui/toast"; import { useCatalog } from "../catalog/useCatalog"; import { addTemplateBots } from "./addTemplateBots"; +import { CrewColorField } from "./CrewColorField"; import type { CrewTemplate } from "./crewTemplates"; import { PickedTemplate, TemplatePicker } from "./TemplatePicker"; import { WorkFolderField } from "./WorkFolderField"; @@ -22,6 +23,7 @@ export function CrewDialog({ crew, onClose }: { crew?: Crew; onClose(): void }) const putCrew = useApp((state) => state.putCrew); const selectCrew = useApp((state) => state.selectCrew); const [name, setName] = useState(crew?.name ?? ""); + const [color, setColor] = useState(crew?.color ?? null); const [folder, setFolder] = useState(null); const [goal, setGoal] = useState(""); const [chiefModel, setChiefModel] = useState("default"); @@ -49,7 +51,7 @@ export function CrewDialog({ crew, onClose }: { crew?: Crew; onClose(): void }) setError(null); try { const d = t.crews.dialog; - const saved = crew + let saved = crew ? await api.call("crews.rename", { crewId: crew.id, name }) : await api.call("crews.create", { name, @@ -62,6 +64,9 @@ export function CrewDialog({ crew, onClose }: { crew?: Crew; onClose(): void }) ...(chiefModel !== "default" && { model: chiefModel }), }, }); + if (crew && color !== crew.color) { + saved = await api.call("crews.setColor", { crewId: crew.id, color }); + } putCrew(saved); if (!crew) { selectCrew(saved.id); @@ -134,6 +139,7 @@ export function CrewDialog({ crew, onClose }: { crew?: Crew; onClose(): void }) autoFocus required /> + {crew && } {!crew && ( <>