v1.0
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { createFormexMaterial, updateFormexMaterial } from '../api/client';
|
||||
import styles from './MaterialModal.module.css';
|
||||
|
||||
export default function MaterialModal({ material, collections, onClose, onSave }) {
|
||||
const isEditing = !!material;
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
formex_code: '',
|
||||
name: '',
|
||||
collection: '',
|
||||
width_mm: '',
|
||||
height_mm: '',
|
||||
thickness_mm: '',
|
||||
formex_url: ''
|
||||
});
|
||||
|
||||
const [error, setError] = useState('');
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (material) {
|
||||
setFormData({
|
||||
formex_code: material.formex_code || '',
|
||||
name: material.name || '',
|
||||
collection: material.collection || '',
|
||||
width_mm: material.width_mm?.toString() || '',
|
||||
height_mm: material.height_mm?.toString() || '',
|
||||
thickness_mm: material.thickness_mm?.toString() || '',
|
||||
formex_url: material.formex_url || ''
|
||||
});
|
||||
}
|
||||
}, [material]);
|
||||
|
||||
const handleChange = (e) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
setError('');
|
||||
|
||||
// Validation
|
||||
if (!formData.formex_code.trim() || !formData.name.trim() || !formData.collection.trim()) {
|
||||
setError('Le code, le nom et la collection sont requis.');
|
||||
return;
|
||||
}
|
||||
|
||||
setSaving(true);
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
formex_code: formData.formex_code.trim(),
|
||||
name: formData.name.trim(),
|
||||
collection: formData.collection.trim(),
|
||||
width_mm: formData.width_mm ? parseInt(formData.width_mm, 10) : null,
|
||||
height_mm: formData.height_mm ? parseInt(formData.height_mm, 10) : null,
|
||||
thickness_mm: formData.thickness_mm ? parseInt(formData.thickness_mm, 10) : null,
|
||||
formex_url: formData.formex_url.trim() || null
|
||||
};
|
||||
|
||||
if (isEditing) {
|
||||
await updateFormexMaterial(material.id, payload);
|
||||
} else {
|
||||
await createFormexMaterial(payload);
|
||||
}
|
||||
|
||||
onSave();
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOverlayClick = (e) => {
|
||||
if (e.target === e.currentTarget) {
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.overlay} onClick={handleOverlayClick}>
|
||||
<div className={styles.modal}>
|
||||
<div className={styles.header}>
|
||||
<h2>{isEditing ? 'Modifier le matériau' : 'Nouveau matériau'}</h2>
|
||||
<button type="button" onClick={onClose} className={styles.closeBtn}>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className={styles.form}>
|
||||
{error && <p className={styles.error}>{error}</p>}
|
||||
|
||||
<div className={styles.field}>
|
||||
<label htmlFor="formex_code">Code Formex *</label>
|
||||
<input
|
||||
type="text"
|
||||
id="formex_code"
|
||||
name="formex_code"
|
||||
value={formData.formex_code}
|
||||
onChange={handleChange}
|
||||
placeholder="ex: 10000"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.field}>
|
||||
<label htmlFor="name">Nom *</label>
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
placeholder="ex: Panneaux mélaminés Duplex Plus 10000 Tilia"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.field}>
|
||||
<label htmlFor="collection">Collection *</label>
|
||||
<input
|
||||
type="text"
|
||||
id="collection"
|
||||
name="collection"
|
||||
value={formData.collection}
|
||||
onChange={handleChange}
|
||||
list="collections-list"
|
||||
placeholder="ex: Duplex Plus"
|
||||
required
|
||||
/>
|
||||
<datalist id="collections-list">
|
||||
{collections.map((c) => (
|
||||
<option key={c} value={c} />
|
||||
))}
|
||||
</datalist>
|
||||
</div>
|
||||
|
||||
<div className={styles.row}>
|
||||
<div className={styles.field}>
|
||||
<label htmlFor="width_mm">Largeur (mm)</label>
|
||||
<input
|
||||
type="number"
|
||||
id="width_mm"
|
||||
name="width_mm"
|
||||
value={formData.width_mm}
|
||||
onChange={handleChange}
|
||||
placeholder="2800"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.field}>
|
||||
<label htmlFor="height_mm">Hauteur (mm)</label>
|
||||
<input
|
||||
type="number"
|
||||
id="height_mm"
|
||||
name="height_mm"
|
||||
value={formData.height_mm}
|
||||
onChange={handleChange}
|
||||
placeholder="2070"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.field}>
|
||||
<label htmlFor="thickness_mm">Épaisseur (mm)</label>
|
||||
<input
|
||||
type="number"
|
||||
id="thickness_mm"
|
||||
name="thickness_mm"
|
||||
value={formData.thickness_mm}
|
||||
onChange={handleChange}
|
||||
placeholder="19"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.field}>
|
||||
<label htmlFor="formex_url">URL Formex</label>
|
||||
<input
|
||||
type="url"
|
||||
id="formex_url"
|
||||
name="formex_url"
|
||||
value={formData.formex_url}
|
||||
onChange={handleChange}
|
||||
placeholder="https://www.formex.ch/fr/shop/..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.actions}>
|
||||
<button type="button" onClick={onClose} className={styles.cancelBtn}>
|
||||
Annuler
|
||||
</button>
|
||||
<button type="submit" disabled={saving} className={styles.saveBtn}>
|
||||
{saving ? 'Enregistrement…' : (isEditing ? 'Enregistrer' : 'Créer')}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user