add page organisation
This commit is contained in:
parent
b9f506cac8
commit
0ac5b589e8
@ -1,305 +1,379 @@
|
|||||||
/**
|
|
||||||
* Organization Settings Page
|
|
||||||
*
|
|
||||||
* Manage organization details
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useAuth } from '@/lib/context/auth-context';
|
||||||
import { organizationsApi } from '@/lib/api';
|
import { getOrganization, updateOrganization } from '@/lib/api/organizations';
|
||||||
|
import type { OrganizationResponse } from '@/types/api';
|
||||||
|
|
||||||
|
interface OrganizationForm {
|
||||||
|
name: string;
|
||||||
|
siren: string; // TODO: Add to backend
|
||||||
|
eori: string; // TODO: Add to backend
|
||||||
|
contact_phone: string;
|
||||||
|
contact_email: string;
|
||||||
|
address_street: string;
|
||||||
|
address_city: string;
|
||||||
|
address_postal_code: string;
|
||||||
|
address_country: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default function OrganizationSettingsPage() {
|
export default function OrganizationSettingsPage() {
|
||||||
const queryClient = useQueryClient();
|
const { user } = useAuth();
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [organization, setOrganization] = useState<OrganizationResponse | null>(null);
|
||||||
const [error, setError] = useState('');
|
const [formData, setFormData] = useState<OrganizationForm>({
|
||||||
const [success, setSuccess] = useState('');
|
|
||||||
|
|
||||||
const { data: organization, isLoading } = useQuery({
|
|
||||||
queryKey: ['organization', 'current'],
|
|
||||||
queryFn: () => organizationsApi.getCurrent(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const [formData, setFormData] = useState({
|
|
||||||
name: '',
|
name: '',
|
||||||
contactEmail: '',
|
siren: '',
|
||||||
contactPhone: '',
|
eori: '',
|
||||||
address: {
|
contact_phone: '',
|
||||||
street: '',
|
contact_email: '',
|
||||||
city: '',
|
address_street: '',
|
||||||
postalCode: '',
|
address_city: '',
|
||||||
country: '',
|
address_postal_code: '',
|
||||||
},
|
address_country: 'FR',
|
||||||
});
|
});
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
||||||
|
|
||||||
const updateMutation = useMutation({
|
useEffect(() => {
|
||||||
mutationFn: (data: typeof formData) => organizationsApi.update(organization?.id || '', data),
|
if (user?.organizationId) {
|
||||||
onSuccess: () => {
|
loadOrganization();
|
||||||
queryClient.invalidateQueries({ queryKey: ['organization'] });
|
}
|
||||||
setSuccess('Organization updated successfully');
|
}, [user?.organizationId]);
|
||||||
setIsEditing(false);
|
|
||||||
setTimeout(() => setSuccess(''), 3000);
|
|
||||||
},
|
|
||||||
onError: (err: any) => {
|
|
||||||
setError(err.response?.data?.message || 'Failed to update organization');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleEdit = () => {
|
const loadOrganization = async () => {
|
||||||
if (organization) {
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
setError(null);
|
||||||
|
const org = await getOrganization(user!.organizationId);
|
||||||
|
setOrganization(org);
|
||||||
setFormData({
|
setFormData({
|
||||||
name: organization.name,
|
name: org.name,
|
||||||
contactEmail: organization.contactEmail,
|
siren: '', // TODO: Get from backend when available
|
||||||
contactPhone: organization.contactPhone,
|
eori: '', // TODO: Get from backend when available
|
||||||
address: organization.address,
|
contact_phone: org.contact_phone || '',
|
||||||
|
contact_email: org.contact_email || '',
|
||||||
|
address_street: org.address_street,
|
||||||
|
address_city: org.address_city,
|
||||||
|
address_postal_code: org.address_postal_code,
|
||||||
|
address_country: org.address_country,
|
||||||
});
|
});
|
||||||
setIsEditing(true);
|
} catch (err) {
|
||||||
setError('');
|
console.error('Failed to load organization:', err);
|
||||||
setSuccess('');
|
setError(err instanceof Error ? err.message : 'Erreur lors du chargement');
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleChange = (field: keyof OrganizationForm, value: string) => {
|
||||||
e.preventDefault();
|
setFormData(prev => ({ ...prev, [field]: value }));
|
||||||
updateMutation.mutate(formData);
|
setSuccessMessage(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
setIsEditing(false);
|
if (organization) {
|
||||||
setError('');
|
setFormData({
|
||||||
|
name: organization.name,
|
||||||
|
siren: '',
|
||||||
|
eori: '',
|
||||||
|
contact_phone: organization.contact_phone || '',
|
||||||
|
contact_email: organization.contact_email || '',
|
||||||
|
address_street: organization.address_street,
|
||||||
|
address_city: organization.address_city,
|
||||||
|
address_postal_code: organization.address_postal_code,
|
||||||
|
address_country: organization.address_country,
|
||||||
|
});
|
||||||
|
setSuccessMessage(null);
|
||||||
|
setError(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (!user?.organizationId) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsSaving(true);
|
||||||
|
setError(null);
|
||||||
|
setSuccessMessage(null);
|
||||||
|
|
||||||
|
// Update organization (excluding SIREN and EORI for now)
|
||||||
|
const updatedOrg = await updateOrganization(user.organizationId, {
|
||||||
|
name: formData.name,
|
||||||
|
contact_phone: formData.contact_phone,
|
||||||
|
contact_email: formData.contact_email,
|
||||||
|
address_street: formData.address_street,
|
||||||
|
address_city: formData.address_city,
|
||||||
|
address_postal_code: formData.address_postal_code,
|
||||||
|
address_country: formData.address_country,
|
||||||
|
});
|
||||||
|
|
||||||
|
setOrganization(updatedOrg);
|
||||||
|
setSuccessMessage('Informations sauvegardées avec succès');
|
||||||
|
|
||||||
|
// TODO: Save SIREN and EORI when backend supports them
|
||||||
|
if (formData.siren || formData.eori) {
|
||||||
|
console.log('SIREN/EORI will be saved when backend is updated:', {
|
||||||
|
siren: formData.siren,
|
||||||
|
eori: formData.eori,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to update organization:', err);
|
||||||
|
setError(err instanceof Error ? err.message : 'Erreur lors de la sauvegarde');
|
||||||
|
} finally {
|
||||||
|
setIsSaving(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center h-64">
|
<div className="flex items-center justify-center min-h-screen">
|
||||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
|
<div className="text-center">
|
||||||
|
<div className="inline-block animate-spin rounded-full h-12 w-12 border-b-4 border-blue-600 mb-4"></div>
|
||||||
|
<p className="text-gray-600">Chargement...</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!organization) {
|
if (!organization) {
|
||||||
return (
|
return (
|
||||||
<div className="text-center py-12">
|
<div className="max-w-4xl mx-auto">
|
||||||
<h2 className="text-2xl font-semibold text-gray-900">Organization not found</h2>
|
<div className="bg-red-50 border border-red-200 rounded-lg p-6">
|
||||||
|
<h3 className="text-lg font-semibold text-red-900 mb-2">Erreur</h3>
|
||||||
|
<p className="text-red-700">{error || "Impossible de charger l'organisation"}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-4xl space-y-6">
|
<div className="max-w-4xl mx-auto">
|
||||||
<div>
|
{/* Header */}
|
||||||
<h1 className="text-2xl font-bold text-gray-900">Organization Settings</h1>
|
<div className="mb-8">
|
||||||
<p className="text-sm text-gray-500 mt-1">Manage your organization information</p>
|
<h1 className="text-3xl font-bold text-gray-900">Paramètres de l'organisation</h1>
|
||||||
|
<p className="text-gray-600 mt-2">Gérez les informations de votre organisation</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{success && (
|
{/* Success Message */}
|
||||||
<div className="rounded-md bg-green-50 p-4">
|
{successMessage && (
|
||||||
<div className="text-sm text-green-800">{success}</div>
|
<div className="mb-6 bg-green-50 border border-green-200 rounded-lg p-4">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<span className="text-green-600 text-xl mr-3">✓</span>
|
||||||
|
<p className="text-green-800 font-medium">{successMessage}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Error Message */}
|
||||||
{error && (
|
{error && (
|
||||||
<div className="rounded-md bg-red-50 p-4">
|
<div className="mb-6 bg-red-50 border border-red-200 rounded-lg p-4">
|
||||||
<div className="text-sm text-red-800">{error}</div>
|
<div className="flex items-center">
|
||||||
|
<span className="text-red-600 text-xl mr-3">✕</span>
|
||||||
|
<p className="text-red-800 font-medium">{error}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="bg-white rounded-lg shadow">
|
{/* Form */}
|
||||||
<div className="px-6 py-4 border-b flex items-center justify-between">
|
<div className="bg-white rounded-lg shadow-md">
|
||||||
<h2 className="text-lg font-semibold text-gray-900">Organization Details</h2>
|
<div className="p-8">
|
||||||
{!isEditing && (
|
<h2 className="text-xl font-semibold text-gray-900 mb-6">Informations</h2>
|
||||||
<button
|
|
||||||
onClick={handleEdit}
|
|
||||||
className="inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50"
|
|
||||||
>
|
|
||||||
<svg className="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={2}
|
|
||||||
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Edit
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className="p-6">
|
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Basic Info */}
|
{/* Nom de la société */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700">Organization Name</label>
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
{isEditing ? (
|
Nom de la société <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.name}
|
value={formData.name}
|
||||||
onChange={e => setFormData({ ...formData, name: e.target.value })}
|
onChange={e => handleChange('name', e.target.value)}
|
||||||
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm px-3 py-2 border"
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
|
placeholder="Xpeditis"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<p className="mt-1 text-sm text-gray-900">{organization.name}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* SIREN */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700">Type</label>
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
<p className="mt-1 text-sm text-gray-900">{organization.type.replace('_', ' ')}</p>
|
SIREN
|
||||||
</div>
|
<span className="ml-2 text-xs text-gray-500">(Système d'Identification du Répertoire des Entreprises)</span>
|
||||||
|
</label>
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium text-gray-700">Contact Email</label>
|
|
||||||
{isEditing ? (
|
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="text"
|
||||||
value={formData.contactEmail}
|
value={formData.siren}
|
||||||
onChange={e => setFormData({ ...formData, contactEmail: e.target.value })}
|
onChange={e => handleChange('siren', e.target.value.replace(/\D/g, '').slice(0, 9))}
|
||||||
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm px-3 py-2 border"
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
required
|
placeholder="123 456 789"
|
||||||
|
maxLength={9}
|
||||||
/>
|
/>
|
||||||
) : (
|
<p className="mt-1 text-xs text-gray-500">9 chiffres</p>
|
||||||
<p className="mt-1 text-sm text-gray-900">{organization.contactEmail}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Numéro EORI */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700">Contact Phone</label>
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
{isEditing ? (
|
Numéro EORI
|
||||||
|
<span className="ml-2 text-xs text-gray-500">(Economic Operators Registration and Identification)</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={formData.eori}
|
||||||
|
onChange={e => handleChange('eori', e.target.value.toUpperCase())}
|
||||||
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
|
placeholder="FR123456789"
|
||||||
|
maxLength={17}
|
||||||
|
/>
|
||||||
|
<p className="mt-1 text-xs text-gray-500">Code pays (2 lettres) + numéro unique (max 15 caractères)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Téléphone */}
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-2">Téléphone</label>
|
||||||
<input
|
<input
|
||||||
type="tel"
|
type="tel"
|
||||||
value={formData.contactPhone}
|
value={formData.contact_phone}
|
||||||
onChange={e => setFormData({ ...formData, contactPhone: e.target.value })}
|
onChange={e => handleChange('contact_phone', e.target.value)}
|
||||||
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm px-3 py-2 border"
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
required
|
placeholder="06 80 18 28 12"
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<p className="mt-1 text-sm text-gray-900">{organization.contactPhone}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Address */}
|
{/* Email */}
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-medium text-gray-900 mb-4">Address</h3>
|
<label className="block text-sm font-medium text-gray-700 mb-2">Email</label>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<input
|
||||||
<div className="md:col-span-2">
|
type="email"
|
||||||
<label className="block text-sm font-medium text-gray-700">Street</label>
|
value={formData.contact_email}
|
||||||
{isEditing ? (
|
onChange={e => handleChange('contact_email', e.target.value)}
|
||||||
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
|
placeholder="contact@xpeditis.com"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Divider */}
|
||||||
|
<div className="border-t border-gray-200 pt-6">
|
||||||
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">Adresse</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Rue */}
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
|
Rue <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.address.street}
|
value={formData.address_street}
|
||||||
onChange={e =>
|
onChange={e => handleChange('address_street', e.target.value)}
|
||||||
setFormData({
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
...formData,
|
placeholder="123 Rue de la Paix"
|
||||||
address: {
|
|
||||||
...formData.address,
|
|
||||||
street: e.target.value,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm px-3 py-2 border"
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<p className="mt-1 text-sm text-gray-900">{organization.address.street}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Ville et Code postal */}
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700">City</label>
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
{isEditing ? (
|
Code postal <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.address.city}
|
value={formData.address_postal_code}
|
||||||
onChange={e =>
|
onChange={e => handleChange('address_postal_code', e.target.value)}
|
||||||
setFormData({
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
...formData,
|
placeholder="75001"
|
||||||
address: {
|
|
||||||
...formData.address,
|
|
||||||
city: e.target.value,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm px-3 py-2 border"
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<p className="mt-1 text-sm text-gray-900">{organization.address.city}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700">Postal Code</label>
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
{isEditing ? (
|
Ville <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.address.postalCode}
|
value={formData.address_city}
|
||||||
onChange={e =>
|
onChange={e => handleChange('address_city', e.target.value)}
|
||||||
setFormData({
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
...formData,
|
placeholder="Paris"
|
||||||
address: {
|
|
||||||
...formData.address,
|
|
||||||
postalCode: e.target.value,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm px-3 py-2 border"
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
) : (
|
</div>
|
||||||
<p className="mt-1 text-sm text-gray-900">{organization.address.postalCode}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Pays */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700">Country</label>
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
{isEditing ? (
|
Pays <span className="text-red-500">*</span>
|
||||||
<input
|
</label>
|
||||||
type="text"
|
<select
|
||||||
value={formData.address.country}
|
value={formData.address_country}
|
||||||
onChange={e =>
|
onChange={e => handleChange('address_country', e.target.value)}
|
||||||
setFormData({
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
...formData,
|
|
||||||
address: {
|
|
||||||
...formData.address,
|
|
||||||
country: e.target.value,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm px-3 py-2 border"
|
|
||||||
required
|
required
|
||||||
/>
|
>
|
||||||
) : (
|
<option value="FR">France</option>
|
||||||
<p className="mt-1 text-sm text-gray-900">{organization.address.country}</p>
|
<option value="BE">Belgique</option>
|
||||||
)}
|
<option value="DE">Allemagne</option>
|
||||||
|
<option value="ES">Espagne</option>
|
||||||
|
<option value="IT">Italie</option>
|
||||||
|
<option value="NL">Pays-Bas</option>
|
||||||
|
<option value="GB">Royaume-Uni</option>
|
||||||
|
<option value="US">États-Unis</option>
|
||||||
|
<option value="CN">Chine</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isEditing && (
|
{/* Actions */}
|
||||||
<div className="flex justify-end space-x-3 pt-6 border-t">
|
<div className="bg-gray-50 px-8 py-4 border-t border-gray-200 flex items-center justify-end space-x-4">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleCancel}
|
onClick={handleCancel}
|
||||||
className="px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50"
|
disabled={isSaving}
|
||||||
|
className="px-6 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||||
>
|
>
|
||||||
Cancel
|
Annuler
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="button"
|
||||||
disabled={updateMutation.isPending}
|
onClick={handleSave}
|
||||||
className="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400"
|
disabled={isSaving || !formData.name || !formData.address_street}
|
||||||
|
className="px-6 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center"
|
||||||
>
|
>
|
||||||
{updateMutation.isPending ? 'Saving...' : 'Save Changes'}
|
{isSaving ? (
|
||||||
|
<>
|
||||||
|
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
|
||||||
|
Enregistrement...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
'Enregistrer'
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Info Note */}
|
||||||
|
{(formData.siren || formData.eori) && (
|
||||||
|
<div className="mt-6 bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||||||
|
<div className="flex items-start">
|
||||||
|
<span className="text-blue-600 text-xl mr-3">ℹ️</span>
|
||||||
|
<div>
|
||||||
|
<p className="text-blue-900 font-medium mb-1">Note importante</p>
|
||||||
|
<p className="text-blue-800 text-sm">
|
||||||
|
Les champs SIREN et EORI seront sauvegardés une fois que le backend sera mis à jour pour les
|
||||||
|
supporter. Pour l'instant, seules les autres informations seront enregistrées.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user