feat: page 404 RPG + onboarding nouveau joueur
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 33s

- 404: têtard perdu dans les marais, boutons retour jeu + guide
- Onboarding: 4 étapes guidées (quêtes, combat, craft, guide)
  - Visible niv 1-3, dismissable, grille 2×2 avec CTA par étape
- DashboardPage: STAT_LABELS importé depuis constants.ts
This commit is contained in:
2026-03-24 23:17:09 +01:00
parent 17c61a2bb8
commit e769c27a42
4 changed files with 143 additions and 4 deletions

View File

@@ -0,0 +1,93 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Swords, Scroll, Hammer, BookOpen, ChevronRight } from 'lucide-react';
const STEPS = [
{
icon: Scroll,
title: 'Accepte une quête',
desc: 'Les quêtes te guident dans ton aventure et donnent le plus d\'XP. Commence par les quêtes des Marais.',
cta: 'Voir les quêtes',
to: '/quests',
},
{
icon: Swords,
title: 'Combats un monstre',
desc: 'Chaque combat coûte 5 endurance. Tu gagneras de l\'XP, de l\'or et des matériaux pour crafter.',
cta: 'Aller au combat',
to: '/combat',
},
{
icon: Hammer,
title: 'Craft ton équipement',
desc: 'Avec les matériaux droppés, fabrique des armes et armures plus puissantes que celles de la boutique.',
cta: 'Voir l\'artisanat',
to: '/craft',
},
{
icon: BookOpen,
title: 'Consulte le guide',
desc: 'Le guide contient tout : bestiaire, recettes, zones, forge. Accessible depuis le bouton 📖 en bas de la sidebar.',
cta: 'Ouvrir le guide',
to: '/guide',
},
];
export function Onboarding({ level, onDismiss }: { level: number; onDismiss: () => void }) {
const navigate = useNavigate();
const [dismissed, setDismissed] = useState(false);
// Ne montrer que pour les joueurs niveau 1-3
if (level > 3 || dismissed) return null;
return (
<div className="card" style={{ marginBottom: '1rem', borderLeft: '3px solid #f4c94e' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.75rem' }}>
<h3 style={{ margin: 0, fontSize: 15, color: '#f4c94e' }}>
Bienvenue, aventurier !
</h3>
<button
onClick={() => { setDismissed(true); onDismiss(); }}
style={{ background: 'none', border: 'none', color: '#6b7a99', cursor: 'pointer', fontSize: 11 }}
>
Masquer
</button>
</div>
<p style={{ margin: '0 0 1rem', fontSize: 12, color: '#9ca3af' }}>
Voici les premières étapes pour bien démarrer ton aventure dans les Marais.
</p>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
{STEPS.map((step, i) => {
const Icon = step.icon;
return (
<button
key={i}
onClick={() => navigate(step.to)}
style={{
display: 'flex', alignItems: 'flex-start', gap: 10,
padding: '0.75rem', background: '#111620', border: '1px solid #2a3448',
borderRadius: 8, cursor: 'pointer', textAlign: 'left',
transition: 'border-color 0.15s',
}}
onMouseEnter={e => (e.currentTarget.style.borderColor = '#f4c94e')}
onMouseLeave={e => (e.currentTarget.style.borderColor = '#2a3448')}
>
<Icon size={18} color="#f4c94e" style={{ flexShrink: 0, marginTop: 2 }} />
<div style={{ flex: 1 }}>
<div style={{ fontSize: 12, fontWeight: 700, color: '#dce4f0', marginBottom: 2 }}>
{i + 1}. {step.title}
</div>
<div style={{ fontSize: 10, color: '#6b7a99', lineHeight: 1.4 }}>{step.desc}</div>
<div style={{ fontSize: 10, color: '#f4c94e', marginTop: 4, display: 'flex', alignItems: 'center', gap: 2 }}>
{step.cta} <ChevronRight size={10} />
</div>
</div>
</button>
);
})}
</div>
</div>
);
}