feat: implement core application structure, UI components, internationalization, and database seeding.

This commit is contained in:
2026-03-04 13:50:37 +01:00
parent 85642b4672
commit 5101f39ba0
49 changed files with 2732 additions and 980 deletions

View File

@@ -4,6 +4,8 @@
import React from 'react';
import { BookProject, UserProfile } from '@/lib/types';
import { Plus, Book, Clock, Star, ChevronRight, LogOut, LayoutDashboard, User, Target, Flame, Edit3 } from 'lucide-react';
import { useLanguage } from '@/providers/LanguageProvider';
import { LanguageSwitcher } from '@/components/LanguageSwitcher';
interface DashboardProps {
user: UserProfile;
@@ -16,6 +18,8 @@ interface DashboardProps {
}
const Dashboard: React.FC<DashboardProps> = ({ user, projects, onSelect, onCreate, onLogout, onPricing, onProfile }) => {
const { t } = useLanguage();
return (
<div className="min-h-screen bg-theme-bg p-8 font-sans transition-colors duration-300">
<div className="max-w-6xl mx-auto space-y-8">
@@ -28,18 +32,19 @@ const Dashboard: React.FC<DashboardProps> = ({ user, projects, onSelect, onCreat
<div className="absolute -bottom-1 -right-1 bg-green-500 w-5 h-5 rounded-full border-4 border-white" />
</div>
<div>
<h2 className="text-3xl font-black text-theme-text">Bonjour, {user.name} 👋</h2>
<h2 className="text-3xl font-black text-theme-text">{t('dashboard.hello')}, {user.name} 👋</h2>
<div className="flex items-center gap-3 mt-1">
<span className="px-3 py-1 rounded-full bg-indigo-100 text-indigo-700 text-[10px] uppercase font-black tracking-widest">{user.subscription.planDetails?.displayName || user.subscription.plan}</span>
<span className="text-theme-muted text-xs font-medium">Membre depuis le 24 janv.</span>
<span className="text-theme-muted text-xs font-medium">{t('dashboard.member_since')} 24 janv.</span>
</div>
</div>
</div>
<div className="flex items-center gap-3">
<LanguageSwitcher />
<button onClick={onProfile} className="bg-theme-bg text-theme-text px-5 py-2.5 rounded-xl text-sm font-bold hover:opacity-80 transition-all flex items-center gap-2 border border-theme-border">
<User size={18} /> Mon Profil
<User size={18} /> {t('dashboard.my_profile')}
</button>
<button onClick={onLogout} className="p-3 text-theme-muted hover:text-red-500 rounded-full hover:bg-red-500/10 transition-colors"><LogOut size={20} /></button>
<button onClick={onLogout} title={t('sidebar.logout')} className="p-3 text-theme-muted hover:text-red-500 rounded-full hover:bg-red-500/10 transition-colors"><LogOut size={20} /></button>
</div>
</div>
@@ -48,22 +53,22 @@ const Dashboard: React.FC<DashboardProps> = ({ user, projects, onSelect, onCreat
<div className="bg-theme-panel p-6 rounded-3xl shadow-sm border border-theme-border flex items-center gap-4">
<div className="bg-orange-100 p-3 rounded-2xl text-orange-600"><Flame size={24} /></div>
<div>
<p className="text-xs font-bold text-theme-muted uppercase tracking-wider">Série actuelle</p>
<p className="text-2xl font-black text-theme-text">{user.stats.writingStreak} Jours</p>
<p className="text-xs font-bold text-theme-muted uppercase tracking-wider">{t('dashboard.streak')}</p>
<p className="text-2xl font-black text-theme-text">{user.stats.writingStreak} {t('dashboard.days')}</p>
</div>
</div>
<div className="bg-theme-panel p-6 rounded-3xl shadow-sm border border-theme-border flex items-center gap-4">
<div className="bg-blue-100 p-3 rounded-2xl text-blue-600"><Edit3 size={24} /></div>
<div>
<p className="text-xs font-bold text-theme-muted uppercase tracking-wider">Mots écrits</p>
<p className="text-xs font-bold text-theme-muted uppercase tracking-wider">{t('dashboard.words_written')}</p>
<p className="text-2xl font-black text-theme-text">{user.stats.totalWordsWritten.toLocaleString()}</p>
</div>
</div>
<div className="bg-theme-panel p-6 rounded-3xl shadow-sm border border-theme-border flex items-center gap-4">
<div className="bg-indigo-100 p-3 rounded-2xl text-indigo-600"><Target size={24} /></div>
<div>
<p className="text-xs font-bold text-theme-muted uppercase tracking-wider">Objectif du jour</p>
<p className="text-2xl font-black text-theme-text">{user.preferences.dailyWordGoal} Mots</p>
<p className="text-xs font-bold text-theme-muted uppercase tracking-wider">{t('dashboard.daily_goal')}</p>
<p className="text-2xl font-black text-theme-text">{user.preferences.dailyWordGoal} {t('dashboard.words')}</p>
</div>
</div>
</div>
@@ -72,12 +77,12 @@ const Dashboard: React.FC<DashboardProps> = ({ user, projects, onSelect, onCreat
{/* Project List */}
<div className="lg:col-span-2 space-y-4">
<div className="flex justify-between items-center mb-6">
<h3 className="text-2xl font-black text-theme-text">Mes Romans</h3>
<h3 className="text-2xl font-black text-theme-text">{t('dashboard.my_novels')}</h3>
<button
onClick={onCreate}
className="flex items-center gap-2 bg-blue-600 text-white px-6 py-3 rounded-2xl font-bold hover:bg-blue-700 transition-all shadow-xl shadow-blue-200"
>
<Plus size={20} /> Écrire un nouveau livre
<Plus size={20} /> {t('dashboard.write_new')}
</button>
</div>
@@ -93,10 +98,10 @@ const Dashboard: React.FC<DashboardProps> = ({ user, projects, onSelect, onCreat
<Book size={24} />
</div>
<h4 className="font-black text-theme-text text-xl truncate mb-1">{p.title}</h4>
<p className="text-theme-muted text-sm">Dernière modification : {new Date(p.lastModified).toLocaleDateString()}</p>
<p className="text-theme-muted text-sm">{t('dashboard.last_modified')} : {new Date(p.lastModified).toLocaleDateString()}</p>
</div>
<div className="flex justify-between items-center text-[10px] text-theme-muted font-black uppercase tracking-widest border-t border-theme-border pt-4 mt-auto">
<span>{p.chapters.length} Chapitres</span>
<span>{p.chapters.length} {t('nav.chapters')}</span>
<ChevronRight size={20} className="group-hover:text-blue-600 transition-transform group-hover:translate-x-1 duration-300" />
</div>
</div>
@@ -104,8 +109,8 @@ const Dashboard: React.FC<DashboardProps> = ({ user, projects, onSelect, onCreat
{projects.length === 0 && (
<div className="col-span-2 py-24 bg-theme-panel rounded-[3rem] border-2 border-dashed border-theme-border flex flex-col items-center justify-center text-theme-muted">
<Book size={64} className="mb-6 opacity-20" />
<p className="font-bold text-lg">Prêt à commencer votre premier roman ?</p>
<button onClick={onCreate} className="mt-4 text-blue-600 font-bold hover:underline">Créer un projet maintenant</button>
<p className="font-bold text-lg">{t('dashboard.empty_projects')}</p>
<button onClick={onCreate} className="mt-4 text-blue-600 font-bold hover:underline">{t('dashboard.create_now')}</button>
</div>
)}
</div>
@@ -115,11 +120,11 @@ const Dashboard: React.FC<DashboardProps> = ({ user, projects, onSelect, onCreat
<div className="space-y-6">
<div className="bg-slate-900 text-white p-8 rounded-[2.5rem] shadow-xl relative overflow-hidden">
<div className="absolute top-0 right-0 w-32 h-32 bg-indigo-500/20 blur-[60px] -z-1" />
<h3 className="font-black text-xl mb-6 flex items-center gap-2"><Star size={20} className="text-yellow-400" /> Utilisation</h3>
<h3 className="font-black text-xl mb-6 flex items-center gap-2"><Star size={20} className="text-yellow-400" /> {t('dashboard.usage')}</h3>
<div className="space-y-8">
<div>
<div className="flex justify-between text-[10px] font-black text-slate-400 uppercase tracking-widest mb-2">
<span>Actions IA</span>
<span>{t('sidebar.ai_actions')}</span>
<span>{user.usage.aiActionsCurrent} / {user.usage.aiActionsLimit === 999999 ? '∞' : user.usage.aiActionsLimit}</span>
</div>
<div className="h-3 w-full bg-slate-800 rounded-full overflow-hidden">
@@ -131,7 +136,7 @@ const Dashboard: React.FC<DashboardProps> = ({ user, projects, onSelect, onCreat
</div>
<div>
<div className="flex justify-between text-[10px] font-black text-slate-400 uppercase tracking-widest mb-2">
<span>Emplacements Roman</span>
<span>{t('dashboard.novel_slots')}</span>
<span>{projects.length} / {user.usage.projectsLimit}</span>
</div>
<div className="h-3 w-full bg-slate-800 rounded-full overflow-hidden">
@@ -143,7 +148,7 @@ const Dashboard: React.FC<DashboardProps> = ({ user, projects, onSelect, onCreat
</div>
</div>
<button onClick={onPricing} className="w-full mt-10 bg-white/10 hover:bg-white/20 py-4 rounded-2xl text-sm font-bold transition-all">
Upgrade Plan
{t('dashboard.upgrade_plan')}
</button>
</div>
</div>