import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import api from '../api/axios';
import { toast } from 'sonner';
import {
ArrowLeft, Save, FileText, CheckCircle2, Search, Eye, Plus,
Trash2, Layers, Sparkles, Settings, ListChecks, Link as LinkIcon, Edit3, X,
Palette, Monitor, Smartphone, Bot, Layout, Sliders, Type, ExternalLink, Calendar
} from 'lucide-react';
export default function AdminDossierConfig() {
const { id } = useParams();
const navigate = useNavigate();
const [dossier, setDossier] = useState(null);
const [extractedTexts, setExtractedTexts] = useState([]);
const [fieldsList, setFieldsList] = useState([]);
const [loading, setLoading] = useState(true);
const [searchTerm, setSearchTerm] = useState('');
// UX State: right panel tabs ('ia', 'manual', 'mapped')
const [activeTab, setActiveTab] = useState('ia');
// Designer State
const [uiConfig, setUiConfig] = useState({
theme: 'modern',
background: 'mesh',
aiPosition: 'right',
aiGreeting: 'Bonjour ! Comment puis-je vous aider a remplir votre dossier ?',
aiName: 'Assistant Dossier',
aiAvatar: '',
showBotIcon: true,
fontFamily: 'font-sans',
primaryColor: '#6366f1',
borderRadius: '12',
inputSpacing: 'compact',
labelStyle: 'uppercase',
glassIntensity: 'medium',
isAiEnabled: false,
showStepper: false,
showProgress: true,
allowSaveDraft: true,
themePreset: 'royal'
});
// Expanded states for accordion-style UX
const [expandedExtraction, setExpandedExtraction] = useState(null);
const [expandedMappedField, setExpandedMappedField] = useState(null);
// Form states
const [draftField, setDraftField] = useState(null);
const [editDraft, setEditDraft] = useState(null);
const [newManualField, setNewManualField] = useState({
label: '',
name: `var_m${Date.now().toString().slice(-4)}`,
type: 'text',
group: 'General',
suffix: '',
options: '',
width: '100', // Default full width
style: 'modern',
fontSize: 'md',
fontWeight: 'bold',
borderRadius: 'default',
animation: 'none',
helpText: '',
tooltip: '',
validation: {
required: true,
pattern: '',
min: '',
max: ''
},
conditions: [], // { fieldId: '', operator: 'eq', value: '' }
transform: 'none',
transformConfig: {}
});
const [analyzing, setAnalyzing] = useState(false);
useEffect(() => {
const fetchData = async () => {
try {
const dossRes = await api.get('/dossiers');
const found = dossRes.data.find(d => d.id === Number(id));
if (!found) return navigate('/admin/dashboard/dossiers');
setDossier(found);
const textRes = await api.get(`/dossiers/${id}/extract-text`);
setExtractedTexts(textRes.data);
if (found.uiConfig) {
setUiConfig(prev => ({ ...prev, ...found.uiConfig }));
}
if (found.fieldsConfig && Array.isArray(found.fieldsConfig)) {
setFieldsList(found.fieldsConfig.map(f => ({
name: f.name,
label: f.label,
pdfFieldName: f.pdfFieldName || '',
type: f.type || 'text',
group: f.group || 'General',
suffix: f.suffix || '',
options: f.options || '',
width: f.width || '100',
style: f.style || 'modern',
fontSize: f.fontSize || 'md',
fontWeight: f.fontWeight || 'bold',
borderRadius: f.borderRadius || 'default',
animation: f.animation || 'none',
helpText: f.helpText || '',
tooltip: f.tooltip || '',
validation: f.validation || { required: true, pattern: '', min: '', max: '' },
conditions: f.conditions || [],
transform: f.transform || 'none',
transformConfig: f.transformConfig || {}
})));
} else {
setFieldsList([]);
}
} catch (error) {
console.error(error);
toast.error('Erreur lors du chargement.');
} finally {
setLoading(false);
}
};
fetchData();
}, [id, navigate]);
// --- IA EXTRACTION HANDLERS ---
const handleOpenExtraction = async (text) => {
if (expandedExtraction === text) {
setExpandedExtraction(null);
setDraftField(null);
return;
}
setExpandedExtraction(text);
if (uiConfig.isAiEnabled) {
setAnalyzing(true);
setDraftField({ pdfFieldName: text, label: 'IA Analyse...', name: '', type: 'text', group: 'General' });
try {
const { data } = await api.post('/dossiers/ai-analyze', { text });
setDraftField({ ...data, pdfFieldName: text });
} catch {
toast.error("Echec de l'IA, passage en mode manuel.");
setDraftField({
pdfFieldName: text,
label: text.substring(0, 30),
name: `var_${Date.now().toString().slice(-4)}`,
type: 'text',
group: 'General',
suffix: '',
options: ''
});
} finally {
setAnalyzing(false);
}
} else {
setDraftField({
pdfFieldName: text,
label: text.substring(0, 30),
name: `var_${Date.now().toString().slice(-4)}`,
type: 'text',
group: 'General',
suffix: '',
options: '',
width: '100',
style: 'modern',
fontSize: 'md',
fontWeight: 'bold',
borderRadius: 'default',
animation: 'none',
helpText: '',
tooltip: '',
validation: { required: true, pattern: '', min: '', max: '' },
conditions: [],
transform: 'none',
transformConfig: {}
});
}
};
const handleAddExtraction = () => {
if (!draftField.name.trim() || !draftField.label.trim()) {
return toast.error("Le label et l'ID sont requis");
}
setFieldsList([...fieldsList, draftField]);
toast.success("Variable associee !");
setExpandedExtraction(null);
setDraftField(null);
// Optional: Auto switch to mapped tab after a few to see progress?
};
// --- MANUAL FIELD HANDLERS ---
const handleAddManualField = () => {
if (!newManualField.label.trim()) return toast.error("Le label est requis");
setFieldsList([...fieldsList, { ...newManualField, pdfFieldName: '' }]);
setNewManualField({
label: '',
name: `var_m${Date.now().toString().slice(-4)}`,
type: 'text',
group: 'General',
suffix: '',
options: '',
width: '100',
style: 'modern',
fontSize: 'md',
fontWeight: 'bold',
borderRadius: 'default',
animation: 'none',
helpText: '',
tooltip: '',
validation: { required: true, pattern: '', min: '', max: '' },
conditions: [],
transform: 'none',
transformConfig: {}
});
toast.success("Champ manuel ajoute !");
};
// --- MAPPED FIELDS HANDLERS ---
const handleEditMapped = (index, field) => {
if (expandedMappedField === index) {
setExpandedMappedField(null);
setEditDraft(null);
} else {
setExpandedMappedField(index);
setEditDraft({ ...field });
}
};
const handleSaveMapped = (index) => {
if (!editDraft.label.trim() || !editDraft.name.trim()) return toast.error("Erreur de saisie");
const updated = [...fieldsList];
updated[index] = { ...editDraft };
setFieldsList(updated);
setExpandedMappedField(null);
setEditDraft(null);
toast.success("Mise a jour effectuee");
};
const handleRemoveMapped = (index) => {
const list = [...fieldsList];
list.splice(index, 1);
setFieldsList(list);
if (expandedMappedField === index) {
setExpandedMappedField(null);
}
};
const handleBurstSplit = () => {
const field = draftField || editDraft;
if (!field || !field.transformConfig?.separator) return;
// Original raw text from PDF
const rawText = field.pdfFieldName || "";
const parts = rawText.split(field.transformConfig.separator);
const newFields = parts
.map(p => p.trim())
.filter(p => p.length > 0)
.map((part, i) => ({
...field, // Keep all metadata
label: part || `Partie ${i + 1}`,
name: `${field.name}_${i + 1}`, // Unique ID
transform: 'split',
transformConfig: {
...field.transformConfig,
index: i // Each child keeps the SAME separator but points to ITS own index
}
}));
if (newFields.length === 0) {
toast.error("Impossible de découper : aucun résultat avec ce séparateur.");
return;
}
setFieldsList([...fieldsList, ...newFields]);
if (draftField) {
setDraftField(null);
setExpandedExtraction(null);
} else {
setEditDraft(null);
setExpandedMappedField(null);
}
toast.success(`${newFields.length} variables intelligentes générées à partir du split !`);
};
const handleSaveAll = async () => {
const configArray = fieldsList.map(config => ({
...config,
required: true,
placeholder: `Saisir ${config.label}...`
}));
try {
await api.put(`/dossiers/${id}/fields`, {
fieldsConfig: configArray,
uiConfig
});
toast.success('Gabarit et design sauvegardes !');
navigate('/admin/dashboard/dossiers');
} catch (error) {
console.error(error);
toast.error('Echec de la sauvegarde.');
}
};
if (loading) return (
);
if (!dossier) return null;
return (
{/*
HEADER MINIMALISTE
*/}
Atelier de Configuration
Editeur
{dossier.name}
{/*
Refined Layout (User Request):
- Left Sidebar: PDF Source (Narrow & Fixed)
- Main Container: Page Preview (Top) + Config Tools (Bottom)
*/}
{/* 1. PDF SOURCE SECTION (Full Width Top) */}
PDF Source
Gabarit de reference
{/* 2. CLIENT SIMULATOR SECTION (Full Width Middle) */}
{/* Background Glows */}
Previsualisation
Experience Client Finale
{fieldsList.length === 0 ? (
) : (
Array.from(new Set(fieldsList.map(f => f.group || 'General'))).map(groupName => (
{fieldsList.filter(f => (f.group || 'General') === groupName).map((field) => {
const widthClass = field.width === '50' ? 'col-span-12 md:col-span-6' : (field.width === '33' ? 'col-span-12 md:col-span-4' : 'col-span-12');
return (
{
setActiveTab('mapped');
setExpandedMappedField(fieldsList.indexOf(field));
setEditDraft({ ...field });
// Scroll to tools after click
document.getElementById('config-tools').scrollIntoView({ behavior: 'smooth' });
}}
className={`${widthClass} group/p-item relative p-4 rounded-2xl border border-transparent hover:bg-white/5 hover:border-white/10 transition-all cursor-pointer`}
>
{field.pdfFieldName && }
{field.placeholder || '...'}
{field.suffix && {field.suffix}}
);
})}
))
)}
{/* 3. CONFIGURATION TOOLS SECTION (Full Width Bottom) */}
);
}