docv/components/FolderModal.tsx
2025-09-30 17:57:28 +02:00

422 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, memo } from 'react';
import Modal from './ui/modal/Modal';
import './FolderModal.css';
import type { FolderData } from '../lib/4nk/models/FolderData';
interface FolderModalProps {
folder?: FolderData;
onSave?: (folderData: FolderData) => void;
onCancel?: () => void;
readOnly?: boolean;
isOpen: boolean;
onClose: () => void;
}
const defaultFolder: FolderData = {
folderNumber: '',
name: '',
deedType: '',
description: '',
archived_description: '',
status: 'active',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
customers: [],
documents: [],
motes: [],
stakeholders: []
};
function FolderModal({
folder = defaultFolder,
onSave,
onCancel,
readOnly = false,
isOpen,
onClose
}: FolderModalProps) {
const [folderData, setFolderData] = useState<FolderData>(folder);
const [currentCustomer, setCurrentCustomer] = useState<string>('');
const [currentStakeholder, setCurrentStakeholder] = useState<string>('');
const [currentMote, setCurrentMote] = useState<string>('');
if (!isOpen) return null;
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
const { name, value } = e.target;
setFolderData(prev => ({
...prev,
[name]: value
}));
};
const addCustomer = () => {
if (currentCustomer.trim() && !folderData.customers.includes(currentCustomer.trim())) {
setFolderData(prev => ({
...prev,
customers: [...prev.customers, currentCustomer.trim()]
}));
setCurrentCustomer('');
}
};
const removeCustomer = (customer: string) => {
setFolderData(prev => ({
...prev,
customers: prev.customers.filter(c => c !== customer)
}));
};
const addStakeholder = () => {
if (currentStakeholder.trim() && !folderData.stakeholders.includes(currentStakeholder.trim())) {
setFolderData(prev => ({
...prev,
stakeholders: [...prev.stakeholders, currentStakeholder.trim()]
}));
setCurrentStakeholder('');
}
};
const removeStakeholder = (stakeholder: string) => {
setFolderData(prev => ({
...prev,
stakeholders: prev.stakeholders.filter(s => s !== stakeholder)
}));
};
const addMote = () => {
if (currentMote.trim() && !folderData.motes.includes(currentMote.trim())) {
setFolderData(prev => ({
...prev,
motes: [...prev.motes, currentMote.trim()]
}));
setCurrentMote('');
}
};
const removeMote = (mote: string) => {
setFolderData(prev => ({
...prev,
motes: prev.motes.filter(m => m !== mote)
}));
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (onSave) {
onSave({
...folderData,
updated_at: new Date().toISOString()
});
}
};
const handleCancel = () => {
if (onCancel) {
onCancel();
} else {
onClose();
}
};
return (
<Modal isOpen={isOpen} onClose={onClose} title="Créer un nouveau dossier" size="lg">
<div className="folder-container">
<form className="folder-form" onSubmit={handleSubmit}>
<div className="form-section">
<h3 className="section-title">Informations principales</h3>
<div className="form-row">
<div className="form-field">
<label>
Numéro de dossier <span className="required">*</span>
</label>
<input
type="text"
name="folderNumber"
value={folderData.folderNumber}
onChange={handleInputChange}
required
disabled={readOnly}
placeholder="ex: DOC-2025-001"
/>
</div>
<div className="form-field">
<label>
Nom <span className="required">*</span>
</label>
<input
type="text"
name="name"
value={folderData.name}
onChange={handleInputChange}
required
disabled={readOnly}
placeholder="Nom du dossier"
/>
</div>
</div>
<div className="form-row">
<div className="form-field">
<label>
Type d'acte <span className="required">*</span>
</label>
<select
name="deedType"
value={folderData.deedType}
onChange={handleInputChange}
required
disabled={readOnly}
>
<option value="">Sélectionnez le type d'acte</option>
<option value="vente">Vente</option>
<option value="achat">Achat</option>
<option value="succession">Succession</option>
<option value="donation">Donation</option>
<option value="hypotheque">Hypothèque</option>
<option value="bail">Bail</option>
<option value="autre">Autre</option>
</select>
</div>
<div className="form-field">
<label>
Statut <span className="required">*</span>
</label>
<select
name="status"
value={folderData.status}
onChange={handleInputChange}
required
disabled={readOnly}
>
<option value="active">Actif</option>
<option value="pending">En attente</option>
<option value="completed">Complété</option>
<option value="archived">Archivé</option>
</select>
</div>
</div>
<div className="form-field">
<label>Description</label>
<textarea
name="description"
value={folderData.description}
onChange={handleInputChange}
disabled={readOnly}
placeholder="Description du dossier"
rows={3}
/>
</div>
{folderData.status === 'archived' && (
<div className="form-field">
<label>Description d'archivage</label>
<textarea
name="archived_description"
value={folderData.archived_description}
onChange={handleInputChange}
disabled={readOnly}
placeholder="Raison d'archivage"
rows={2}
/>
</div>
)}
</div>
<div className="form-section">
<h3 className="section-title">Clients</h3>
<div className="tag-list">
{folderData.customers.map((customer, index) => (
<div key={index} className="tag-item">
<span>{customer}</span>
{!readOnly && (
<button
type="button"
className="tag-remove"
onClick={() => removeCustomer(customer)}
aria-label="Supprimer ce client"
>
×
</button>
)}
</div>
))}
</div>
{!readOnly && (
<div className="form-field tag-input-container">
<input
type="text"
value={currentCustomer}
onChange={(e) => setCurrentCustomer(e.target.value)}
placeholder="Ajouter un client"
onKeyPress={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
addCustomer();
}
}}
/>
<button
type="button"
className="btn-add-tag"
onClick={addCustomer}
>
Ajouter
</button>
</div>
)}
</div>
<div className="form-section">
<h3 className="section-title">Parties prenantes</h3>
<div className="tag-list">
{folderData.stakeholders.map((stakeholder, index) => (
<div key={index} className="tag-item">
<span>{stakeholder}</span>
{!readOnly && (
<button
type="button"
className="tag-remove"
onClick={() => removeStakeholder(stakeholder)}
aria-label="Supprimer cette partie prenante"
>
×
</button>
)}
</div>
))}
</div>
{!readOnly && (
<div className="form-field tag-input-container">
<input
type="text"
value={currentStakeholder}
onChange={(e) => setCurrentStakeholder(e.target.value)}
placeholder="Ajouter une partie prenante"
onKeyPress={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
addStakeholder();
}
}}
/>
<button
type="button"
className="btn-add-tag"
onClick={addStakeholder}
>
Ajouter
</button>
</div>
)}
</div>
<div className="form-section">
<h3 className="section-title">Notes</h3>
<div className="tag-list">
{folderData.motes.map((mote, index) => (
<div key={index} className="tag-item">
<span>{mote}</span>
{!readOnly && (
<button
type="button"
className="tag-remove"
onClick={() => removeMote(mote)}
aria-label="Supprimer cette note"
>
×
</button>
)}
</div>
))}
</div>
{!readOnly && (
<div className="form-field tag-input-container">
<input
type="text"
value={currentMote}
onChange={(e) => setCurrentMote(e.target.value)}
placeholder="Ajouter une note"
onKeyPress={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
addMote();
}
}}
/>
<button
type="button"
className="btn-add-tag"
onClick={addMote}
>
Ajouter
</button>
</div>
)}
</div>
<div className="form-section">
<h3 className="section-title">Informations système</h3>
<div className="form-row">
<div className="form-field">
<label>Créé le</label>
<input
type="text"
value={new Date(folderData.created_at).toLocaleDateString('fr-FR', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
})}
disabled
readOnly
/>
</div>
<div className="form-field">
<label>Dernière mise à jour</label>
<input
type="text"
value={new Date(folderData.updated_at).toLocaleDateString('fr-FR', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
})}
disabled
readOnly
/>
</div>
</div>
</div>
<div className="form-actions">
<button
type="button"
className="btn-cancel"
onClick={handleCancel}
>
Annuler
</button>
<button
type="submit"
className="btn-submit"
disabled={readOnly}
>
Enregistrer
</button>
</div>
</form>
</div>
</Modal>
);
};
FolderModal.displayName = 'FolderModal';
export default memo(FolderModal);