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