163 lines
8.3 KiB
TypeScript
163 lines
8.3 KiB
TypeScript
|
|
import React, { useState, useRef } from 'react';
|
|
import { ViewMode, BookProject, UserProfile, Chapter, Entity } from '../types';
|
|
import LandingPage from './LandingPage';
|
|
import FeaturesPage from './FeaturesPage';
|
|
import Pricing from './Pricing';
|
|
import Checkout from './Checkout';
|
|
import AuthPage from './AuthPage';
|
|
import LoginPage from './LoginPage';
|
|
import Dashboard from './Dashboard';
|
|
import UserProfileSettings from './UserProfileSettings';
|
|
import ExportModal from './ExportModal';
|
|
import HelpModal from './HelpModal';
|
|
import EditorShell from './layout/EditorShell';
|
|
import RichTextEditor, { RichTextEditorHandle } from './RichTextEditor';
|
|
import WorldBuilder from './WorldBuilder';
|
|
import StoryWorkflow from './StoryWorkflow';
|
|
import IdeaBoard from './IdeaBoard';
|
|
import BookSettingsComponent from './BookSettings';
|
|
import { transformText } from '../services/geminiService';
|
|
|
|
interface AppRouterProps {
|
|
user: UserProfile | null;
|
|
projects: BookProject[];
|
|
currentProjectId: string | null;
|
|
viewMode: ViewMode;
|
|
chatHistory: any[];
|
|
isGenerating: boolean;
|
|
onLogin: (data: any) => Promise<any>;
|
|
onSignup: (data: any) => Promise<any>;
|
|
onLogout: () => void;
|
|
onViewModeChange: (mode: ViewMode) => void;
|
|
onSelectProject: (id: string) => void;
|
|
onCreateProject: () => void;
|
|
onUpdateProject: (updates: Partial<BookProject>) => void;
|
|
onUpdateChapter: (chapterId: string, updates: Partial<Chapter>) => void;
|
|
onAddChapter: () => Promise<string | null>;
|
|
onCreateEntity: (entity: Omit<Entity, 'id'>) => Promise<string | null>;
|
|
onUpdateEntity: (entityId: string, updates: Partial<Entity>) => void;
|
|
onDeleteEntity: (entityId: string) => void;
|
|
onUpdateProfile: (updates: Partial<UserProfile>) => void;
|
|
onUpgradePlan: (plan: any) => void;
|
|
onSendMessage: (msg: string) => void;
|
|
onIncrementUsage: () => void;
|
|
}
|
|
|
|
const AppRouter: React.FC<AppRouterProps> = (props) => {
|
|
const [currentChapterId, setCurrentChapterId] = useState<string>('');
|
|
const [isExportModalOpen, setIsExportModalOpen] = useState(false);
|
|
const [isHelpModalOpen, setIsHelpModalOpen] = useState(false);
|
|
const [targetEntityId, setTargetEntityId] = useState<string | null>(null);
|
|
const editorRef = useRef<RichTextEditorHandle>(null);
|
|
|
|
const { user, viewMode, currentProjectId, projects } = props;
|
|
const project = projects.find(p => p.id === currentProjectId);
|
|
console.log('props', props);
|
|
// DEBUG: Check all props
|
|
console.log("[AppRouter DEBUG] PROPS RECEIVED:", {
|
|
user,
|
|
userId: user?.id,
|
|
viewMode,
|
|
currentProjectId,
|
|
projectsCount: projects?.length,
|
|
fullProps: props
|
|
});
|
|
React.useEffect(() => {
|
|
if (project && (!currentChapterId || !project.chapters.some(c => c.id === currentChapterId))) {
|
|
setCurrentChapterId(project.chapters[0]?.id || '');
|
|
}
|
|
}, [currentProjectId, project]);
|
|
|
|
if (viewMode === 'landing') return <LandingPage onLogin={() => props.onViewModeChange('auth')} onFeatures={() => props.onViewModeChange('features')} onPricing={() => props.onViewModeChange('pricing')} />;
|
|
|
|
// Use new LoginPage for 'auth' view (Login)
|
|
if (viewMode === 'auth') return <LoginPage onSuccess={() => props.onViewModeChange('dashboard')} onRegister={() => props.onViewModeChange('signup')} />;
|
|
|
|
// Use existing AuthPage for 'signup' view (Register) - defaulted to signup mode inside AuthPage if possible,
|
|
// but AuthPage manages its own state. We can pass a prop if AuthPage supports it, or just let user toggle.
|
|
// Since AuthPage has internal state for mode, we might just render it.
|
|
// Ideally AuthPage should accept an initialMode prop. Let's check AuthPage again or just render it.
|
|
if (viewMode === 'signup') return <AuthPage onBack={() => props.onViewModeChange('landing')} onSuccess={() => props.onViewModeChange('dashboard')} initialMode='signup' />;
|
|
if (viewMode === 'features') return <FeaturesPage onBack={() => props.onViewModeChange(user ? 'dashboard' : 'landing')} />;
|
|
if (viewMode === 'pricing') return <Pricing currentPlan={user?.subscription.plan || 'free'} onBack={() => props.onViewModeChange(user ? 'dashboard' : 'landing')} onSelectPlan={() => user ? props.onViewModeChange('checkout') : props.onViewModeChange('auth')} />;
|
|
if (viewMode === 'checkout') return <Checkout onComplete={() => props.onUpgradePlan('pro')} onCancel={() => props.onViewModeChange('pricing')} />;
|
|
if (viewMode === 'dashboard' && user) return <Dashboard user={user} projects={projects} onSelect={props.onSelectProject} onCreate={props.onCreateProject} onLogout={props.onLogout} onPricing={() => props.onViewModeChange('pricing')} onProfile={() => props.onViewModeChange('profile')} />;
|
|
if (viewMode === 'profile' && user) return <UserProfileSettings user={user} onUpdate={props.onUpdateProfile} onBack={() => props.onViewModeChange('dashboard')} />;
|
|
|
|
console.log("[AppRouter] Render State:", { viewMode, hasUser: !!user, hasProject: !!project, currentProjectId, currentChapterId });
|
|
|
|
if (!project || !user) {
|
|
// If we are here, we are in a protected route ('write', 'world_building', etc.)
|
|
// BUT we don't have a project or user. This is an invalid state.
|
|
console.warn("[AppRouter] Fallthrough to NULL - displaying fallback");
|
|
return (
|
|
<div className="flex flex-col items-center justify-center h-screen bg-slate-100 text-slate-800">
|
|
<h2 className="text-xl font-bold mb-2">État Indéfini</h2>
|
|
<p>Mode: {viewMode}</p>
|
|
<p>Utilisateur: {user ? 'Connecté' : 'Non connecté'}</p>
|
|
<p>Projet sélectionné: {currentProjectId || 'Aucun'}</p>
|
|
<button className="mt-4 px-4 py-2 bg-blue-600 text-white rounded" onClick={() => props.onViewModeChange('landing')}>
|
|
Retour à l'accueil
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const currentChapter = project.chapters.find(c => c.id === currentChapterId);
|
|
|
|
return (
|
|
<EditorShell
|
|
project={project}
|
|
user={user}
|
|
viewMode={viewMode}
|
|
currentChapterId={currentChapterId}
|
|
chatHistory={props.chatHistory}
|
|
isGenerating={props.isGenerating}
|
|
onViewModeChange={props.onViewModeChange}
|
|
onChapterSelect={(id) => { setCurrentChapterId(id); props.onViewModeChange('write'); }}
|
|
onUpdateProject={props.onUpdateProject}
|
|
onAddChapter={async () => {
|
|
const id = await props.onAddChapter();
|
|
if (id) setCurrentChapterId(id);
|
|
}}
|
|
onDeleteChapter={(id) => {
|
|
if (project.chapters.length > 1) {
|
|
const newChapters = project.chapters.filter(c => c.id !== id);
|
|
props.onUpdateProject({ chapters: newChapters });
|
|
if (currentChapterId === id) setCurrentChapterId(newChapters[0].id);
|
|
}
|
|
}}
|
|
onLogout={props.onLogout}
|
|
onSendMessage={props.onSendMessage}
|
|
onInsertText={(text) => editorRef.current?.insertHtml(text)}
|
|
onOpenExport={() => setIsExportModalOpen(true)}
|
|
onOpenHelp={() => setIsHelpModalOpen(true)}
|
|
>
|
|
<ExportModal isOpen={isExportModalOpen} onClose={() => setIsExportModalOpen(false)} project={project} onPrint={() => { }} />
|
|
<HelpModal isOpen={isHelpModalOpen} onClose={() => setIsHelpModalOpen(false)} viewMode={viewMode} />
|
|
|
|
{viewMode === 'write' && <RichTextEditor
|
|
ref={editorRef}
|
|
initialContent={currentChapter?.content || ""}
|
|
onSave={(html) => props.onUpdateChapter(currentChapterId, { content: html })}
|
|
onAiTransform={(text, mode) => transformText(text, mode, currentChapter?.content || "", user, props.onIncrementUsage)}
|
|
/>}
|
|
{viewMode === 'world_building' && <WorldBuilder
|
|
entities={project.entities}
|
|
onCreate={props.onCreateEntity}
|
|
onUpdate={props.onUpdateEntity}
|
|
onDelete={props.onDeleteEntity}
|
|
templates={project.templates || []}
|
|
onUpdateTemplates={(t) => props.onUpdateProject({ templates: t })}
|
|
initialSelectedId={targetEntityId}
|
|
/>}
|
|
{viewMode === 'ideas' && <IdeaBoard ideas={project.ideas || []} onUpdate={(i) => props.onUpdateProject({ ideas: i })} />}
|
|
{viewMode === 'workflow' && <StoryWorkflow data={project.workflow || { nodes: [], connections: [] }} onUpdate={(w) => props.onUpdateProject({ workflow: w })} entities={project.entities} onNavigateToEntity={(id) => { setTargetEntityId(id); props.onViewModeChange('world_building'); }} />}
|
|
{viewMode === 'settings' && <BookSettingsComponent project={project} onUpdate={props.onUpdateProject} />}
|
|
</EditorShell>
|
|
);
|
|
};
|
|
|
|
export default AppRouter;
|