Add manual CR assignment and difficulty breakdown panel
Implement issue #21: custom combatants can now have a challenge rating assigned via a new breakdown panel, opened by tapping the difficulty indicator. Bestiary-linked combatants show read-only CR with source name; custom combatants get a CR picker with all standard 5e values. CR persists across reloads and round-trips through JSON export/import. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
36
apps/web/src/components/cr-picker.tsx
Normal file
36
apps/web/src/components/cr-picker.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { VALID_CR_VALUES } from "@initiative/domain";
|
||||
|
||||
const CR_LABELS: Record<string, string> = {
|
||||
"0": "CR 0",
|
||||
"1/8": "CR 1/8",
|
||||
"1/4": "CR 1/4",
|
||||
"1/2": "CR 1/2",
|
||||
};
|
||||
|
||||
function formatCr(cr: string): string {
|
||||
return CR_LABELS[cr] ?? `CR ${cr}`;
|
||||
}
|
||||
|
||||
export function CrPicker({
|
||||
value,
|
||||
onChange,
|
||||
}: {
|
||||
value: string | null;
|
||||
onChange: (cr: string | undefined) => void;
|
||||
}) {
|
||||
return (
|
||||
<select
|
||||
className="rounded border border-border bg-card px-1.5 py-0.5 text-xs"
|
||||
value={value ?? ""}
|
||||
onChange={(e) => onChange(e.target.value || undefined)}
|
||||
aria-label="Challenge rating"
|
||||
>
|
||||
<option value="">Assign</option>
|
||||
{VALID_CR_VALUES.map((cr) => (
|
||||
<option key={cr} value={cr}>
|
||||
{formatCr(cr)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user