Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 934c50dc65 | |||
| 8dda1d52e3 | |||
| 23437fd7f3 | |||
| c58330cfbd | |||
| c5c932dda6 | |||
| 1ff85d6cb4 | |||
| 8732374c9a | |||
| caa40699f9 | |||
| fd9a1e3aaf | |||
| b9bf740b64 |
@@ -1,5 +1,5 @@
|
||||
VITE_TOKEN_NAME = 'dmnu_a_t'
|
||||
VITE_REFRESH_TOKEN_NAME = 'dmnu-a-rt'
|
||||
VITE_TOKEN_NAME = 'dkala_a_t'
|
||||
VITE_REFRESH_TOKEN_NAME = 'dkala-a-rt'
|
||||
|
||||
VITE_BASE_URL = 'https://dkala-api.danakcorp.com'
|
||||
# VITE_BASE_URL = 'http://10.191.241.88:4000'
|
||||
|
||||
+26
-4
@@ -1,20 +1,42 @@
|
||||
FROM node:20-alpine AS builder
|
||||
FROM node:22-alpine AS builder
|
||||
|
||||
# Change Alpine repo
|
||||
RUN sed -i 's|https://dl-cdn.alpinelinux.org/alpine|https://mirror.de.velop.ir/alpine|g' /etc/apk/repositories
|
||||
|
||||
# Configure npm registry mirror (Liara)
|
||||
ENV NPM_CONFIG_REGISTRY=https://package-mirror.liara.ir/repository/npm/
|
||||
RUN npm config set registry https://package-mirror.liara.ir/repository/npm/
|
||||
|
||||
# Install tzdata to support timezone settings
|
||||
RUN apk add --no-cache tzdata
|
||||
|
||||
# Set the timezone to Asia/Tehran
|
||||
|
||||
RUN cp /usr/share/zoneinfo/Asia/Tehran /etc/localtime && echo "Asia/Tehran" > /etc/timezone
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Optional build-args (CapRover / docker build --build-arg). When unset, Vite reads .env from COPY.
|
||||
ARG VITE_BASE_URL
|
||||
ARG VITE_SOCKET_URL
|
||||
ARG VITE_TOKEN_NAME
|
||||
ARG VITE_REFRESH_TOKEN_NAME
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
RUN npm ci --legacy-peer-deps
|
||||
COPY . ./
|
||||
RUN npm run build
|
||||
RUN set -e; \
|
||||
env_args=""; \
|
||||
[ -n "$VITE_BASE_URL" ] && env_args="$env_args VITE_BASE_URL=$VITE_BASE_URL"; \
|
||||
[ -n "$VITE_SOCKET_URL" ] && env_args="$env_args VITE_SOCKET_URL=$VITE_SOCKET_URL"; \
|
||||
[ -n "$VITE_TOKEN_NAME" ] && env_args="$env_args VITE_TOKEN_NAME=$VITE_TOKEN_NAME"; \
|
||||
[ -n "$VITE_REFRESH_TOKEN_NAME" ] && env_args="$env_args VITE_REFRESH_TOKEN_NAME=$VITE_REFRESH_TOKEN_NAME"; \
|
||||
eval "env$env_args npm run build"
|
||||
|
||||
FROM nginx:stable-alpine AS production-stage
|
||||
|
||||
# Change Alpine repo
|
||||
RUN sed -i 's|https://dl-cdn.alpinelinux.org/alpine|https://mirror.de.velop.ir/alpine|g' /etc/apk/repositories
|
||||
|
||||
COPY --from=builder /build/dist /usr/share/nginx/html
|
||||
|
||||
COPY --from=builder /build/nginx.con[f] /etc/nginx/conf.d/default.conf
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>پنل مدیریت دی منو</title>
|
||||
<title>پنل مدیریت دی کالا</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="314.19 250.9 232.51 57.53">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
font-family: Roboto-Regular, Roboto;
|
||||
font-size: 50.42px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
fill: #231f20;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #000;
|
||||
}
|
||||
|
||||
.cls-3, .cls-2 {
|
||||
stroke-width: 0px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<polygon class="cls-2" points="453.41 265.34 464.36 295.35 469.19 295.35 455.48 259.5 451.34 259.5 437.65 295.35 442.52 295.35 453.41 265.34"/>
|
||||
<polygon class="cls-2" points="530.91 265.34 541.86 295.35 546.7 295.35 532.98 259.5 528.85 259.5 515.16 295.35 520.03 295.35 530.91 265.34"/>
|
||||
<path class="cls-2" d="M382.18,279.33h-12.14v-3.81h12.14v3.81Z"/>
|
||||
<g>
|
||||
<text class="cls-1" transform="translate(392.71 295.91) scale(1.15 1)"><tspan x="0" y="0">K</tspan></text>
|
||||
<text class="cls-1" transform="translate(475.71 295.91) scale(1.15 1)"><tspan x="0" y="0">L</tspan></text>
|
||||
</g>
|
||||
<path class="cls-3" d="M328.76,295.36v-3.71c.56-.04,1.06-.1,1.56-.1,4.19,0,8.39.05,12.58,0,7.74-.07,13.98-6.26,14.04-13.87.06-7.76-6.05-14.02-13.88-14.18-3.38-.07-6.76-.01-10.36-.01v19.78h-3.96v-23.45c.14-.1.23-.23.32-.23,5.51.05,11.05-.24,16.52.25,7.93.71,14.46,7.77,15.18,15.73.78,8.55-4.24,16.49-12.09,18.94-1.62.51-3.36.86-5.06.9-4.59.13-9.19.05-13.79.05-.33,0-.67-.07-1.08-.12Z"/>
|
||||
<path class="cls-3" d="M326.53,285.37c.6.07,1.09.18,1.57.18,4.77.01,9.54.05,14.31,0,4.94-.05,8.49-3.5,8.43-8.11-.06-4.61-3.66-7.95-8.61-7.96-2.4,0-4.81,0-7.41,0v-4.07c3.86.24,7.76.01,11.45.81,5.51,1.19,9.11,6.9,8.49,12.4-.68,6-5.24,10.61-11.11,10.77-6.78.19-13.56.05-20.34.05-.16,0-.32-.09-.55-.16"/>
|
||||
<path class="cls-3" d="M319.41,295.5h-5.09v-1.66c0-.55.11-.97.34-1.25.23-.28.57-.42,1.01-.42.24,0,.45.07.63.2.18.14.32.32.42.55.08-.27.22-.49.44-.65.22-.16.47-.24.77-.24.46,0,.82.15,1.08.44s.39.71.39,1.25v1.77ZM316.49,294.83v-1.01c0-.29-.07-.53-.22-.7-.15-.18-.35-.26-.6-.26-.28,0-.48.08-.61.24-.13.16-.19.41-.19.74v.99h1.62ZM317.03,294.83h1.83v-1.11c0-.31-.08-.56-.24-.74-.16-.18-.39-.27-.67-.27-.61,0-.92.33-.92,1v1.12Z"/>
|
||||
<path class="cls-3" d="M316.88,289.24l-2.55-1.33v-.76l3.19,1.75h1.9v.67h-1.9l-3.19,1.75v-.77l2.55-1.32Z"/>
|
||||
<path class="cls-3" d="M319.29,284.05h-5.1v-1.44c0-.44.1-.84.29-1.18.2-.34.48-.6.84-.79.36-.19.78-.28,1.25-.28h.33c.48,0,.9.09,1.27.28s.64.45.83.8c.19.34.29.75.3,1.2v1.41ZM314.74,283.38h4v-.71c0-.52-.16-.92-.48-1.21-.32-.29-.78-.43-1.38-.43h-.3c-.58,0-1.03.14-1.35.41-.32.27-.48.66-.49,1.16v.79Z"/>
|
||||
<path class="cls-3" d="M319.29,269.97v.68l-3.93,2.57h3.93v.68h-5.1v-.68l3.95-2.58h-3.95v-.67h5.1Z"/>
|
||||
<path class="cls-3" d="M316.92,262.01l.65.62h1.72v.67h-5.1v-.67h2.52l-2.52-2.27v-.81l2.25,2.01,2.85-2.17v.81l-2.37,1.81Z"/>
|
||||
<polygon class="cls-3" points="315.02 277.24 319.29 275.68 319.29 274.99 314.19 276.95 314.19 277.54 319.29 279.48 319.29 278.79 315.02 277.24"/>
|
||||
<polygon class="cls-3" points="315.02 266.69 319.29 265.13 319.29 264.44 314.19 266.39 314.19 266.98 319.29 268.93 319.29 268.24 315.02 266.69"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -6,7 +6,7 @@ const ServiceSection: FC = () => {
|
||||
<div className='size-10 rounded-xl bg-green-300'></div>
|
||||
<div>
|
||||
<div className='text-sm'>
|
||||
دی منو
|
||||
دی کالا
|
||||
</div>
|
||||
<div className='text-xs text-description'>
|
||||
منو فروشگاه
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { type FC } from 'react'
|
||||
import LogoImage from '../../assets/images/logo.png'
|
||||
import LogoImage from '../../assets/images/logo.svg'
|
||||
import LogoSmallImage from '../../assets/images/logo-small.png'
|
||||
import { useAuthStore } from './store/AuthStore'
|
||||
import LoginStep1 from './components/LoginStep1'
|
||||
|
||||
@@ -18,9 +18,7 @@ export const useOrderFiltersFields = (): FieldType[] => {
|
||||
{ label: 'در انتظار پرداخت', value: OrderStatus.PENDING_PAYMENT },
|
||||
{ label: 'پرداخت شده', value: OrderStatus.PAID },
|
||||
{ label: 'در حال آماده سازی', value: OrderStatus.PREPARING },
|
||||
{ label: 'آماده', value: OrderStatus.READY },
|
||||
{ label: 'تحویل به پیشخدمت', value: OrderStatus.DELIVERED_TO_WAITER },
|
||||
{ label: 'تحویل به پذیرش', value: OrderStatus.DELIVERED_TO_RECEPTIONIST },
|
||||
{ label: 'تحویل به پذیرش', value: OrderStatus.DELIVERED_TO_RECEPIENT },
|
||||
{ label: 'ارسال شده', value: OrderStatus.SHIPPED },
|
||||
{ label: 'تکمیل شده', value: OrderStatus.COMPLETED },
|
||||
{ label: 'لغو شده', value: OrderStatus.CANCELED },
|
||||
|
||||
@@ -17,6 +17,27 @@ import {
|
||||
import { useSingleUpload } from '../uploader/hooks/useUploaderData'
|
||||
import { extractErrorMessage } from '@/config/func'
|
||||
|
||||
function findCategoryById(cats: Category[], id: string | null): Category | undefined {
|
||||
if (!id) return undefined
|
||||
for (const c of cats) {
|
||||
if (c.id === id) return c
|
||||
const found = findCategoryById(c.children || [], id)
|
||||
if (found) return found
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
function flattenCategories(cats: Category[]): Category[] {
|
||||
const result: Category[] = []
|
||||
for (const c of cats) {
|
||||
result.push(c)
|
||||
if (c.children?.length) {
|
||||
result.push(...flattenCategories(c.children))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type CategoryFormValues = {
|
||||
title: string
|
||||
icon: File[]
|
||||
@@ -39,7 +60,8 @@ const CategoryProduct: FC = () => {
|
||||
|
||||
const categories = categoriesData?.data || []
|
||||
|
||||
const filteredCategories = categories.filter((category) => {
|
||||
const flattenedCategories = flattenCategories(categories)
|
||||
const filteredCategories = flattenedCategories.filter((category) => {
|
||||
if (filters.search) {
|
||||
return category.title.toLowerCase().includes(filters.search.toLowerCase())
|
||||
}
|
||||
@@ -122,7 +144,8 @@ const CategoryProduct: FC = () => {
|
||||
formik.setValues({
|
||||
title: category.title,
|
||||
icon: [],
|
||||
order: category.order || 0
|
||||
order: category.order || 0,
|
||||
parentId: category.parent || undefined
|
||||
})
|
||||
setIsActive(category.isActive)
|
||||
setIconFiles([])
|
||||
@@ -153,7 +176,7 @@ const CategoryProduct: FC = () => {
|
||||
}
|
||||
|
||||
const handleStatusChange = (id: string, value: boolean) => {
|
||||
const category = categories.find((cat) => cat.id === id)
|
||||
const category = findCategoryById(categories, id)
|
||||
if (category) {
|
||||
const categoryData: CreateCategoryType = {
|
||||
title: category.title,
|
||||
@@ -176,6 +199,7 @@ const CategoryProduct: FC = () => {
|
||||
}
|
||||
|
||||
const columns = CategoryTableColumns({
|
||||
categories,
|
||||
onStatusChange: handleStatusChange,
|
||||
onEdit: handleEdit,
|
||||
onDelete: handleDelete,
|
||||
|
||||
@@ -23,10 +23,7 @@ const CreateProduct: FC = () => {
|
||||
const { mutate: createProduct, isPending } = useCreateProduct()
|
||||
const { mutate: multipleUpload, isPending: isUploading } = useMultipleUpload()
|
||||
|
||||
const categories = data?.data?.map(category => ({
|
||||
label: category.title,
|
||||
value: category.id
|
||||
})) || []
|
||||
const categories = data?.data ?? []
|
||||
|
||||
const formik = useFormik<CreateProductType>({
|
||||
initialValues: {
|
||||
|
||||
@@ -27,10 +27,7 @@ const UpdateProduct: FC = () => {
|
||||
const { mutate: updateProduct, isPending } = useUpdateProduct()
|
||||
const { mutate: multipleUpload, isPending: isUploading } = useMultipleUpload()
|
||||
const navigate = useNavigate()
|
||||
const categories = categoriesData?.data?.map(category => ({
|
||||
label: category.title,
|
||||
value: category.id
|
||||
})) || []
|
||||
const categories = categoriesData?.data ?? []
|
||||
|
||||
const product = productData?.data
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { type FC, useState, useEffect } from 'react'
|
||||
import { type FC, useState, useEffect, useMemo } from 'react'
|
||||
import type { FormikProps } from 'formik'
|
||||
import Input from '@/components/Input'
|
||||
import Select from '@/components/Select'
|
||||
import Textarea from '@/components/Textarea'
|
||||
import Button from '@/components/Button'
|
||||
import RadioGroup from '@/components/RadioGroup'
|
||||
import type { CreateProductType, ProductVariant } from '../types/Types'
|
||||
import type { CreateProductType, ProductVariant, Category } from '../types/Types'
|
||||
import { Add, Trash } from 'iconsax-react'
|
||||
|
||||
type BasicInfoSectionProps = {
|
||||
formik: FormikProps<CreateProductType>
|
||||
categories: Array<{ label: string; value: string }>
|
||||
categories: Category[]
|
||||
/** در صفحه ویرایش، اگر کالا تنوع دارد مقدار true پاس داده شود */
|
||||
initialHasVariants?: boolean
|
||||
}
|
||||
@@ -19,6 +19,24 @@ const newVariant = (): ProductVariant => ({ value: '', price: 0 })
|
||||
|
||||
const BasicInfoSection: FC<BasicInfoSectionProps> = ({ formik, categories, initialHasVariants }) => {
|
||||
const [hasVariants, setHasVariants] = useState<boolean>(initialHasVariants ?? false)
|
||||
/** دسته اصلی انتخابشده برای نمایش زیردستهها */
|
||||
const [parentCategoryId, setParentCategoryId] = useState<string>('')
|
||||
|
||||
const mainCategories = useMemo(
|
||||
() => categories.filter((c) => !c.parent).map((c) => ({ label: c.title, value: c.id })),
|
||||
[categories]
|
||||
)
|
||||
|
||||
const selectedParent = useMemo(
|
||||
() => categories.find((c) => c.id === parentCategoryId),
|
||||
[categories, parentCategoryId]
|
||||
)
|
||||
|
||||
const subCategories = useMemo(
|
||||
() =>
|
||||
(selectedParent?.children || []).map((c) => ({ label: c.title, value: c.id })),
|
||||
[selectedParent]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (initialHasVariants !== undefined) {
|
||||
@@ -26,6 +44,19 @@ const BasicInfoSection: FC<BasicInfoSectionProps> = ({ formik, categories, initi
|
||||
}
|
||||
}, [initialHasVariants])
|
||||
|
||||
/** همگامسازی parentCategoryId با categoryId وقتی فرم مقداردهی میشود (مثلاً در ویرایش) */
|
||||
useEffect(() => {
|
||||
const catId = formik.values.categoryId
|
||||
if (!catId) return
|
||||
const cat = categories.find((c) => c.id === catId)
|
||||
const child = categories.flatMap((c) => c.children || []).find((ch) => ch.id === catId)
|
||||
if (child) {
|
||||
setParentCategoryId(child.parent || '')
|
||||
} else if (cat && !cat.parent) {
|
||||
setParentCategoryId(catId)
|
||||
}
|
||||
}, [formik.values.categoryId, categories])
|
||||
|
||||
const handleHasVariantsChange = (value: string | boolean) => {
|
||||
const next = value === true
|
||||
setHasVariants(next)
|
||||
@@ -65,20 +96,44 @@ const BasicInfoSection: FC<BasicInfoSectionProps> = ({ formik, categories, initi
|
||||
error_text={formik.touched.title && formik.errors.title ? formik.errors.title : ''}
|
||||
/>
|
||||
|
||||
<div className='mt-5'>
|
||||
<div className='mt-5 rowTwoInput flex flex-wrap gap-4'>
|
||||
<div className='flex-1 min-w-[200px]'>
|
||||
<Select
|
||||
items={categories}
|
||||
label='دسته بندی'
|
||||
items={mainCategories}
|
||||
label='دسته اصلی'
|
||||
placeholder='انتخاب کنید'
|
||||
name='categoryId'
|
||||
value={formik.values.categoryId}
|
||||
name='parentCategoryId'
|
||||
value={parentCategoryId}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value
|
||||
setParentCategoryId(value)
|
||||
formik.setFieldValue('categoryId', value)
|
||||
}}
|
||||
error_text={formik.touched.categoryId && formik.errors.categoryId ? String(formik.errors.categoryId) : ''}
|
||||
/>
|
||||
</div>
|
||||
{subCategories.length > 0 && (
|
||||
<div className='flex-1 min-w-[200px]'>
|
||||
<Select
|
||||
items={subCategories}
|
||||
label='زیر دسته'
|
||||
placeholder='انتخاب کنید (اختیاری)'
|
||||
name='subcategoryId'
|
||||
value={
|
||||
subCategories.some((s) => s.value === formik.values.categoryId)
|
||||
? formik.values.categoryId
|
||||
: ''
|
||||
}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value
|
||||
formik.setFieldValue('categoryId', value || parentCategoryId)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{formik.touched.categoryId && formik.errors.categoryId && (
|
||||
<div className='mt-1 text-xs text-red-500'>{formik.errors.categoryId}</div>
|
||||
)}
|
||||
|
||||
<div className='mt-5'>
|
||||
<Input
|
||||
|
||||
@@ -74,12 +74,11 @@ const CategoryForm: FC<Props> = ({
|
||||
<div className='mb-3 lg:mb-4'>
|
||||
<Select
|
||||
label='والد (اختیاری)'
|
||||
items={categories?.data?.map((item) => {
|
||||
return {
|
||||
label: item.title,
|
||||
value: item.id
|
||||
items={
|
||||
categories?.data
|
||||
?.filter((item) => !item.parent)
|
||||
?.map((item) => ({ label: item.title, value: item.id })) ?? []
|
||||
}
|
||||
}) || []}
|
||||
placeholder='انتخاب'
|
||||
{...formik.getFieldProps('parentId')}
|
||||
/>
|
||||
|
||||
@@ -3,14 +3,25 @@ import SwitchComponent from '@/components/Switch'
|
||||
import TrashWithConfrim from '@/components/TrashWithConfrim'
|
||||
import type { Category } from '../types/Types'
|
||||
|
||||
function findCategoryById(cats: Category[], id: string | null): Category | undefined {
|
||||
if (!id) return undefined
|
||||
for (const c of cats) {
|
||||
if (c.id === id) return c
|
||||
const found = findCategoryById(c.children || [], id)
|
||||
if (found) return found
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
type Props = {
|
||||
categories: Category[]
|
||||
onStatusChange: (id: string, value: boolean) => void
|
||||
onEdit: (category: Category) => void
|
||||
onDelete: (id: string) => void
|
||||
isDeleting?: boolean
|
||||
}
|
||||
|
||||
const CategoryTableColumns = ({ onStatusChange, onEdit, onDelete, isDeleting = false }: Props) => {
|
||||
const CategoryTableColumns = ({ categories, onStatusChange, onEdit, onDelete, isDeleting = false }: Props) => {
|
||||
return [
|
||||
{
|
||||
title: 'آیکون',
|
||||
@@ -33,14 +44,20 @@ const CategoryTableColumns = ({ onStatusChange, onEdit, onDelete, isDeleting = f
|
||||
},
|
||||
{
|
||||
title: 'عنوان',
|
||||
key: 'title'
|
||||
key: 'title',
|
||||
render: (item: Category) => (
|
||||
<div className={item.parent ? 'pr-6' : ''}>
|
||||
{item.title}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: 'والد',
|
||||
key: 'categoryId',
|
||||
render: (item: Category) => {
|
||||
const parent = typeof item.parent === 'string' ? findCategoryById(categories, item.parent) : item.parent
|
||||
return (
|
||||
<div>{item.parent?.title || '-'}</div>
|
||||
<div>{parent?.title || '-'}</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -29,12 +29,13 @@ export type Category = {
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt: string | null;
|
||||
parent: string | null;
|
||||
title: string;
|
||||
isActive: boolean;
|
||||
restId: string;
|
||||
shop: string;
|
||||
avatarUrl: string;
|
||||
order: number | null;
|
||||
parent?: Category;
|
||||
children: Category[];
|
||||
};
|
||||
|
||||
export type ProductDetailsCategory = {
|
||||
|
||||
@@ -17,11 +17,11 @@ interface GetFoodSalesPieChartParams {
|
||||
}
|
||||
|
||||
export const getFoodSalesPieChart = async (
|
||||
params?: GetFoodSalesPieChartParams
|
||||
params?: GetFoodSalesPieChartParams,
|
||||
): Promise<IFoodSalesPieChartResponse> => {
|
||||
const { data } = await axios.get<IFoodSalesPieChartResponse>(
|
||||
"/admin/orders/food-sales-pie-chart",
|
||||
{ params }
|
||||
"/admin/orders/product-sales-pie-chart",
|
||||
{ params },
|
||||
);
|
||||
return data;
|
||||
};
|
||||
@@ -33,11 +33,11 @@ interface GetPaymentsChartParams {
|
||||
}
|
||||
|
||||
export const getPaymentsChart = async (
|
||||
params?: GetPaymentsChartParams
|
||||
params?: GetPaymentsChartParams,
|
||||
): Promise<IPaymentChartResponse> => {
|
||||
const { data } = await axios.get<IPaymentChartResponse>(
|
||||
"/admin/payments/chart",
|
||||
{ params }
|
||||
{ params },
|
||||
);
|
||||
return data;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { type FC, useEffect } from 'react'
|
||||
import LogoImage from '../assets/images/logo.png'
|
||||
import LogoImage from '../assets/images/logo.svg'
|
||||
import LogoSmall from '../assets/images/logo-small.png'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { DocumentText, Home2, Logout, People, Setting2, TicketDiscount, Calendar, Security, Card, SecurityUser, TruckFast, Element3, Star1, NotificationBing, SmsEdit } from 'iconsax-react'
|
||||
|
||||
Reference in New Issue
Block a user