From 00d46d26b9b53d15e83a8d5b7d930432e36fbe3d Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Mon, 5 May 2025 15:19:44 +0330 Subject: [PATCH] support plan --- src/config/Pages.ts | 1 + src/langs/fa.json | 8 +- src/pages/support/Create.tsx | 4 +- src/pages/support/List.tsx | 55 ++++- src/pages/support/Update.tsx | 232 ++++++++++++++++++++ src/pages/support/components/Delete.tsx | 36 +++ src/pages/support/hooks/useSupportData.ts | 13 ++ src/pages/support/service/SupportService.ts | 10 + src/pages/support/types/SupportTypes.ts | 2 +- src/router/Main.tsx | 2 + 10 files changed, 357 insertions(+), 6 deletions(-) create mode 100644 src/pages/support/Update.tsx create mode 100644 src/pages/support/components/Delete.tsx diff --git a/src/config/Pages.ts b/src/config/Pages.ts index 46cdef6..33b0c7e 100644 --- a/src/config/Pages.ts +++ b/src/config/Pages.ts @@ -109,5 +109,6 @@ export const Pages = { support: { create: "/support/create", list: "/support/list", + detail: "/support/detail/", }, }; diff --git a/src/langs/fa.json b/src/langs/fa.json index 4a35c3a..4fdb0ce 100644 --- a/src/langs/fa.json +++ b/src/langs/fa.json @@ -777,6 +777,12 @@ "technical_expert_access": "دسترسی به متخصصین فنی", "on_site_support": "پشتیبانی در محل", "on_site_training": "آموزش در محل", - "ticket_limit": "ظرفیت ارسال تیکت" + "ticket_limit": "ظرفیت ارسال تیکت", + "plans": "پلن ها", + "plan_name": "نام پلن", + "price": "قیمت", + "duration": "مدت", + "features": "ویژگی ها", + "actions": "عملیات" } } diff --git a/src/pages/support/Create.tsx b/src/pages/support/Create.tsx index 7b29220..361dfd1 100644 --- a/src/pages/support/Create.tsx +++ b/src/pages/support/Create.tsx @@ -69,7 +69,7 @@ const CreatePlan: FC = () => { return { featureKey: feature.featureKey, featureValue: feature.featureValue as string, - featureType: 'string', + featureType: 'text', } } }) @@ -99,7 +99,7 @@ const CreatePlan: FC = () => { features: preparedFeatures.map(feature => ({ featureKey: feature.featureKey, featureValue: String(feature.featureValue), - featureType: feature.featureType as "string" | "boolean" + featureType: feature.featureType as "text" | "boolean" })) } createSupport.mutate(planData, { diff --git a/src/pages/support/List.tsx b/src/pages/support/List.tsx index 9c1dce2..df73e04 100644 --- a/src/pages/support/List.tsx +++ b/src/pages/support/List.tsx @@ -1,8 +1,59 @@ import { FC } from 'react' - +import { useGetPlans } from './hooks/useSupportData' +import { useTranslation } from 'react-i18next' +import Td from '../../components/Td' +import { NumberFormat } from '../../config/func' +import { Edit } from 'iconsax-react' +import { Link } from 'react-router-dom' +import { Pages } from '../../config/Pages' +import Delete from './components/Delete' const SupportList: FC = () => { + + const { t } = useTranslation('global') + const { data, refetch } = useGetPlans() + return ( -
List
+
+
+
+ {t('support.plans')} +
+
+ +
+ + + + + + + { + data?.data?.supportPlans?.map((item: { id: string, name: string, price: number, duration: string }) => { + return ( + + + + ) + }) + } + +
+ + + +
+ + + +
+ + + + +
+
+
+
) } diff --git a/src/pages/support/Update.tsx b/src/pages/support/Update.tsx new file mode 100644 index 0000000..7d157b9 --- /dev/null +++ b/src/pages/support/Update.tsx @@ -0,0 +1,232 @@ +import { FC, useState, useEffect } from 'react' +import Input from '../../components/Input' +import SwitchComponent from '../../components/Switch' +import Textarea from '../../components/Textarea' +import Button from '../../components/Button' +import { SupportPlanFeatureKey } from './enum/SupportEnum' +import { useTranslation } from 'react-i18next' +import PlanItem from './components/PlanItem' +import { useFormik } from 'formik' +import { CreatePlanType } from './types/SupportTypes' +import * as Yup from 'yup' +import Select from '../../components/Select' +import { useGetPlanById, useUpdateSupport } from './hooks/useSupportData' +import { toast } from 'react-toastify' +import { ErrorType } from '../../helpers/types' +import { useNavigate, useParams } from 'react-router-dom' +import { Pages } from '../../config/Pages' + +interface PlanFeature { + featureKey: string; + featureValue: string | boolean; + featureType: 'boolean' | 'text'; + isEnabled: boolean; +} + +const UpdatePlan: FC = () => { + const { id } = useParams() + const navigate = useNavigate() + const { t } = useTranslation('global') + const { data: planData } = useGetPlanById(id ?? '') + const updateSupport = useUpdateSupport() + + const [features, setFeatures] = useState([]) + + useEffect(() => { + if (planData?.data) { + const plan = planData.data?.supportPlan + const mappedFeatures = Object.values(SupportPlanFeatureKey).map(key => { + const existingFeature = plan.features.find((f: { featureKey: string }) => f.featureKey === key) + return { + featureKey: key, + featureValue: existingFeature?.featureValue ?? true, + featureType: existingFeature?.featureType ?? 'boolean', + isEnabled: true + } + }) + setFeatures(mappedFeatures) + } + }, [planData]) + + const handleFeatureChange = (id: string, value: string | boolean, isEnabled: boolean) => { + setFeatures(prevFeatures => + prevFeatures.map(feature => + feature.featureKey === id ? { ...feature, featureValue: value, isEnabled } : feature + ) + ) + } + + const handleFeatureTypeChange = (id: string, type: 'boolean' | 'text') => { + setFeatures(prevFeatures => + prevFeatures.map(feature => + feature.featureKey === id ? { + ...feature, + featureType: type, + featureValue: type === 'boolean' ? true : '', + isEnabled: type === 'boolean' ? true : false + } : feature + ) + ) + } + + const prepareFeaturesForSubmission = (features: PlanFeature[]) => { + return features.map(feature => { + if (feature.featureType === 'boolean') { + return { + featureKey: feature.featureKey, + featureValue: feature.isEnabled, + featureType: 'boolean', + } + } else { + return { + featureKey: feature.featureKey, + featureValue: feature.featureValue as string, + featureType: 'text', + } + } + }) + } + + const formik = useFormik({ + enableReinitialize: true, + initialValues: { + name: planData?.data?.supportPlan?.name ?? '', + description: planData?.data?.supportPlan?.description ?? '', + price: planData?.data?.supportPlan?.price ?? 0, + duration: planData?.data?.supportPlan?.duration ?? 0, + isActive: planData?.data?.supportPlan?.isActive ?? true, + features: [], + }, + validationSchema: Yup.object({ + name: Yup.string().required('نام پلن الزامی است'), + description: Yup.string().required('توضیحات پلن الزامی است'), + price: Yup.number().required('قیمت پلن الزامی است'), + duration: Yup.number().required('مدت پلن الزامی است'), + }), + onSubmit: (values) => { + values.price = Number(values.price) + values.duration = Number(values.duration) + const preparedFeatures = prepareFeaturesForSubmission(features) + const planData: CreatePlanType = { + ...values, + features: preparedFeatures.map(feature => ({ + featureKey: feature.featureKey, + featureValue: String(feature.featureValue), + featureType: feature.featureType as "text" | "boolean" + })) + } + updateSupport.mutate({ id: id ?? '', data: planData }, { + onSuccess: () => { + toast.success('پلن با موفقیت ویرایش شد') + navigate(Pages.support.list) + }, + onError: (error: ErrorType) => { + toast.error(error.response?.data?.error.message[0]) + } + }) + }, + }) + + if (!planData?.data) { + return null + } + + console.log(formik.errors); + + + return ( +
+
ویرایش پلن
+ +
+
اطلاعات اصلی پلن
+
+
+ +
+ +
+ + + +
+ +
+