banner mobile
This commit is contained in:
@@ -9,6 +9,7 @@ type Props = {
|
||||
isMultiple?: boolean,
|
||||
onChange?: (file: File[]) => void;
|
||||
isReset?: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const UploadBox: FC<Props> = (props: Props) => {
|
||||
@@ -17,6 +18,9 @@ const UploadBox: FC<Props> = (props: Props) => {
|
||||
const [files, setFiles] = useState<File[]>([])
|
||||
|
||||
const onDrop = useCallback((acceptedFiles: File[]) => {
|
||||
if (props.disabled) {
|
||||
return
|
||||
}
|
||||
if (props.isMultiple) {
|
||||
const array = [...files]
|
||||
array.push(acceptedFiles[0])
|
||||
@@ -31,8 +35,8 @@ const UploadBox: FC<Props> = (props: Props) => {
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [files])
|
||||
const { getRootProps, getInputProps } = useDropzone({ onDrop })
|
||||
}, [files, props.disabled, props.isMultiple, props.onChange])
|
||||
const { getRootProps, getInputProps } = useDropzone({ onDrop, disabled: props.disabled })
|
||||
|
||||
const handleRemove = (index: number) => {
|
||||
const array = [...files]
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useState, type FC } from 'react'
|
||||
import PageTitle from '../../components/PageTitle'
|
||||
import { useDeleteBanner, useGetBanners, useUpdateBanner } from './hooks/useSettingData'
|
||||
import { type BannerItem, type UpdateBannerType } from './types/Types'
|
||||
import PageLoading from '../../components/PageLoading'
|
||||
import Error from '../../components/Error'
|
||||
import Td from '../../components/Td'
|
||||
import PageTitle from '@/components/PageTitle'
|
||||
import PageLoading from '@/components/PageLoading'
|
||||
import Error from '@/components/Error'
|
||||
import Td from '@/components/Td'
|
||||
import Button from '@/components/Button'
|
||||
import TrashWithConfrim from '@/components/TrashWithConfrim'
|
||||
import Switch from '@/components/Switch'
|
||||
import { useDeleteBanner, useGetBanners, useUpdateBanner } from '@/pages/setting/hooks/useSettingData'
|
||||
import { type BannerItem, type UpdateBannerType } from '@/pages/setting/types/Types'
|
||||
import { Calendar, Add, Edit, Eye } from 'iconsax-react'
|
||||
import Button from '../../components/Button'
|
||||
import TrashWithConfrim from '../../components/TrashWithConfrim'
|
||||
import Switch from '../../components/Switch'
|
||||
import CreateBannerModal from './components/CreateBannerModal'
|
||||
import EditBannerModal from './components/EditBannerModal'
|
||||
|
||||
@@ -55,7 +55,8 @@ const Banners: FC = () => {
|
||||
title: banner.title,
|
||||
linkUrl: banner.linkUrl,
|
||||
isActive: !banner.isActive,
|
||||
order: banner.order
|
||||
order: banner.order,
|
||||
displayLocation: banner.displayLocation
|
||||
}
|
||||
|
||||
updateBanner.mutate({ id: banner._id, params: updateData })
|
||||
@@ -87,6 +88,7 @@ const Banners: FC = () => {
|
||||
<Td text={'عنوان'} />
|
||||
<Td text={'متن جایگزین'} />
|
||||
<Td text={'لینک'} />
|
||||
<Td text={'محل نمایش'} />
|
||||
<Td text={'ترتیب'} />
|
||||
<Td text={'وضعیت'} />
|
||||
<Td text={'تاریخ ایجاد'} />
|
||||
@@ -96,7 +98,7 @@ const Banners: FC = () => {
|
||||
<tbody>
|
||||
{banners.length === 0 ? (
|
||||
<tr className='tr'>
|
||||
<td colSpan={8} className="text-center py-8 text-gray-500">
|
||||
<td colSpan={9} className="text-center py-8 text-gray-500">
|
||||
هیچ بنری یافت نشد
|
||||
</td>
|
||||
</tr>
|
||||
@@ -137,6 +139,11 @@ const Banners: FC = () => {
|
||||
</a>
|
||||
</div>
|
||||
</Td>
|
||||
<Td text="">
|
||||
<span className="capitalize">
|
||||
{banner.displayLocation === 'desktop' ? 'دسکتاپ' : 'موبایل'}
|
||||
</span>
|
||||
</Td>
|
||||
<Td text={banner.order.toString()} />
|
||||
<Td text="">
|
||||
<Switch
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import React, { useState } from 'react'
|
||||
import { type FC } from 'react'
|
||||
import Button from '../../../components/Button'
|
||||
import Input from '../../../components/Input'
|
||||
import DefaulModal from '../../../components/DefaulModal'
|
||||
import { useCreateBanner } from '../hooks/useSettingData'
|
||||
import { useUploadSingle } from '../../../pages/uploader/hooks/useUploaderData'
|
||||
import { type CreateBannerType } from '../types/Types'
|
||||
import Button from '@/components/Button'
|
||||
import Input from '@/components/Input'
|
||||
import DefaulModal from '@/components/DefaulModal'
|
||||
import UploadBox from '@/components/UploadBox'
|
||||
import Switch from '@/components/Switch'
|
||||
import Select, { type ItemsSelectType } from '@/components/Select'
|
||||
import { useCreateBanner } from '@/pages/setting/hooks/useSettingData'
|
||||
import { useUploadSingle } from '@/pages/uploader/hooks/useUploaderData'
|
||||
import { type CreateBannerType } from '@/pages/setting/types/Types'
|
||||
import { toast } from 'react-toastify'
|
||||
import { extractErrorMessage } from '@/helpers/utils'
|
||||
import UploadBox from '../../../components/UploadBox'
|
||||
import Switch from '../../../components/Switch'
|
||||
|
||||
interface CreateBannerModalProps {
|
||||
isOpen: boolean
|
||||
@@ -17,14 +18,24 @@ interface CreateBannerModalProps {
|
||||
onSuccess: () => void
|
||||
}
|
||||
|
||||
type CreateBannerFormState = Omit<CreateBannerType, 'displayLocation'> & {
|
||||
displayLocation: '' | 'desktop' | 'mobile'
|
||||
}
|
||||
|
||||
const displayLocationOptions: ItemsSelectType[] = [
|
||||
{ value: 'desktop', label: 'دسکتاپ' },
|
||||
{ value: 'mobile', label: 'موبایل' }
|
||||
]
|
||||
|
||||
const CreateBannerModal: FC<CreateBannerModalProps> = ({ isOpen, onClose }) => {
|
||||
const [formData, setFormData] = useState<CreateBannerType>({
|
||||
const [formData, setFormData] = useState<CreateBannerFormState>({
|
||||
imageUrl: '',
|
||||
altText: '',
|
||||
title: '',
|
||||
linkUrl: '',
|
||||
isActive: true,
|
||||
order: 1,
|
||||
displayLocation: '',
|
||||
})
|
||||
|
||||
const [imageFile, setImageFile] = useState<File[]>([])
|
||||
@@ -40,6 +51,11 @@ const CreateBannerModal: FC<CreateBannerModalProps> = ({ isOpen, onClose }) => {
|
||||
return
|
||||
}
|
||||
|
||||
if (!formData.displayLocation) {
|
||||
toast.error('لطفا محل نمایش بنر را مشخص کنید')
|
||||
return
|
||||
}
|
||||
|
||||
if (imageFile.length === 0) {
|
||||
toast.error('لطفا تصویر بنر را انتخاب کنید')
|
||||
return
|
||||
@@ -68,6 +84,7 @@ const CreateBannerModal: FC<CreateBannerModalProps> = ({ isOpen, onClose }) => {
|
||||
linkUrl: formData.linkUrl,
|
||||
isActive: formData.isActive,
|
||||
order: formData.order,
|
||||
displayLocation: formData.displayLocation,
|
||||
}, {
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
@@ -89,6 +106,7 @@ const CreateBannerModal: FC<CreateBannerModalProps> = ({ isOpen, onClose }) => {
|
||||
linkUrl: '',
|
||||
isActive: true,
|
||||
order: 1,
|
||||
displayLocation: '',
|
||||
})
|
||||
setImageFile([])
|
||||
onClose()
|
||||
@@ -97,12 +115,25 @@ const CreateBannerModal: FC<CreateBannerModalProps> = ({ isOpen, onClose }) => {
|
||||
return (
|
||||
<DefaulModal open={isOpen} close={handleClose} isHeader={true} title_header="افزودن بنر جدید">
|
||||
<form onSubmit={handleSubmit} className="w-[500px] mt-4 space-y-6">
|
||||
{/* محل نمایش */}
|
||||
<div>
|
||||
<Select
|
||||
label='محل نمایش'
|
||||
placeholder='انتخاب محل نمایش'
|
||||
items={displayLocationOptions}
|
||||
value={formData.displayLocation}
|
||||
onChange={(e) => setFormData(prev => ({ ...prev, displayLocation: e.target.value as CreateBannerFormState['displayLocation'] }))}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* تصویر بنر */}
|
||||
<div>
|
||||
<UploadBox
|
||||
label='تصویر بنر'
|
||||
isMultiple={false}
|
||||
onChange={(files) => setImageFile(files)}
|
||||
disabled={!formData.displayLocation}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { type FC } from 'react'
|
||||
import Button from '../../../components/Button'
|
||||
import Input from '../../../components/Input'
|
||||
import DefaulModal from '../../../components/DefaulModal'
|
||||
import { useUpdateBanner } from '../hooks/useSettingData'
|
||||
import { useUploadSingle } from '../../../pages/uploader/hooks/useUploaderData'
|
||||
import { type BannerItem, type UpdateBannerType } from '../types/Types'
|
||||
import Button from '@/components/Button'
|
||||
import Input from '@/components/Input'
|
||||
import DefaulModal from '@/components/DefaulModal'
|
||||
import UploadBox from '@/components/UploadBox'
|
||||
import Switch from '@/components/Switch'
|
||||
import Select, { type ItemsSelectType } from '@/components/Select'
|
||||
import { useUpdateBanner } from '@/pages/setting/hooks/useSettingData'
|
||||
import { useUploadSingle } from '@/pages/uploader/hooks/useUploaderData'
|
||||
import { type BannerItem, type UpdateBannerType } from '@/pages/setting/types/Types'
|
||||
import { toast } from 'react-toastify'
|
||||
import { extractErrorMessage } from '@/helpers/utils'
|
||||
import UploadBox from '../../../components/UploadBox'
|
||||
import Switch from '../../../components/Switch'
|
||||
|
||||
interface EditBannerModalProps {
|
||||
banner: BannerItem
|
||||
@@ -18,6 +19,11 @@ interface EditBannerModalProps {
|
||||
onSuccess: () => void
|
||||
}
|
||||
|
||||
const displayLocationOptions: ItemsSelectType[] = [
|
||||
{ value: 'desktop', label: 'دسکتاپ' },
|
||||
{ value: 'mobile', label: 'موبایل' }
|
||||
]
|
||||
|
||||
const EditBannerModal: FC<EditBannerModalProps> = ({ banner, isOpen, onClose, onSuccess }) => {
|
||||
const [formData, setFormData] = useState<UpdateBannerType>({
|
||||
imageUrl: '',
|
||||
@@ -26,6 +32,7 @@ const EditBannerModal: FC<EditBannerModalProps> = ({ banner, isOpen, onClose, on
|
||||
linkUrl: '',
|
||||
isActive: true,
|
||||
order: 1,
|
||||
displayLocation: 'desktop',
|
||||
})
|
||||
|
||||
const [imageFile, setImageFile] = useState<File[]>([])
|
||||
@@ -42,6 +49,7 @@ const EditBannerModal: FC<EditBannerModalProps> = ({ banner, isOpen, onClose, on
|
||||
linkUrl: banner.linkUrl,
|
||||
isActive: banner.isActive,
|
||||
order: banner.order,
|
||||
displayLocation: banner.displayLocation,
|
||||
})
|
||||
}
|
||||
}, [banner])
|
||||
@@ -59,6 +67,11 @@ const EditBannerModal: FC<EditBannerModalProps> = ({ banner, isOpen, onClose, on
|
||||
return
|
||||
}
|
||||
|
||||
if (!formData.displayLocation) {
|
||||
toast.error('لطفا محل نمایش بنر را مشخص کنید')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
let finalImageUrl = formData.imageUrl
|
||||
|
||||
@@ -83,6 +96,7 @@ const EditBannerModal: FC<EditBannerModalProps> = ({ banner, isOpen, onClose, on
|
||||
linkUrl: formData.linkUrl,
|
||||
isActive: formData.isActive,
|
||||
order: formData.order,
|
||||
displayLocation: formData.displayLocation,
|
||||
}
|
||||
}, {
|
||||
onError: (error) => {
|
||||
@@ -106,6 +120,7 @@ const EditBannerModal: FC<EditBannerModalProps> = ({ banner, isOpen, onClose, on
|
||||
linkUrl: '',
|
||||
isActive: true,
|
||||
order: 1,
|
||||
displayLocation: 'desktop',
|
||||
})
|
||||
setImageFile([])
|
||||
onClose()
|
||||
@@ -114,6 +129,17 @@ const EditBannerModal: FC<EditBannerModalProps> = ({ banner, isOpen, onClose, on
|
||||
return (
|
||||
<DefaulModal open={isOpen} close={handleClose} isHeader={true} title_header="ویرایش بنر">
|
||||
<form onSubmit={handleSubmit} className="w-[500px] mt-4 space-y-6">
|
||||
{/* محل نمایش */}
|
||||
<div>
|
||||
<Select
|
||||
label='محل نمایش'
|
||||
items={displayLocationOptions}
|
||||
value={formData.displayLocation}
|
||||
onChange={(e) => setFormData(prev => ({ ...prev, displayLocation: e.target.value as UpdateBannerType['displayLocation'] }))}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* تصویر بنر */}
|
||||
<div>
|
||||
<div className="mb-4">
|
||||
|
||||
@@ -220,6 +220,7 @@ export interface BannerItem {
|
||||
linkUrl: string;
|
||||
isActive: boolean;
|
||||
order: number;
|
||||
displayLocation: "desktop" | "mobile";
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
@@ -241,6 +242,7 @@ export interface CreateBannerType {
|
||||
linkUrl: string;
|
||||
isActive: boolean;
|
||||
order: number;
|
||||
displayLocation: "desktop" | "mobile";
|
||||
}
|
||||
|
||||
export interface UpdateBannerType {
|
||||
@@ -250,6 +252,7 @@ export interface UpdateBannerType {
|
||||
linkUrl: string;
|
||||
isActive: boolean;
|
||||
order: number;
|
||||
displayLocation: "desktop" | "mobile";
|
||||
}
|
||||
|
||||
export interface SliderItem {
|
||||
|
||||
Reference in New Issue
Block a user