carnet panel contact
This commit is contained in:
parent
cdc14ec59d
commit
cb44599a4f
@ -43,7 +43,7 @@ interface Contact {
|
|||||||
|
|
||||||
export default function CarnetPage() {
|
export default function CarnetPage() {
|
||||||
const { data: session, status } = useSession();
|
const { data: session, status } = useSession();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [layoutMode, setLayoutMode] = useState<string>("item-selection");
|
const [layoutMode, setLayoutMode] = useState<string>("item-selection");
|
||||||
const [selectedNote, setSelectedNote] = useState<Note | null>(null);
|
const [selectedNote, setSelectedNote] = useState<Note | null>(null);
|
||||||
const [isMobile, setIsMobile] = useState(false);
|
const [isMobile, setIsMobile] = useState(false);
|
||||||
@ -259,30 +259,55 @@ export default function CarnetPage() {
|
|||||||
|
|
||||||
const fetchContacts = async (folder: string) => {
|
const fetchContacts = async (folder: string) => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
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}`);
|
const response = await fetch(`/api/nextcloud/files?folder=${folder}`);
|
||||||
if (!response.ok) {
|
if (response.ok) {
|
||||||
throw new Error('Failed to fetch contacts');
|
const files = await response.json();
|
||||||
}
|
const vcfFiles = files.filter((file: any) => file.basename.endsWith('.vcf'));
|
||||||
const data = await response.json();
|
|
||||||
const vcfFiles = data.files.filter((file: any) => file.filename.endsWith('.vcf'));
|
|
||||||
|
|
||||||
const contacts = await Promise.all(
|
// Parse VCF files and extract contact information
|
||||||
|
const parsedContacts = await Promise.all(
|
||||||
vcfFiles.map(async (file: any) => {
|
vcfFiles.map(async (file: any) => {
|
||||||
|
try {
|
||||||
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) {
|
||||||
throw new Error(`Failed to fetch content for ${file.filename}`);
|
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 [];
|
||||||
}
|
}
|
||||||
const content = await contentResponse.text();
|
|
||||||
return parseVCard(content);
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
setContacts(contacts.flat());
|
// Flatten the array of contact arrays
|
||||||
setIsLoading(false);
|
setContacts(parsedContacts.flat().filter(Boolean));
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching contacts:', 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) => {
|
const handleContactSave = async (contact: Contact) => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
const vcfContent = generateVCard(contact);
|
||||||
const filePath = `/files/cube-${session?.user?.id}/Private/Contacts/${selectedFolder}`;
|
const response = await fetch('/api/nextcloud/files', {
|
||||||
|
|
||||||
// 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', {
|
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: {
|
||||||
body: JSON.stringify({ path: filePath, content: newContent })
|
'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');
|
throw new Error('Failed to save contact');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh contacts list
|
// Refresh contacts list
|
||||||
await fetchContacts(selectedFolder);
|
fetchContacts(selectedFolder);
|
||||||
setIsLoading(false);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error saving contact:', error);
|
console.error('Error saving contact:', error);
|
||||||
setIsLoading(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleContactDelete = async (contact: Contact) => {
|
const handleContactDelete = async (contact: Contact) => {
|
||||||
try {
|
if (!confirm('Êtes-vous sûr de vouloir supprimer ce contact ?')) {
|
||||||
setIsLoading(true);
|
return;
|
||||||
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
|
try {
|
||||||
const existingContacts = currentContent.split('BEGIN:VCARD')
|
const response = await fetch('/api/nextcloud/files', {
|
||||||
.filter(card => card.trim())
|
method: 'DELETE',
|
||||||
.map(card => parseVCard('BEGIN:VCARD' + card))
|
headers: {
|
||||||
.flat();
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
const updatedContacts = existingContacts.filter(c => c.id !== contact.id);
|
body: JSON.stringify({
|
||||||
|
path: `/files/cube-${session?.user?.id}/Private/Contacts/${selectedFolder}`
|
||||||
// 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 })
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!saveResponse.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Failed to delete contact');
|
throw new Error('Failed to delete contact');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh contacts list
|
// Clear selected contact and refresh list
|
||||||
await fetchContacts(selectedFolder);
|
|
||||||
setSelectedContact(null);
|
setSelectedContact(null);
|
||||||
setIsLoading(false);
|
fetchContacts('Contacts');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting contact:', error);
|
console.error('Error deleting contact:', error);
|
||||||
setIsLoading(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -500,17 +489,18 @@ export default function CarnetPage() {
|
|||||||
'BEGIN:VCARD',
|
'BEGIN:VCARD',
|
||||||
'VERSION:3.0',
|
'VERSION:3.0',
|
||||||
`UID:${contact.id}`,
|
`UID:${contact.id}`,
|
||||||
`FN:${contact.fullName}`,
|
'PRODID:-//Infomaniak//Workspace//pim',
|
||||||
contact.email ? `EMAIL;TYPE=INTERNET:${contact.email}` : '',
|
contact.fullName ? `FN:${contact.fullName}` : '',
|
||||||
contact.phone ? `TEL;TYPE=CELL:${contact.phone}` : '',
|
contact.fullName ? `N:${contact.fullName.split(' ').reverse().join(';')};` : '',
|
||||||
contact.organization ? `ORG:${contact.organization}` : '',
|
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.notes ? `NOTE:${contact.notes}` : '',
|
||||||
contact.group ? `CATEGORIES:${contact.group}` : '',
|
|
||||||
'END:VCARD'
|
'END:VCARD'
|
||||||
];
|
].filter(Boolean);
|
||||||
|
|
||||||
return lines.filter(line => line).join('\r\n');
|
return lines.join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user