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 (
+
+
ویرایش پلن
+
+
+
اطلاعات اصلی پلن
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ formik.setFieldValue('isActive', active)}
+ label='فعال'
+ />
+
+
+
+
+
+
ویژگیهای پلن
+
+ {features.map((feature) => (
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+
+
+ )
+}
+
+export default UpdatePlan
\ No newline at end of file
diff --git a/src/pages/support/components/Delete.tsx b/src/pages/support/components/Delete.tsx
new file mode 100644
index 0000000..5ac8f6e
--- /dev/null
+++ b/src/pages/support/components/Delete.tsx
@@ -0,0 +1,36 @@
+import { Trash } from 'iconsax-react'
+import { FC, useState } from 'react'
+import { useDeletePlan } from '../hooks/useSupportData'
+import ModalConfrim from '../../../components/ModalConfrim'
+
+type Props = {
+ id: string,
+ refetch: () => void
+}
+
+const Delete: FC = ({ id, refetch }) => {
+ const { mutate: deletePlan, isPending } = useDeletePlan()
+ const [isOpen, setIsOpen] = useState(false)
+ const close = () => setIsOpen(false)
+ return (
+
+ setIsOpen(true)} />
+
+ {
+ deletePlan(id, {
+ onSuccess: () => {
+ setIsOpen(false)
+ refetch()
+ }
+ })
+ }}
+ isLoading={isPending}
+ />
+
+ )
+}
+
+export default Delete
\ No newline at end of file
diff --git a/src/pages/support/hooks/useSupportData.ts b/src/pages/support/hooks/useSupportData.ts
index e583771..6a6056d 100644
--- a/src/pages/support/hooks/useSupportData.ts
+++ b/src/pages/support/hooks/useSupportData.ts
@@ -8,6 +8,13 @@ export const useCreateSupport = () => {
});
};
+export const useUpdateSupport = () => {
+ return useMutation({
+ mutationFn: ({ id, data }: { id: string; data: CreatePlanType }) =>
+ api.updatePlan(id, data),
+ });
+};
+
export const useGetPlans = () => {
return useQuery({
queryKey: ["plans"],
@@ -21,3 +28,9 @@ export const useGetPlanById = (id: string) => {
queryFn: () => api.getPlanById(id),
});
};
+
+export const useDeletePlan = () => {
+ return useMutation({
+ mutationFn: (id: string) => api.deletePlan(id),
+ });
+};
diff --git a/src/pages/support/service/SupportService.ts b/src/pages/support/service/SupportService.ts
index 041c24a..fd879ad 100644
--- a/src/pages/support/service/SupportService.ts
+++ b/src/pages/support/service/SupportService.ts
@@ -6,6 +6,11 @@ export const createPlan = async (plan: CreatePlanType) => {
return data;
};
+export const updatePlan = async (id: string, plan: CreatePlanType) => {
+ const { data } = await axios.patch(`/support-plans/${id}`, plan);
+ return data;
+};
+
export const getPlans = async () => {
const { data } = await axios.get("/support-plans/list");
return data;
@@ -15,3 +20,8 @@ export const getPlanById = async (id: string) => {
const { data } = await axios.get(`/support-plans/${id}`);
return data;
};
+
+export const deletePlan = async (id: string) => {
+ const { data } = await axios.delete(`/support-plans/${id}`);
+ return data;
+};
diff --git a/src/pages/support/types/SupportTypes.ts b/src/pages/support/types/SupportTypes.ts
index 41a7827..15450d5 100644
--- a/src/pages/support/types/SupportTypes.ts
+++ b/src/pages/support/types/SupportTypes.ts
@@ -7,6 +7,6 @@ export type CreatePlanType = {
features: {
featureKey: string;
featureValue: string | boolean;
- featureType: "boolean" | "string";
+ featureType: "boolean" | "text";
}[];
};
diff --git a/src/router/Main.tsx b/src/router/Main.tsx
index 28794a1..a21201d 100644
--- a/src/router/Main.tsx
+++ b/src/router/Main.tsx
@@ -67,6 +67,7 @@ import UpdateSlider from '../pages/slider/Update'
import Comments from '../pages/blog/Comments'
import CreatePlan from '../pages/support/Create'
import SupportList from '../pages/support/List'
+import UpdateSupport from '../pages/support/Update'
const MainRouter: FC = () => {
const { hasSubMenu } = useSharedStore()
@@ -145,6 +146,7 @@ const MainRouter: FC = () => {
} />
} />
} />
+ } />