From 676eedad007aab501e4a64a9b62ac9d22ef8bf22 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Tue, 30 Sep 2025 09:38:47 +0330 Subject: [PATCH] fine --- src/components/DefaulModal.tsx | 2 +- src/pages/payment/Fines.tsx | 165 +++++++++++++++++- src/pages/payment/service/PaymentService.ts | 10 +- src/pages/payment/types/Types.ts | 17 ++ src/pages/report/Category.tsx | 27 +++ .../components/CreateReportCategoryModal.tsx | 84 +++++++++ src/pages/report/hooks/useReportData.ts | 8 +- src/pages/report/service/ReportService.ts | 14 +- src/pages/report/types/Types.ts | 4 + src/router/Main.tsx | 2 + 10 files changed, 321 insertions(+), 12 deletions(-) create mode 100644 src/pages/report/Category.tsx create mode 100644 src/pages/report/components/CreateReportCategoryModal.tsx diff --git a/src/components/DefaulModal.tsx b/src/components/DefaulModal.tsx index 1af8dae..9a60e5b 100644 --- a/src/components/DefaulModal.tsx +++ b/src/components/DefaulModal.tsx @@ -35,7 +35,7 @@ const DefaulModal: FC = (props: Props) => {
{ props.isHeader && props.title_header && -
+
diff --git a/src/pages/payment/Fines.tsx b/src/pages/payment/Fines.tsx index ce96690..72ce2aa 100644 --- a/src/pages/payment/Fines.tsx +++ b/src/pages/payment/Fines.tsx @@ -1,10 +1,163 @@ -import { type FC } from 'react' +import { type FC, useState } from 'react' +import { useGetFines } from './hooks/usePaymentData'; +import { type FineRule } from './types/Types'; +import PageLoading from '../../components/PageLoading'; +import Error from '../../components/Error'; +import Td from '../../components/Td'; +import Button from '@/components/Button'; +import { Link } from 'react-router-dom'; +import { Pages } from '@/config/Pages'; +import DefaulModal from '../../components/DefaulModal'; +import { Eye } from 'iconsax-react'; const Fines: FC = () => { - return ( -
Fines
- ) -} + const { data, isLoading, error } = useGetFines(); + const [selectedFine, setSelectedFine] = useState(null); + const [isModalOpen, setIsModalOpen] = useState(false); -export default Fines \ No newline at end of file + const openModal = (fine: FineRule) => { + setSelectedFine(fine); + setIsModalOpen(true); + }; + + const closeModal = () => { + setIsModalOpen(false); + setSelectedFine(null); + }; + + if (isLoading) { + return ( +
+ +
+ ); + } + + if (error) { + return ( +
+ +
+ ); + } + + const fines = data?.results?.fineRules || []; + + const formatDate = (dateString: string) => { + return new Date(dateString).toLocaleDateString('fa-IR', { + year: 'numeric', + month: 'long', + day: 'numeric', + }); + }; + + return ( +
+
+ +
+ +
+ + + + + + + {fines.length === 0 ? ( + + + + ) : ( + fines.map((fine: FineRule) => ( + + + + )) + )} + +
+ + + +
+ هیچ قانون جریمه‌ای یافت نشد +
+ + + +
+ + + {/* عملیات ویرایش - در صورت نیاز */} + {/* + + */} + + {/* عملیات حذف - در صورت نیاز */} + {/* { + console.log('Delete fine:', fine._id); + }} + /> */} +
+
+
+ + + {selectedFine && ( +
+
+

اطلاعات قانون جریمه

+
+
+ +

{selectedFine.title}

+
+
+ +

{selectedFine.fine_percentage}%

+
+
+ +

+ {selectedFine.deleted ? 'غیرفعال' : 'فعال'} +

+
+
+ +

{formatDate(selectedFine.createdAt)}

+
+
+ +

{formatDate(selectedFine.updatedAt)}

+
+
+
+
+ )} +
+
+ ); +}; + +export default Fines; \ No newline at end of file diff --git a/src/pages/payment/service/PaymentService.ts b/src/pages/payment/service/PaymentService.ts index a7e7ed4..4d6f4ff 100644 --- a/src/pages/payment/service/PaymentService.ts +++ b/src/pages/payment/service/PaymentService.ts @@ -1,5 +1,9 @@ import axios from "../../../config/axios"; -import type { CreateFineType, PaymentResponse } from "../types/Types"; +import type { + CreateFineType, + PaymentResponse, + GetFinesResponse, +} from "../types/Types"; export const getPayments = async ( page: number = 1 @@ -13,7 +17,7 @@ export const createFine = async (params: CreateFineType) => { return data; }; -export const getFines = async () => { - const { data } = await axios.get(`/admin/fine/fines`); +export const getFines = async (): Promise => { + const { data } = await axios.get(`/admin/fine/rule`); return data; }; diff --git a/src/pages/payment/types/Types.ts b/src/pages/payment/types/Types.ts index b4feb4c..2623b48 100644 --- a/src/pages/payment/types/Types.ts +++ b/src/pages/payment/types/Types.ts @@ -54,3 +54,20 @@ export type CreateFineType = { title: string; fine_percentage: number; }; + +export interface FineRule { + _id: string; + title: string; + fine_percentage: number; + deleted: boolean; + createdAt: string; + updatedAt: string; +} + +export interface GetFinesResponse { + status: number; + success: boolean; + results: { + fineRules: FineRule[]; + }; +} diff --git a/src/pages/report/Category.tsx b/src/pages/report/Category.tsx new file mode 100644 index 0000000..f2b8571 --- /dev/null +++ b/src/pages/report/Category.tsx @@ -0,0 +1,27 @@ +import { type FC, useState } from 'react' +import Button from '@/components/Button'; +import CreateReportCategoryModal from './components/CreateReportCategoryModal.tsx'; + +const CategoryReport: FC = () => { + const [isModalOpen, setIsModalOpen] = useState(false); + + return ( +
+
+
+
+ + setIsModalOpen(false)} + /> +
+ ) +} + +export default CategoryReport \ No newline at end of file diff --git a/src/pages/report/components/CreateReportCategoryModal.tsx b/src/pages/report/components/CreateReportCategoryModal.tsx new file mode 100644 index 0000000..2c777b7 --- /dev/null +++ b/src/pages/report/components/CreateReportCategoryModal.tsx @@ -0,0 +1,84 @@ +import { type FC } from 'react' +import { useCreateReportCategory } from '../hooks/useReportData'; +import DefaulModal from '@/components/DefaulModal'; +import Input from '@/components/Input'; +import Button from '@/components/Button'; +import { TickCircle } from 'iconsax-react'; +import { useFormik } from 'formik'; +import * as Yup from 'yup'; +import { toast } from 'react-toastify'; + +const CreateReportCategoryModal: FC<{ isOpen: boolean; onClose: () => void }> = ({ isOpen, onClose }) => { + const createReportCategoryMutation = useCreateReportCategory(); + + const formik = useFormik({ + initialValues: { + title: '', + }, + validationSchema: Yup.object({ + title: Yup.string().required('عنوان دسته‌بندی الزامی است'), + }), + onSubmit: async (values) => { + createReportCategoryMutation.mutate(values, { + onSuccess: () => { + toast.success('دسته‌بندی گزارش با موفقیت ایجاد شد'); + onClose(); + formik.resetForm(); + }, + onError: () => { + toast.error('خطا در ایجاد دسته‌بندی گزارش'); + } + }); + }, + }); + + const handleClose = () => { + onClose(); + formik.resetForm(); + }; + + return ( + +
+
+ + +
+ + +
+
+
+
+ ); +}; + +export default CreateReportCategoryModal diff --git a/src/pages/report/hooks/useReportData.ts b/src/pages/report/hooks/useReportData.ts index 8218181..45ad602 100644 --- a/src/pages/report/hooks/useReportData.ts +++ b/src/pages/report/hooks/useReportData.ts @@ -1,4 +1,4 @@ -import { useQuery } from "@tanstack/react-query"; +import { useMutation, useQuery } from "@tanstack/react-query"; import * as api from "../service/ReportService"; export const useGetProductReport = () => { @@ -7,3 +7,9 @@ export const useGetProductReport = () => { queryFn: api.getProductReport, }); }; + +export const useCreateReportCategory = () => { + return useMutation({ + mutationFn: api.createReportCategory, + }); +}; diff --git a/src/pages/report/service/ReportService.ts b/src/pages/report/service/ReportService.ts index 045969a..bd16c76 100644 --- a/src/pages/report/service/ReportService.ts +++ b/src/pages/report/service/ReportService.ts @@ -1,7 +1,19 @@ import axios from "../../../config/axios"; -import type { ReportResponse } from "../types/Types"; +import type { CreateReportCategoryType, ReportResponse } from "../types/Types"; export const getProductReport = async (): Promise => { const { data } = await axios.get("/admin/products/user-reports"); return data; }; + +export const createReportCategory = async ( + params: CreateReportCategoryType +) => { + const { data } = await axios.post("/admin/products/report-question", params); + return data; +}; + +export const getReportQuestions = async () => { + const { data } = await axios.get("/admin/products/report-questions"); + return data; +}; diff --git a/src/pages/report/types/Types.ts b/src/pages/report/types/Types.ts index 4d73f44..bac9584 100644 --- a/src/pages/report/types/Types.ts +++ b/src/pages/report/types/Types.ts @@ -81,3 +81,7 @@ export interface ReportResponse { success: boolean; results: ReportResults; } + +export interface CreateReportCategoryType { + title: string; +} diff --git a/src/router/Main.tsx b/src/router/Main.tsx index 88325cc..9534022 100644 --- a/src/router/Main.tsx +++ b/src/router/Main.tsx @@ -43,6 +43,7 @@ import CreateFine from '@/pages/payment/CreateFine' import Fines from '@/pages/payment/Fines' import TicketsList from '@/pages/tickets/List' import ProductReport from '@/pages/report/ProductReport' +import CategoryReport from '@/pages/report/Category' const MainRouter: FC = () => { const { hasSubMenu } = useSharedStore() @@ -109,6 +110,7 @@ const MainRouter: FC = () => { } /> } /> + } />