From 557267fc72fb2aff34f13aa46ca1826a1855b34c Mon Sep 17 00:00:00 2001 From: Hikari Date: Thu, 19 Mar 2026 21:16:27 -0700 Subject: [PATCH] feat: show zone unlock requirements on boss and quest panels --- apps/web/src/components/game/bossPanel.tsx | 38 +++++++++++++++++++ apps/web/src/components/game/questPanel.tsx | 41 ++++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/apps/web/src/components/game/bossPanel.tsx b/apps/web/src/components/game/bossPanel.tsx index 4b04ff1..e676142 100644 --- a/apps/web/src/components/game/bossPanel.tsx +++ b/apps/web/src/components/game/bossPanel.tsx @@ -267,6 +267,23 @@ const BossPanel = (): JSX.Element => { } const { zones, bosses, quests, autoBoss, prestige: playerPrestige } = state; + + const activeZone = zones.find((zone) => { + return zone.id === activeZoneId; + }); + const zoneIsLocked = activeZone?.status === "locked"; + const unlockBoss = activeZone?.unlockBossId === null + || activeZone?.unlockBossId === undefined + ? undefined + : bosses.find((boss) => { + return boss.id === activeZone.unlockBossId; + }); + const unlockQuest = activeZone?.unlockQuestId === null + || activeZone?.unlockQuestId === undefined + ? undefined + : quests.find((quest) => { + return quest.id === activeZone.unlockQuestId; + }); const zoneBosses = bosses.filter((boss) => { return boss.zoneId === activeZoneId; }); @@ -393,6 +410,27 @@ const BossPanel = (): JSX.Element => { zones={zones} /> + {zoneIsLocked && (unlockBoss !== undefined || unlockQuest !== undefined) + ?
+

{"🔒 This zone is locked. Unlock bosses by:"}

+ {unlockBoss === undefined + ? null + :

+ {"⚔️ Defeat: "} + {unlockBoss.name} +

+ } + {unlockQuest === undefined + ? null + :

+ {"📜 Complete: "} + {unlockQuest.name} +

+ } +
+ : null + } +
{"⚔️ Party DPS"} diff --git a/apps/web/src/components/game/questPanel.tsx b/apps/web/src/components/game/questPanel.tsx index 315ea58..64b6596 100644 --- a/apps/web/src/components/game/questPanel.tsx +++ b/apps/web/src/components/game/questPanel.tsx @@ -4,6 +4,7 @@ * @license Naomi's Public License * @author Naomi Carrigan */ +/* eslint-disable max-lines -- QuestPanel with sub-component and helper functions */ /* eslint-disable react/no-multi-comp -- QuestCard sub-component is tightly coupled */ /* eslint-disable max-lines-per-function -- Complex component with many render paths */ /* eslint-disable complexity -- Many conditional render paths */ @@ -207,7 +208,24 @@ const QuestPanel = (): JSX.Element => { ); } - const { adventurers, autoQuest, quests, zones } = state; + const { adventurers, autoQuest, bosses, quests, zones } = state; + + const activeZone = zones.find((zone) => { + return zone.id === activeZoneId; + }); + const zoneIsLocked = activeZone?.status === "locked"; + const unlockBoss = activeZone?.unlockBossId === null + || activeZone?.unlockBossId === undefined + ? undefined + : bosses.find((boss) => { + return boss.id === activeZone.unlockBossId; + }); + const unlockQuest = activeZone?.unlockQuestId === null + || activeZone?.unlockQuestId === undefined + ? undefined + : quests.find((quest) => { + return quest.id === activeZone.unlockQuestId; + }); let partyCombatPower = 0; for (const adventurer of adventurers) { const contribution = adventurer.combatPower * adventurer.count; @@ -306,6 +324,27 @@ const QuestPanel = (): JSX.Element => { zones={zones} /> + {zoneIsLocked && (unlockBoss !== undefined || unlockQuest !== undefined) + ?
+

{"🔒 This zone is locked. Unlock quests by:"}

+ {unlockBoss === undefined + ? null + :

+ {"⚔️ Defeat: "} + {unlockBoss.name} +

+ } + {unlockQuest === undefined + ? null + :

+ {"📜 Complete: "} + {unlockQuest.name} +

+ } +
+ : null + } +

{"⚠️ If a quest fails, it resets with no rewards — you must retry."}