quik acess
This commit is contained in:
@@ -7,7 +7,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import { ItemServiceType } from '../pages/service/types/ServiecTypes'
|
||||
|
||||
type Props = {
|
||||
item: ItemServiceType
|
||||
item: ItemServiceType,
|
||||
className?: string,
|
||||
}
|
||||
|
||||
const ServiceItem: FC<Props> = (props: Props) => {
|
||||
@@ -16,7 +17,7 @@ const ServiceItem: FC<Props> = (props: Props) => {
|
||||
const { item } = props
|
||||
|
||||
return (
|
||||
<div className='flex-1 min-w-[45%] xl:min-w-[30%] bg-white rounded-3xl xl:p-6 p-4'>
|
||||
<div className={`flex-1 min-w-[45%] xl:min-w-[30%] bg-white rounded-3xl xl:p-6 p-4 ${props.className}`}>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<div className='xl:size-[50px] size-10 overflow-hidden rounded-xl'>
|
||||
<img src={item.icon} alt={item.name} className='w-full h-full' />
|
||||
|
||||
@@ -419,5 +419,18 @@
|
||||
"amount": "مبلغ پرداختی",
|
||||
"date": "تاریخ",
|
||||
"back": "بازگشت"
|
||||
},
|
||||
"discount": {
|
||||
"number": "شماره",
|
||||
"type": "نوع تحفیف",
|
||||
"code": "کد تخفیف",
|
||||
"CODE": "کد",
|
||||
"start_date": "تاریخ شروع",
|
||||
"end_date": "تاریخ پایان",
|
||||
"percent_ammount": "درصد / مبلغ تخفیف",
|
||||
"service": "سرویس",
|
||||
"status": "وضعیت",
|
||||
"active": "فعال",
|
||||
"deactive": "غیرفعال"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { FC } from 'react'
|
||||
import { useGetMyDiscount } from './hooks/useDiscountData'
|
||||
import PageLoading from '../../components/PageLoading'
|
||||
import Td from '../../components/Td'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { DiscountItemType } from './types/DiscountTypes'
|
||||
import moment from 'moment-jalaali'
|
||||
|
||||
const MyDiscountList: FC = () => {
|
||||
|
||||
const { t } = useTranslation('global')
|
||||
const getDiscounts = useGetMyDiscount()
|
||||
|
||||
return (
|
||||
<div className='mt-4'>
|
||||
{
|
||||
getDiscounts.isPending ?
|
||||
<PageLoading />
|
||||
:
|
||||
<div className='relative overflow-x-auto rounded-3xl mt-9 w-full'>
|
||||
<table className='w-full text-sm '>
|
||||
<thead className='thead'>
|
||||
<tr>
|
||||
<Td text={t('discount.number')} />
|
||||
<Td text={t('discount.type')} />
|
||||
<Td text={t('discount.code')} />
|
||||
<Td text={t('discount.start_date')} />
|
||||
<Td text={t('discount.end_date')} />
|
||||
<Td text={t('discount.percent_ammount')} />
|
||||
<Td text={t('discount.service')} />
|
||||
<Td text={t('discount.status')} />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
getDiscounts.data?.data?.discounts?.map((item: DiscountItemType, index: number) => {
|
||||
return (
|
||||
<tr key={item.id} className='tr'>
|
||||
<Td text={String(index + 1)} />
|
||||
<Td text={t(`discount.${item.type}`)} />
|
||||
<Td text={item.code} />
|
||||
<Td text={moment(item.startDate).format('jYYYY-jMM-jDD')} />
|
||||
<Td text={moment(item.endDate).format('jYYYY-jMM-jDD')} />
|
||||
<Td text={item.type === 'CODE' ? item.amount + '%' : item.amount + 'تومان'} />
|
||||
<Td text={item.subscriptionPlans[0]?.service?.name} />
|
||||
<Td text={''}>
|
||||
{item.isActive ? <span className='text-green-400'>{t('discount.active')}</span> : <span className='text-gray-500'>{t('discount.inactive')}</span>}
|
||||
</Td>
|
||||
</tr>
|
||||
)
|
||||
})
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MyDiscountList
|
||||
@@ -0,0 +1,9 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import * as api from "../service/DiscountService";
|
||||
|
||||
export const useGetMyDiscount = () => {
|
||||
return useQuery({
|
||||
queryKey: ["my-discount"],
|
||||
queryFn: () => api.getMyDiscounts(),
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
import axios from "../../../config/axios";
|
||||
|
||||
export const getMyDiscounts = async () => {
|
||||
const { data } = await axios.get(`/discounts/user-discounts`);
|
||||
return data;
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
export type DiscountItemType = {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
title: string;
|
||||
type: string;
|
||||
calculationType: string;
|
||||
amount: number;
|
||||
isActive: boolean;
|
||||
code: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
subscriptionPlans: {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
name: string;
|
||||
duration: number;
|
||||
price: number;
|
||||
isActive: boolean;
|
||||
service: {
|
||||
id: string;
|
||||
name: string;
|
||||
title: string;
|
||||
description: string;
|
||||
link: string;
|
||||
icon: string;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
+37
-6
@@ -1,4 +1,4 @@
|
||||
import { FC } from 'react'
|
||||
import { FC, Fragment } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ArrowLeft, Element3, Messages3, NotificationStatus, Receipt21 } from 'iconsax-react'
|
||||
import ItemDashboard from './components/ItemDashboard'
|
||||
@@ -10,14 +10,26 @@ import { Carousel } from "@material-tailwind/react";
|
||||
import { useGetAds } from '../ads/hooks/useAdsData'
|
||||
import { AdsDisplayLocation, AdsItemType } from '../ads/types/AdsTypes'
|
||||
import { Pages } from '../../config/Pages'
|
||||
import { useGetQuikAccess } from './hooks/useHomeData'
|
||||
import { QuikAccessItemType } from './types/HomeTypes'
|
||||
import ServiceItem from '../../components/ServiceItem'
|
||||
import PageLoading from '../../components/PageLoading'
|
||||
|
||||
|
||||
const Home: FC = () => {
|
||||
|
||||
const { t } = useTranslation('global')
|
||||
const getAds = useGetAds(AdsDisplayLocation.HOMEPAGE_TOP)
|
||||
const getQuikAccess = useGetQuikAccess()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{
|
||||
getAds.isPending || getQuikAccess.isPending ?
|
||||
<div className='mt-5'>
|
||||
<PageLoading />
|
||||
</div>
|
||||
:
|
||||
<div className='w-full flex gap-6'>
|
||||
<div className='flex-1'>
|
||||
<Carousel autoplay className="rounded-xl h-fit dltr" placeholder="" onPointerEnterCapture={() => { }} onPointerLeaveCapture={() => { }} >
|
||||
@@ -100,20 +112,39 @@ const Home: FC = () => {
|
||||
<TitleLine title={t('home.access')} />
|
||||
</div>
|
||||
|
||||
<div className='mt-8 flex flex-wrap gap-6 items-center'>
|
||||
<div className='flex-1 min-w-[40%] xl:min-w-[20%] h-[160px] rounded-3xl bg-white flex flex-col gap-4 justify-center items-center'>
|
||||
<div className='mt-8 flex flex-wrap gap-6 items-stretch'>
|
||||
{
|
||||
getQuikAccess?.data?.data?.quickAccesses?.length === 0 &&
|
||||
<div className='flex-1 min-w-[40%] xl:min-w-[20%] min-h-[152px] rounded-3xl bg-white flex flex-col gap-4 justify-center items-center'>
|
||||
<img src={AccessbilityImage} className='w-10' />
|
||||
<div className='text-xs'>
|
||||
{t('home.add_access')}
|
||||
</div>
|
||||
</div>
|
||||
<BoxNewAccessbility />
|
||||
<BoxNewAccessbility />
|
||||
<BoxNewAccessbility />
|
||||
}
|
||||
{
|
||||
getQuikAccess.data?.data?.quickAccesses?.map((item: QuikAccessItemType) => {
|
||||
return (
|
||||
<ServiceItem
|
||||
key={item.service.id}
|
||||
item={item.service}
|
||||
className='flex-1 min-w-[40%] xl:!min-w-[20%] xl:p-6 p-4 flex flex-col'
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
{Array.from({ length: 4 - (getQuikAccess.data?.data?.quickAccesses?.length || 1) }).map((_, index) => (
|
||||
<BoxNewAccessbility key={index} />
|
||||
))}
|
||||
|
||||
<div className='flex-1 min-w-[40%] xl:min-w-[20%] xl:p-6 p-4'></div>
|
||||
<div className='flex-1 min-w-[40%] xl:min-w-[20%] xl:p-6 p-4'></div>
|
||||
</div>
|
||||
</div>
|
||||
<DanakLearning />
|
||||
</div>
|
||||
}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@ import { FC, useState } from 'react'
|
||||
import DefaulModal from '../../../components/DefaulModal'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Input from '../../../components/Input'
|
||||
import SwitchComponent from '../../../components/Switch'
|
||||
import { useGetMyServices } from '../../service/hooks/useServiceData'
|
||||
import { MyServicesItem } from '../../service/types/ServiecTypes'
|
||||
import PageLoading from '../../../components/PageLoading'
|
||||
import { useGetQuikAccess, useQuikAccess, useRemoveQuikAccess } from '../hooks/useHomeData'
|
||||
import ChangeQuikAccess from './ChangeQuikAccess'
|
||||
|
||||
const BoxNewAccessbility: FC = () => {
|
||||
|
||||
@@ -14,12 +15,31 @@ const BoxNewAccessbility: FC = () => {
|
||||
const [open, setOpen] = useState<boolean>(false)
|
||||
const { t } = useTranslation('global')
|
||||
const getMyservices = useGetMyServices(search)
|
||||
const getQuikAccess = useGetQuikAccess()
|
||||
const quikAccess = useQuikAccess()
|
||||
const removeQuikAceess = useRemoveQuikAccess()
|
||||
|
||||
const handleQuikAccess = (value: boolean, id: string) => {
|
||||
if (value) {
|
||||
quikAccess.mutate(id, {
|
||||
onSuccess: () => {
|
||||
getQuikAccess.refetch()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
removeQuikAceess.mutate(id, {
|
||||
onSuccess: () => {
|
||||
getQuikAccess.refetch()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
onClick={() => setOpen(true)}
|
||||
className="flex-1 min-w-[40%] xl:min-w-[20%] flex justify-center items-center h-[160px]"
|
||||
className="flex-1 min-w-[40%] xl:p-6 p-4 xl:min-w-[20%] flex justify-center items-center min-h-[152px]"
|
||||
style={{
|
||||
position: 'relative',
|
||||
}}
|
||||
@@ -91,6 +111,7 @@ const BoxNewAccessbility: FC = () => {
|
||||
</div>
|
||||
:
|
||||
getMyservices.data?.data?.subscriptions?.map((item: MyServicesItem) => {
|
||||
const active = getQuikAccess.data?.data?.quickAccesses?.find((o: any) => o.service?.id === item.plan?.service?.id) ? true : false
|
||||
return (
|
||||
<div key={item.id} className='flex-1 xl:min-w-[40%] min-w-full flex justify-between items-center border-b border-[#8C90A3] border-opacity-30 py-2'>
|
||||
<div className='flex gap-4'>
|
||||
@@ -107,9 +128,10 @@ const BoxNewAccessbility: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<SwitchComponent
|
||||
active
|
||||
onChange={() => { }}
|
||||
<ChangeQuikAccess
|
||||
id={item.plan?.service?.id}
|
||||
value={active}
|
||||
onChange={handleQuikAccess}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { FC, useState } from 'react'
|
||||
import SwitchComponent from '../../../components/Switch'
|
||||
|
||||
type Props = {
|
||||
id: string,
|
||||
value: boolean,
|
||||
onChange: (value: boolean, id: string) => void
|
||||
}
|
||||
|
||||
|
||||
const ChangeQuikAccess: FC<Props> = (props: Props) => {
|
||||
|
||||
const [active, setActive] = useState<boolean>(props.value)
|
||||
|
||||
return (
|
||||
<SwitchComponent
|
||||
active={active}
|
||||
onChange={(value) => {
|
||||
props.onChange(value, props.id)
|
||||
setActive(value)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChangeQuikAccess
|
||||
@@ -0,0 +1,21 @@
|
||||
import * as api from "../service/HomeService";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
|
||||
export const useQuikAccess = () => {
|
||||
return useMutation({
|
||||
mutationFn: (variables: string) => api.quikAccess(variables),
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetQuikAccess = () => {
|
||||
return useQuery({
|
||||
queryKey: ["quik-access"],
|
||||
queryFn: () => api.getQuikAccess(),
|
||||
});
|
||||
};
|
||||
|
||||
export const useRemoveQuikAccess = () => {
|
||||
return useMutation({
|
||||
mutationFn: (variables: string) => api.removeQuikAccess(variables),
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import axios from "../../../config/axios";
|
||||
|
||||
export const quikAccess = async (serviceId: string) => {
|
||||
const { data } = await axios.post(
|
||||
`/subscriptions/${serviceId}/add-quick-access`
|
||||
);
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getQuikAccess = async () => {
|
||||
const { data } = await axios.get(`/subscriptions/quick-access`);
|
||||
return data;
|
||||
};
|
||||
|
||||
export const removeQuikAccess = async (serviceId: string) => {
|
||||
const { data } = await axios.delete(
|
||||
`/subscriptions/${serviceId}/remove-quick-access`
|
||||
);
|
||||
return data;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
import { ItemServiceType } from "../../service/types/ServiecTypes";
|
||||
|
||||
export type QuikAccessItemType = {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
isActive: boolean;
|
||||
service: ItemServiceType;
|
||||
author: string;
|
||||
createDate: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
@@ -95,10 +95,15 @@ const TicketDetail: FC = () => {
|
||||
:
|
||||
<div className='flex xl:flex-row flex-col-reverse gap-6 xl:mt-8 mt-6'>
|
||||
<div className='flex-1 bg-white py-8 xl:px-10 px-4 rounded-3xl'>
|
||||
<div className='gap-6 rowTwoInput'>
|
||||
<Input
|
||||
label={t('ticket.subject')}
|
||||
value={getMessages.data?.data?.ticket?.subject}
|
||||
readOnly
|
||||
/>
|
||||
<div className='gap-6 rowTwoInput mt-5'>
|
||||
<Input
|
||||
label={t('ticket.select_your_service')}
|
||||
value={'دی منو'}
|
||||
value={getMessages.data?.data?.ticket?.danakService?.name}
|
||||
readOnly
|
||||
/>
|
||||
<Input
|
||||
@@ -108,10 +113,6 @@ const TicketDetail: FC = () => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-8 xl:text-sm text-xs'>
|
||||
{getMessages.data?.data?.ticket?.subject}
|
||||
</div>
|
||||
|
||||
{
|
||||
getMessages.data?.data?.messages.map((item: any) => {
|
||||
if (item?.author?.roles[0]?.name === 'user') {
|
||||
|
||||
@@ -26,6 +26,7 @@ import CreateTicket from '../pages/ticket/CreateTicket'
|
||||
import TicketDetail from '../pages/ticket/Detail'
|
||||
import Financial from '../pages/financial/Financial'
|
||||
import CallBack from '../pages/wallet/CallBack'
|
||||
import MyDiscountList from '../pages/discounts/List'
|
||||
|
||||
const MainRouter: FC = () => {
|
||||
return (
|
||||
@@ -55,6 +56,7 @@ const MainRouter: FC = () => {
|
||||
<Route path={Pages.callback + ':id'} element={<CallBack />} />
|
||||
<Route path={Pages.profile} element={<Profile />} />
|
||||
<Route path={Pages.financial} element={<Financial />} />
|
||||
<Route path={Pages.discounts} element={<MyDiscountList />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user