feat: add contacts settings with import/export functionality and update UI components
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Search, Plus, BookUser, Info, Check, Trash2, Users, Download, X, UserPlus, Upload } from "lucide-react";
|
||||
import { Search, Plus, BookUser, Info, Check, Trash2, Users, Download, X, UserPlus } from "lucide-react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ContactListItem } from "./contact-list-item";
|
||||
@@ -17,7 +17,6 @@ interface ContactListProps {
|
||||
onSearchChange: (query: string) => void;
|
||||
onSelectContact: (id: string) => void;
|
||||
onCreateNew: () => void;
|
||||
onImport?: () => void;
|
||||
supportsSync: boolean;
|
||||
className?: string;
|
||||
selectedContactIds: Set<string>;
|
||||
@@ -36,7 +35,6 @@ export function ContactList({
|
||||
onSearchChange,
|
||||
onSelectContact,
|
||||
onCreateNew,
|
||||
onImport,
|
||||
supportsSync,
|
||||
className,
|
||||
selectedContactIds,
|
||||
@@ -185,12 +183,6 @@ export function ContactList({
|
||||
<UserPlus className="w-4 h-4 mr-1.5" />
|
||||
{t("create_new")}
|
||||
</Button>
|
||||
{onImport && (
|
||||
<Button variant="outline" size="sm" onClick={onImport}>
|
||||
<Upload className="w-4 h-4 mr-1.5" />
|
||||
{t("import_vcard")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useCallback } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Upload, Download } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { SettingsSection, SettingItem } from "./settings-section";
|
||||
import { ContactImportDialog } from "@/components/contacts/contact-import-dialog";
|
||||
import { exportContacts } from "@/components/contacts/contact-export";
|
||||
import { useContactStore } from "@/stores/contact-store";
|
||||
import { useAuthStore } from "@/stores/auth-store";
|
||||
import { toast } from "@/stores/toast-store";
|
||||
|
||||
export function ContactsSettings() {
|
||||
const t = useTranslations("contacts");
|
||||
const tSettings = useTranslations("settings.contacts");
|
||||
const { client } = useAuthStore();
|
||||
const {
|
||||
contacts,
|
||||
supportsSync,
|
||||
importContacts,
|
||||
} = useContactStore();
|
||||
const [showImport, setShowImport] = useState(false);
|
||||
|
||||
const individuals = contacts.filter(c => c.kind !== "group");
|
||||
|
||||
const handleImport = useCallback(async (importedContacts: import("@/lib/jmap/types").ContactCard[]) => {
|
||||
return importContacts(
|
||||
supportsSync && client ? client : null,
|
||||
importedContacts
|
||||
);
|
||||
}, [supportsSync, client, importContacts]);
|
||||
|
||||
const handleExport = () => {
|
||||
if (individuals.length > 0) {
|
||||
exportContacts(individuals);
|
||||
toast.success(t("export.success", { count: individuals.length }));
|
||||
}
|
||||
};
|
||||
|
||||
if (showImport) {
|
||||
return (
|
||||
<div className="border border-border rounded-lg overflow-hidden" style={{ minHeight: 400 }}>
|
||||
<ContactImportDialog
|
||||
existingContacts={contacts}
|
||||
onImport={handleImport}
|
||||
onClose={() => setShowImport(false)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsSection
|
||||
title={tSettings("title")}
|
||||
description={tSettings("description")}
|
||||
>
|
||||
<SettingItem
|
||||
label={tSettings("import_label")}
|
||||
description={tSettings("import_description")}
|
||||
>
|
||||
<Button variant="outline" size="sm" onClick={() => setShowImport(true)}>
|
||||
<Upload className="w-4 h-4 mr-2" />
|
||||
{t("import.title")}
|
||||
</Button>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem
|
||||
label={tSettings("export_label")}
|
||||
description={tSettings("export_description")}
|
||||
>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleExport}
|
||||
disabled={individuals.length === 0}
|
||||
>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
{t("export.title")}
|
||||
</Button>
|
||||
</SettingItem>
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user