Files
tm_panel/src/components/Tables/customers/useCustomerListPresenter.ts
T
AmirReza Jamali 72948a9b55 feat(dashboard): add daily trend chart and statistics section to dashboard
- Introduced DailyTrendChart component for visualizing daily scraped TED notices, documents, and translated notices.
- Implemented StatisticsSection to display key metrics with animated counters and a days selector for data range.
- Created utility function to convert API data into labeled points for chart rendering.
- Updated dashboard index to include the new StatisticsSection, enhancing overall dashboard functionality and user experience.
- Refactored existing trends chart to utilize the new DailyPoint type for consistency in data handling.
2026-06-07 12:39:15 +03:30

235 lines
6.4 KiB
TypeScript

"use client";
import { SortDirection } from "@/components/ui/tableSortContext";
import {
useAssignCompany,
useCompanyFullList,
useCustomersQuery,
useDeleteCustomerQuery,
useResetCustomerPassword,
} from "@/hooks/queries";
import { useHybridPagination } from "@/hooks/useHybridPagination";
import { useTableSectionRowAnimations } from "@/hooks/useTableSectionRowAnimations";
import { TAssignCustomerToCompanyCredentials, TCustomer } from "@/lib/api";
import { apiDefaultParams } from "@/constants/Api_Params";
import { buildQueryString, deleteEmptyKeys } from "@/utils/shared";
import { useIsMutating } from "@tanstack/react-query";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useForm } from "react-hook-form";
const useCustomerListPresenter = () => {
const [isAssignCompanyModalOpen, setIsAssignCompanyModalOpen] =
useState(false);
const [selectedCompanies, setSelectedCompanies] = useState<
TAssignCustomerToCompanyCredentials | undefined
>();
const [currentCustomer, setCurrentCustomer] = useState<TCustomer | null>(
null,
);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isResetPasswordModalOpen, setIsResetPasswordModalOpen] =
useState(false);
const [generatedPassword, setGeneratedPassword] = useState<string | null>(
null,
);
const pathName = usePathname();
const searchParams = useSearchParams();
const [params, setParams] = useState<Record<string, any>>({
...apiDefaultParams,
});
const router = useRouter();
const isMutating = useIsMutating();
const {
register: filterRegister,
handleSubmit: handleFilterSubmit,
reset: filterFormReset,
watch,
setValue: setFilterValue,
} = useForm();
const tableSectionRef = useRef<HTMLDivElement>(null);
const skeletonTbodyRef = useRef<HTMLTableSectionElement>(null);
const dataTbodyRef = useRef<HTMLTableSectionElement>(null);
useEffect(() => {
const newParams: Record<string, any> = {
...apiDefaultParams,
offset: 0,
limit: 10,
};
for (const [key, value] of searchParams.entries()) {
newParams[key] = value;
}
setParams(newParams);
filterFormReset(newParams);
}, [searchParams, filterFormReset]);
const { data, isPending, isError, error } = useCustomersQuery(params);
const { pagination, handlePaginationChange, buildFirstPageParams } =
useHybridPagination({
meta: data?.meta,
params,
setParams,
isError,
error,
});
useTableSectionRowAnimations(isPending, data, {
tableSectionRef,
skeletonTbodyRef,
dataTbodyRef,
});
const assignCompanyCompaniesQuery = useCompanyFullList({
enabled: isAssignCompanyModalOpen,
});
const { mutate: deleteCustomer } = useDeleteCustomerQuery(() =>
setIsModalOpen(false),
);
const { mutate: assignSelectedCompanies } = useAssignCompany(
currentCustomer?.id ?? "",
() => {
setIsAssignCompanyModalOpen(false);
},
);
const { mutate: resetCustomerPassword, isPending: isResettingPassword } =
useResetCustomerPassword({
successCallback: (password) => setGeneratedPassword(password),
});
const openResetPasswordModalForCustomer = useCallback(
(customer: TCustomer) => {
setCurrentCustomer(customer);
setGeneratedPassword(null);
setIsResetPasswordModalOpen(true);
resetCustomerPassword(customer.id);
},
[resetCustomerPassword],
);
const closeResetPasswordModal = useCallback(() => {
setIsResetPasswordModalOpen(false);
setGeneratedPassword(null);
}, []);
const search = (formData: any) => {
const newParams = buildFirstPageParams({ ...params, ...formData });
const cleanedParams = deleteEmptyKeys(newParams);
const queryString = new URLSearchParams(cleanedParams).toString();
router.push(`${pathName}?${queryString}`);
};
const clearAllFilters = useCallback(() => {
filterFormReset({ status: undefined, role: undefined, type: undefined });
router.push(pathName);
}, [pathName, router, filterFormReset]);
const columns = [
"row",
"full name",
"email",
"created at",
"type",
"status",
"company",
"role",
"actions",
];
const onConfirmDelete = () => {
if (currentCustomer) {
deleteCustomer(currentCustomer.id);
}
};
/** Column label → BSON `sort_by` field. */
const columnSortKeys: Record<string, string> = {
"full name": "full_name",
email: "email",
"created at": "created_at",
type: "type",
status: "status",
role: "role",
};
/** First-click direction per column. */
const columnDefaultOrder: Record<string, SortDirection> = {
"full name": "asc",
email: "asc",
type: "asc",
role: "asc",
"created at": "desc",
};
const sortBy = (params.sort_by as string) ?? "created_at";
const sortOrder = (params.sort_order as SortDirection) ?? "desc";
const handleSortChange = useCallback(
(key: string, order: SortDirection) => {
const newParams = buildFirstPageParams({
...params,
sort_by: key,
sort_order: order,
});
const cleanedParams = deleteEmptyKeys(newParams);
const queryString = buildQueryString(cleanedParams);
router.push(`${pathName}?${queryString}`);
},
[buildFirstPageParams, params, pathName, router],
);
const customers = data?.data?.customers ?? [];
const shouldShowPagination =
!isPending && (data?.meta?.pages ?? 1) * (data?.meta?.limit ?? 10) > 10;
return {
allCustomers: customers,
metadata: data?.meta,
currentCustomer,
columns,
columnSortKeys,
columnDefaultOrder,
sortBy,
sortOrder,
handleSortChange,
isPending,
setCurrentCustomer,
selectedCompanies,
setSelectedCompanies,
onConfirmDelete,
setIsAssignCompanyModalOpen,
isAssignCompanyModalOpen,
assignSelectedCompanies,
pathName,
router,
isModalOpen,
setIsModalOpen,
filterRegister,
handleFilterSubmit,
search,
watch,
setFilterValue,
isMutating,
setParams,
assignCompanyCompaniesQuery,
shouldShowPagination,
clearAllFilters,
tableSectionRef,
skeletonTbodyRef,
dataTbodyRef,
pagination,
handlePaginationChange,
isResetPasswordModalOpen,
closeResetPasswordModal,
openResetPasswordModalForCustomer,
generatedPassword,
isResettingPassword,
};
};
export default useCustomerListPresenter;