import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
CircleX,
Copy,
Pencil,
Save,
Building2,
UserCircle,
Mail,
FileText,
} from "lucide-react";
import {
Form,
useDataProvider,
useGetIdentity,
useGetOne,
useNotify,
useTranslate,
} from "ra-core";
import { useState } from "react";
import { useFormState } from "react-hook-form";
import { useNavigate } from "react-router";
import { RecordField } from "@/components/ds/admin/record-field";
import { TextInput } from "@/components/ds/admin/text-input";
import { Button } from "@/components/ds/ui/button";
import { Card, CardContent } from "@/components/ds/ui/card";
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ds/ui/tabs";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ds/ui/tooltip";
import ImageEditorField from "../misc/ImageEditorField";
import type { CrmDataProvider } from "../providers/types";
import type { SalesFormData } from "../types";
import { TemplatesList } from "../invoices/TemplatesList";
import { isDemoMode } from "@/lib/demo-utils";
import { Alert, AlertDescription } from "@/components/ds/ui/alert";
import { Info, Brain } from "lucide-react";
import { AgentToggle } from "./AgentToggle";
export const SettingsPage = () => {
const translate = useTranslate();
return (
{translate("crm.nav.settings")}
{translate("crm.settings.section.profile") || "Profile"}
{translate("crm.settings.section.organization") || "Organization"}
{translate("resources.invoice_templates.name", {
smart_count: 2,
}) || "Templates"}
);
};
const ProfileSettings = () => {
const [isEditMode, setEditMode] = useState(false);
const { identity, refetch: refetchIdentity } = useGetIdentity();
const { data, refetch: refetchUser } = useGetOne("sales", {
id: identity?.id,
});
const notify = useNotify();
const translate = useTranslate();
const dataProvider = useDataProvider();
const { mutate } = useMutation({
mutationKey: ["profile-update"],
mutationFn: async (data: SalesFormData) => {
if (!identity) throw new Error("Identity not found");
return dataProvider.salesUpdate(identity.id, data);
},
onSuccess: () => {
refetchIdentity();
refetchUser();
setEditMode(false);
notify(translate("crm.settings.notification.profile_updated"));
},
onError: () => {
notify(translate("crm.settings.notification.error"), { type: "error" });
},
});
if (!identity) return null;
return (
);
};
const OrganizationSettings = () => {
const [isEditMode, setEditMode] = useState(false);
const notify = useNotify();
const translate = useTranslate();
const dataProvider = useDataProvider();
const queryClient = useQueryClient();
const {
data: businessProfile,
isLoading,
refetch,
} = useQuery({
queryKey: ["business_profile"],
queryFn: async () => {
const { data } = await dataProvider.getOne("business_profile", { id: 1 });
return data;
},
});
const { mutate } = useMutation({
mutationFn: async (values: any) => {
return dataProvider.update("business_profile", {
id: 1,
data: values,
previousData: businessProfile,
});
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["business_profile"] });
refetch();
setEditMode(false);
notify(
translate("resources.business_profile.notification.updated") ||
"Organization profile updated",
);
},
onError: (error: any) => {
notify(error.message || "Error updating organization profile", {
type: "error",
});
},
});
if (isLoading) return Loading...
;
return (
);
};
// Sub-components
const PasswordChangeButton = () => {
const translate = useTranslate();
const navigate = useNavigate();
const isDemo = isDemoMode();
return (
{isDemo && (
Password changes are disabled in demo mode
)}
);
};
const SaveButton = () => {
const translate = useTranslate();
const { isDirty } = useFormState();
return (
);
};
const TextRender = ({
source,
label,
isEditMode,
multiline = false,
rows = 1,
helperText,
type = "text",
disabled = false,
}: {
source: string;
label: string;
isEditMode: boolean;
multiline?: boolean;
rows?: number;
helperText?: string;
type?: "text" | "password";
disabled?: boolean;
}) => {
if (isEditMode) {
return (
);
}
return (
);
};
const CopyPaste = ({ value }: { value: string }) => {
const [copied, setCopied] = useState(false);
const translate = useTranslate();
const handleCopy = () => {
setCopied(true);
navigator.clipboard.writeText(value);
setTimeout(() => setCopied(false), 1500);
};
return (
{copied
? "Copied!"
: translate("crm.integrations.api_keys.action.copy")}
);
};
SettingsPage.path = "/settings";