fix hidden free plan + show remain days
This commit is contained in:
@@ -5,6 +5,8 @@ import { ArrowLeft, More } from 'iconsax-react'
|
||||
import Button from './Button'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ItemServiceType } from '../pages/service/types/ServiecTypes'
|
||||
import moment from 'moment-jalaali'
|
||||
import { NumberFormat } from '../config/func'
|
||||
|
||||
type Props = {
|
||||
item: ItemServiceType,
|
||||
@@ -15,6 +17,7 @@ type Props = {
|
||||
isQuikAccess?: boolean,
|
||||
onMoreClick?: () => void,
|
||||
subscriptionId?: string,
|
||||
endDate?: string,
|
||||
}
|
||||
|
||||
const ServiceItem: FC<Props> = (props: Props) => {
|
||||
@@ -22,6 +25,34 @@ const ServiceItem: FC<Props> = (props: Props) => {
|
||||
const { t } = useTranslation('global')
|
||||
const { item } = props
|
||||
|
||||
const getRemainingDays = (endDate: string): number => {
|
||||
const now = moment()
|
||||
const end = moment(endDate)
|
||||
const diff = end.diff(now, 'days')
|
||||
return diff
|
||||
}
|
||||
|
||||
const getRemainingDaysColor = (days: number): string => {
|
||||
if (days < 0) return 'text-red-600'
|
||||
if (days <= 7) return 'text-red-500'
|
||||
if (days <= 30) return 'text-orange-500'
|
||||
return 'text-green-600'
|
||||
}
|
||||
|
||||
const getRemainingDaysText = (endDate: string): string => {
|
||||
const days = getRemainingDays(endDate)
|
||||
if (days < 0) {
|
||||
return `${NumberFormat(Math.abs(days))} روز گذشته`
|
||||
}
|
||||
if (days === 0) {
|
||||
return 'امروز آخرین روز'
|
||||
}
|
||||
if (days === 1) {
|
||||
return '۱ روز باقی مانده'
|
||||
}
|
||||
return `${NumberFormat(days)} روز باقی مانده`
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`flex-1 relative flex flex-col self-stretch min-w-[45%] xl:min-w-[30%] bg-white rounded-3xl xl:p-6 p-4 ${props.className} ${props.isDisabled ? 'opacity-50' : ''}`}>
|
||||
{
|
||||
@@ -44,8 +75,16 @@ const ServiceItem: FC<Props> = (props: Props) => {
|
||||
{props.businessName}
|
||||
</div>
|
||||
}
|
||||
{
|
||||
props.isLinkPanel && props.endDate &&
|
||||
<div className={`mt-1 text-[11px] ${getRemainingDaysColor(getRemainingDays(props.endDate))}`}>
|
||||
{getRemainingDaysText(props.endDate)}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{
|
||||
!props.isLinkPanel &&
|
||||
<div className='mt-4 text-xs'>
|
||||
|
||||
+2
-1
@@ -136,7 +136,8 @@
|
||||
"short_description": "توضیح کوتاه",
|
||||
"confrim_and_invoice": "تایید و صدور صورت حساب",
|
||||
"extent": "تمدید پلن",
|
||||
"extend": "تمدید"
|
||||
"extend": "تمدید",
|
||||
"end_date": "تاریخ پایان"
|
||||
},
|
||||
"loading": "در حال بارگذاری",
|
||||
"footer": {
|
||||
|
||||
@@ -66,6 +66,7 @@ const MyServices: FC = () => {
|
||||
businessName={item.businessName}
|
||||
isDisabled={item.status === 'INACTIVE'}
|
||||
subscriptionId={item.id}
|
||||
endDate={item.endDate}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { FC, useEffect, useState, useMemo } from 'react'
|
||||
import RadioGroup from '../../../components/RadioGroup'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '../../../components/Button'
|
||||
@@ -6,7 +6,7 @@ import { ArrowLeft } from 'iconsax-react'
|
||||
import { PlanItemType, ServiceDetailDataType } from '../types/ServiecTypes'
|
||||
import { NumberFormat } from '../../../config/func'
|
||||
import { useBuyService } from '../hooks/useServiceData'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Link, useSearchParams } from 'react-router-dom'
|
||||
import { Pages } from '../../../config/Pages'
|
||||
import ExtendPlan from './ExtendPlan'
|
||||
|
||||
@@ -14,33 +14,48 @@ type Props = {
|
||||
data: ServiceDetailDataType,
|
||||
}
|
||||
|
||||
const ServiceHeader: FC<Props> = (props: Props) => {
|
||||
|
||||
const { data } = props
|
||||
const ServiceHeader: FC<Props> = ({ data }) => {
|
||||
const { t } = useTranslation('global')
|
||||
// Get query params from URL
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const [subscriptionId, setSubscriptionId] = useState<string>('')
|
||||
|
||||
const [planSelected, setPlanSelected] = useState<string>(data?.subscriptionPlans[0]?.id)
|
||||
const [price, setPrice] = useState<number>(data?.subscriptionPlans[0]?.price)
|
||||
const [finalPrice, setFinalPrice] = useState<number>(0)
|
||||
const [searchParams] = useSearchParams()
|
||||
const subscriptionId = searchParams.get('id') || ''
|
||||
const buyService = useBuyService()
|
||||
|
||||
// فیلتر کردن پلنهای رایگان هنگام تمدید
|
||||
const availablePlans = useMemo(() => {
|
||||
if (!data?.subscriptionPlans) return []
|
||||
|
||||
return subscriptionId
|
||||
? data.subscriptionPlans.filter((plan: PlanItemType) => plan.price > 0)
|
||||
: data.subscriptionPlans
|
||||
}, [subscriptionId, data?.subscriptionPlans])
|
||||
|
||||
const [planSelected, setPlanSelected] = useState<string>(availablePlans[0]?.id || '')
|
||||
const [finalPrice, setFinalPrice] = useState<number>(0)
|
||||
const [originalPrice, setOriginalPrice] = useState<number>(0)
|
||||
|
||||
// بهروزرسانی قیمتها هنگام تغییر پلن انتخاب شده
|
||||
useEffect(() => {
|
||||
const selectedPlan = availablePlans.find((plan) => plan.id === planSelected)
|
||||
if (selectedPlan) {
|
||||
setFinalPrice(selectedPlan.price)
|
||||
setOriginalPrice(selectedPlan.originalPrice)
|
||||
}
|
||||
}, [planSelected, availablePlans])
|
||||
|
||||
const plan: PlanItemType = data?.subscriptionPlans.find((item) => item.id === planSelected)
|
||||
setFinalPrice(plan.price)
|
||||
setPrice(plan?.originalPrice)
|
||||
|
||||
}, [planSelected])
|
||||
|
||||
// انتخاب خودکار اولین پلن موجود در صورت عدم وجود پلن انتخاب شده
|
||||
useEffect(() => {
|
||||
setSubscriptionId(urlParams.get('id') || '')
|
||||
}, [window.location.search])
|
||||
|
||||
|
||||
if (availablePlans.length > 0 && !availablePlans.find(p => p.id === planSelected)) {
|
||||
setPlanSelected(availablePlans[0].id)
|
||||
}
|
||||
}, [availablePlans, planSelected])
|
||||
|
||||
// تبدیل پلنها به فرمت مورد نیاز RadioGroup
|
||||
const planItems = useMemo(() => {
|
||||
return availablePlans.map((plan) => ({
|
||||
label: plan.name,
|
||||
value: plan.id
|
||||
}))
|
||||
}, [availablePlans])
|
||||
|
||||
return (
|
||||
<div className='w-full p-6 bg-white rounded-3xl flex xl:flex-row flex-col items-end xl:justify-between'>
|
||||
@@ -58,12 +73,7 @@ const ServiceHeader: FC<Props> = (props: Props) => {
|
||||
</p>
|
||||
<div className='hidden xl:flex gap-5 mt-5'>
|
||||
<RadioGroup
|
||||
items={data?.subscriptionPlans?.map((item) => {
|
||||
return {
|
||||
label: item?.name,
|
||||
value: item?.id
|
||||
}
|
||||
})}
|
||||
items={planItems}
|
||||
onChange={setPlanSelected}
|
||||
selected={planSelected}
|
||||
/>
|
||||
@@ -74,12 +84,7 @@ const ServiceHeader: FC<Props> = (props: Props) => {
|
||||
<div className='flex w-full flex-col justify-between xl:items-end'>
|
||||
<div className='flex xl:!hidden gap-5 mt-5'>
|
||||
<RadioGroup
|
||||
items={data?.subscriptionPlans?.map((item) => {
|
||||
return {
|
||||
label: item?.name,
|
||||
value: item?.id
|
||||
}
|
||||
})}
|
||||
items={planItems}
|
||||
onChange={setPlanSelected}
|
||||
selected={planSelected}
|
||||
/>
|
||||
@@ -87,43 +92,36 @@ const ServiceHeader: FC<Props> = (props: Props) => {
|
||||
<div className='flex gap-4 mt-5 xl:mt-0 items-center justify-between xl:justify-normal'>
|
||||
<div className='text-xs whitespace-nowrap flex gap-1 items-center'>
|
||||
<div className='flex gap-2'>
|
||||
{
|
||||
finalPrice !== price &&
|
||||
{finalPrice !== originalPrice && (
|
||||
<div className='line-through text-xs text-description'>
|
||||
{NumberFormat(Number(price))}
|
||||
{NumberFormat(originalPrice)}
|
||||
</div>
|
||||
}
|
||||
<div>{finalPrice === 0 ? t('free') : NumberFormat(Number(finalPrice))}</div>
|
||||
)}
|
||||
<div>
|
||||
{finalPrice === 0 ? t('free') : NumberFormat(finalPrice)}
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
finalPrice !== 0 && <span>{t('toman')}</span>
|
||||
}
|
||||
{finalPrice !== 0 && <span>{t('toman')}</span>}
|
||||
</div>
|
||||
{
|
||||
subscriptionId ? (
|
||||
<ExtendPlan
|
||||
subscriptionId={subscriptionId}
|
||||
planId={planSelected}
|
||||
serviceId={data.id}
|
||||
/>
|
||||
) :
|
||||
planSelected ?
|
||||
<Link to={Pages.services.buy + `${data.id}/${planSelected}`}>
|
||||
<Button
|
||||
// onClick={handleBuy}
|
||||
isLoading={buyService.isPending}
|
||||
className='bg-description xl:max-w-full max-w-[100px] text-xs h-8 bg-opacity-20 text-black px-4'
|
||||
>
|
||||
<div className='flex gap-1 items-center'>
|
||||
<div>
|
||||
{t('service.buy')}
|
||||
</div>
|
||||
<ArrowLeft className='size-4' color='black' />
|
||||
</div>
|
||||
</Button>
|
||||
</Link>
|
||||
: null
|
||||
}
|
||||
{subscriptionId ? (
|
||||
<ExtendPlan
|
||||
subscriptionId={subscriptionId}
|
||||
planId={planSelected}
|
||||
serviceId={data.id}
|
||||
/>
|
||||
) : planSelected && (
|
||||
<Link to={`${Pages.services.buy}${data.id}/${planSelected}`}>
|
||||
<Button
|
||||
isLoading={buyService.isPending}
|
||||
className='bg-description xl:max-w-full max-w-[100px] text-xs h-8 bg-opacity-20 text-black px-4'
|
||||
>
|
||||
<div className='flex gap-1 items-center'>
|
||||
<div>{t('service.buy')}</div>
|
||||
<ArrowLeft className='size-4' color='black' />
|
||||
</div>
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user