diff --git a/src/pages/customers/List.tsx b/src/pages/customers/List.tsx index 618fae9..60d2889 100644 --- a/src/pages/customers/List.tsx +++ b/src/pages/customers/List.tsx @@ -1,29 +1,36 @@ import Table from '@/components/Table' -import Filters, { type FilterValues, type FieldType } from '@/components/Filters' -import { type FC, useState, useMemo, useCallback } from 'react' +import Filters, { type FieldType } from '@/components/Filters' +import { type FC, useMemo } from 'react' import { useGetUsers } from './hooks/useUsersData' -import type { Customer, CustomerListRow } from '@/pages/customers/types/Types' +import { useCustomerFilters } from './hooks/useCustomerFilters' +import type { CustomerListRow, UserRestaurant } from '@/pages/customers/types/Types' import { formatOptionalDate, formatFaNumber } from '@/helpers/func' -const mapCustomerToRow = (customer: Customer): CustomerListRow => { - const fullName = [customer.firstName, customer.lastName].filter(Boolean).join(' ').trim() +const mapUserRestaurantToRow = (userRestaurant: UserRestaurant): CustomerListRow => { + const { user, orderCount, totalOrderAmount } = userRestaurant + const fullName = [user.firstName, user.lastName].filter(Boolean).join(' ').trim() return { - id: customer.id, + id: user.id, fullName: fullName || 'بدون نام', - phone: customer.phone || '-', - birthDate: formatOptionalDate(customer.birthDate), - marriageDate: formatOptionalDate(customer.marriageDate), - wallet: formatFaNumber(customer.wallet), - points: formatFaNumber(customer.points), - status: customer.isActive ? 'فعال' : 'غیرفعال', + phone: user.phone || '-', + birthDate: formatOptionalDate(user.birthDate), + marriageDate: formatOptionalDate(user.marriageDate), + orderCount: formatFaNumber(orderCount), + totalOrderAmount: formatFaNumber(totalOrderAmount), + status: user.isActive !== false ? 'فعال' : 'غیرفعال', } } const CustomersList: FC = () => { - const { data: usersData, isLoading } = useGetUsers() - const [filters, setFilters] = useState({ search: '', status: 'all' }) - const [currentPage, setCurrentPage] = useState(1) - const limit = 10 + const { + filters, + currentPage, + apiParams, + handleFiltersChange, + handlePageChange, + } = useCustomerFilters() + + const { data: usersData, isLoading } = useGetUsers(apiParams) const filterFields = useMemo(() => [ { @@ -31,49 +38,15 @@ const CustomersList: FC = () => { name: 'search', placeholder: 'نام یا شماره تماس', }, - { - type: 'select', - name: 'status', - placeholder: 'انتخاب وضعیت', - defaultValue: 'all', - options: [ - { label: 'همه وضعیت‌ها', value: 'all' }, - { label: 'فعال', value: 'active' }, - { label: 'غیرفعال', value: 'inactive' }, - ], - }, ], []) - const customers = useMemo(() => usersData?.data ?? [], [usersData]) + const userRestaurants = usersData?.data ?? [] + const tableData = useMemo( + () => userRestaurants.map(mapUserRestaurantToRow), + [userRestaurants], + ) - const filteredCustomers = useMemo(() => { - const searchValue = (filters.search as string || '').toLowerCase().trim() - const statusFilter = filters.status || 'all' - - return customers.filter((customer) => { - const fullName = [customer.firstName, customer.lastName].filter(Boolean).join(' ').toLowerCase().trim() - const matchesSearch = - searchValue === '' || - fullName.includes(searchValue) || - (customer.phone || '').includes(searchValue) - - const matchesStatus = - statusFilter === 'all' || - (statusFilter === 'active' && customer.isActive) || - (statusFilter === 'inactive' && !customer.isActive) - - return matchesSearch && matchesStatus - }) - }, [customers, filters]) - - const totalPages = Math.max(1, Math.ceil(filteredCustomers.length / limit) || 1) - - const paginatedCustomers = useMemo(() => { - const startIndex = (currentPage - 1) * limit - return filteredCustomers.slice(startIndex, startIndex + limit) - }, [filteredCustomers, currentPage, limit]) - - const tableData = useMemo(() => paginatedCustomers.map(mapCustomerToRow), [paginatedCustomers]) + const totalPages = usersData?.meta?.totalPages || 1 const columns = useMemo(() => [ { @@ -93,12 +66,12 @@ const CustomersList: FC = () => { title: 'تاریخ ازدواج', }, { - key: 'wallet', - title: 'کیف پول (تومان)', + key: 'orderCount', + title: 'تعداد سفارش', }, { - key: 'points', - title: 'امتیاز', + key: 'totalOrderAmount', + title: 'مجموع سفارش (تومان)', }, { key: 'status', @@ -117,27 +90,10 @@ const CustomersList: FC = () => { }, ], []) - const handlePageChange = (page: number) => { - setCurrentPage(page) - } - - const handleFiltersChange = useCallback((newFilters: FilterValues) => { - setFilters(newFilters) - setCurrentPage(1) - }, []) - return (

لیست مشتریان

- {/* - - */}
@@ -164,4 +120,4 @@ const CustomersList: FC = () => { ) } -export default CustomersList \ No newline at end of file +export default CustomersList diff --git a/src/pages/customers/hooks/useCustomerFilters.ts b/src/pages/customers/hooks/useCustomerFilters.ts new file mode 100644 index 0000000..cedd17b --- /dev/null +++ b/src/pages/customers/hooks/useCustomerFilters.ts @@ -0,0 +1,43 @@ +import { useState, useMemo } from "react"; +import type { FilterValues } from "@/components/Filters"; +import type { GetUsersParams } from "../types/Types"; + +const DEFAULT_PAGE = 1; +const DEFAULT_LIMIT = 10; + +export const useCustomerFilters = () => { + const [filters, setFilters] = useState({}); + const [currentPage, setCurrentPage] = useState(DEFAULT_PAGE); + const [limit] = useState(DEFAULT_LIMIT); + + const apiParams = useMemo(() => { + const params: GetUsersParams = { + page: currentPage, + limit, + }; + + if (filters.search) { + params.search = filters.search as string; + } + + return params; + }, [filters, currentPage, limit]); + + const handleFiltersChange = (newFilters: FilterValues) => { + setFilters(newFilters); + setCurrentPage(DEFAULT_PAGE); + }; + + const handlePageChange = (page: number) => { + setCurrentPage(page); + }; + + return { + filters, + currentPage, + apiParams, + handleFiltersChange, + handlePageChange, + limit, + }; +}; diff --git a/src/pages/customers/hooks/useUsersData.ts b/src/pages/customers/hooks/useUsersData.ts index 515b10c..89294ed 100644 --- a/src/pages/customers/hooks/useUsersData.ts +++ b/src/pages/customers/hooks/useUsersData.ts @@ -1,9 +1,10 @@ import * as api from "../service/UsersService"; import { useQuery } from "@tanstack/react-query"; +import type { GetUsersParams } from "../types/Types"; -export const useGetUsers = () => { +export const useGetUsers = (params?: GetUsersParams) => { return useQuery({ - queryKey: ["users"], - queryFn: api.getUsers, + queryKey: ["users", params], + queryFn: () => api.getUsers(params), }); }; diff --git a/src/pages/customers/service/UsersService.ts b/src/pages/customers/service/UsersService.ts index de42b17..c72788b 100644 --- a/src/pages/customers/service/UsersService.ts +++ b/src/pages/customers/service/UsersService.ts @@ -1,7 +1,12 @@ import axios from "@/config/axios"; -import type { GetCustomersResponse } from "@/pages/customers/types/Types"; +import type { + GetCustomersResponse, + GetUsersParams, +} from "@/pages/customers/types/Types"; -export const getUsers = async () => { - const { data } = await axios.get(`/admin/users`); +export const getUsers = async (params?: GetUsersParams) => { + const { data } = await axios.get(`/admin/users`, { + params, + }); return data; }; diff --git a/src/pages/customers/types/Types.ts b/src/pages/customers/types/Types.ts index 040f893..e532531 100644 --- a/src/pages/customers/types/Types.ts +++ b/src/pages/customers/types/Types.ts @@ -1,32 +1,57 @@ import type { IResponse } from "@/types/response.types"; import type { RowDataType } from "@/components/types/TableTypes"; -export interface Customer { +export type User = { id: string; createdAt: string; updatedAt: string; deletedAt: string | null; - restaurant: string; firstName: string; - lastName: string; + lastName?: string; phone: string; - birthDate: string; - marriageDate: string; - referrer: string | null; - isActive: boolean; - gender: boolean; - wallet: number; - points: number; -} + birthDate?: string; + marriageDate?: string; + referrer?: string | null; + isActive?: boolean; + gender?: boolean; +}; -export type GetCustomersResponse = IResponse; +export type UserRestaurant = { + id: string; + createdAt: string; + updatedAt: string; + deletedAt: string | null; + user: User; + restaurant: string; + orderCount: number; + totalOrderAmount: number; +}; + +export type PaginationMeta = { + total: number; + page: number; + limit: number; + totalPages: number; +}; + +export type GetUsersParams = { + page?: number; + limit?: number; + search?: string; + orderBy?: string; + order?: "asc" | "desc"; +}; + +export type GetCustomersResponse = IResponse & { + meta: PaginationMeta; +}; export type CustomerListRow = RowDataType & { fullName: string; phone: string; birthDate: string; marriageDate: string; - wallet: string; - points: string; + orderCount: string; + totalOrderAmount: string; status: string; };