feat: UX game — stats live, production détaillée, prestige visible, badge achievements

- Click-zone : production/s, puissance ponte, multiplicateur toujours visibles
- GeneratorShop : production totale en header, prod individuelle par générateur
- PrestigePanel : toujours affiché (hint "Atteins 1M" si pas encore dispo)
- Badge achievements X/27 dans la sidebar avec lien vers /achievements
- Landing : tadpole sprite animé en accroche visuelle
This commit is contained in:
2026-03-20 15:26:55 +01:00
parent dece214102
commit b38bb4b4c7
5 changed files with 105 additions and 18 deletions

View File

@@ -6,35 +6,48 @@ import { formatNumber } from "../utils/formatNumber";
export function GeneratorShop() {
const generators = useGameStore((s) => s.state.generators);
const resources = useGameStore((s) => s.state.resources);
const productionPerSecond = useGameStore((s) => s.productionPerSecond);
const buy = useGameStore((s) => s.buy);
const generatorCost = useGameStore((s) => s.generatorCost);
return (
<div className="flex flex-col gap-3 p-4 rounded-xl bg-gray-900/80 backdrop-blur-sm max-w-md w-full">
<h2 className="text-lg font-bold text-white">Générateurs</h2>
<div className="flex flex-col gap-2 p-4 rounded-xl bg-gray-900/80 backdrop-blur-sm max-w-md w-full">
<div className="flex justify-between items-center">
<h2 className="text-sm font-bold text-white">Générateurs</h2>
<span className="text-xs text-emerald-400 font-medium">
{formatNumber(productionPerSecond)}/s
</span>
</div>
{generators.map((gen) => {
const cost = generatorCost(gen);
const canAfford = resources >= cost;
const currentProd = gen.baseProduction * gen.owned;
return (
<div
key={gen.id}
className={`flex items-center justify-between gap-3 p-3 rounded-lg border transition-colors ${
className={`flex items-center justify-between gap-2 p-2.5 rounded-lg border transition-colors ${
canAfford
? "border-emerald-500/50 bg-emerald-950/30 hover:bg-emerald-950/50"
: "border-gray-700/50 bg-gray-800/30 opacity-60"
}`}
>
<div className="flex flex-col min-w-0">
<span className="text-white font-semibold text-sm">{gen.name}</span>
<div className="flex items-center gap-2">
<span className="text-white font-semibold text-sm">{gen.name}</span>
{gen.owned > 0 && (
<span className="text-emerald-400 text-xs font-medium">x{gen.owned}</span>
)}
</div>
<span className="text-gray-400 text-xs">
+{gen.baseProduction}/s &middot; x{gen.owned}
+{gen.baseProduction}/s chacun
{gen.owned > 0 && ` · ${formatNumber(currentProd)}/s total`}
</span>
</div>
<button
onClick={() => buy(gen.id)}
disabled={!canAfford}
className={`shrink-0 px-3 py-1.5 rounded-md text-sm font-medium transition-colors cursor-pointer ${
className={`shrink-0 px-3 py-1.5 rounded-md text-xs font-medium transition-colors cursor-pointer ${
canAfford
? "bg-emerald-600 hover:bg-emerald-500 text-white"
: "bg-gray-700 text-gray-500 cursor-not-allowed"

View File

@@ -29,24 +29,29 @@ export function PrestigePanel() {
return (
<div className="flex flex-col gap-2 p-4 rounded-xl bg-purple-900/60 backdrop-blur-sm max-w-md w-full">
<div className="flex flex-wrap gap-4 text-sm text-purple-200">
<span>Générations : {prestigeCount}</span>
<span>Mult : x{prestigeMultiplier.toFixed(1)}</span>
<span>ADN : {ancestralDna}</span>
<h2 className="text-sm font-bold text-purple-100">Prestige</h2>
<div className="flex flex-wrap gap-3 text-xs text-purple-200">
<span>Gén. {prestigeCount}</span>
<span>Mult x{prestigeMultiplier.toFixed(1)}</span>
<span>ADN {ancestralDna}</span>
</div>
{canPrestige && (
<div className="flex flex-col gap-2 mt-2">
{canPrestige ? (
<div className="flex flex-col gap-2 mt-1">
<p className="text-sm text-purple-100">
Nouvelle Génération : <strong>+{dnaPreview} ADN</strong> + <strong>+0.1x mult</strong>
+{dnaPreview} ADN · +0.1x mult
</p>
<button
onClick={handlePrestige}
className="px-4 py-2 rounded-lg bg-purple-600 hover:bg-purple-500 text-white font-semibold text-sm transition-colors cursor-pointer"
className="px-4 py-2 rounded-lg bg-purple-600 hover:bg-purple-500 text-white font-semibold text-sm transition-colors cursor-pointer animate-pulse"
>
Nouvelle Génération
</button>
</div>
) : (
<p className="text-xs text-purple-300/60">
Atteins 1M têtards pour prestige
</p>
)}
</div>
);