Add section field to boss battles for run progression dividers
Adds a nullable `section` column to boss battles (e.g. "Main Story", "Endgame") with dividers rendered in the run view between sections. Admin UI gets a Section column in the table and a text input in the form. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -459,6 +459,20 @@ export function RunEncounters() {
|
||||
return nextBoss.levelCap
|
||||
}, [nextBoss, sortedBosses])
|
||||
|
||||
// Pre-compute which bosses get a section divider rendered AFTER them
|
||||
// (when the next boss in order has a different section)
|
||||
const sectionDividerAfterBoss = useMemo(() => {
|
||||
const map = new Map<number, string>()
|
||||
for (let i = 0; i < sortedBosses.length - 1; i++) {
|
||||
const current = sortedBosses[i]
|
||||
const next = sortedBosses[i + 1]
|
||||
if (next.section != null && current.section !== next.section) {
|
||||
map.set(current.id, next.section)
|
||||
}
|
||||
}
|
||||
return map
|
||||
}, [sortedBosses])
|
||||
|
||||
// Map afterRouteId → BossBattle[] for interleaving
|
||||
const bossesAfterRoute = useMemo(() => {
|
||||
const map = new Map<number, BossBattle[]>()
|
||||
@@ -1023,6 +1037,7 @@ export function RunEncounters() {
|
||||
{/* Boss battle cards after this route */}
|
||||
{bossesHere.map((boss) => {
|
||||
const isDefeated = defeatedBossIds.has(boss.id)
|
||||
const sectionAfter = sectionDividerAfterBoss.get(boss.id)
|
||||
const bossTypeLabel: Record<string, string> = {
|
||||
gym_leader: 'Gym Leader',
|
||||
elite_four: 'Elite Four',
|
||||
@@ -1051,12 +1066,12 @@ export function RunEncounters() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={`boss-${boss.id}`}
|
||||
className={`my-2 rounded-lg border-2 ${bossTypeColors[boss.bossType] ?? bossTypeColors.other} ${
|
||||
isDefeated ? 'bg-green-50/50 dark:bg-green-900/10' : 'bg-white dark:bg-gray-800'
|
||||
} px-4 py-3`}
|
||||
>
|
||||
<div key={`boss-${boss.id}`}>
|
||||
<div
|
||||
className={`my-2 rounded-lg border-2 ${bossTypeColors[boss.bossType] ?? bossTypeColors.other} ${
|
||||
isDefeated ? 'bg-green-50/50 dark:bg-green-900/10' : 'bg-white dark:bg-gray-800'
|
||||
} px-4 py-3`}
|
||||
>
|
||||
<div
|
||||
className="flex items-start justify-between cursor-pointer select-none"
|
||||
onClick={toggleBoss}
|
||||
@@ -1122,6 +1137,14 @@ export function RunEncounters() {
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{sectionAfter && (
|
||||
<div className="flex items-center gap-3 my-4">
|
||||
<div className="flex-1 h-px bg-gray-300 dark:bg-gray-600" />
|
||||
<span className="text-sm font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">{sectionAfter}</span>
|
||||
<div className="flex-1 h-px bg-gray-300 dark:bg-gray-600" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user