import { useMutation } from "@tanstack/react-query";
import { KeyRound, MoreHorizontal, RefreshCw } from "lucide-react";
import * as React from "react";
import {
useDataProvider,
useGetIdentity,
useListContext,
useNotify,
useRecordContext,
useRefresh,
useTranslate,
} from "ra-core";
import { CreateButton } from "@/components/ds/admin/create-button";
import { DataTable } from "@/components/ds/admin/data-table";
import { ExportButton } from "@/components/ds/admin/export-button";
import { List } from "@/components/ds/admin/list";
import { SearchInput } from "@/components/ds/admin/search-input";
import { Badge } from "@/components/ds/ui/badge";
import { Button } from "@/components/ds/ui/button";
import { Card } from "@/components/ds/ui/card";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ds/ui/dialog";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ds/ui/dropdown-menu";
import { Skeleton } from "@/components/ds/ui/skeleton";
import { TopToolbar } from "../layout/TopToolbar";
import useAppBarHeight from "../misc/useAppBarHeight";
import type { CrmDataProvider } from "../providers/types";
const SalesListActions = () => {
const translate = useTranslate();
return (
);
};
const filters = [];
const OptionsField = (_props: { label?: string | boolean }) => {
const record = useRecordContext();
const translate = useTranslate();
if (!record) return null;
return (
{record.administrator && (
{translate("crm.user.field.administrator")}
)}
{record.disabled && (
{translate("crm.user.field.disabled")}
)}
);
};
const RowActions = () => {
const record = useRecordContext();
const dataProvider = useDataProvider();
const notify = useNotify();
const refresh = useRefresh();
const translate = useTranslate();
const [inviteDialogOpen, setInviteDialogOpen] = React.useState(false);
const [resetDialogOpen, setResetDialogOpen] = React.useState(false);
const { mutate: resendInvite, isPending: isInvitePending } = useMutation({
mutationFn: async () => {
return dataProvider.resendInvite(record.id);
},
onSuccess: () => {
notify(translate("crm.user.notification.invite_sent"));
setInviteDialogOpen(false);
refresh();
},
onError: () => {
notify(translate("crm.user.notification.invite_error"), {
type: "error",
});
setInviteDialogOpen(false);
},
});
const { mutate: resetPassword, isPending: isResetPending } = useMutation({
mutationFn: async () => {
return dataProvider.resetPassword(record.id);
},
onSuccess: () => {
notify(translate("crm.user.notification.reset_sent"));
setResetDialogOpen(false);
refresh();
},
onError: () => {
notify(translate("crm.user.notification.reset_error"), { type: "error" });
setResetDialogOpen(false);
},
});
if (!record) return null;
// Determine which action to show based on confirmation status
const isConfirmed = record.email_confirmed_at !== null;
const isDisabled = record.disabled === true;
return (
<>
{translate("crm.user.field.email_actions")}
{!isConfirmed && (
{
e.preventDefault();
e.stopPropagation();
setInviteDialogOpen(true);
}}
>
{translate("crm.user.action.resend_invite")}
)}
{isConfirmed && !isDisabled && (
setResetDialogOpen(true)}>
{translate("crm.user.action.send_password_reset")}
)}
{/* Resend Invite Dialog */}
{/* Password Reset Dialog */}
>
);
};
export function SalesList() {
return (
}
sort={{ field: "first_name", order: "ASC" }}
>
);
}
const SalesListLayout = () => {
const { data, isPending, filterValues } = useListContext();
const { identity } = useGetIdentity();
const hasFilters = filterValues && Object.keys(filterValues).length > 0;
// Show loading skeleton while identity or data is loading
if (!identity || isPending) {
return (
);
}
// Show empty state when no data
if (!data?.length && !hasFilters) {
return ;
}
return (
);
};
const SalesEmpty = () => {
const appbarHeight = useAppBarHeight();
const translate = useTranslate();
return (
{translate("crm.user.empty.title")}
{translate("crm.user.empty.description")}
);
};