Android build v1.1.2

This commit is contained in:
Warren H
2026-06-29 22:35:49 -04:00
parent cbe42b6164
commit c6251167a5
52 changed files with 5554 additions and 3117 deletions
+187
View File
@@ -0,0 +1,187 @@
import type { CombatLogEntry } from '../game'
import type { DungeonReward, LootRoll } from '../profile'
type BonusItem = NonNullable<DungeonReward['bonusItem']>
export function LevelGain({
previousLevel,
newLevel,
talentPointsGained,
}: {
previousLevel: number | null
newLevel: number | null
talentPointsGained: number
}) {
if (!previousLevel || !newLevel || talentPointsGained <= 0) return null
return (
<p className="level-gain">
Level {previousLevel} to {newLevel}
<small>+{talentPointsGained} talent point</small>
</p>
)
}
export function AbilityUnlocks({
abilities,
}: {
abilities: DungeonReward['unlockedAbilities']
}) {
return (
<>
{abilities.map((ability) => (
<p className="ability-unlock" key={ability.id}>
<span>{ability.glyph}</span>
Ability Unlocked: {ability.name}
</p>
))}
</>
)
}
export function RewardXpSummary({
reward,
}: {
reward: {
experienceGained: number
previousLevel: number | null
newLevel: number | null
talentPointsGained: number
unlockedAbilities: DungeonReward['unlockedAbilities']
}
}) {
return (
<>
<p>+{reward.experienceGained} XP</p>
<LevelGain previousLevel={reward.previousLevel} newLevel={reward.newLevel} talentPointsGained={reward.talentPointsGained} />
<AbilityUnlocks abilities={reward.unlockedAbilities} />
</>
)
}
export function BonusItemReward({
item,
eyebrow,
compact = false,
}: {
item?: BonusItem | null
eyebrow?: string
compact?: boolean
}) {
if (!item) return null
if (compact) {
return (
<p className="ability-unlock">
<span>{item.glyph}</span>
{item.name} x{item.quantity}
{item.duplicate ? ` (owned x${item.quantityAfter})` : ''}
</p>
)
}
return (
<div className="bonus-item">
{eyebrow && <p className="eyebrow">{eyebrow}</p>}
<div className="bonus-item-detail">
<span>{item.glyph}</span>
<strong className={`rarity-${item.rarity}`}>{item.name}</strong>
<small>Item Level {item.itemLevel} x{item.quantity}</small>
{item.duplicate && <small> (owned x{item.quantityAfter})</small>}
</div>
</div>
)
}
export function LootRollList({
rolls,
expectedRolls,
}: {
rolls: LootRoll[]
expectedRolls: number
}) {
return (
<div className="run-loot-rolls">
{rolls.map((roll) => (
<div className={roll.dropped ? 'dropped' : 'empty'} key={roll.encounterId}>
<strong>{roll.encounterName}</strong>
<span>
{roll.items.length > 0
? roll.items
.map((item) => `${item.glyph} ${item.name} x${item.quantity}${item.duplicate ? ` (owned x${item.quantityAfter})` : ''}`)
.join(', ')
: 'No components dropped'}
</span>
</div>
))}
{rolls.length < expectedRolls && <small>Finishing loot rolls...</small>}
</div>
)
}
export function PvpRunLootList({
loot,
}: {
loot: BonusItem[]
}) {
return (
<div className="run-loot-rolls">
{loot.length > 0 ? loot.map((item, index) => (
<div className="dropped" key={`${item.id}-${index}`}>
<strong>Boss {index + 1}</strong>
<span>
{item.glyph} {item.name} x{item.quantity}
{item.duplicate ? ` (owned x${item.quantityAfter})` : ''}
</span>
</div>
)) : (
<div>
<strong>Loot</strong>
<span>No boss loot awarded</span>
</div>
)}
</div>
)
}
export function ResultLogToggle({
log,
showEndLog,
onToggle,
}: {
log: CombatLogEntry[]
showEndLog: boolean
onToggle: () => void
}) {
if (log.length === 0) return null
return (
<>
<button className="secondary-result-button" onClick={onToggle} type="button">
{showEndLog ? 'Hide Combat Log' : 'View Combat Log'}
</button>
{showEndLog && (
<div className="result-log">
{log.slice().reverse().map((entry) => (
<div className={`log-entry ${entry.tone}`} key={entry.id}>{entry.text}</div>
))}
</div>
)}
</>
)
}
export function RematchControls({
requested,
message,
onRematch,
}: {
requested: boolean
message: string
onRematch: () => void
}) {
return (
<>
<button disabled={requested} onClick={onRematch} type="button">
{requested ? 'Waiting for Rematch' : 'Rematch'}
</button>
{message && <p>{message}</p>}
</>
)
}