carnet panel contact

This commit is contained in:
alma 2025-04-20 19:38:17 +02:00
parent a654994b1f
commit ef842a15d6
2 changed files with 76 additions and 77 deletions

View File

@ -31,8 +31,8 @@ interface Note {
interface Contact { interface Contact {
id: string; id: string;
fullName: string; fullName?: string;
email: string; email?: string;
phone?: string; phone?: string;
organization?: string; organization?: string;
address?: string; address?: string;
@ -132,51 +132,33 @@ export default function CarnetPage() {
}, [isSmallScreen, isMediumScreen]); }, [isSmallScreen, isMediumScreen]);
useEffect(() => { useEffect(() => {
const fetchNotes = async () => { if (selectedFolder === 'Contacts') {
try { // When "Contacts" is selected, show all contacts
setIsLoadingNotes(true); fetchContacts('Contacts');
const response = await fetch(`/api/nextcloud/files?folder=${selectedFolder}`); } else if (selectedFolder.endsWith('.vcf')) {
if (!response.ok) { // When a specific VCF file is selected, show its contacts
throw new Error('Failed to fetch notes'); fetchContacts(selectedFolder);
} } else {
const data = await response.json(); // For other folders (Notes, etc.), fetch notes
if (selectedFolder === 'Contacts') { const fetchNotes = async () => {
// For contacts, parse the VCF files try {
const parsedContacts = await Promise.all( setIsLoadingNotes(true);
data.map(async (file: any) => { const response = await fetch(`/api/nextcloud/files?folder=${selectedFolder}`);
try { if (!response.ok) {
// Use the full filename for fetching content throw new Error('Failed to fetch notes');
const contentResponse = await fetch(`/api/nextcloud/files/content?path=${encodeURIComponent(file.filename)}`); }
if (contentResponse.ok) { const data = await response.json();
const content = await contentResponse.text();
return parseVCard(content);
}
console.error('Failed to fetch VCF content:', contentResponse.status);
return null;
} catch (error) {
console.error('Error fetching VCF content:', error);
return null;
}
})
);
setContacts(parsedContacts.filter(Boolean));
} else {
setNotes(data); setNotes(data);
} } catch (error) {
} catch (error) { console.error('Error fetching notes:', error);
console.error('Error fetching data:', error);
if (selectedFolder === 'Contacts') {
setContacts([]);
} else {
setNotes([]); setNotes([]);
} finally {
setIsLoadingNotes(false);
} }
} finally { };
setIsLoadingNotes(false); fetchNotes();
} }
}; }, [selectedFolder, session?.user?.id]);
fetchNotes();
}, [selectedFolder]);
const parseVCard = (content: string): Contact[] => { const parseVCard = (content: string): Contact[] => {
try { try {
@ -277,39 +259,52 @@ export default function CarnetPage() {
const fetchContacts = async (folder: string) => { const fetchContacts = async (folder: string) => {
try { try {
setIsLoadingContacts(true); setIsLoadingContacts(true);
const response = await fetch(`/api/nextcloud/files?folder=${folder}`); // First, check if we're looking at a specific VCF file
if (response.ok) { if (folder.endsWith('.vcf')) {
const files = await response.json(); const response = await fetch(`/api/nextcloud/files/content?path=${encodeURIComponent(`/files/cube-${session?.user?.id}/Private/Contacts/${folder}`)}`);
const vcfFiles = files.filter((file: any) => file.basename.endsWith('.vcf')); if (response.ok) {
const { content } = await response.json();
// Parse VCF files and extract contact information const contacts = parseVCard(content);
const parsedContacts = await Promise.all( setContacts(contacts.map(contact => ({
vcfFiles.map(async (file: any) => { ...contact,
try { group: folder.replace('.vcf', '')
// Construct the full WebDAV path })));
const webdavPath = `/files/${file.filename}`; }
const contentResponse = await fetch(`/api/nextcloud/files/content?path=${encodeURIComponent(webdavPath)}`); } else {
if (contentResponse.ok) { // If not a VCF file, list all VCF files in the folder
const content = await contentResponse.text(); const response = await fetch(`/api/nextcloud/files?folder=${folder}`);
const contacts = parseVCard(content); if (response.ok) {
return contacts.map(contact => ({ const files = await response.json();
...contact, const vcfFiles = files.filter((file: any) => file.basename.endsWith('.vcf'));
group: folder
})); // 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 [];
} }
return []; })
} catch (error) { );
console.error('Error fetching VCF content:', error);
return []; // Flatten the array of contact arrays
} setContacts(parsedContacts.flat().filter(Boolean));
}) }
);
// Flatten the array of contact arrays
setContacts(parsedContacts.flat().filter(Boolean));
} }
} catch (error) { } catch (error) {
console.error('Error fetching contacts:', error); console.error('Error fetching contacts:', error);
setContacts([]);
} finally { } finally {
setIsLoadingContacts(false); setIsLoadingContacts(false);
} }

View File

@ -5,8 +5,8 @@ import { Search, User, Mail, Phone, Building, MapPin, ChevronRight } from 'lucid
interface Contact { interface Contact {
id: string; id: string;
fullName: string; fullName?: string;
email: string; email?: string;
phone?: string; phone?: string;
organization?: string; organization?: string;
address?: string; address?: string;
@ -76,8 +76,12 @@ export const ContactsView: React.FC<ContactsViewProps> = ({
<User className="h-5 w-5 text-primary" /> <User className="h-5 w-5 text-primary" />
</div> </div>
<div> <div>
<div className="font-medium text-carnet-text-primary">{contact.fullName}</div> <div className="font-medium text-carnet-text-primary">
<div className="text-sm text-carnet-text-muted">{contact.email}</div> {contact.fullName || contact.email || 'Sans nom'}
</div>
{contact.email && (
<div className="text-sm text-carnet-text-muted">{contact.email}</div>
)}
</div> </div>
</div> </div>
<ChevronRight className="h-4 w-4 text-carnet-text-muted" /> <ChevronRight className="h-4 w-4 text-carnet-text-muted" />