Merge branch 'master' of https://github.com/Danakcorp/danak-admin
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { FC, SelectHTMLAttributes } from 'react'
|
||||
import { clx } from '../helpers/utils'
|
||||
import { ArrowDown2 } from 'iconsax-react'
|
||||
|
||||
export type ItemsSelectType = {
|
||||
value: string,
|
||||
@@ -23,7 +24,7 @@ const Select: FC<Props> = (props: Props) => {
|
||||
</label>
|
||||
}
|
||||
<select {...props} className={clx(
|
||||
'w-full text-black block border border-border px-2.5 h-10 text-sm rounded-2.5 bg-gray',
|
||||
'w-full text-black block border appearance-none border-border px-2.5 h-10 text-sm rounded-2.5 bg-gray',
|
||||
props.className,
|
||||
props.label && 'mt-1'
|
||||
)}>
|
||||
@@ -41,6 +42,10 @@ const Select: FC<Props> = (props: Props) => {
|
||||
})
|
||||
}
|
||||
</select>
|
||||
<ArrowDown2 size={16} color='black' className={clx(
|
||||
'absolute z-0 top-3 left-2',
|
||||
props.label && 'top-10'
|
||||
)} />
|
||||
{
|
||||
props.error_text && props.error_text !== '' ?
|
||||
<div className='text-xs text-right text-red-600 mt-2 mr-2 font-medium'>
|
||||
|
||||
+3
-2
@@ -12,8 +12,9 @@ export const Pages = {
|
||||
},
|
||||
transactions: "/transactions",
|
||||
receipts: {
|
||||
index: "/receipts",
|
||||
detail: "/receipts/",
|
||||
index: "/receipts/list",
|
||||
detail: "/receipts/detail/",
|
||||
create: "/receipts/create",
|
||||
},
|
||||
ticket: {
|
||||
list: "/tickets",
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export const SideBarItemHasSubMenu = [
|
||||
"services",
|
||||
"customers",
|
||||
"receipts",
|
||||
"users",
|
||||
"transactions",
|
||||
];
|
||||
+18
-1
@@ -68,6 +68,9 @@
|
||||
"setting": "تنظیمات",
|
||||
"logout": "خروج"
|
||||
},
|
||||
"submenu": {
|
||||
"services_list": "لیست سرویس ها"
|
||||
},
|
||||
"header": {
|
||||
"search": "جستجو"
|
||||
},
|
||||
@@ -240,7 +243,9 @@
|
||||
"percent": "درصد"
|
||||
},
|
||||
"receip": {
|
||||
"receips": "صورتحساب ها",
|
||||
"receip_list": "لیست صورتحساب ها",
|
||||
"add_receip": "افزودن صورتحساب",
|
||||
"dont_pay": "پرداخت نشده",
|
||||
"dont_confrim": "تایید نشده",
|
||||
"paid": "پرداخت شده",
|
||||
@@ -269,7 +274,19 @@
|
||||
"date_factor": "تاریخ صدور فاکتور",
|
||||
"due_date": "تاریخ سررسید فاکتور",
|
||||
"factor_number": "شماره فاکتور",
|
||||
"status_factor": "وضعیت فاکتور"
|
||||
"status_factor": "وضعیت فاکتور",
|
||||
"submit_receip": "ثبت صورتحساب",
|
||||
"customer_information": "اطلاعات مشتری",
|
||||
"customer": "مشتری",
|
||||
"receipt_information": "اطلاعات صورتحساب",
|
||||
"number": "شماره",
|
||||
"product_name": "نام کالا",
|
||||
"count": "تعداد",
|
||||
"unit_amount": "مبلغ واحد",
|
||||
"discount": "تخفیف(٪)",
|
||||
"total_amount": "مبلغ کل(ریال)",
|
||||
"tax": "مالیات بر ارزش افزوده (۰.۹ درصد)",
|
||||
"total": "جمع"
|
||||
},
|
||||
"edit": "ویرایش",
|
||||
"transaction": {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import StatusWithText from '../../components/StatusWithText'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { ArrowLeft2 } from 'iconsax-react'
|
||||
|
||||
const AnnouncementDetail: FC = () => {
|
||||
|
||||
@@ -14,8 +15,9 @@ const AnnouncementDetail: FC = () => {
|
||||
<div>
|
||||
{t('announcement.text_announcement')}
|
||||
</div>
|
||||
<div onClick={() => navigate(-1)} className='text-xs font-extralight'>
|
||||
<div onClick={() => navigate(-1)} className='text-xs flex gap-0.5 items-center font-extralight'>
|
||||
{t('back')}
|
||||
<ArrowLeft2 size={12} color='black' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -26,14 +26,14 @@ const DanakLearning: FC = () => {
|
||||
</div>
|
||||
|
||||
<div className='text-xs'>
|
||||
<div>
|
||||
<div className='leading-5'>
|
||||
لورم ایپسوم متن ساختگی با تولید سادگی
|
||||
</div>
|
||||
<div className='flex gap-1 mt-2'>
|
||||
<div className='flex gap-1 text-[11px] mt-3 text-description'>
|
||||
<div>دیزاین ,</div>
|
||||
<div>۲۴ دقیقه</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className='text-description text-[11px] mt-2'>
|
||||
آذر ماه 1403
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '../../components/Button'
|
||||
import { Add, TickCircle, TickSquare } from 'iconsax-react'
|
||||
import Select from '../../components/Select'
|
||||
import Input from '../../components/Input'
|
||||
|
||||
const CreateReceipt: FC = () => {
|
||||
|
||||
const { t } = useTranslation('global')
|
||||
|
||||
return (
|
||||
<div className='mt-4'>
|
||||
<div className='flex justify-between items-center'>
|
||||
<div>
|
||||
{t('receip.add_receip')}
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
className='px-5'
|
||||
>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<TickCircle size={20} color='white' />
|
||||
<div>
|
||||
{t('receip.submit_receip')}
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex gap-6 xl:mt-8 mt-4'>
|
||||
<div className='flex-1 bg-white py-8 xl:px-10 px-4 rounded-3xl'>
|
||||
<div>
|
||||
{t('receip.customer_information')}
|
||||
</div>
|
||||
|
||||
<div className='mt-8'>
|
||||
<div className='w-full xl:w-1/2'>
|
||||
<Select
|
||||
label={t('receip.customer')}
|
||||
items={[
|
||||
{ label: 'محمد', value: 'mohammad' },
|
||||
{ label: 'علی', value: 'ali' },
|
||||
{ label: 'حسین', value: 'hossein' },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-10 bg-[#F6F7FB] p-8 rounded-3xl text-sm'>
|
||||
<div className='flex justify-between items-center border-b border-border border-dashed pb-7'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='text-description'>{t('receip.type_person')}</div>
|
||||
<div>حقوقی</div>
|
||||
</div>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='text-description'>{t('receip.representativeـname')}</div>
|
||||
<div>مهرداد مظفری</div>
|
||||
</div>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='text-description'>{t('receip.company_name')}</div>
|
||||
<div>راوک</div>
|
||||
</div>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='text-description'>{t('receip.registration_number')}</div>
|
||||
<div>۱۲۳۴</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex justify-between items-center mt-7'>
|
||||
<div className='flex items-center gap-2 flex-1'>
|
||||
<div className='text-description'>{t('receip.tel_company')}</div>
|
||||
<div>۰۸۶۹۱۰۰۹۱۰۰۱</div>
|
||||
</div>
|
||||
<div className='flex items-center gap-2 flex-1'>
|
||||
<div className='text-description'>{t('receip.national_code')}</div>
|
||||
<div>۰۰۱۲۳۴۵۶۷۸</div>
|
||||
</div>
|
||||
<div className='flex items-center gap-2 flex-1'>
|
||||
<div className='text-description'>{t('receip.postal_code')}</div>
|
||||
<div>۰۰۱۲۳۴۵۶۷۸</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex justify-between items-center mt-7'>
|
||||
<div className='flex items-center gap-2 flex-1'>
|
||||
<div className='text-description'>{t('receip.state')}</div>
|
||||
<div>مرکزی </div>
|
||||
</div>
|
||||
<div className='flex items-center gap-2 flex-1'>
|
||||
<div className='text-description'>{t('receip.city')}</div>
|
||||
<div>اراک </div>
|
||||
</div>
|
||||
<div className='flex items-center gap-2 flex-1'>
|
||||
<div className='text-description'>{t('receip.address')}</div>
|
||||
<div>اراک -خیابان شریعتی-خیابان جنت</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-10'>
|
||||
<div>{t('receip.receipt_information')}</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-8 border-b border-dashed border-border pb-7 flex items-end justify-between text-xs text-description'>
|
||||
<div className='flex flex-col gap-2 items-center'>
|
||||
<div>
|
||||
{t('receip.number')}
|
||||
</div>
|
||||
<div className='size-10 bg-[#EBEDF5] rounded-xl flex justify-center items-center'>
|
||||
1
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col gap-2 items-center'>
|
||||
<div>
|
||||
{t('receip.product_name')}
|
||||
</div>
|
||||
<Input
|
||||
className='text-center'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col gap-2 items-center'>
|
||||
<div>
|
||||
{t('receip.count')}
|
||||
</div>
|
||||
<Input
|
||||
type='number'
|
||||
className='w-16 text-center'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col gap-2 items-center'>
|
||||
<div>
|
||||
{t('receip.unit_amount')}
|
||||
</div>
|
||||
<Input
|
||||
className='text-center'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col gap-2 items-center'>
|
||||
<div>
|
||||
{t('receip.discount')}
|
||||
</div>
|
||||
<Input
|
||||
type='number'
|
||||
className='w-16 text-center'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col gap-2 items-center'>
|
||||
<div>
|
||||
{t('receip.total_amount')}
|
||||
</div>
|
||||
<Input
|
||||
className='text-center bg-[#EBEDF5]'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='size-10 border border-border rounded-xl flex justify-center items-center'>
|
||||
<Add size={20} color='black' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-8 flex flex-col gap-4 items-end'>
|
||||
<div className='xl:w-1/2 h-12 w-full rounded-xl flex px-4 bg-[#EBEDF5] text-sm text-description justify-between items-center'>
|
||||
<div>
|
||||
{t('receip.tax')}
|
||||
</div>
|
||||
<div className='text-black'>
|
||||
100,000
|
||||
</div>
|
||||
</div>
|
||||
<div className='xl:w-1/2 h-12 w-full rounded-xl flex px-4 bg-[#EBEDF5] text-sm text-description justify-between items-center'>
|
||||
<div>
|
||||
{t('receip.total')}
|
||||
</div>
|
||||
<div className='text-black'>
|
||||
100,000
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className='bg-white w-sidebar xl:block hidden py-10 px-5 h-fit rounded-3xl'>
|
||||
<div className='text-sm'>
|
||||
{t('ticket.title_hint')}
|
||||
</div>
|
||||
|
||||
<div className='mt-6'>
|
||||
<div className='flex items-start gap-2 border-b pb-5'>
|
||||
<div>
|
||||
<TickSquare size={20} color='black' variant='Bold' />
|
||||
</div>
|
||||
<div className='text-description text-xs leading-5'>
|
||||
سوالات - مشکلاتی که به یک موضوع مربوط میشوند را در یک درخواست پشتیبانی پیگیر باشید و چند درخواست برای یک موضوع باز نکنید.
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex items-start gap-2 mt-6 border-b pb-5'>
|
||||
<div>
|
||||
<TickSquare size={20} color='black' variant='Bold' />
|
||||
</div>
|
||||
<div className='text-description text-xs leading-5'>
|
||||
لطفاً برای بررسی و رفع مشکلات احتمالی صبور باشید بررسی و رفع مشکلات در برخی موارد زمان گیر است.
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex items-start gap-2 mt-6'>
|
||||
<div>
|
||||
<TickSquare size={20} color='black' variant='Bold' />
|
||||
</div>
|
||||
<div className='text-description text-xs leading-5'>
|
||||
پاسخگویی 24 ساعته تلفنی را تنها از میهن وب هاست می توانید انتظار داشته باشید .بخش پشتیبانی در هر ساعتی حتی در روز های تعطیل آماده پیگیری سریع مشکلات کاربران است.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CreateReceipt
|
||||
@@ -41,53 +41,49 @@ const MyServices: FC = () => {
|
||||
</div>
|
||||
|
||||
<div className='flex flex-wrap xl:gap-6 gap-4 items-center mt-8'>
|
||||
<Link to={Pages.services.detail + '1'}>
|
||||
<div className='flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6'>
|
||||
<ServiceSection
|
||||
|
||||
<Link to={Pages.services.detail + '1'} className='flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6'>
|
||||
<ServiceSection
|
||||
/>
|
||||
<div className='mt-6 flex gap-1 items-center'>
|
||||
<StatusCircle
|
||||
color='#00BA4B'
|
||||
/>
|
||||
<div className='mt-6 flex gap-1 items-center'>
|
||||
<StatusCircle
|
||||
color='#00BA4B'
|
||||
/>
|
||||
<div className='text-xs text-description'>1 {t('service.active_menu')}</div>
|
||||
</div>
|
||||
<div className='text-xs text-description'>1 {t('service.active_menu')}</div>
|
||||
</div>
|
||||
|
||||
</Link>
|
||||
<Link to={Pages.services.detail + '1'} className='flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6'>
|
||||
<ServiceSection
|
||||
/>
|
||||
<div className='mt-6 flex gap-1 items-center'>
|
||||
<StatusCircle
|
||||
color='#00BA4B'
|
||||
/>
|
||||
<div className='text-xs text-description'>1 {t('service.active_menu')}</div>
|
||||
</div>
|
||||
</Link>
|
||||
<Link to={Pages.services.detail + '1'}>
|
||||
<div className='flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6'>
|
||||
<ServiceSection
|
||||
<Link to={Pages.services.detail + '1'} className='flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6'>
|
||||
<ServiceSection
|
||||
/>
|
||||
<div className='mt-6 flex gap-1 items-center'>
|
||||
<StatusCircle
|
||||
color='#00BA4B'
|
||||
/>
|
||||
<div className='mt-6 flex gap-1 items-center'>
|
||||
<StatusCircle
|
||||
color='#00BA4B'
|
||||
/>
|
||||
<div className='text-xs text-description'>1 {t('service.active_menu')}</div>
|
||||
</div>
|
||||
<div className='text-xs text-description'>1 {t('service.active_menu')}</div>
|
||||
</div>
|
||||
</Link>
|
||||
<Link to={Pages.services.detail + '1'}>
|
||||
<div className='flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6'>
|
||||
<ServiceSection
|
||||
|
||||
<Link to={Pages.services.detail + '1'} className='flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6'>
|
||||
<ServiceSection
|
||||
/>
|
||||
<div className='mt-6 flex gap-1 items-center'>
|
||||
<StatusCircle
|
||||
color='#00BA4B'
|
||||
/>
|
||||
<div className='mt-6 flex gap-1 items-center'>
|
||||
<StatusCircle
|
||||
color='#00BA4B'
|
||||
/>
|
||||
<div className='text-xs text-description'>1 {t('service.active_menu')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<Link to={Pages.services.detail + '1'}>
|
||||
<div className='flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6'>
|
||||
<ServiceSection
|
||||
/>
|
||||
<div className='mt-6 flex gap-1 items-center'>
|
||||
<StatusCircle
|
||||
color='#00BA4B'
|
||||
/>
|
||||
<div className='text-xs text-description'>1 {t('service.active_menu')}</div>
|
||||
</div>
|
||||
<div className='text-xs text-description'>1 {t('service.active_menu')}</div>
|
||||
</div>
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -45,104 +45,104 @@ const Setting: FC = () => {
|
||||
|
||||
<div className='flex xl:flex-row flex-col gap-6 text-sm mt-8'>
|
||||
<div className='flex-1 border border-border px-4 rounded-2xl min-h-14 items-center flex justify-between'>
|
||||
<div className='xl:text-sm text-xs'>
|
||||
<div className='xl:text-[13px] text-xs'>
|
||||
{t('setting.notification_announcement')}
|
||||
</div>
|
||||
<div className='flex xl:gap-4 gap-2'>
|
||||
<div className='flex gap-1 text-xs items-center text-description'>
|
||||
<div className='flex gap-2 text-xs items-center text-description'>
|
||||
<div>
|
||||
{t('setting.email')}
|
||||
</div>
|
||||
<SwitchComponent
|
||||
active={true}
|
||||
onChange={() => { }}
|
||||
/>
|
||||
<div>
|
||||
{t('setting.email')}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex gap-1 text-xs items-center text-description'>
|
||||
<div className='flex gap-2 text-xs items-center text-description'>
|
||||
<div>
|
||||
{t('setting.sms')}
|
||||
</div>
|
||||
<SwitchComponent
|
||||
active={false}
|
||||
onChange={() => { }}
|
||||
/>
|
||||
<div>
|
||||
{t('setting.sms')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex-1 border border-border px-4 rounded-2xl min-h-14 items-center flex justify-between'>
|
||||
<div className='xl:text-sm text-xs'>
|
||||
<div className='xl:text-[13px] text-xs'>
|
||||
{t('setting.notification_announcement')}
|
||||
</div>
|
||||
<div className='flex xl:gap-4 gap-2'>
|
||||
<div className='flex gap-1 text-xs items-center text-description'>
|
||||
<div className='flex gap-2 text-xs items-center text-description'>
|
||||
<div>
|
||||
{t('setting.email')}
|
||||
</div>
|
||||
<SwitchComponent
|
||||
active={true}
|
||||
onChange={() => { }}
|
||||
/>
|
||||
<div>
|
||||
{t('setting.email')}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex gap-1 text-xs items-center text-description'>
|
||||
<div className='flex gap-2 text-xs items-center text-description'>
|
||||
<div>
|
||||
{t('setting.sms')}
|
||||
</div>
|
||||
<SwitchComponent
|
||||
active={false}
|
||||
onChange={() => { }}
|
||||
/>
|
||||
<div>
|
||||
{t('setting.sms')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex xl:flex-row flex-col gap-6 text-sm mt-6'>
|
||||
<div className='flex-1 border border-border px-4 rounded-2xl min-h-14 items-center flex justify-between'>
|
||||
<div className='xl:text-sm text-xs'>
|
||||
<div className='xl:text-[13px] text-xs'>
|
||||
{t('setting.notification_announcement')}
|
||||
</div>
|
||||
<div className='flex xl:gap-4 gap-2'>
|
||||
<div className='flex gap-1 text-xs items-center text-description'>
|
||||
<div className='flex gap-2 text-xs items-center text-description'>
|
||||
<div>
|
||||
{t('setting.email')}
|
||||
</div>
|
||||
<SwitchComponent
|
||||
active={true}
|
||||
onChange={() => { }}
|
||||
/>
|
||||
<div>
|
||||
{t('setting.email')}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex gap-1 text-xs items-center text-description'>
|
||||
<div className='flex gap-2 text-xs items-center text-description'>
|
||||
<div>
|
||||
{t('setting.sms')}
|
||||
</div>
|
||||
<SwitchComponent
|
||||
active={false}
|
||||
onChange={() => { }}
|
||||
/>
|
||||
<div>
|
||||
{t('setting.sms')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex-1 border border-border px-4 rounded-2xl min-h-14 items-center flex justify-between'>
|
||||
<div className='xl:text-sm text-xs'>
|
||||
<div className='xl:text-[13px] text-xs'>
|
||||
{t('setting.notification_announcement')}
|
||||
</div>
|
||||
<div className='flex xl:gap-4 gap-2'>
|
||||
<div className='flex gap-1 text-xs items-center text-description'>
|
||||
<div className='flex gap-2 text-xs items-center text-description'>
|
||||
<div>
|
||||
{t('setting.email')}
|
||||
</div>
|
||||
<SwitchComponent
|
||||
active={true}
|
||||
onChange={() => { }}
|
||||
/>
|
||||
<div>
|
||||
{t('setting.email')}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex gap-1 text-xs items-center text-description'>
|
||||
<div className='flex gap-2 text-xs items-center text-description'>
|
||||
<div>
|
||||
{t('setting.sms')}
|
||||
</div>
|
||||
<SwitchComponent
|
||||
active={false}
|
||||
onChange={() => { }}
|
||||
/>
|
||||
<div>
|
||||
{t('setting.sms')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+14
-2
@@ -27,14 +27,25 @@ import OtherServices from '../pages/service/OtherServices'
|
||||
import Footer from '../shared/Footer'
|
||||
import AnnouncementDetail from '../pages/annoncement/Detail'
|
||||
import DetailService from '../pages/service/DetailService'
|
||||
import { clx } from '../helpers/utils'
|
||||
import { useSharedStore } from '../shared/store/sharedStore'
|
||||
import CreateReceipt from '../pages/receipts/Create'
|
||||
|
||||
const MainRouter: FC = () => {
|
||||
|
||||
const { hasSubMenu } = useSharedStore()
|
||||
|
||||
return (
|
||||
<div className='p-4 overflow-hidden'>
|
||||
<SideBar />
|
||||
<Header />
|
||||
<div className='flex-1 xl:ms-[269px] mt-[68px] xl:mt-[81px]'>
|
||||
<div className={`overflow-auto w-[${window.innerWidth}] max-h-[calc(100vh-113px)]`}>
|
||||
<div className={clx(
|
||||
'flex-1 xl:ms-[269px] mt-[68px] xl:mt-[81px]',
|
||||
hasSubMenu && 'xl:ms-[305px]',
|
||||
)}>
|
||||
<div className={clx(
|
||||
`overflow-auto w-[${window.innerWidth}] max-h-[calc(100vh-113px)]`,
|
||||
)}>
|
||||
<div>
|
||||
<Routes>
|
||||
<Route path={Pages.dashboard} element={<Home />} />
|
||||
@@ -53,6 +64,7 @@ const MainRouter: FC = () => {
|
||||
<Route path={Pages.transactions} element={<TransactionList />} />
|
||||
<Route path={Pages.receipts.index} element={<ReceiptsList />} />
|
||||
<Route path={Pages.receipts.detail + ':id'} element={<ReceiptsDetail />} />
|
||||
<Route path={Pages.receipts.create} element={<CreateReceipt />} />
|
||||
<Route path={Pages.announcement.list} element={<AnnouncementtList />} />
|
||||
<Route path={Pages.announcement.detail + ':id'} element={<AnnouncementDetail />} />
|
||||
<Route path={Pages.criticisms} element={<AddCriticisms />} />
|
||||
|
||||
@@ -14,7 +14,7 @@ const Header: FC = () => {
|
||||
const { setOpenSidebar, openSidebar } = useSharedStore()
|
||||
|
||||
return (
|
||||
<div className='fixed z-10 right-4 left-4 xl:right-[285px] top-4 xl:h-16 h-12 flex items-center px-6 bg-white justify-between rounded-[32px] xl:w-[calc(100%-305px)]'>
|
||||
<div className='fixed z-10 right-4 left-4 xl:right-[317px] top-4 xl:h-16 h-12 flex items-center px-6 bg-white justify-between rounded-[32px] xl:w-[calc(100%-335px)]'>
|
||||
|
||||
<div className='min-w-[270px] hidden xl:block'>
|
||||
<Input
|
||||
@@ -26,14 +26,14 @@ const Header: FC = () => {
|
||||
<HambergerMenu size={24} color='black' />
|
||||
</div>
|
||||
{/* <img src={LogoImage} className='h-6 xl:hidden block absolute right-0 left-0 mx-auto' /> */}
|
||||
<div className='flex xl:gap-6 gap-3 items-center'>
|
||||
<Element3 color='black' className='xl:size-[18px] size-4' />
|
||||
<div className='flex xl:gap-6 gap-4 items-center'>
|
||||
<Element3 color='black' className='xl:size-[18px] size-[17px]' />
|
||||
<Link to={Pages.wallet}>
|
||||
<Wallet className='xl:size-[18px] size-4' color='black' />
|
||||
<Wallet className='xl:size-[18px] size-[17px]' color='black' />
|
||||
</Link>
|
||||
<Notifications />
|
||||
<div className='flex gap-2 items-center'>
|
||||
<div className='size-7 rounded-full bg-description overflow-hidden'>
|
||||
<div className='size-6 rounded-full bg-description overflow-hidden'>
|
||||
<Link to={Pages.profile}>
|
||||
<img src={AvatarImage} className='size-full object-cover' />
|
||||
</Link>
|
||||
|
||||
+64
-7
@@ -1,5 +1,6 @@
|
||||
import { FC } from 'react'
|
||||
import { FC, useEffect } from 'react'
|
||||
import LogoImage from '../assets/images/logo.svg'
|
||||
import LogoSmall from '../assets/images/logo-small.svg'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Card, Code, CodeCircle, DocumentLike, DocumentText, Element3, Home2, Logout, Messages3, NotificationStatus, People, Profile, Receipt21, Setting2, SmsTracking, Teacher, TicketDiscount, UserSquare } from 'iconsax-react'
|
||||
import SideBarItem from './SideBarItem'
|
||||
@@ -7,19 +8,43 @@ import { useLocation } from 'react-router-dom'
|
||||
import { Pages } from '../config/Pages'
|
||||
import { useSharedStore } from './store/sharedStore'
|
||||
import { clx } from '../helpers/utils'
|
||||
import ServicesSubMenu from './components/ServicesSubMenu'
|
||||
import { SideBarItemHasSubMenu } from '../config/SideBarSubMenu'
|
||||
import TransactionsSubMenu from './components/TransactionsSubMenu'
|
||||
import ReceiptSubMenu from './components/ReceiptSubMenu'
|
||||
|
||||
const SideBar: FC = () => {
|
||||
|
||||
const { t } = useTranslation('global')
|
||||
const { openSidebar, setOpenSidebar } = useSharedStore()
|
||||
const { openSidebar, setOpenSidebar, hasSubMenu, setSubMenuName, setSubtMenu, subMenuName } = useSharedStore()
|
||||
const location = useLocation()
|
||||
|
||||
const isActive = (name: string) => {
|
||||
return location.pathname.includes(name)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const split = location.pathname.split('/')
|
||||
console.log('split', split);
|
||||
|
||||
|
||||
if (SideBarItemHasSubMenu.includes(split[1])) {
|
||||
setSubMenuName(split[1])
|
||||
setSubtMenu(true)
|
||||
} else {
|
||||
setSubMenuName('')
|
||||
setSubtMenu(false)
|
||||
}
|
||||
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [location.pathname])
|
||||
|
||||
|
||||
const iconSizeSideBar = 20
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{
|
||||
@@ -28,15 +53,24 @@ const SideBar: FC = () => {
|
||||
<div
|
||||
className={clx(
|
||||
'fixed xl:flex translate-x-[400px] xl:translate-x-0 transition-all ease-in-out opacity-0 invisible xl:visible xl:opacity-100 xl:right-4 right-0 xl:top-4 top-0 xl:bottom-4 bottom-0 xl:rounded-[32px] w-[250px] bg-white flex-col py-12',
|
||||
openSidebar && 'opacity-100 visible -translate-x-[0px] block z-40'
|
||||
openSidebar && 'opacity-100 visible -translate-x-[0px] block z-40',
|
||||
hasSubMenu && 'w-24 !rounded-tl-none !rounded-bl-none'
|
||||
)}
|
||||
>
|
||||
<div className='flex justify-center'>
|
||||
<img src={LogoImage} className='w-[140px]' />
|
||||
{
|
||||
!hasSubMenu ?
|
||||
<img src={LogoImage} className='w-[140px]' />
|
||||
:
|
||||
<img src={LogoSmall} className='w-7' />
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className='flex-1 h-full overflow-y-auto no-scrollbar'>
|
||||
<div className='mt-10 px-12 text-header text-sm font-normal'>
|
||||
<div className={clx(
|
||||
'mt-10 px-12 text-header text-sm font-normal',
|
||||
hasSubMenu && 'px-2 text-center'
|
||||
)}>
|
||||
{t('sidebar.menu')}
|
||||
</div>
|
||||
|
||||
@@ -52,6 +86,7 @@ const SideBar: FC = () => {
|
||||
title={t('sidebar.services')}
|
||||
isActive={isActive('services')}
|
||||
link={Pages.services.mine}
|
||||
name='services'
|
||||
/>
|
||||
<SideBarItem
|
||||
icon={<People variant={isActive('customers') ? 'Bold' : 'Outline'} color={isActive('customers') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||
@@ -105,7 +140,10 @@ const SideBar: FC = () => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-10 px-12 text-header text-sm font-normal'>
|
||||
<div className={clx(
|
||||
'mt-10 px-12 text-header text-sm font-normal',
|
||||
hasSubMenu && 'px-2 text-center'
|
||||
)}>
|
||||
{t('sidebar.other')}
|
||||
</div>
|
||||
|
||||
@@ -129,7 +167,10 @@ const SideBar: FC = () => {
|
||||
</div>
|
||||
|
||||
|
||||
<div className='mt-10 px-12 text-header text-sm font-normal'>
|
||||
<div className={clx(
|
||||
'mt-10 px-12 text-header text-sm font-normal',
|
||||
hasSubMenu && 'px-2 text-center text-xs'
|
||||
)}>
|
||||
{t('sidebar.mnage_content')}
|
||||
</div>
|
||||
|
||||
@@ -200,6 +241,22 @@ const SideBar: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{
|
||||
hasSubMenu && (openSidebar || window.innerWidth > 1000) &&
|
||||
<div className='fixed xl:right-[112px] right-[96px] bg-white z-20 xl:top-4 xl:bottom-4 top-0 bottom-0 rounded-tl-[32px] rounded-bl-[32px] w-[190px] border-r'>
|
||||
{
|
||||
subMenuName === 'services' ?
|
||||
<ServicesSubMenu />
|
||||
:
|
||||
subMenuName === 'transactions' ?
|
||||
<TransactionsSubMenu />
|
||||
: subMenuName === 'receipts' ?
|
||||
<ReceiptSubMenu />
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { FC, ReactNode } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { clx } from '../helpers/utils'
|
||||
import { Pages } from '../config/Pages'
|
||||
import { useSharedStore } from './store/sharedStore'
|
||||
|
||||
type Props = {
|
||||
icon: ReactNode,
|
||||
@@ -9,22 +10,38 @@ type Props = {
|
||||
isActive: boolean,
|
||||
link: string,
|
||||
isLogout?: boolean,
|
||||
name?: string
|
||||
}
|
||||
|
||||
const SideBarItem: FC<Props> = (props: Props) => {
|
||||
|
||||
const { hasSubMenu, setSubMenuName, setSubtMenu } = useSharedStore()
|
||||
const handleLogout = () => {
|
||||
localStorage.removeItem(import.meta.env.VITE_TOKEN_NAME)
|
||||
window.location.href = Pages.auth.login
|
||||
}
|
||||
|
||||
const handleClick = () => {
|
||||
if (props.name) {
|
||||
setSubMenuName(props.name)
|
||||
setSubtMenu(true)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Link onClick={props.isLogout ? handleLogout : undefined} to={props.link} className='flex text-xs gap-9 mt-4'>
|
||||
<Link onClick={props.isLogout ? handleLogout : handleClick} to={props.link} className={clx(
|
||||
'flex text-xs gap-9 mt-4',
|
||||
hasSubMenu && 'flex-col',
|
||||
)}>
|
||||
<div className={clx(
|
||||
'w-1 bg-black h-6',
|
||||
!props.isActive && 'invisible'
|
||||
!props.isActive && 'invisible',
|
||||
hasSubMenu && 'hidden',
|
||||
)}></div>
|
||||
<div className='flex gap-3 items-center'>
|
||||
<div className={clx(
|
||||
'flex gap-3 items-center',
|
||||
hasSubMenu && 'flex-col text-[10px]',
|
||||
)}>
|
||||
{props.icon}
|
||||
<div className={props.isActive ? 'text-black' : ''}>
|
||||
{props.title}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { Receipt21 } from 'iconsax-react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import SubMenuItem from './SubMenuItem'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { Pages } from '../../config/Pages'
|
||||
|
||||
const ReceiptSubMenu: FC = () => {
|
||||
|
||||
const location = useLocation()
|
||||
const { t } = useTranslation('global')
|
||||
|
||||
const isActive = (name: string) => {
|
||||
return location.pathname.includes(name)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='py-12'>
|
||||
<div className='flex gap-3 items-center border-b pb-10 px-6'>
|
||||
<Receipt21
|
||||
size={24}
|
||||
color='#000'
|
||||
variant='Bold'
|
||||
/>
|
||||
<div className='text-xs'>
|
||||
{t('receip.receips')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col mt-10 gap-4'>
|
||||
<SubMenuItem
|
||||
title={t('receip.receip_list')}
|
||||
isActive={isActive('list')}
|
||||
link={Pages.receipts.index}
|
||||
/>
|
||||
<SubMenuItem
|
||||
title={t('receip.add_receip')}
|
||||
isActive={isActive('create')}
|
||||
link={Pages.receipts.create}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ReceiptSubMenu
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Element3 } from 'iconsax-react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import SubMenuItem from './SubMenuItem'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
|
||||
const ServicesSubMenu: FC = () => {
|
||||
|
||||
const location = useLocation()
|
||||
const { t } = useTranslation('global')
|
||||
|
||||
|
||||
const isActive = (name: string) => {
|
||||
return location.pathname.includes(name)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='py-12'>
|
||||
<div className='flex gap-3 items-center border-b pb-10 px-6'>
|
||||
<Element3
|
||||
size={24}
|
||||
color='#000'
|
||||
variant='Bold'
|
||||
/>
|
||||
<div className='text-xs'>
|
||||
{t('sidebar.services')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col mt-10 gap-4'>
|
||||
<SubMenuItem
|
||||
title={t('submenu.services_list')}
|
||||
isActive={isActive('services')}
|
||||
link='/services'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ServicesSubMenu
|
||||
@@ -0,0 +1,33 @@
|
||||
import { FC } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { clx } from '../../helpers/utils'
|
||||
|
||||
type Props = {
|
||||
title: string,
|
||||
isActive: boolean,
|
||||
link: string,
|
||||
isLogout?: boolean,
|
||||
}
|
||||
|
||||
const SubMenuItem: FC<Props> = (props: Props) => {
|
||||
return (
|
||||
<Link to={props.link} className={clx(
|
||||
'flex text-xs gap-6 mt-1',
|
||||
)}>
|
||||
<div className={clx(
|
||||
'w-1 bg-black h-6',
|
||||
!props.isActive && 'invisible',
|
||||
)}></div>
|
||||
<div className={clx(
|
||||
'flex gap-3 items-center mt-1',
|
||||
)}>
|
||||
<div className={props.isActive ? 'text-black' : 'text-description'}>
|
||||
{props.title}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default SubMenuItem
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Card } from 'iconsax-react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import SubMenuItem from './SubMenuItem'
|
||||
|
||||
const TransactionsSubMenu: FC = () => {
|
||||
|
||||
const { t } = useTranslation('global')
|
||||
|
||||
const isActive = (name: string) => {
|
||||
return location.pathname.includes(name)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='py-12'>
|
||||
<div className='flex gap-3 items-center border-b pb-10 px-6'>
|
||||
<Card
|
||||
size={24}
|
||||
color='#000'
|
||||
variant='Bold'
|
||||
/>
|
||||
<div className='text-xs'>
|
||||
{t('sidebar.transactions')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col mt-10 gap-4'>
|
||||
<SubMenuItem
|
||||
title={t('sidebar.services')}
|
||||
isActive={isActive('services')}
|
||||
link='/services'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default TransactionsSubMenu
|
||||
@@ -4,4 +4,8 @@ import { SharedStoreType } from "../types/SharedTypes";
|
||||
export const useSharedStore = create<SharedStoreType>((set) => ({
|
||||
openSidebar: false,
|
||||
setOpenSidebar: (value) => set({ openSidebar: value }),
|
||||
hasSubMenu: false,
|
||||
setSubtMenu: (value: boolean) => set({ hasSubMenu: value }),
|
||||
subMenuName: "",
|
||||
setSubMenuName: (value: string) => set({ subMenuName: value }),
|
||||
}));
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
export type SharedStoreType = {
|
||||
openSidebar: boolean;
|
||||
setOpenSidebar: (value: boolean) => void;
|
||||
hasSubMenu: boolean;
|
||||
setSubtMenu: (value: boolean) => void;
|
||||
subMenuName: string;
|
||||
setSubMenuName: (value: string) => void;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user