Files
nuzlocke-tracker/frontend/src/components/RulesConfiguration.tsx
Julian Tabel 512d1bfce5
All checks were successful
CI / backend-lint (pull_request) Successful in 9s
CI / actions-lint (pull_request) Successful in 14s
CI / frontend-lint (pull_request) Successful in 20s
Implement dark-first design system with Geist typography
Add Tailwind v4 @theme tokens for surfaces, accents, text, borders,
and status colors. Self-host Geist Sans/Mono variable fonts. Redesign
nav with backdrop blur and active states, home page with gradient hero.
Migrate all 50+ components from ad-hoc gray/blue Tailwind classes to
semantic theme tokens (surface-*, text-*, border-*, accent-*, status-*).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 20:47:26 +01:00

115 lines
3.8 KiB
TypeScript

import type { NuzlockeRules } from '../types/rules'
import { RULE_DEFINITIONS, DEFAULT_RULES } from '../types/rules'
import { RuleToggle } from './RuleToggle'
interface RulesConfigurationProps {
rules: NuzlockeRules
onChange: (rules: NuzlockeRules) => void
onReset?: (() => void) | undefined
hiddenRules?: Set<keyof NuzlockeRules> | undefined
}
export function RulesConfiguration({
rules,
onChange,
onReset,
hiddenRules,
}: RulesConfigurationProps) {
const visibleRules = hiddenRules
? RULE_DEFINITIONS.filter((r) => !hiddenRules.has(r.key))
: RULE_DEFINITIONS
const coreRules = visibleRules.filter((r) => r.category === 'core')
const difficultyRules = visibleRules.filter((r) => r.category === 'difficulty')
const completionRules = visibleRules.filter((r) => r.category === 'completion')
const handleRuleChange = (key: keyof NuzlockeRules, value: boolean) => {
onChange({ ...rules, [key]: value })
}
const handleResetToDefault = () => {
onChange(DEFAULT_RULES)
onReset?.()
}
const enabledCount = visibleRules.filter((r) => rules[r.key]).length
const totalCount = visibleRules.length
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h2 className="text-xl font-semibold text-text-primary">Rules Configuration</h2>
<p className="text-sm text-text-tertiary">
{enabledCount} of {totalCount} rules enabled
</p>
</div>
<button
type="button"
onClick={handleResetToDefault}
className="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
>
Reset to Default
</button>
</div>
<div className="bg-surface-1 rounded-lg shadow">
<div className="px-4 py-3 border-b border-border-default">
<h3 className="text-lg font-medium text-text-primary">Core Rules</h3>
<p className="text-sm text-text-tertiary">
The fundamental rules of a Nuzlocke challenge
</p>
</div>
<div className="px-4">
{coreRules.map((rule) => (
<RuleToggle
key={rule.key}
name={rule.name}
description={rule.description}
enabled={rules[rule.key]}
onChange={(value) => handleRuleChange(rule.key, value)}
/>
))}
</div>
</div>
<div className="bg-surface-1 rounded-lg shadow">
<div className="px-4 py-3 border-b border-border-default">
<h3 className="text-lg font-medium text-text-primary">Difficulty Modifiers</h3>
<p className="text-sm text-text-tertiary">Optional rules to increase the challenge</p>
</div>
<div className="px-4">
{difficultyRules.map((rule) => (
<RuleToggle
key={rule.key}
name={rule.name}
description={rule.description}
enabled={rules[rule.key]}
onChange={(value) => handleRuleChange(rule.key, value)}
/>
))}
</div>
</div>
{completionRules.length > 0 && (
<div className="bg-surface-1 rounded-lg shadow">
<div className="px-4 py-3 border-b border-border-default">
<h3 className="text-lg font-medium text-text-primary">Completion</h3>
<p className="text-sm text-text-tertiary">When is the run considered complete</p>
</div>
<div className="px-4">
{completionRules.map((rule) => (
<RuleToggle
key={rule.key}
name={rule.name}
description={rule.description}
enabled={rules[rule.key]}
onChange={(value) => handleRuleChange(rule.key, value)}
/>
))}
</div>
</div>
)}
</div>
)
}