- Économie : ~1240 lignes de code dupliqué - Réduction : ~60% du code modal - Amélioration : Cohérence et maintenabilité
178 lines
5.4 KiB
TypeScript
178 lines
5.4 KiB
TypeScript
'use client';
|
|
import { useEffect } from 'react';
|
|
import { Input } from '@/components/ui/input';
|
|
import { Label } from '@/components/ui/label';
|
|
import { propositionService } from '@/lib/services';
|
|
import { Proposition } from '@/types';
|
|
import { MarkdownEditor } from '@/components/MarkdownEditor';
|
|
import { useFormState } from '@/hooks/useFormState';
|
|
import { FormModal } from './FormModal';
|
|
import { handleFormError } from '@/lib/form-utils';
|
|
|
|
interface PropositionFormModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
onSuccess: () => void;
|
|
mode: 'add' | 'edit';
|
|
campaignId?: string;
|
|
proposition?: Proposition | null;
|
|
}
|
|
|
|
export default function PropositionFormModal({
|
|
isOpen,
|
|
onClose,
|
|
onSuccess,
|
|
mode,
|
|
campaignId,
|
|
proposition
|
|
}: PropositionFormModalProps) {
|
|
const initialData = {
|
|
title: '',
|
|
description: '',
|
|
author_first_name: mode === 'add' ? 'admin' : '',
|
|
author_last_name: mode === 'add' ? 'admin' : '',
|
|
author_email: mode === 'add' ? 'admin@example.com' : ''
|
|
};
|
|
|
|
const { formData, setFormData, loading, setLoading, error, setError, handleChange, resetForm } = useFormState(initialData);
|
|
|
|
useEffect(() => {
|
|
if (proposition && mode === 'edit') {
|
|
setFormData({
|
|
title: proposition.title,
|
|
description: proposition.description,
|
|
author_first_name: proposition.author_first_name,
|
|
author_last_name: proposition.author_last_name,
|
|
author_email: proposition.author_email
|
|
});
|
|
}
|
|
}, [proposition, mode, setFormData]);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setLoading(true);
|
|
setError('');
|
|
|
|
try {
|
|
if (mode === 'add' && campaignId) {
|
|
await propositionService.create({
|
|
campaign_id: campaignId,
|
|
title: formData.title,
|
|
description: formData.description,
|
|
author_first_name: formData.author_first_name,
|
|
author_last_name: formData.author_last_name,
|
|
author_email: formData.author_email
|
|
});
|
|
} else if (mode === 'edit' && proposition) {
|
|
await propositionService.update(proposition.id, {
|
|
title: formData.title,
|
|
description: formData.description,
|
|
author_first_name: formData.author_first_name,
|
|
author_last_name: formData.author_last_name,
|
|
author_email: formData.author_email
|
|
});
|
|
}
|
|
|
|
onSuccess();
|
|
if (mode === 'add') {
|
|
resetForm();
|
|
}
|
|
} catch (err: any) {
|
|
const operation = mode === 'add' ? 'la création de la proposition' : 'la modification de la proposition';
|
|
setError(handleFormError(err, operation));
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleClose = () => {
|
|
if (mode === 'add') {
|
|
resetForm();
|
|
}
|
|
onClose();
|
|
};
|
|
|
|
const isEditMode = mode === 'edit';
|
|
if (isEditMode && !proposition) return null;
|
|
|
|
return (
|
|
<FormModal
|
|
isOpen={isOpen}
|
|
onClose={handleClose}
|
|
onSubmit={handleSubmit}
|
|
title={isEditMode ? "Modifier la proposition" : "Ajouter une proposition"}
|
|
description={
|
|
isEditMode
|
|
? "Modifiez les détails de cette proposition."
|
|
: "Créez une nouvelle proposition pour cette campagne de budget participatif."
|
|
}
|
|
loading={loading}
|
|
error={error}
|
|
submitText={isEditMode ? "Modifier la proposition" : "Créer la proposition"}
|
|
loadingText={isEditMode ? "Modification..." : "Création..."}
|
|
>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="title">Titre de la proposition *</Label>
|
|
<Input
|
|
id="title"
|
|
name="title"
|
|
value={formData.title}
|
|
onChange={handleChange}
|
|
placeholder="Ex: Installation de bancs dans le parc"
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<MarkdownEditor
|
|
value={formData.description}
|
|
onChange={(value) => setFormData(prev => ({ ...prev, description: value }))}
|
|
placeholder="Décrivez votre proposition en détail..."
|
|
label="Description *"
|
|
maxLength={2000}
|
|
/>
|
|
|
|
<div className="border-t border-slate-200 dark:border-slate-700 pt-4">
|
|
<h3 className="text-sm font-medium text-slate-900 dark:text-slate-100 mb-3">
|
|
Informations de l'auteur
|
|
</h3>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="author_first_name">Prénom *</Label>
|
|
<Input
|
|
id="author_first_name"
|
|
name="author_first_name"
|
|
value={formData.author_first_name}
|
|
onChange={handleChange}
|
|
placeholder="Prénom"
|
|
required
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="author_last_name">Nom *</Label>
|
|
<Input
|
|
id="author_last_name"
|
|
name="author_last_name"
|
|
value={formData.author_last_name}
|
|
onChange={handleChange}
|
|
placeholder="Nom"
|
|
required
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="space-y-2 mt-3">
|
|
<Label htmlFor="author_email">Email *</Label>
|
|
<Input
|
|
id="author_email"
|
|
name="author_email"
|
|
type="email"
|
|
value={formData.author_email}
|
|
onChange={handleChange}
|
|
placeholder="email@example.com"
|
|
required
|
|
/>
|
|
</div>
|
|
</div>
|
|
</FormModal>
|
|
);
|
|
}
|