diff --git a/src/config/Pages.ts b/src/config/Pages.ts
index f018ee0..ba2b4dd 100644
--- a/src/config/Pages.ts
+++ b/src/config/Pages.ts
@@ -26,6 +26,7 @@ export const Pages = {
add: "/orders/add",
detail: "/orders/detail/",
foodReport: "/orders/report/by-food",
+ dailyReport: "/orders/report/by-day",
},
customers: {
list: "/customers/list",
diff --git a/src/langs/fa.json b/src/langs/fa.json
index a502903..a631a7e 100644
--- a/src/langs/fa.json
+++ b/src/langs/fa.json
@@ -98,6 +98,7 @@
"categories": "دسته بندی ها",
"orders_list": "لیست سفارشات",
"orders_food_report": "گزارش فروش به تفکیک غذا",
+ "orders_daily_report": "گزارش فروش روزانه",
"add_order": "افزودن سفارش",
"discount_list": "لیست تخفیف",
"add_discount": "افزودن تخفیف",
diff --git a/src/pages/orders/DailyOrderReport.tsx b/src/pages/orders/DailyOrderReport.tsx
new file mode 100644
index 0000000..69af019
--- /dev/null
+++ b/src/pages/orders/DailyOrderReport.tsx
@@ -0,0 +1,81 @@
+import { type FC, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { DocumentDownload } from 'iconsax-react';
+import Table from '@/components/Table';
+import Filters from '@/components/Filters';
+import Button from '@/components/Button';
+import { useGetDailyOrderReport } from './hooks/useDailyOrderReportData';
+import { useDailyOrderReportFilters } from './hooks/useDailyOrderReportFilters';
+import { getDailyOrderReportTableColumns } from './components/DailyOrderReportTableColumns';
+import { useDailyOrderReportFiltersFields } from './components/DailyOrderReportFiltersFields';
+import { getDailyOrderReport } from './service/OrderService';
+import { exportDailyOrderReportExcel } from './utils/exportDailyOrderReportExcel';
+import type { DailyOrderReportItem } from './types/Types';
+import type { RowDataType } from '@/components/types/TableTypes';
+
+const DailyOrderReport: FC = () => {
+ const { t } = useTranslation('global');
+ const { filters, apiParams, handleFiltersChange } = useDailyOrderReportFilters();
+ const { data: reportData, isLoading } = useGetDailyOrderReport(apiParams);
+ const [isExporting, setIsExporting] = useState(false);
+
+ const columns = getDailyOrderReportTableColumns();
+ const filterFields = useDailyOrderReportFiltersFields();
+
+ const reportItems = useMemo(() => {
+ return (reportData?.data || []).map((item) => ({
+ ...item,
+ id: item.date,
+ }));
+ }, [reportData?.data]);
+
+ const handleExportExcel = async () => {
+ setIsExporting(true);
+ try {
+ const response = await getDailyOrderReport(apiParams);
+ const items = (response?.data || []).map((item) => ({
+ ...item,
+ id: item.date,
+ }));
+ exportDailyOrderReportExcel(items);
+ } finally {
+ setIsExporting(false);
+ }
+ };
+
+ return (
+
+
+
{t('submenu.orders_daily_report')}
+
+
+
+
+
+
+
+
+ columns={columns}
+ data={reportItems as (DailyOrderReportItem & RowDataType)[]}
+ isloading={isLoading}
+ />
+
+ );
+};
+
+export default DailyOrderReport;
diff --git a/src/pages/orders/components/DailyOrderReportFiltersFields.tsx b/src/pages/orders/components/DailyOrderReportFiltersFields.tsx
new file mode 100644
index 0000000..09ea415
--- /dev/null
+++ b/src/pages/orders/components/DailyOrderReportFiltersFields.tsx
@@ -0,0 +1,28 @@
+import { useMemo } from 'react';
+import type { FieldType } from '@/components/Filters';
+
+export const useDailyOrderReportFiltersFields = (): FieldType[] => {
+ return useMemo(() => [
+ {
+ type: 'datetime',
+ name: 'from',
+ placeholder: 'از تاریخ',
+ },
+ {
+ type: 'datetime',
+ name: 'to',
+ placeholder: 'تا تاریخ',
+ },
+ {
+ type: 'select',
+ name: 'sortBy',
+ placeholder: 'مرتبسازی',
+ defaultValue: 'date',
+ options: [
+ { label: 'تاریخ', value: 'date' },
+ { label: 'مبلغ کل', value: 'totalAmount' },
+ { label: 'تعداد سفارش', value: 'orderCount' },
+ ],
+ },
+ ], []);
+};
diff --git a/src/pages/orders/components/DailyOrderReportTableColumns.tsx b/src/pages/orders/components/DailyOrderReportTableColumns.tsx
new file mode 100644
index 0000000..1193477
--- /dev/null
+++ b/src/pages/orders/components/DailyOrderReportTableColumns.tsx
@@ -0,0 +1,23 @@
+import type { ColumnType } from '@/components/types/TableTypes';
+import type { DailyOrderReportItem } from '../types/Types';
+import { formatDateShort, formatFaNumber, formatPrice } from '@/helpers/func';
+
+export const getDailyOrderReportTableColumns = (): ColumnType[] => {
+ return [
+ {
+ key: 'date',
+ title: 'تاریخ',
+ render: (item: DailyOrderReportItem) => formatDateShort(item.date),
+ },
+ {
+ key: 'orderCount',
+ title: 'تعداد سفارش',
+ render: (item: DailyOrderReportItem) => formatFaNumber(item.orderCount),
+ },
+ {
+ key: 'totalAmount',
+ title: 'مبلغ کل',
+ render: (item: DailyOrderReportItem) => formatPrice(item.totalAmount),
+ },
+ ];
+};
diff --git a/src/pages/orders/hooks/useDailyOrderReportData.ts b/src/pages/orders/hooks/useDailyOrderReportData.ts
new file mode 100644
index 0000000..68a811a
--- /dev/null
+++ b/src/pages/orders/hooks/useDailyOrderReportData.ts
@@ -0,0 +1,10 @@
+import { useQuery } from '@tanstack/react-query';
+import * as api from '../service/OrderService';
+import type { GetDailyOrderReportParams } from '../service/OrderService';
+
+export const useGetDailyOrderReport = (params?: GetDailyOrderReportParams) => {
+ return useQuery({
+ queryKey: ['daily-order-report', params],
+ queryFn: () => api.getDailyOrderReport(params),
+ });
+};
diff --git a/src/pages/orders/hooks/useDailyOrderReportFilters.ts b/src/pages/orders/hooks/useDailyOrderReportFilters.ts
new file mode 100644
index 0000000..1ef1549
--- /dev/null
+++ b/src/pages/orders/hooks/useDailyOrderReportFilters.ts
@@ -0,0 +1,37 @@
+import { useState, useMemo } from 'react';
+import type { FilterValues } from '@/components/Filters';
+import type { GetDailyOrderReportParams } from '../service/OrderService';
+
+export const useDailyOrderReportFilters = () => {
+ const [filters, setFilters] = useState({
+ sortBy: 'date',
+ });
+
+ const apiParams = useMemo(() => {
+ const params: GetDailyOrderReportParams = {};
+
+ if (filters.from) {
+ params.from = filters.from as string;
+ }
+
+ if (filters.to) {
+ params.to = filters.to as string;
+ }
+
+ if (filters.sortBy) {
+ params.sortBy = filters.sortBy as GetDailyOrderReportParams['sortBy'];
+ }
+
+ return params;
+ }, [filters]);
+
+ const handleFiltersChange = (newFilters: FilterValues) => {
+ setFilters(newFilters);
+ };
+
+ return {
+ filters,
+ apiParams,
+ handleFiltersChange,
+ };
+};
diff --git a/src/pages/orders/service/OrderService.ts b/src/pages/orders/service/OrderService.ts
index 0156037..3fcf7f8 100644
--- a/src/pages/orders/service/OrderService.ts
+++ b/src/pages/orders/service/OrderService.ts
@@ -1,5 +1,10 @@
import axios from "@/config/axios";
-import type { GetOrdersResponse, GetOrderByIdResponse, GetFoodOrderReportResponse } from "../types/Types";
+import type {
+ GetOrdersResponse,
+ GetOrderByIdResponse,
+ GetFoodOrderReportResponse,
+ GetDailyOrderReportResponse,
+} from "../types/Types";
export interface GetOrdersParams {
page?: number;
@@ -98,3 +103,19 @@ export const getFoodOrderReport = async (
);
return data;
};
+
+export interface GetDailyOrderReportParams {
+ from?: string;
+ to?: string;
+ sortBy?: 'date' | 'totalAmount' | 'orderCount';
+}
+
+export const getDailyOrderReport = async (
+ params?: GetDailyOrderReportParams
+) => {
+ const { data } = await axios.get(
+ '/admin/orders/report/by-day',
+ { params }
+ );
+ return data;
+};
diff --git a/src/pages/orders/types/Types.ts b/src/pages/orders/types/Types.ts
index 2234496..e2178cf 100644
--- a/src/pages/orders/types/Types.ts
+++ b/src/pages/orders/types/Types.ts
@@ -234,3 +234,11 @@ export interface FoodOrderReportItem extends RowDataType {
}
export type GetFoodOrderReportResponse = IResponse;
+
+export interface DailyOrderReportItem extends RowDataType {
+ date: string;
+ orderCount: number;
+ totalAmount: number;
+}
+
+export type GetDailyOrderReportResponse = IResponse;
diff --git a/src/pages/orders/utils/exportDailyOrderReportExcel.ts b/src/pages/orders/utils/exportDailyOrderReportExcel.ts
new file mode 100644
index 0000000..e69c3ce
--- /dev/null
+++ b/src/pages/orders/utils/exportDailyOrderReportExcel.ts
@@ -0,0 +1,18 @@
+import * as XLSX from 'xlsx';
+import type { DailyOrderReportItem } from '../types/Types';
+import { formatDateShort } from '@/helpers/func';
+
+export const exportDailyOrderReportExcel = (items: DailyOrderReportItem[]) => {
+ const rows = items.map((item) => ({
+ تاریخ: formatDateShort(item.date),
+ 'تعداد سفارش': item.orderCount,
+ 'مبلغ کل': item.totalAmount,
+ }));
+
+ const worksheet = XLSX.utils.json_to_sheet(rows);
+ const workbook = XLSX.utils.book_new();
+ XLSX.utils.book_append_sheet(workbook, worksheet, 'گزارش فروش روزانه');
+
+ const fileName = `daily-order-report-${new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-')}.xlsx`;
+ XLSX.writeFile(workbook, fileName);
+};
diff --git a/src/router/Main.tsx b/src/router/Main.tsx
index 1e51732..ccf814e 100644
--- a/src/router/Main.tsx
+++ b/src/router/Main.tsx
@@ -16,6 +16,7 @@ import CreateCustomer from '@/pages/customers/Create'
import OrdersList from '@/pages/orders/List'
import OrderDetails from '@/pages/orders/Details'
import FoodOrderReport from '@/pages/orders/FoodOrderReport'
+import DailyOrderReport from '@/pages/orders/DailyOrderReport'
import CommentsList from '@/pages/comments/List'
import CommentsDetails from '@/pages/comments/Details'
import ScheduleList from '@/pages/schedule/List'
@@ -73,6 +74,7 @@ const MainRouter: FC = () => {
} />
} />
} />
+ } />
} />
} />
} />
diff --git a/src/shared/components/OrdersSubMenu.tsx b/src/shared/components/OrdersSubMenu.tsx
index 4e6ce56..2997f88 100644
--- a/src/shared/components/OrdersSubMenu.tsx
+++ b/src/shared/components/OrdersSubMenu.tsx
@@ -38,6 +38,11 @@ const OrdersSubMenu: FC = () => {
isActive={isActive('report/by-food')}
link={Pages.orders.foodReport}
/>
+
{/*