Files
webmail/components/settings/contacts-settings.tsx
T
Linus Rath cf2c27157d Merge branch 'main' into feat/stalwart-1.0
# Conflicts:
#	components/contacts/contacts-app.tsx
#	components/email/__tests__/composer-discard.test.tsx
#	components/email/calendar-invitation-banner.tsx
#	components/email/email-composer.tsx
#	components/mail/mail-app.tsx
#	components/pro/pro-compose-tab-body.tsx
#	components/pro/pro-email-tab-body.tsx
#	components/ui/__tests__/avatar.test.tsx
#	components/ui/avatar.tsx
#	hooks/use-mailbox-drop.ts
#	lib/__tests__/calendar-alerts.test.ts
#	lib/__tests__/jmap-calendar-tasks.test.ts
#	lib/__tests__/jmap-send-threading.test.ts
#	lib/demo/demo-client.ts
#	lib/demo/fixtures/calendars.ts
#	lib/jmap/client-interface.ts
#	lib/jmap/client.ts
#	lib/web-push.ts
#	stores/__tests__/contact-store.test.ts
#	stores/__tests__/email-store-thread-key.test.ts
#	stores/calendar-store.ts
#	stores/contact-store.ts
#	stores/email-store.ts
2026-10-26 10:14:12 +01:00

113 lines
3.7 KiB
TypeScript

"use client";
import { useState, useCallback } from "react";
import { useTranslations } from "next-intl";
import { Upload, Download, Loader2 } from "@/components/icons";
import { Button } from "@/components/ui/button";
import { SettingsSection, SettingItem, ToggleSwitch } from "./settings-section";
import { ContactImportDialog } from "@/components/contacts/contact-import-dialog";
import { exportContacts, useContactExportBusy } from "@/components/contacts/contact-export";
import { useContactStore } from "@/stores/contact-store";
import { useAuthStore } from "@/stores/auth-store";
import { useSettingsStore } from "@/stores/settings-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 groupContactsByLetter = useSettingsStore((s) => s.groupContactsByLetter);
const sortContactsByLastName = useSettingsStore((s) => s.sortContactsByLastName);
const updateSetting = useSettingsStore((s) => s.updateSetting);
const [showImport, setShowImport] = useState(false);
const exporting = useContactExportBusy();
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 = async () => {
if (individuals.length > 0 && await 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
id="contacts"
title={tSettings("title")}
description={tSettings("description")}
>
<SettingItem
label={tSettings("group_by_letter_label")}
description={tSettings("group_by_letter_description")}
>
<ToggleSwitch
checked={groupContactsByLetter}
onChange={(checked) => updateSetting("groupContactsByLetter", checked)}
/>
</SettingItem>
<SettingItem
label={tSettings("sort_by_last_name_label")}
description={tSettings("sort_by_last_name_description")}
>
<ToggleSwitch
checked={sortContactsByLastName}
onChange={(checked) => updateSetting("sortContactsByLastName", checked)}
/>
</SettingItem>
<SettingItem
label={tSettings("import_label")}
description={tSettings("import_description")}
>
<Button variant="outline" size="sm" onClick={() => setShowImport(true)}>
<Upload className="w-4 h-4 me-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 || exporting}
aria-busy={exporting}
>
{exporting
? <Loader2 className="w-4 h-4 me-2 animate-spin" />
: <Download className="w-4 h-4 me-2" />}
{exporting ? t("export.exporting") : t("export.title")}
</Button>
</SettingItem>
</SettingsSection>
);
}