connection base prisma + postgres + login ok

This commit is contained in:
2026-02-26 21:58:16 +01:00
parent 78dc8813f1
commit 56b5615abf
1462 changed files with 429582 additions and 2546 deletions

View File

@@ -0,0 +1,254 @@
'use client';
import React, { useEffect, useState } from 'react';
import { BookProject, BookSettings } from '@/lib/types';
import { GENRES, TONES, POV_OPTIONS, TENSE_OPTIONS } from '@/lib/constants';
import { Settings, Book, Feather, Users, Clock, Target, Hash } from 'lucide-react';
interface BookSettingsProps {
project: BookProject;
onUpdate: (project: BookProject) => void;
onDeleteProject: () => void;
}
const DEFAULT_SETTINGS: BookSettings = {
genre: '',
subGenre: '',
targetAudience: '',
tone: '',
pov: '',
tense: '',
synopsis: '',
themes: ''
};
const BookSettingsComponent: React.FC<BookSettingsProps> = ({ project, onUpdate, onDeleteProject }) => {
const [settings, setSettings] = useState<BookSettings>(project.settings || DEFAULT_SETTINGS);
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
useEffect(() => {
if (project.settings) {
setSettings(project.settings);
}
}, [project.settings]);
const handleChange = (key: keyof BookSettings, value: string) => {
const newSettings = { ...settings, [key]: value };
setSettings(newSettings);
onUpdate({ ...project, settings: newSettings });
};
const handleStyleGuideChange = (value: string) => {
onUpdate({ ...project, styleGuide: value });
};
return (
<div className="h-full bg-[#eef2ff] p-8 overflow-y-auto">
<div className="max-w-4xl mx-auto bg-white rounded-xl shadow-lg border border-slate-200 overflow-hidden">
<div className="bg-slate-900 text-white p-6 border-b border-slate-800 flex items-center gap-4">
<div className="bg-blue-600 p-3 rounded-lg">
<Settings size={24} />
</div>
<div>
<h2 className="text-2xl font-bold">Paramètres Généraux du Roman</h2>
<p className="text-slate-400 text-sm">Définissez l'identité, le ton et les règles de votre œuvre pour guider l'IA.</p>
</div>
</div>
<div className="p-8 space-y-8">
<section className="space-y-4">
<h3 className="text-lg font-bold text-slate-800 flex items-center gap-2 border-b border-slate-100 pb-2">
<Book size={18} className="text-blue-600" /> Informations de Base
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="block text-sm font-semibold text-slate-600 mb-1">Titre du Roman</label>
<input
type="text"
value={project.title}
onChange={(e) => onUpdate({ ...project, title: e.target.value })}
className="w-full p-2.5 bg-[#eef2ff] border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none font-serif font-bold text-lg"
/>
</div>
<div>
<label className="block text-sm font-semibold text-slate-600 mb-1">Nom d'Auteur</label>
<input
type="text"
value={project.author}
onChange={(e) => onUpdate({ ...project, author: e.target.value })}
className="w-full p-2.5 bg-[#eef2ff] border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none"
/>
</div>
</div>
<div>
<label className="block text-sm font-semibold text-slate-600 mb-1">Synopsis Global</label>
<textarea
value={settings.synopsis}
onChange={(e) => handleChange('synopsis', e.target.value)}
className="w-full p-3 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none h-24 text-sm bg-[#eef2ff]"
placeholder="De quoi parle votre histoire dans les grandes lignes ?"
/>
</div>
</section>
<section className="space-y-4">
<h3 className="text-lg font-bold text-slate-800 flex items-center gap-2 border-b border-slate-100 pb-2">
<Target size={18} className="text-red-500" /> Genre & Public
</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div>
<label className="block text-sm font-semibold text-slate-600 mb-1">Genre Principal</label>
<input
type="text"
list="genre-suggestions"
value={settings.genre}
onChange={(e) => handleChange('genre', e.target.value)}
className="w-full p-2.5 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none bg-[#eef2ff]"
placeholder="Ex: Fantasy"
/>
<datalist id="genre-suggestions">
{GENRES.map(g => <option key={g} value={g} />)}
</datalist>
</div>
<div>
<label className="block text-sm font-semibold text-slate-600 mb-1">Sous-Genre</label>
<input
type="text"
value={settings.subGenre || ''}
onChange={(e) => handleChange('subGenre', e.target.value)}
className="w-full p-2.5 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none bg-[#eef2ff]"
placeholder="Ex: Dark Fantasy"
/>
</div>
<div>
<label className="block text-sm font-semibold text-slate-600 mb-1">Public Cible</label>
<input
type="text"
value={settings.targetAudience}
onChange={(e) => handleChange('targetAudience', e.target.value)}
className="w-full p-2.5 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none bg-[#eef2ff]"
placeholder="Ex: Jeune Adulte, Adulte..."
/>
</div>
</div>
<div>
<label className="block text-sm font-semibold text-slate-600 mb-1">Thèmes Clés</label>
<div className="relative">
<Hash size={14} className="absolute left-3 top-3 text-slate-400" />
<input
type="text"
value={settings.themes}
onChange={(e) => handleChange('themes', e.target.value)}
className="w-full pl-9 p-2.5 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none bg-[#eef2ff]"
placeholder="Ex: Vengeance, Rédemption, Voyage initiatique..."
/>
</div>
</div>
</section>
<section className="space-y-4">
<h3 className="text-lg font-bold text-slate-800 flex items-center gap-2 border-b border-slate-100 pb-2">
<Feather size={18} className="text-purple-600" /> Narration & Style
</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div>
<label className="block text-sm font-semibold text-slate-600 mb-1 flex items-center gap-1">
<Users size={14} /> Point de Vue (POV)
</label>
<select
value={settings.pov}
onChange={(e) => handleChange('pov', e.target.value)}
className="w-full p-2.5 bg-[#eef2ff] border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none"
>
<option value="">Sélectionner...</option>
{POV_OPTIONS.map(o => <option key={o} value={o}>{o}</option>)}
</select>
</div>
<div>
<label className="block text-sm font-semibold text-slate-600 mb-1 flex items-center gap-1">
<Clock size={14} /> Temps du récit
</label>
<select
value={settings.tense}
onChange={(e) => handleChange('tense', e.target.value)}
className="w-full p-2.5 bg-[#eef2ff] border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none"
>
<option value="">Sélectionner...</option>
{TENSE_OPTIONS.map(o => <option key={o} value={o}>{o}</option>)}
</select>
</div>
<div>
<label className="block text-sm font-semibold text-slate-600 mb-1">Ton Général</label>
<input
type="text"
list="tone-suggestions"
value={settings.tone}
onChange={(e) => handleChange('tone', e.target.value)}
className="w-full p-2.5 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none bg-[#eef2ff]"
placeholder="Ex: Sombre, Ironique..."
/>
<datalist id="tone-suggestions">
{TONES.map(t => <option key={t} value={t} />)}
</datalist>
</div>
</div>
<div className="mt-4">
<label className="block text-sm font-semibold text-slate-600 mb-1">
Guide de Style & Instructions IA (Prompt Système)
</label>
<p className="text-xs text-slate-400 mb-2">
Ces instructions seront envoyées à l'IA à chaque génération. Décrivez ici le style d'écriture désiré (ex: "phrases courtes", "vocabulaire soutenu", "beaucoup de métaphores").
</p>
<textarea
value={project.styleGuide || ''}
onChange={(e) => handleStyleGuideChange(e.target.value)}
className="w-full p-3 border border-indigo-100 bg-[#eef2ff] rounded-lg focus:ring-2 focus:ring-indigo-500 outline-none h-32 text-sm font-mono text-slate-700"
placeholder="Ex: Utilise un style descriptif et sensoriel. Évite les adverbes. Le narrateur est cynique."
/>
</div>
</section>
<section className="space-y-4 pt-8 border-t border-red-200">
<h3 className="text-lg font-bold text-red-600 flex items-center gap-2 pb-2">
<span className="bg-red-100 p-1 rounded"></span> Zone de Danger
</h3>
<div className="bg-red-50 border border-red-200 rounded-lg p-6">
<h4 className="font-bold text-red-900 mb-2">Supprimer le projet</h4>
<p className="text-sm text-red-700 mb-4">
Cette action est irréversible. Toutes les données associées à ce projet (chapitres, entités, idées) seront définitivement effacées.
</p>
{showDeleteConfirm ? (
<div className="flex items-center gap-4 bg-white p-4 rounded border border-red-200">
<span className="text-sm font-bold text-slate-700">Êtes-vous sûr ?</span>
<button
onClick={onDeleteProject}
className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 text-sm font-bold"
>
Oui, supprimer définitivement
</button>
<button
onClick={() => setShowDeleteConfirm(false)}
className="px-4 py-2 bg-slate-200 text-slate-700 rounded hover:bg-slate-300 text-sm"
>
Annuler
</button>
</div>
) : (
<button
onClick={() => setShowDeleteConfirm(true)}
className="px-4 py-2 bg-white border border-red-300 text-red-600 rounded hover:bg-red-50 text-sm font-bold"
>
Supprimer ce projet
</button>
)}
</div>
</section>
</div>
</div>
</div>
);
};
export default BookSettingsComponent;