skeleton logout and ...
This commit is contained in:
+1
-1
@@ -82,7 +82,7 @@ define(['./workbox-e7681877'], (function (workbox) { 'use strict';
|
|||||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||||
}, {
|
}, {
|
||||||
"url": "index.html",
|
"url": "index.html",
|
||||||
"revision": "0.qrm0hc87vi"
|
"revision": "0.l1l8csoi5qg"
|
||||||
}], {});
|
}], {});
|
||||||
workbox.cleanupOutdatedCaches();
|
workbox.cleanupOutdatedCaches();
|
||||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import { clx } from '../../helpers/utils'
|
|||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { Pages } from '../../config/Pages'
|
import { Pages } from '../../config/Pages'
|
||||||
import { useGetAnnoncement } from './hooks/useAnnoncementData'
|
import { useGetAnnoncement } from './hooks/useAnnoncementData'
|
||||||
import PageLoading from '../../components/PageLoading'
|
|
||||||
import { AnnoncementItemType } from './types/AnnoncementTypes'
|
import { AnnoncementItemType } from './types/AnnoncementTypes'
|
||||||
import moment from 'moment-jalaali'
|
import moment from 'moment-jalaali'
|
||||||
import { Helmet } from 'react-helmet-async'
|
import { Helmet } from 'react-helmet-async'
|
||||||
|
import AnouncementSkeleton from './components/AnouncementSkeleton'
|
||||||
|
|
||||||
const AnnouncementtList: FC = () => {
|
const AnnouncementtList: FC = () => {
|
||||||
|
|
||||||
@@ -62,19 +62,20 @@ const AnnouncementtList: FC = () => {
|
|||||||
</div> */}
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{
|
|
||||||
getAnnoncements.isPending ?
|
|
||||||
<div className='mt-8'>
|
|
||||||
<PageLoading />
|
|
||||||
</div>
|
|
||||||
:
|
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className='mt-8'>
|
<div className='mt-8'>
|
||||||
{
|
{
|
||||||
|
getAnnoncements.isPending ?
|
||||||
|
<Fragment>
|
||||||
|
<AnouncementSkeleton />
|
||||||
|
<AnouncementSkeleton />
|
||||||
|
<AnouncementSkeleton />
|
||||||
|
</Fragment>
|
||||||
|
:
|
||||||
getAnnoncements.data?.data?.announcements?.map((item: AnnoncementItemType) => {
|
getAnnoncements.data?.data?.announcements?.map((item: AnnoncementItemType) => {
|
||||||
return (
|
return (
|
||||||
<div onClick={() => handleChange(item)} className={clx(
|
<div onClick={() => handleChange(item)} className={clx(
|
||||||
'p-4 border-b',
|
'p-4 border-b cursor-pointer',
|
||||||
item.id === itemSelected?.id && 'bg-[#F8F9FB]'
|
item.id === itemSelected?.id && 'bg-[#F8F9FB]'
|
||||||
)}>
|
)}>
|
||||||
<div className='flex justify-between'>
|
<div className='flex justify-between'>
|
||||||
@@ -114,7 +115,6 @@ const AnnouncementtList: FC = () => {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { FC } from 'react'
|
||||||
|
import Skeleton from 'react-loading-skeleton'
|
||||||
|
|
||||||
|
const AnouncementSkeleton: FC = () => {
|
||||||
|
return (
|
||||||
|
<div className={'p-4 border-b'}>
|
||||||
|
<div className='flex items-center justify-between'>
|
||||||
|
<div className='leading-6 text-xs xl:text-[12.5px] max-w-[70%]'>
|
||||||
|
<Skeleton
|
||||||
|
height={7}
|
||||||
|
width={100}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex gap-1'>
|
||||||
|
<Skeleton
|
||||||
|
className='!w-10 !h-6 !rounded-full'
|
||||||
|
/>
|
||||||
|
<Skeleton
|
||||||
|
className='!w-10 !h-6 !rounded-full'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='m-2 flex justify-between items-center text-[11px]'>
|
||||||
|
<Skeleton
|
||||||
|
height={7}
|
||||||
|
width={150}
|
||||||
|
/>
|
||||||
|
<div className='text-description'>
|
||||||
|
<Skeleton
|
||||||
|
height={7}
|
||||||
|
width={40}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AnouncementSkeleton
|
||||||
@@ -37,3 +37,9 @@ export const useRegister = () => {
|
|||||||
mutationFn: (variables: RegisterType) => api.register(variables),
|
mutationFn: (variables: RegisterType) => api.register(variables),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useLogout = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (_) => api.logout(),
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -43,3 +43,8 @@ export const refreshToken = async (params: RefreshTokenType) => {
|
|||||||
const { data } = await axios.post(`/auth/refresh`, params);
|
const { data } = await axios.post(`/auth/refresh`, params);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const logout = async () => {
|
||||||
|
const { data } = await axios.post(`/auth/logout`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import Td from '../../components/Td'
|
|||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Pages } from '../../config/Pages'
|
import { Pages } from '../../config/Pages'
|
||||||
import { useGetInvoices } from './hooks/useReceiptData'
|
import { useGetInvoices } from './hooks/useReceiptData'
|
||||||
import PageLoading from '../../components/PageLoading'
|
|
||||||
import { NumberFormat } from '../../config/func'
|
import { NumberFormat } from '../../config/func'
|
||||||
import { ReceiptItemType } from './types/ReceiptTypes'
|
import { ReceiptItemType } from './types/ReceiptTypes'
|
||||||
import moment from 'moment-jalaali'
|
import moment from 'moment-jalaali'
|
||||||
import { Helmet } from 'react-helmet-async'
|
import { Helmet } from 'react-helmet-async'
|
||||||
|
import DefaultTableSkeleton from '../../components/DefaultTableSkeleton'
|
||||||
|
|
||||||
const ReceiptsList: FC = () => {
|
const ReceiptsList: FC = () => {
|
||||||
|
|
||||||
@@ -63,12 +63,7 @@ const ReceiptsList: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{
|
|
||||||
getInvoices.isPending ?
|
|
||||||
<div className='mt-5'>
|
|
||||||
<PageLoading />
|
|
||||||
</div>
|
|
||||||
:
|
|
||||||
<div className='relative overflow-x-auto rounded-3xl mt-9 w-full'>
|
<div className='relative overflow-x-auto rounded-3xl mt-9 w-full'>
|
||||||
<table className='w-full text-sm '>
|
<table className='w-full text-sm '>
|
||||||
<thead className='thead'>
|
<thead className='thead'>
|
||||||
@@ -86,6 +81,10 @@ const ReceiptsList: FC = () => {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
getInvoices.isPending ?
|
||||||
|
<DefaultTableSkeleton tdCount={8} />
|
||||||
|
:
|
||||||
getInvoices.data?.data?.invoices?.map((item: ReceiptItemType) => {
|
getInvoices.data?.data?.invoices?.map((item: ReceiptItemType) => {
|
||||||
return (
|
return (
|
||||||
<tr className='tr'>
|
<tr className='tr'>
|
||||||
@@ -129,7 +128,6 @@ const ReceiptsList: FC = () => {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import { ArrowLeft } from 'iconsax-react'
|
import { ArrowLeft } from 'iconsax-react'
|
||||||
import TitleLine from '../../components/TitleLine'
|
import TitleLine from '../../components/TitleLine'
|
||||||
import { useGetSuggestedServices } from './hooks/useServiceData'
|
import { useGetSuggestedServices } from './hooks/useServiceData'
|
||||||
import PageLoading from '../../components/PageLoading'
|
|
||||||
import { ItemServiceType } from './types/ServiecTypes'
|
import { ItemServiceType } from './types/ServiecTypes'
|
||||||
import ServiceItem from '../../components/ServiceItem'
|
import ServiceItem from '../../components/ServiceItem'
|
||||||
import OtherServicesComponent from './components/OtherServices'
|
import OtherServicesComponent from './components/OtherServices'
|
||||||
import { useGetAds } from '../ads/hooks/useAdsData'
|
import { useGetAds } from '../ads/hooks/useAdsData'
|
||||||
import { AdsDisplayLocation, AdsItemType } from '../ads/types/AdsTypes'
|
import { AdsDisplayLocation, AdsItemType } from '../ads/types/AdsTypes'
|
||||||
import { Helmet } from 'react-helmet-async'
|
import { Helmet } from 'react-helmet-async'
|
||||||
|
import Skeleton from 'react-loading-skeleton'
|
||||||
|
import OtherServiceSkeleton from './components/OtherServiceSkeleton'
|
||||||
|
|
||||||
|
|
||||||
const OtherServices: FC = () => {
|
const OtherServices: FC = () => {
|
||||||
@@ -30,7 +31,7 @@ const OtherServices: FC = () => {
|
|||||||
<div className='flex-1'>
|
<div className='flex-1'>
|
||||||
{
|
{
|
||||||
getSuggestedServices.isPending || getAdsLeft.isPending ?
|
getSuggestedServices.isPending || getAdsLeft.isPending ?
|
||||||
<PageLoading />
|
<OtherServiceSkeleton />
|
||||||
:
|
:
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Carousel autoplay className="rounded-3xl overflow-hidden h-fit dltr z-[1]" placeholder="" onPointerEnterCapture={() => { }} onPointerLeaveCapture={() => { }} >
|
<Carousel autoplay className="rounded-3xl overflow-hidden h-fit dltr z-[1]" placeholder="" onPointerEnterCapture={() => { }} onPointerLeaveCapture={() => { }} >
|
||||||
@@ -96,6 +97,9 @@ const OtherServices: FC = () => {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
|
getAdsLeft.isPending ?
|
||||||
|
<Skeleton className='!w-sidebar !rounded-3xl !hidden xl:!block' height={550} />
|
||||||
|
:
|
||||||
getAdsLeft.isSuccess && getAdsLeft.data.data.ads[0] &&
|
getAdsLeft.isSuccess && getAdsLeft.data.data.ads[0] &&
|
||||||
<a href={getAdsLeft.data?.data?.ads[0].link} target='_blank' className='bg-white w-sidebar h-fit hidden xl:block rounded-3xl overflow-hidden sticky top-0'>
|
<a href={getAdsLeft.data?.data?.ads[0].link} target='_blank' className='bg-white w-sidebar h-fit hidden xl:block rounded-3xl overflow-hidden sticky top-0'>
|
||||||
<img
|
<img
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { FC } from 'react'
|
||||||
|
import Skeleton from 'react-loading-skeleton'
|
||||||
|
import TitleLine from '../../../components/TitleLine'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import ServiceItemSkeleton from './ServiceItemSkeleton'
|
||||||
|
|
||||||
|
const OtherServiceSkeleton: FC = () => {
|
||||||
|
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Skeleton
|
||||||
|
height={300}
|
||||||
|
className='!rounded-3xl'
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className='w-full mt-8'>
|
||||||
|
<TitleLine title={t('service.selected_danak')} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex flex-wrap xl:gap-6 gap-4 items-center mt-8'>
|
||||||
|
<ServiceItemSkeleton />
|
||||||
|
<ServiceItemSkeleton />
|
||||||
|
<ServiceItemSkeleton />
|
||||||
|
<ServiceItemSkeleton />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OtherServiceSkeleton
|
||||||
@@ -68,50 +68,10 @@ const OtherServicesComponent: FC = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
<div className='flex-1 min-w-[40%] xl:min-w-[30%] xl:p-6 p-4'></div>
|
<div className='flex-1 min-w-[40%] xl:min-w-[30%] xl:p-6 p-4'></div>
|
||||||
|
<div className='flex-1 min-w-[40%] xl:min-w-[30%] xl:p-6 p-4'></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <a target='_blank' key={item.id} href={item.status === 'ACTIVE' ? item.plan.service.link + item.id : '#'} className={clx(
|
|
||||||
'flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6 flex flex-col items-center self-stretch',
|
|
||||||
item.status === 'INACTIVE' && 'opacity-50'
|
|
||||||
)}>
|
|
||||||
<div className="flex-grow">
|
|
||||||
<ServiceSection
|
|
||||||
item={{
|
|
||||||
author: item.plan.service.author,
|
|
||||||
createDate: item.plan?.service?.createDate,
|
|
||||||
createdAt: item.createdAt,
|
|
||||||
description: item.plan?.service?.title,
|
|
||||||
icon: item.plan?.service.icon,
|
|
||||||
id: item.plan.service.id,
|
|
||||||
isActive: item.plan.isActive,
|
|
||||||
isDanakSuggest: item.plan.service.isDanakSuggest,
|
|
||||||
link: item.plan.service.link,
|
|
||||||
metaDescription: item.plan.service.metaDescription,
|
|
||||||
name: item.plan.service.name,
|
|
||||||
serviceLanguage: item.plan.service.serviceLanguage,
|
|
||||||
softwareLanguage: item.plan.service.softwareLanguage,
|
|
||||||
updatedAt: item.plan.service.updatedAt,
|
|
||||||
userCount: item.plan.service?.userCount,
|
|
||||||
title: item.plan.service.title,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='mt-6 flex gap-1 items-center'>
|
|
||||||
<StatusCircle
|
|
||||||
color={item.status === 'ACTIVE' ? '#00BA4B' : '#FF0000'}
|
|
||||||
/>
|
|
||||||
<div className='text-xs text-description'>
|
|
||||||
{
|
|
||||||
item.status === 'ACTIVE' ?
|
|
||||||
t('active')
|
|
||||||
:
|
|
||||||
t('inactive')
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a> */}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { Pages } from '../../config/Pages'
|
|||||||
import { useGetTickets } from './hooks/useTicketData'
|
import { useGetTickets } from './hooks/useTicketData'
|
||||||
import moment from 'moment-jalaali'
|
import moment from 'moment-jalaali'
|
||||||
import { Helmet } from 'react-helmet-async'
|
import { Helmet } from 'react-helmet-async'
|
||||||
|
import DefaultTableSkeleton from '../../components/DefaultTableSkeleton'
|
||||||
|
|
||||||
const TicketList: FC = () => {
|
const TicketList: FC = () => {
|
||||||
|
|
||||||
@@ -88,6 +89,9 @@ const TicketList: FC = () => {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{
|
{
|
||||||
|
getTickets.isPending ?
|
||||||
|
<DefaultTableSkeleton tdCount={9} />
|
||||||
|
:
|
||||||
getTickets.data?.data?.tickets?.map((item: any) => (
|
getTickets.data?.data?.tickets?.map((item: any) => (
|
||||||
<tr key={item.id} className='tr'>
|
<tr key={item.id} className='tr'>
|
||||||
<Td text={item.numericId} />
|
<Td text={item.numericId} />
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { FC, ReactNode } from 'react'
|
|||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { clx } from '../helpers/utils'
|
import { clx } from '../helpers/utils'
|
||||||
import { Pages } from '../config/Pages'
|
import { Pages } from '../config/Pages'
|
||||||
|
import { useLogout } from '../pages/auth/hooks/useAuthData'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
icon: ReactNode,
|
icon: ReactNode,
|
||||||
@@ -14,7 +15,10 @@ type Props = {
|
|||||||
|
|
||||||
const SideBarItem: FC<Props> = (props: Props) => {
|
const SideBarItem: FC<Props> = (props: Props) => {
|
||||||
|
|
||||||
const handleLogout = () => {
|
const logout = useLogout()
|
||||||
|
|
||||||
|
const handleLogout = async () => {
|
||||||
|
await logout.mutateAsync()
|
||||||
localStorage.removeItem(import.meta.env.VITE_TOKEN_NAME)
|
localStorage.removeItem(import.meta.env.VITE_TOKEN_NAME)
|
||||||
window.location.href = Pages.auth.login
|
window.location.href = Pages.auth.login
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ export default defineConfig({
|
|||||||
VitePWA({
|
VitePWA({
|
||||||
registerType: "autoUpdate",
|
registerType: "autoUpdate",
|
||||||
devOptions: {
|
devOptions: {
|
||||||
enabled: true, // در حالت توسعه هم کار کند
|
enabled: false, // در حالت توسعه هم کار کند
|
||||||
},
|
},
|
||||||
manifest: {
|
manifest: {
|
||||||
name: "Danak Console",
|
name: "Danak Console",
|
||||||
|
|||||||
Reference in New Issue
Block a user