From cb44599a4fcf7db2d85d702c843e07d3bf772609 Mon Sep 17 00:00:00 2001 From: alma Date: Sun, 20 Apr 2025 20:25:08 +0200 Subject: [PATCH] carnet panel contact --- app/carnet/page.tsx | 180 +++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 95 deletions(-) diff --git a/app/carnet/page.tsx b/app/carnet/page.tsx index ac9b085b..0b65bd7f 100644 --- a/app/carnet/page.tsx +++ b/app/carnet/page.tsx @@ -43,7 +43,7 @@ interface Contact { export default function CarnetPage() { const { data: session, status } = useSession(); - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(true); const [layoutMode, setLayoutMode] = useState("item-selection"); const [selectedNote, setSelectedNote] = useState(null); const [isMobile, setIsMobile] = useState(false); @@ -259,30 +259,55 @@ export default function CarnetPage() { const fetchContacts = async (folder: string) => { try { - setIsLoading(true); - const response = await fetch(`/api/nextcloud/files?folder=${folder}`); - if (!response.ok) { - throw new Error('Failed to fetch contacts'); + setIsLoadingContacts(true); + // First, check if we're looking at a specific VCF file + if (folder.endsWith('.vcf')) { + const response = await fetch(`/api/nextcloud/files/content?path=${encodeURIComponent(`/files/cube-${session?.user?.id}/Private/Contacts/${folder}`)}`); + if (response.ok) { + const { content } = await response.json(); + const contacts = parseVCard(content); + setContacts(contacts.map(contact => ({ + ...contact, + group: folder.replace('.vcf', '') + }))); + } + } else { + // If not a VCF file, list all VCF files in the folder + const response = await fetch(`/api/nextcloud/files?folder=${folder}`); + if (response.ok) { + const files = await response.json(); + const vcfFiles = files.filter((file: any) => file.basename.endsWith('.vcf')); + + // Parse VCF files and extract contact information + const parsedContacts = await Promise.all( + vcfFiles.map(async (file: any) => { + try { + const contentResponse = await fetch(`/api/nextcloud/files/content?path=${encodeURIComponent(file.filename)}`); + if (contentResponse.ok) { + const { content } = await contentResponse.json(); + const contacts = parseVCard(content); + return contacts.map(contact => ({ + ...contact, + group: file.basename.replace('.vcf', '') + })); + } + return []; + } catch (error) { + console.error('Error fetching VCF content:', error); + return []; + } + }) + ); + + // Flatten the array of contact arrays + setContacts(parsedContacts.flat().filter(Boolean)); + } } - const data = await response.json(); - const vcfFiles = data.files.filter((file: any) => file.filename.endsWith('.vcf')); - - const contacts = await Promise.all( - vcfFiles.map(async (file: any) => { - const contentResponse = await fetch(`/api/nextcloud/files/content?path=${encodeURIComponent(file.filename)}`); - if (!contentResponse.ok) { - throw new Error(`Failed to fetch content for ${file.filename}`); - } - const content = await contentResponse.text(); - return parseVCard(content); - }) - ); - - setContacts(contacts.flat()); - setIsLoading(false); } catch (error) { console.error('Error fetching contacts:', error); - setIsLoading(false); + setContacts([]); + } finally { + setIsLoadingContacts(false); } }; @@ -408,90 +433,54 @@ export default function CarnetPage() { const handleContactSave = async (contact: Contact) => { try { - setIsLoading(true); - const filePath = `/files/cube-${session?.user?.id}/Private/Contacts/${selectedFolder}`; - - // Fetch current VCF content - const response = await fetch(`/api/nextcloud/files/content?path=${encodeURIComponent(filePath)}`); - if (!response.ok) { - throw new Error('Failed to fetch VCF content'); - } - const currentContent = await response.text(); - - // Parse current contacts and update/add the edited contact - const existingContacts = currentContent.split('BEGIN:VCARD') - .filter(card => card.trim()) - .map(card => parseVCard('BEGIN:VCARD' + card)) - .flat(); - - const updatedContacts = contact.id - ? existingContacts.map(c => c.id === contact.id ? contact : c) - : [...existingContacts, { ...contact, id: crypto.randomUUID() }]; - - // Generate new VCF content - const newContent = updatedContacts.map(c => generateVCard(c)).join('\r\n'); - - // Save updated VCF file - const saveResponse = await fetch('/api/nextcloud/files', { + const vcfContent = generateVCard(contact); + const response = await fetch('/api/nextcloud/files', { method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ path: filePath, content: newContent }) + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + path: `/files/cube-${session?.user?.id}/Private/Contacts/${selectedFolder}`, + content: vcfContent + }), }); - - if (!saveResponse.ok) { + + if (!response.ok) { throw new Error('Failed to save contact'); } - + // Refresh contacts list - await fetchContacts(selectedFolder); - setIsLoading(false); + fetchContacts(selectedFolder); } catch (error) { console.error('Error saving contact:', error); - setIsLoading(false); } }; const handleContactDelete = async (contact: Contact) => { + if (!confirm('Êtes-vous sûr de vouloir supprimer ce contact ?')) { + return; + } + try { - setIsLoading(true); - const filePath = `/files/cube-${session?.user?.id}/Private/Contacts/${selectedFolder}`; - - // Fetch current VCF content - const response = await fetch(`/api/nextcloud/files/content?path=${encodeURIComponent(filePath)}`); - if (!response.ok) { - throw new Error('Failed to fetch VCF content'); - } - const currentContent = await response.text(); - - // Parse current contacts and remove the deleted contact - const existingContacts = currentContent.split('BEGIN:VCARD') - .filter(card => card.trim()) - .map(card => parseVCard('BEGIN:VCARD' + card)) - .flat(); - - const updatedContacts = existingContacts.filter(c => c.id !== contact.id); - - // Generate new VCF content - const newContent = updatedContacts.map(c => generateVCard(c)).join('\r\n'); - - // Save updated VCF file - const saveResponse = await fetch('/api/nextcloud/files', { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ path: filePath, content: newContent }) + 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 (!saveResponse.ok) { + + if (!response.ok) { throw new Error('Failed to delete contact'); } - - // Refresh contacts list - await fetchContacts(selectedFolder); + + // Clear selected contact and refresh list setSelectedContact(null); - setIsLoading(false); + fetchContacts('Contacts'); } catch (error) { console.error('Error deleting contact:', error); - setIsLoading(false); } }; @@ -500,17 +489,18 @@ export default function CarnetPage() { 'BEGIN:VCARD', 'VERSION:3.0', `UID:${contact.id}`, - `FN:${contact.fullName}`, - contact.email ? `EMAIL;TYPE=INTERNET:${contact.email}` : '', - contact.phone ? `TEL;TYPE=CELL:${contact.phone}` : '', + 'PRODID:-//Infomaniak//Workspace//pim', + contact.fullName ? `FN:${contact.fullName}` : '', + contact.fullName ? `N:${contact.fullName.split(' ').reverse().join(';')};` : '', contact.organization ? `ORG:${contact.organization}` : '', - contact.address ? `ADR;TYPE=HOME:;;${contact.address}` : '', + 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}` : '', - contact.group ? `CATEGORIES:${contact.group}` : '', 'END:VCARD' - ]; + ].filter(Boolean); - return lines.filter(line => line).join('\r\n'); + return lines.join('\n'); }; if (isLoading) {