diff --git a/frontend/src/pages/CombatPage.tsx b/frontend/src/pages/CombatPage.tsx index 09f19d1..ee0922c 100644 --- a/frontend/src/pages/CombatPage.tsx +++ b/frontend/src/pages/CombatPage.tsx @@ -1,8 +1,10 @@ import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; -import { combatApi } from '../api/endpoints'; +import { combatApi, characterApi } from '../api/endpoints'; import type { Monster, CombatResult } from '../api/types'; -import { Swords, Trophy, Skull, Clock } from 'lucide-react'; +import { Swords, Trophy, Skull, Clock, Zap } from 'lucide-react'; + +const COMBAT_COST = 5; const ATTACK_TYPES = [ { id: 'melee', label: 'Mêlée', emoji: '⚔️', stat: 'Force × 1.5' }, @@ -84,6 +86,10 @@ export function CombatPage() { const [attackType, setAttackType] = useState('melee'); const [lastResult, setLastResult] = useState(null); + const { data: char } = useQuery({ queryKey: ['character'], queryFn: characterApi.me }); + const endurance = (char as any)?.enduranceCurrent ?? (char as any)?.endurance ?? 0; + const canFight = endurance >= COMBAT_COST; + const { data: monsters, isLoading } = useQuery({ queryKey: ['monsters'], queryFn: combatApi.monsters, @@ -150,17 +156,23 @@ export function CombatPage() { ))} + {/* Coût endurance */} +
+ Coût : {COMBAT_COST} endurance — Disponible : {endurance} + {canFight && ({Math.floor(endurance / COMBAT_COST)} combats possibles)} +
+ {/* Bouton combattre */} diff --git a/frontend/src/pages/DashboardPage.tsx b/frontend/src/pages/DashboardPage.tsx index 46eb06b..3c25195 100644 --- a/frontend/src/pages/DashboardPage.tsx +++ b/frontend/src/pages/DashboardPage.tsx @@ -153,6 +153,11 @@ export function DashboardPage() { const xpNext = (char as any).xpToNextLevel ?? Math.round(100 * Math.pow(char.level, 1.5)); const statPoints = (char as any).statPoints ?? 0; const needsHeal = char.hpCurrent < char.hpMax; + const endurance = (char as any).enduranceCurrent ?? (char as any).endurance ?? 0; + const REST_COST = 10; + const COMBAT_COST = 5; + const FORGE_COST = 10; + const canRest = endurance >= REST_COST && needsHeal; return (
@@ -210,17 +215,28 @@ export function DashboardPage() {
+ {/* Budget endurance */} +
+ ⚡ Budget : + {' '}{Math.floor(endurance / COMBAT_COST)} combats + {' · '}{Math.floor(endurance / FORGE_COST)} forges + {' · '}{Math.floor(endurance / REST_COST)} repos +
+ {needsHeal && ( )} + {needsHeal && !canRest && endurance < REST_COST && ( +

Endurance insuffisante pour se reposer

+ )} {restMut.isError &&

{(restMut.error as Error).message}

} diff --git a/frontend/src/pages/ForgePage.tsx b/frontend/src/pages/ForgePage.tsx index be851e4..c8655a6 100644 --- a/frontend/src/pages/ForgePage.tsx +++ b/frontend/src/pages/ForgePage.tsx @@ -1,17 +1,71 @@ import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; -import { itemApi, forgeApi } from '../api/endpoints'; +import { itemApi, forgeApi, characterApi } from '../api/endpoints'; import type { CharacterItem } from '../api/types'; -import { Shield, CheckCircle, XCircle, AlertTriangle } from 'lucide-react'; +import { Shield, CheckCircle, XCircle, AlertTriangle, Zap, Coins } from 'lucide-react'; const FORGE_RISK = [0, 0, 0, 20, 30, 40]; const FORGE_LABEL = ['—', '—', 'Garanti', '20% échec', '30% échec', '40% échec']; +const FORGE_ENDURANCE_COST = 10; +const FORGE_GOLD_COST: Record = { 1: 50, 2: 100, 3: 250, 4: 500, 5: 1000 }; + +function ForgePanel({ nextLevel, risk, endurance, gold, isPending, onForge }: { + nextLevel: number; risk: number; endurance: number; gold: number; isPending: boolean; onForge: () => void; +}) { + const goldCost = FORGE_GOLD_COST[nextLevel] ?? 0; + const canForge = endurance >= FORGE_ENDURANCE_COST && gold >= goldCost; + + return ( + <> +
+
Prochain niveau : +{nextLevel}
+
+ {risk === 0 + ? <> Succès garanti + : <> {FORGE_LABEL[nextLevel]} + } +
+
+ +
+ = FORGE_ENDURANCE_COST ? '#5ba4f5' : '#e84040' }}> + {FORGE_ENDURANCE_COST} endurance + + = goldCost ? '#f4c94e' : '#e84040' }}> + {goldCost} or + +
+ + + {!canForge && ( +

+ {endurance < FORGE_ENDURANCE_COST ? 'Endurance insuffisante' : 'Or insuffisant'} +

+ )} + + ); +} export function ForgePage() { const qc = useQueryClient(); const [selected, setSelected] = useState(null); const [lastResult, setLastResult] = useState<{ success: boolean; newLevel: number } | null>(null); + const { data: char } = useQuery({ queryKey: ['character'], queryFn: characterApi.me }); + const endurance = (char as any)?.enduranceCurrent ?? (char as any)?.endurance ?? 0; + const gold = char?.gold ?? 0; + const { data: inventory, isLoading } = useQuery({ queryKey: ['inventory'], queryFn: itemApi.inventory, @@ -22,7 +76,7 @@ export function ForgePage() { onSuccess: (res) => { setLastResult({ success: res.success, newLevel: res.newForgeLevel }); qc.invalidateQueries({ queryKey: ['inventory'] }); - // Refresh selected item from updated inventory + qc.invalidateQueries({ queryKey: ['character'] }); setSelected(res.item); }, }); @@ -88,30 +142,10 @@ export function ForgePage() { {!atMax ? ( - <> -
-
Prochain niveau : +{nextLevel}
-
- {risk === 0 - ? <> Succès garanti - : <> {FORGE_LABEL[nextLevel]} - } -
-
- - - + forgeMut.mutate()} + /> ) : (
✨ Niveau maximum atteint (+5) diff --git a/src/forge/forge.service.ts b/src/forge/forge.service.ts index 7348ce6..75d2134 100644 --- a/src/forge/forge.service.ts +++ b/src/forge/forge.service.ts @@ -18,7 +18,7 @@ const FORGE_GOLD_COST: Record = { 5: 1000, }; -const FORGE_ENDURANCE_COST = 15; +const FORGE_ENDURANCE_COST = 10; // Risque d'échec par niveau cible (GDD exact) const FORGE_FAIL_CHANCE: Record = {