From 5059afe51051496b4f30b8b9fe7039d2b62c946c Mon Sep 17 00:00:00 2001 From: alma Date: Sun, 20 Apr 2025 20:16:54 +0200 Subject: [PATCH] carnet panel contact --- app/carnet/page.tsx | 78 +++++++++- components/carnet/contact-details.tsx | 199 +++++++++++++++++--------- 2 files changed, 209 insertions(+), 68 deletions(-) diff --git a/app/carnet/page.tsx b/app/carnet/page.tsx index 23f080e9..0b65bd7f 100644 --- a/app/carnet/page.tsx +++ b/app/carnet/page.tsx @@ -431,6 +431,78 @@ export default function CarnetPage() { } }; + const handleContactSave = async (contact: Contact) => { + try { + const vcfContent = generateVCard(contact); + const response = await fetch('/api/nextcloud/files', { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + path: `/files/cube-${session?.user?.id}/Private/Contacts/${selectedFolder}`, + content: vcfContent + }), + }); + + if (!response.ok) { + throw new Error('Failed to save contact'); + } + + // Refresh contacts list + fetchContacts(selectedFolder); + } catch (error) { + console.error('Error saving contact:', error); + } + }; + + const handleContactDelete = async (contact: Contact) => { + if (!confirm('Êtes-vous sûr de vouloir supprimer ce contact ?')) { + return; + } + + try { + const response = await fetch('/api/nextcloud/files', { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + path: `/files/cube-${session?.user?.id}/Private/Contacts/${selectedFolder}` + }), + }); + + if (!response.ok) { + throw new Error('Failed to delete contact'); + } + + // Clear selected contact and refresh list + setSelectedContact(null); + fetchContacts('Contacts'); + } catch (error) { + console.error('Error deleting contact:', error); + } + }; + + const generateVCard = (contact: Contact): string => { + const lines = [ + 'BEGIN:VCARD', + 'VERSION:3.0', + `UID:${contact.id}`, + 'PRODID:-//Infomaniak//Workspace//pim', + contact.fullName ? `FN:${contact.fullName}` : '', + contact.fullName ? `N:${contact.fullName.split(' ').reverse().join(';')};` : '', + contact.organization ? `ORG:${contact.organization}` : '', + contact.email ? `EMAIL;TYPE=WORK:${contact.email}` : '', + contact.phone ? `TEL;TYPE=WORK:${contact.phone}` : '', + contact.address ? `ADR;TYPE=WORK:;;${contact.address};;;;` : '', + contact.notes ? `NOTE:${contact.notes}` : '', + 'END:VCARD' + ].filter(Boolean); + + return lines.join('\n'); + }; + if (isLoading) { return (
@@ -497,7 +569,11 @@ export default function CarnetPage() { {/* Editor Panel */}
{selectedFolder === 'Contacts' || selectedFolder.endsWith('.vcf') ? ( - + ) : ( void; + onDelete?: (contact: Contact) => void; } -export const ContactDetails: React.FC = ({ contact }) => { +export const ContactDetails: React.FC = ({ contact, onSave, onDelete }) => { + const [isEditing, setIsEditing] = useState(false); + const [editedContact, setEditedContact] = useState(null); + + // Initialize edited contact when a contact is selected + React.useEffect(() => { + setEditedContact(contact); + setIsEditing(false); + }, [contact]); + if (!contact) { return (
@@ -28,83 +39,137 @@ export const ContactDetails: React.FC = ({ contact }) => { ); } + const handleSave = () => { + if (editedContact && onSave) { + onSave(editedContact); + setIsEditing(false); + } + }; + + const handleCancel = () => { + setEditedContact(contact); + setIsEditing(false); + }; + + const renderField = (label: string, value: string | undefined, field: keyof Contact, icon: React.ReactNode) => { + const bgColor = { + email: 'bg-blue-50', + phone: 'bg-green-50', + organization: 'bg-purple-50', + address: 'bg-orange-50' + }[field] || 'bg-gray-50'; + + const textColor = { + email: 'text-blue-500', + phone: 'text-green-500', + organization: 'text-purple-500', + address: 'text-orange-500' + }[field] || 'text-gray-500'; + + return ( +
+
+
{icon}
+
+
+

{label}

+ {isEditing ? ( + setEditedContact(prev => prev ? {...prev, [field]: e.target.value} : null)} + className="w-full text-sm text-carnet-text-primary bg-transparent border-b border-primary focus:outline-none" + /> + ) : ( +

{value}

+ )} +
+
+ ); + }; + return (
-
- {/* Contact Header */} +
-

- {contact.fullName || contact.email || 'Sans nom'} -

- {contact.organization && ( -

- {contact.organization} -

+ {isEditing ? ( + setEditedContact(prev => prev ? {...prev, fullName: e.target.value} : null)} + className="text-xl font-semibold text-carnet-text-primary bg-transparent border-b border-primary focus:outline-none" + placeholder="Nom complet" + /> + ) : ( +

+ {contact.fullName || contact.email || 'Sans nom'} +

)}
- - {/* Contact Information */} -
- {contact.email && ( -
-
- -
-
-

Email

-

{contact.email}

-
-
- )} - - {contact.phone && ( -
-
- -
-
-

Téléphone

-

{contact.phone}

-
-
- )} - - {contact.organization && ( -
-
- -
-
-

Organisation

-

{contact.organization}

-
-
- )} - - {contact.address && ( -
-
- -
-
-

Adresse

-

{contact.address}

-
-
+
+ {isEditing ? ( + <> + + + + ) : ( + <> + + {onDelete && ( + + )} + )}
+
- {/* Notes Section */} - {contact.notes && ( -
-

Notes

-

{contact.notes}

-
+
+ {renderField('Email', contact.email, 'email', )} + {renderField('Téléphone', contact.phone, 'phone', )} + {renderField('Organisation', contact.organization, 'organization', )} + {renderField('Adresse', contact.address, 'address', )} +
+ +
+

Notes

+ {isEditing ? ( +