63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
import { de } from '../strings/de'
|
|
import { ALL_TRAITS } from '../format/traits'
|
|
import './charakterbogen.css'
|
|
|
|
export interface CharakterbogenProps {
|
|
/** Selected trait keys. */
|
|
traits: string[]
|
|
note: string
|
|
onTraitsChange: (traits: string[]) => void
|
|
onNoteChange: (note: string) => void
|
|
}
|
|
|
|
/**
|
|
* FEAT-14: character sheet — a checkbox grid of traits + a free note.
|
|
* Controlled & reusable: rendered on the animal detail page (persisted) and in
|
|
* the Abgabe listing composer (feeds the AI sale-text). German labels from
|
|
* de.character.traits; the stored value is the trait KEY.
|
|
*/
|
|
export default function Charakterbogen({
|
|
traits,
|
|
note,
|
|
onTraitsChange,
|
|
onNoteChange,
|
|
}: CharakterbogenProps) {
|
|
const t = de.character
|
|
const selected = new Set(traits)
|
|
|
|
const toggle = (key: string) => {
|
|
const next = new Set(selected)
|
|
if (next.has(key)) next.delete(key)
|
|
else next.add(key)
|
|
// Preserve the vocabulary order for stable output.
|
|
onTraitsChange(ALL_TRAITS.filter((tr) => next.has(tr.key)).map((tr) => tr.key))
|
|
}
|
|
|
|
return (
|
|
<div className="charakterbogen">
|
|
<ul className="trait-grid">
|
|
{ALL_TRAITS.map((tr) => (
|
|
<li key={tr.key}>
|
|
<label className="trait-chip">
|
|
<input
|
|
type="checkbox"
|
|
checked={selected.has(tr.key)}
|
|
onChange={() => toggle(tr.key)}
|
|
/>
|
|
<span>{tr.label}</span>
|
|
</label>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<label className="field">
|
|
<span>{t.noteLabel}</span>
|
|
<textarea
|
|
value={note}
|
|
placeholder={t.notePlaceholder}
|
|
onChange={(e) => onNoteChange(e.target.value)}
|
|
/>
|
|
</label>
|
|
</div>
|
|
)
|
|
}
|