carnet panel contact

This commit is contained in:
alma 2025-04-20 22:09:14 +02:00
parent add7e45af9
commit 6beb394a84

View File

@ -11,7 +11,7 @@ import { useMediaQuery } from "@/hooks/use-media-query";
import { ContactsView } from '@/components/carnet/contacts-view';
import { X, Menu } from "lucide-react";
import { ContactDetails } from '@/components/carnet/contact-details';
import { VCard } from 'vcard-js';
import { parse as parseVCard, format as formatVCard } from 'vcard-parser';
// Layout modes
export enum PaneLayout {
@ -162,24 +162,23 @@ export default function CarnetPage() {
}
}, [selectedFolder, session?.user?.id]);
const parseVCard = (content: string): Contact[] => {
const parseVCardContent = (content: string): Contact[] => {
try {
// Split the content into individual vCards
const vcards = content.split('BEGIN:VCARD').filter(section => section.trim());
return vcards.map(section => {
const vcard = new VCard();
vcard.parse('BEGIN:VCARD' + section);
const vcard = parseVCard('BEGIN:VCARD' + section);
// Extract contact properties with proper type handling
const uid = vcard.getProperty('UID')?.value;
const fullName = vcard.getProperty('FN')?.value;
const email = vcard.getProperty('EMAIL')?.value;
const phone = vcard.getProperty('TEL')?.value;
const organization = vcard.getProperty('ORG')?.value;
const address = vcard.getProperty('ADR')?.value;
const notes = vcard.getProperty('NOTE')?.value;
const group = vcard.getProperty('CATEGORIES')?.value;
const uid = vcard.uid?.[0]?.value;
const fullName = vcard.fn?.[0]?.value;
const email = vcard.email?.[0]?.value;
const phone = vcard.tel?.[0]?.value;
const organization = vcard.org?.[0]?.value;
const address = vcard.adr?.[0]?.value;
const notes = vcard.note?.[0]?.value;
const group = vcard.categories?.[0]?.value;
// Create a clean contact object
const contact: Contact = {
@ -210,7 +209,7 @@ export default function CarnetPage() {
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);
const contacts = parseVCardContent(content);
setContacts(contacts.map(contact => ({
...contact,
group: folder.replace('.vcf', '')
@ -230,7 +229,7 @@ export default function CarnetPage() {
const contentResponse = await fetch(`/api/nextcloud/files/content?path=${encodeURIComponent(file.filename)}`);
if (contentResponse.ok) {
const { content } = await contentResponse.json();
const contacts = parseVCard(content);
const contacts = parseVCardContent(content);
return contacts.map(contact => ({
...contact,
group: file.basename.replace('.vcf', '')
@ -394,7 +393,7 @@ export default function CarnetPage() {
}
const { content } = await response.json();
const contacts = parseVCard(content);
const contacts = parseVCardContent(content);
// Update or add the contact
const existingIndex = contacts.findIndex(c => c.id === contact.id);
@ -405,7 +404,7 @@ export default function CarnetPage() {
}
// Generate new VCF content
const vcfContent = contacts.map(c => generateVCard(c)).join('\n');
const vcfContent = contacts.map(c => generateVCardContent(c)).join('\n');
// Save the updated VCF file
const saveResponse = await fetch('/api/nextcloud/files', {
@ -455,13 +454,13 @@ export default function CarnetPage() {
}
const { content } = await response.json();
const contacts = parseVCard(content);
const contacts = parseVCardContent(content);
// Remove the contact
const updatedContacts = contacts.filter(c => c.id !== contact.id);
// Generate new VCF content
const vcfContent = updatedContacts.map(c => generateVCard(c)).join('\n');
const vcfContent = updatedContacts.map(c => generateVCardContent(c)).join('\n');
// Save the updated VCF file
const saveResponse = await fetch('/api/nextcloud/files', {
@ -492,22 +491,20 @@ export default function CarnetPage() {
}
};
const generateVCard = (contact: Contact): string => {
const vcard = new VCard();
// Ensure required fields are not undefined
vcard.setProperty('UID', contact.id || Math.random().toString(36).substr(2, 9));
vcard.setProperty('FN', contact.fullName || 'Unknown Contact');
// Add optional fields only if they have values
if (contact.email) vcard.setProperty('EMAIL', contact.email);
if (contact.phone) vcard.setProperty('TEL', contact.phone);
if (contact.organization) vcard.setProperty('ORG', contact.organization);
if (contact.address) vcard.setProperty('ADR', contact.address);
if (contact.notes) vcard.setProperty('NOTE', contact.notes);
if (contact.group) vcard.setProperty('CATEGORIES', contact.group);
return vcard.toString();
const generateVCardContent = (contact: Contact): string => {
const vcard = {
version: '3.0',
uid: contact.id,
fn: contact.fullName,
email: contact.email ? [{ value: contact.email }] : undefined,
tel: contact.phone ? [{ value: contact.phone }] : undefined,
org: contact.organization ? [{ value: contact.organization }] : undefined,
adr: contact.address ? [{ value: contact.address }] : undefined,
note: contact.notes ? [{ value: contact.notes }] : undefined,
categories: contact.group ? [{ value: contact.group }] : undefined
};
return formatVCard(vcard);
};
if (isLoading) {