Add post-game completion rule option

Add postGameCompletion toggle to nuzlocke rules so players can indicate
whether a run ends after the Champion or continues into post-game. Adds
a new "Completion" category section in rules configuration with a green
badge color.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Julian Tabel
2026-02-09 12:24:06 +01:00
parent 6d955439eb
commit f9f94e5e9c
4 changed files with 53 additions and 8 deletions

View File

@@ -1,10 +1,11 @@
--- ---
# nuzlocke-tracker-tyvc # nuzlocke-tracker-tyvc
title: Add end-of-run condition rule title: Add end-of-run condition rule
status: todo status: completed
type: feature type: feature
priority: normal
created_at: 2026-02-09T08:35:39Z created_at: 2026-02-09T08:35:39Z
updated_at: 2026-02-09T08:35:39Z updated_at: 2026-02-09T11:23:11Z
--- ---
Add a new nuzlocke rule: **End of Run Condition**. This is a toggle/switch that lets the player decide when a run is considered complete: Add a new nuzlocke rule: **End of Run Condition**. This is a toggle/switch that lets the player decide when a run is considered complete:
@@ -15,7 +16,7 @@ Add a new nuzlocke rule: **End of Run Condition**. This is a toggle/switch that
This affects when the player is expected to mark a run as "completed" and could influence level caps and boss tracking in the future. This affects when the player is expected to mark a run as "completed" and could influence level caps and boss tracking in the future.
## Checklist ## Checklist
- [ ] Add `postGameCompletion` (boolean, default false) to the `NuzlockeRules` TypeScript interface and `DEFAULT_RULES` - [x] Add `postGameCompletion` (boolean, default false) to the `NuzlockeRules` TypeScript interface and `DEFAULT_RULES`
- [ ] Add a rule definition to `RULE_DEFINITIONS` in `frontend/src/types/rules.ts` - [x] Add a rule definition to `RULE_DEFINITIONS` in `frontend/src/types/rules.ts`
- [ ] Verify the rule appears in the `RulesConfiguration` component (should work automatically via RULE_DEFINITIONS) - [x] Verify the rule appears in the `RulesConfiguration` component (added new "Completion" section)
- [ ] Verify the rule is stored correctly via the existing run/genlocke creation flows (JSONB, no backend schema change needed) - [x] Verify the rule is stored correctly via the existing run/genlocke creation flows (JSONB, no backend schema change needed)

View File

@@ -25,7 +25,9 @@ export function RuleBadges({ rules }: RuleBadgesProps) {
className={`px-2 py-0.5 rounded-full text-xs font-medium ${ className={`px-2 py-0.5 rounded-full text-xs font-medium ${
def.category === 'core' def.category === 'core'
? 'bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300' ? 'bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300'
: 'bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300' : def.category === 'completion'
? 'bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300'
: 'bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300'
}`} }`}
> >
{def.name} {def.name}

View File

@@ -22,6 +22,9 @@ export function RulesConfiguration({
const difficultyRules = visibleRules.filter( const difficultyRules = visibleRules.filter(
(r) => r.category === 'difficulty' (r) => r.category === 'difficulty'
) )
const completionRules = visibleRules.filter(
(r) => r.category === 'completion'
)
const handleRuleChange = (key: keyof NuzlockeRules, value: boolean) => { const handleRuleChange = (key: keyof NuzlockeRules, value: boolean) => {
onChange({ ...rules, [key]: value }) onChange({ ...rules, [key]: value })
@@ -98,6 +101,30 @@ export function RulesConfiguration({
))} ))}
</div> </div>
</div> </div>
{completionRules.length > 0 && (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow">
<div className="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
<h3 className="text-lg font-medium text-gray-900 dark:text-gray-100">
Completion
</h3>
<p className="text-sm text-gray-500 dark:text-gray-400">
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> </div>
) )
} }

View File

@@ -11,6 +11,9 @@ export interface NuzlockeRules {
hardcoreMode: boolean hardcoreMode: boolean
levelCaps: boolean levelCaps: boolean
setModeOnly: boolean setModeOnly: boolean
// Completion
postGameCompletion: boolean
} }
export const DEFAULT_RULES: NuzlockeRules = { export const DEFAULT_RULES: NuzlockeRules = {
@@ -26,13 +29,16 @@ export const DEFAULT_RULES: NuzlockeRules = {
hardcoreMode: false, hardcoreMode: false,
levelCaps: false, levelCaps: false,
setModeOnly: false, setModeOnly: false,
// Completion
postGameCompletion: false,
} }
export interface RuleDefinition { export interface RuleDefinition {
key: keyof NuzlockeRules key: keyof NuzlockeRules
name: string name: string
description: string description: string
category: 'core' | 'difficulty' category: 'core' | 'difficulty' | 'completion'
} }
export const RULE_DEFINITIONS: RuleDefinition[] = [ export const RULE_DEFINITIONS: RuleDefinition[] = [
@@ -102,4 +108,13 @@ export const RULE_DEFINITIONS: RuleDefinition[] = [
'The game must be played in "Set" battle style, meaning you cannot switch Pokémon after knocking out an opponent.', 'The game must be played in "Set" battle style, meaning you cannot switch Pokémon after knocking out an opponent.',
category: 'difficulty', category: 'difficulty',
}, },
// Completion
{
key: 'postGameCompletion',
name: 'Post-Game Completion',
description:
'The run continues into post-game content instead of ending after the Champion is defeated.',
category: 'completion',
},
] ]