From 7de3678ab0add6f880e10c27a7d19837f6fceb5f Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sun, 28 Dec 2025 09:32:05 +0330 Subject: [PATCH] buy dmenu --- src/components/ServiceItem.tsx | 74 ++++++++--- src/config/Pages.ts | 1 + src/langs/fa.json | 11 ++ src/pages/service/ManageRestaurant.tsx | 136 ++++++++++++++++++++ src/pages/service/hooks/useServiceData.ts | 22 ++++ src/pages/service/service/ServiceService.ts | 23 ++++ src/pages/service/types/ServiecTypes.ts | 91 +++++++++++++ src/router/Main.tsx | 2 + 8 files changed, 343 insertions(+), 17 deletions(-) create mode 100644 src/pages/service/ManageRestaurant.tsx diff --git a/src/components/ServiceItem.tsx b/src/components/ServiceItem.tsx index 1089902..8cfe857 100644 --- a/src/components/ServiceItem.tsx +++ b/src/components/ServiceItem.tsx @@ -1,5 +1,5 @@ -import { FC } from 'react' -import { Link } from 'react-router-dom' +import { FC, useState, useEffect } from 'react' +import { Link, useNavigate } from 'react-router-dom' import { Pages } from '../config/Pages' import { ArrowLeft, More } from 'iconsax-react' import Button from './Button' @@ -7,6 +7,7 @@ import { useTranslation } from 'react-i18next' import { ItemServiceType } from '../pages/service/types/ServiecTypes' import moment from 'moment-jalaali' import { NumberFormat } from '../config/func' +import { useGetDmenuSubscription } from '../pages/service/hooks/useServiceData' type Props = { item: ItemServiceType, @@ -23,8 +24,13 @@ type Props = { const ServiceItem: FC = (props: Props) => { const { t } = useTranslation('global') + const navigate = useNavigate() + const [isChecked, setIsChecked] = useState(false) const { item } = props + const isDmenu = item?.slug === 'Dmenu' + const { data: dmenuSubscription, isPending, isError } = useGetDmenuSubscription(isChecked && isDmenu && props.isLinkPanel ? props.subscriptionId! : '',) + const getRemainingDays = (endDate: string): number => { const now = moment() const end = moment(endDate) @@ -53,6 +59,39 @@ const ServiceItem: FC = (props: Props) => { return `${NumberFormat(days)} روز باقی مانده` } + useEffect(() => { + if (isChecked && isDmenu && props.isLinkPanel) { + alert(props.subscriptionId) + if (dmenuSubscription && !isPending) { + if (item.link) { + window.open(item.link, '_blank') + } + setIsChecked(false) + } else if (isError && !isPending) { + if (props.subscriptionId) { + navigate(Pages.services.manageRestaurant + props.subscriptionId) + } + setIsChecked(false) + } + } + }, [dmenuSubscription, isError, isPending, isChecked, isDmenu, props.isLinkPanel, props.subscriptionId, item.link, navigate]) + + const handleCheckSubscription = () => { + if (props.isDisabled) { + return + } + + if (props.isLinkPanel && item.link) { + if (isDmenu && props.subscriptionId) { + setIsChecked(true) + } else { + window.open(item.link, '_blank') + } + } else { + navigate(Pages.services.detail + item.slug) + } + } + return (
{ @@ -94,21 +133,22 @@ const ServiceItem: FC = (props: Props) => {
- - - + { props.subscriptionId && diff --git a/src/config/Pages.ts b/src/config/Pages.ts index 8855f64..f13c8a4 100644 --- a/src/config/Pages.ts +++ b/src/config/Pages.ts @@ -6,6 +6,7 @@ export const Pages = { }, dashboard: "/dashboard", services: { + manageRestaurant: "/services/manage-restaurant/", mine: "/services", other: "/other-service", detail: "/services/detail/", diff --git a/src/langs/fa.json b/src/langs/fa.json index a6c83da..b1d583f 100644 --- a/src/langs/fa.json +++ b/src/langs/fa.json @@ -524,5 +524,16 @@ "duration": "مدت", "features": "ویژگی ها", "actions": "عملیات" + }, + "restaurant": { + "manage": "مدیریت رستوران", + "restaurant_info": "اطلاعات رستوران", + "enter_restaurant_info": "لطفا اطلاعات رستوران خود را وارد کنید", + "name": "نام رستوران", + "enter_name": "نام رستوران را وارد کنید", + "slug": "اسلاگ", + "enter_slug": "اسلاگ را وارد کنید", + "established_year": "سال تأسیس", + "enter_year": "سال تأسیس را وارد کنید" } } diff --git a/src/pages/service/ManageRestaurant.tsx b/src/pages/service/ManageRestaurant.tsx new file mode 100644 index 0000000..7f75e64 --- /dev/null +++ b/src/pages/service/ManageRestaurant.tsx @@ -0,0 +1,136 @@ +import { type FC } from 'react' +import { useParams } from 'react-router-dom' +import { useTranslation } from 'react-i18next' +import { useCreateDmenuRestaurant, useGetSubscription } from './hooks/useServiceData' +import { useFormik } from 'formik' +import { DmenuCreateRestaurantType } from './types/ServiecTypes' +import * as Yup from 'yup' +import { toast } from '../../components/Toast' +import { ErrorType } from '../../helpers/types' +import Input from '../../components/Input' +import Button from '../../components/Button' +import { TickCircle } from 'iconsax-react' +import { Helmet } from 'react-helmet-async' + +export const ManageRestaurant: FC = () => { + + const { t } = useTranslation('global') + const { subscriptionId } = useParams() + const createDmenuRestaurant = useCreateDmenuRestaurant() + const getSubscription = useGetSubscription(subscriptionId!) + + const formik = useFormik({ + initialValues: { + name: '', + slug: '', + establishedYear: 0, + phone: '', + userSubscriptionId: subscriptionId || '' + }, + validationSchema: Yup.object({ + name: Yup.string().required(t('errors.required')), + slug: Yup.string().required(t('errors.required')), + establishedYear: Yup.number() + .required(t('errors.required')) + .min(1300, 'سال باید حداقل ۱۳۰۰ باشد') + .max(1500, 'سال باید حداکثر ۱۵۰۰ باشد'), + phone: Yup.string().required(t('errors.required')), + userSubscriptionId: Yup.string().required(t('errors.required')) + }), + onSubmit: (values) => { + const submitValues = { + ...values, + establishedYear: Number(values.establishedYear) + } + createDmenuRestaurant.mutate(submitValues, { + onSuccess: () => { + toast(t('success'), 'success') + formik.resetForm() + window.location.href = getSubscription?.data?.data?.userSubscription?.plan?.service?.link as string + }, + onError: (error: ErrorType) => { + toast(error.response?.data?.error?.message[0], 'error') + } + }) + } + }) + + return ( + <> + + {t('restaurant.manage')} + +
+
+ {t('restaurant.manage') || 'مدیریت رستوران'} +
+ +
+
+
+
+ {t('restaurant.restaurant_info') || 'اطلاعات رستوران'} +
+
+ {t('restaurant.enter_restaurant_info') || 'لطفا اطلاعات رستوران خود را وارد کنید'} +
+
+ +
+
+ + + +
+ +
+ + + +
+ +
+ +
+
+
+
+
+ + ) +} diff --git a/src/pages/service/hooks/useServiceData.ts b/src/pages/service/hooks/useServiceData.ts index 532db65..e67e825 100644 --- a/src/pages/service/hooks/useServiceData.ts +++ b/src/pages/service/hooks/useServiceData.ts @@ -62,3 +62,25 @@ export const useExtentSubscription = () => { mutationFn: api.extentSubscription, }); }; + +export const useGetDmenuSubscription = (subscriptionId: string) => { + return useQuery({ + queryKey: ["dmenu-subscription", subscriptionId], + queryFn: () => api.getDmenuSubscription(subscriptionId), + enabled: !!subscriptionId, + }); +}; + +export const useCreateDmenuRestaurant = () => { + return useMutation({ + mutationFn: api.createDmenuRestaurant, + }); +}; + +export const useGetSubscription = (subscriptionId: string) => { + return useQuery({ + queryKey: ["subscription", subscriptionId], + queryFn: () => api.getSubscription(subscriptionId), + enabled: !!subscriptionId, + }); +}; diff --git a/src/pages/service/service/ServiceService.ts b/src/pages/service/service/ServiceService.ts index 5646be8..4b0ee07 100644 --- a/src/pages/service/service/ServiceService.ts +++ b/src/pages/service/service/ServiceService.ts @@ -4,6 +4,8 @@ import { CreateReviewType, ExtentSubscriptionType, ExtentSubscriptionResponseType, + DmenuCreateRestaurantType, + GetSubscriptionResponseType, } from "../types/ServiecTypes"; export const getServiceSuggestedDanak = async () => { @@ -62,3 +64,24 @@ export const extentSubscription = async ( ); return data; }; + +export const getDmenuSubscription = async (subscriptionId: string) => { + const { data } = await axios.get( + `/dmenu/restaurants/subscription/${subscriptionId}` + ); + return data; +}; + +export const createDmenuRestaurant = async ( + params: DmenuCreateRestaurantType +) => { + const { data } = await axios.post(`/dmenu/restaurants`, params); + return data; +}; + +export const getSubscription = async ( + subscriptionId: string +): Promise => { + const { data } = await axios.get(`/subscriptions/user/${subscriptionId}`); + return data; +}; diff --git a/src/pages/service/types/ServiecTypes.ts b/src/pages/service/types/ServiecTypes.ts index 73fc52d..5e430da 100644 --- a/src/pages/service/types/ServiecTypes.ts +++ b/src/pages/service/types/ServiecTypes.ts @@ -277,3 +277,94 @@ export type ExtentSubscriptionResponseType = { invoice: InvoiceType; }; }; + +export type DmenuCreateRestaurantType = { + name: string; + slug: string; + establishedYear: number; + phone: string; + userSubscriptionId: string; +}; + +export type ServiceImageType = { + id: string; + createdAt: string; + updatedAt: string; + imageUrl: string; +}; + +export type SubscriptionPlanItemType = { + id: string; + createdAt: string; + updatedAt: string; + name: string; + duration: number; + isFree: boolean; + price: number; + originalPrice: number; + isActive: boolean; + deletedAt: string | null; +}; + +export type ServiceWithDetailsType = { + id: string; + createdAt: string; + updatedAt: string; + name: string; + title: string; + pageTitle: string; + pageDescription: string; + slug: string; + isDanakSuggest: boolean; + description: string; + author: string; + createDate: string; + userCount: number; + serviceLanguage: string; + softwareLanguage: string; + metaDescription: string; + isActive: boolean; + showInSlider: boolean; + link: string; + icon: string; + coverUrl: string; + images: ServiceImageType[]; + subscriptionPlans: SubscriptionPlanItemType[]; + deletedAt: string | null; +}; + +export type PlanWithServiceType = { + id: string; + createdAt: string; + updatedAt: string; + name: string; + duration: number; + isFree: boolean; + price: number; + originalPrice: number; + isActive: boolean; + service: ServiceWithDetailsType; + deletedAt: string | null; +}; + +export type UserSubscriptionWithDetailsType = { + id: string; + createdAt: string; + updatedAt: string; + plan: PlanWithServiceType; + startDate: string; + endDate: string; + businessName: string; + businessPhone: string; + description: string | null; + slug: string; + status: "ACTIVE" | "INACTIVE" | "CANCELED"; +}; + +export type GetSubscriptionResponseType = { + statusCode: number; + success: boolean; + data: { + userSubscription: UserSubscriptionWithDetailsType; + }; +}; diff --git a/src/router/Main.tsx b/src/router/Main.tsx index e5a1b98..0461f43 100644 --- a/src/router/Main.tsx +++ b/src/router/Main.tsx @@ -32,6 +32,7 @@ import BuyService from '../pages/service/BuyService' import Support from '../pages/support/Support' import SupportInfo from '../pages/support/SupportInfo' import Invoice from '../pages/receipts/Invoice' +import { ManageRestaurant } from '../pages/service/ManageRestaurant' const MainRouter: FC = () => { return ( @@ -45,6 +46,7 @@ const MainRouter: FC = () => { } /> } /> } /> + } /> } /> } /> } />