diff --git a/src/components/ServiceItem.tsx b/src/components/ServiceItem.tsx index 9a6bf8f..d884aab 100644 --- a/src/components/ServiceItem.tsx +++ b/src/components/ServiceItem.tsx @@ -14,6 +14,7 @@ type Props = { isDisabled?: boolean, isQuikAccess?: boolean, onMoreClick?: () => void, + subscriptionId?: string, } const ServiceItem: FC = (props: Props) => { @@ -53,10 +54,10 @@ const ServiceItem: FC = (props: Props) => { } -
+
+ + { + props.subscriptionId && + +
+ {t('service.extend')} + +
+ + + }
) diff --git a/src/langs/fa.json b/src/langs/fa.json index 509371c..41e2e0f 100644 --- a/src/langs/fa.json +++ b/src/langs/fa.json @@ -134,7 +134,9 @@ "business_name": "نام کسب و کار", "phone_business": "شماره تماس کسب و کار", "short_description": "توضیح کوتاه", - "confrim_and_invoice": "تایید و صدور صورت حساب" + "confrim_and_invoice": "تایید و صدور صورت حساب", + "extent": "تمدید پلن", + "extend": "تمدید" }, "loading": "در حال بارگذاری", "footer": { diff --git a/src/pages/service/DetailService.tsx b/src/pages/service/DetailService.tsx index c716d60..5ac413a 100644 --- a/src/pages/service/DetailService.tsx +++ b/src/pages/service/DetailService.tsx @@ -17,6 +17,7 @@ import { ReviewItemType } from './types/ServiecTypes' const DetailService: FC = () => { const { id } = useParams() + const { t } = useTranslation('global') const getAdsLeft = useGetAds(AdsDisplayLocation.SINGLE_SERVICE_PAGE) diff --git a/src/pages/service/MyServices.tsx b/src/pages/service/MyServices.tsx index 84d3889..d815a7d 100644 --- a/src/pages/service/MyServices.tsx +++ b/src/pages/service/MyServices.tsx @@ -65,6 +65,7 @@ const MyServices: FC = () => { isLinkPanel businessName={item.businessName} isDisabled={item.status === 'INACTIVE'} + subscriptionId={item.id} /> ) }) diff --git a/src/pages/service/components/ExtendPlan.tsx b/src/pages/service/components/ExtendPlan.tsx new file mode 100644 index 0000000..fa683b9 --- /dev/null +++ b/src/pages/service/components/ExtendPlan.tsx @@ -0,0 +1,57 @@ +import { type FC } from 'react' +import { useTranslation } from 'react-i18next' +import Button from '../../../components/Button' +import { ArrowLeft } from 'iconsax-react' +import { useExtentSubscription } from '../hooks/useServiceData' +import { toast } from '../../../components/Toast' +import { ErrorType } from '../../../helpers/types' +import { Pages } from '../../../config/Pages' +import { useNavigate } from 'react-router-dom' + +type Props = { + subscriptionId: string + planId: string, + serviceId: string +} +const ExtendPlan: FC = (props) => { + + const { t } = useTranslation('global') + const { subscriptionId, planId, serviceId } = props + const { mutate: extentSubscription, isPending } = useExtentSubscription() + const navigate = useNavigate() + const handleExtentSubscription = () => { + extentSubscription({ + subscriptionId: subscriptionId, + planId: planId, + serviceId: serviceId, + }, { + onSuccess: (data) => { + toast(data?.data?.message, 'success') + navigate(Pages.receipts.detail + data?.data?.invoice?.id) + + }, + onError: (error: ErrorType) => { + toast(error?.response?.data?.error.message[0], 'error') + } + }) + } + + return ( +
+ +
+ ) +} + +export default ExtendPlan \ No newline at end of file diff --git a/src/pages/service/components/ServiceHeader.tsx b/src/pages/service/components/ServiceHeader.tsx index 302494c..b1810f4 100644 --- a/src/pages/service/components/ServiceHeader.tsx +++ b/src/pages/service/components/ServiceHeader.tsx @@ -8,6 +8,7 @@ import { NumberFormat } from '../../../config/func' import { useBuyService } from '../hooks/useServiceData' import { Link } from 'react-router-dom' import { Pages } from '../../../config/Pages' +import ExtendPlan from './ExtendPlan' type Props = { data: ServiceDetailDataType, @@ -17,6 +18,10 @@ const ServiceHeader: FC = (props: Props) => { const { data } = props const { t } = useTranslation('global') + // Get query params from URL + const urlParams = new URLSearchParams(window.location.search) + const [subscriptionId, setSubscriptionId] = useState('') + const [planSelected, setPlanSelected] = useState(data?.subscriptionPlans[0]?.id) const [price, setPrice] = useState(data?.subscriptionPlans[0]?.price) const [finalPrice, setFinalPrice] = useState(0) @@ -30,6 +35,12 @@ const ServiceHeader: FC = (props: Props) => { }, [planSelected]) + useEffect(() => { + setSubscriptionId(urlParams.get('id') || '') + }, [window.location.search]) + + + return (
@@ -89,21 +100,29 @@ const ServiceHeader: FC = (props: Props) => { }
{ - planSelected && - - - + subscriptionId ? ( + + ) : + planSelected ? + + + + : null } diff --git a/src/pages/service/hooks/useServiceData.ts b/src/pages/service/hooks/useServiceData.ts index 508cd66..532db65 100644 --- a/src/pages/service/hooks/useServiceData.ts +++ b/src/pages/service/hooks/useServiceData.ts @@ -56,3 +56,9 @@ export const useGetServiceBySlug = (slug: string) => { queryFn: () => api.getServiceBySlug(slug), }); }; + +export const useExtentSubscription = () => { + return useMutation({ + mutationFn: api.extentSubscription, + }); +}; diff --git a/src/pages/service/service/ServiceService.ts b/src/pages/service/service/ServiceService.ts index ea0cabd..5646be8 100644 --- a/src/pages/service/service/ServiceService.ts +++ b/src/pages/service/service/ServiceService.ts @@ -1,5 +1,10 @@ import axios from "../../../config/axios"; -import { BuyServiceType, CreateReviewType } from "../types/ServiecTypes"; +import { + BuyServiceType, + CreateReviewType, + ExtentSubscriptionType, + ExtentSubscriptionResponseType, +} from "../types/ServiecTypes"; export const getServiceSuggestedDanak = async () => { const { data } = await axios.get(`/danak-services/suggested`); @@ -47,3 +52,13 @@ export const getServiceBySlug = async (slug: string) => { const { data } = await axios.get(`/danak-services/slug/${slug}`); return data; }; + +export const extentSubscription = async ( + params: ExtentSubscriptionType +): Promise => { + const { data } = await axios.put( + `/subscriptions/${params.subscriptionId}/subscribe`, + params + ); + return data; +}; diff --git a/src/pages/service/types/ServiecTypes.ts b/src/pages/service/types/ServiecTypes.ts index 075c014..73fc52d 100644 --- a/src/pages/service/types/ServiecTypes.ts +++ b/src/pages/service/types/ServiecTypes.ts @@ -148,3 +148,132 @@ export type ReviewItemType = { profilePic: string | null; }; }; + +export type ExtentSubscriptionType = { + planId: string; + serviceId: string; + subscriptionId?: string; +}; + +export type UserType = { + id: string; + createdAt: string; + updatedAt: string; + email: string; + phone: string; + userName: string; + firstName: string; + lastName: string; + birthDate: string; + nationalCode: string; + profilePic: string | null; + emailVerified: boolean; + financialType: string; + deletedAt: string | null; +}; + +export type PlanType = { + id: string; + createdAt: string; + updatedAt: string; + name: string; + duration: number; + isFree: boolean; + price: number; + originalPrice: number; + isActive: boolean; + service: ServiceType; + deletedAt: string | null; +}; + +export type ServiceType = { + 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; + deletedAt: string | null; +}; + +export type UserSubscriptionType = { + id: string; + createdAt: string; + updatedAt: string; + user: UserType; + plan: PlanType; + startDate: string; + endDate: string; + businessName: string; + businessPhone: string; + description: string; + slug: string; + status: "ACTIVE" | "INACTIVE" | "CANCELED"; +}; + +export type InvoiceItemType = { + id: string; + createdAt: string; + updatedAt: string; + name: string; + count: number; + discount: number; + unitPrice: number; + totalPrice: number; + subscriptionPlan: UserSubscriptionType; +}; + +export type InvoiceType = { + id: string; + createdAt: string; + updatedAt: string; + numericId: number; + user: UserType; + totalPrice: { + s: number; + e: number; + d: number[]; + }; + originalPrice: { + s: number; + e: number; + d: number[]; + }; + status: "WAIT_PAYMENT" | "PAID" | "CANCELED"; + dueDate: string; + paidAt: string | null; + tax: number; + lateFee: number | null; + isRecurring: boolean; + recurringPeriod: string | null; + maxRecurringCycles: number; + currentRecurringCycle: number; + isExternal: boolean; + externalBusinessId: string | null; + items: InvoiceItemType[]; +}; + +export type ExtentSubscriptionResponseType = { + statusCode: number; + success: boolean; + data: { + message: string; + userSubscription: UserSubscriptionType; + invoice: InvoiceType; + }; +};