crd warranty
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import { type FC, useState } from 'react'
|
||||
import { useFormik } from 'formik'
|
||||
import { type CreateWarrantyType } from './types/Types'
|
||||
import * as Yup from 'yup'
|
||||
import { useCreateWarranty } from './hooks/useWarrantyData'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import Input from '../../components/Input'
|
||||
import Button from '../../components/Button'
|
||||
import { TickCircle } from 'iconsax-react'
|
||||
import { useUploadSingle } from '../uploader/hooks/useUploaderData'
|
||||
import UploadBoxDraggble from '@/components/UploadBoxDraggble'
|
||||
import { toast } from 'react-toastify'
|
||||
import { extractErrorMessage } from '@/helpers/utils'
|
||||
import { Pages } from '@/config/Pages'
|
||||
|
||||
const CreateWarranty: FC = () => {
|
||||
const navigate = useNavigate()
|
||||
const uploadSingle = useUploadSingle()
|
||||
const createWarrantyMutation = useCreateWarranty()
|
||||
|
||||
const [logoFile, setLogoFile] = useState<File[]>([])
|
||||
|
||||
const formik = useFormik<CreateWarrantyType>({
|
||||
initialValues: {
|
||||
name: '',
|
||||
duration: '',
|
||||
logoUrl: '',
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
name: Yup.string().required('عنوان گارانتی الزامی است'),
|
||||
duration: Yup.string().required('مدت زمان گارانتی الزامی است'),
|
||||
}),
|
||||
onSubmit: async (values) => {
|
||||
let logoUrl = values.logoUrl
|
||||
|
||||
if (logoFile.length > 0) {
|
||||
const logoResponse = await uploadSingle.mutateAsync(logoFile[0])
|
||||
logoUrl = logoResponse.results?.url?.url || ''
|
||||
}
|
||||
|
||||
const submitData = {
|
||||
...values,
|
||||
logoUrl
|
||||
}
|
||||
|
||||
createWarrantyMutation.mutate(submitData, {
|
||||
onSuccess: () => {
|
||||
toast.success('گارانتی با موفقیت ایجاد شد')
|
||||
navigate(Pages.products.warranty.list)
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<div className='mt-4'>
|
||||
<div className='flex justify-between items-center'>
|
||||
<div className='flex items-center gap-3'>
|
||||
<h1>ساخت گارانتی جدید</h1>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
className='px-6'
|
||||
onClick={() => formik.handleSubmit()}
|
||||
isLoading={createWarrantyMutation.isPending || uploadSingle.isPending}
|
||||
disabled={!formik.isValid || createWarrantyMutation.isPending || uploadSingle.isPending}
|
||||
>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<TickCircle size={16} color='#fff' />
|
||||
<div>ثبت گارانتی</div>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex gap-6 xl:mt-8 mt-6'>
|
||||
{/* اطلاعات اصلی */}
|
||||
<div className='flex-1 text-sm bg-white py-8 xl:px-10 px-6 rounded-3xl'>
|
||||
<h2 className='text-lg font-medium mb-6'>اطلاعات اصلی</h2>
|
||||
|
||||
<div className='space-y-6'>
|
||||
<div className='grid grid-cols-1 md:grid-cols-2 gap-6'>
|
||||
<Input
|
||||
label='عنوان گارانتی'
|
||||
placeholder='مثال: گارانتی طلایی'
|
||||
{...formik.getFieldProps('name')}
|
||||
error_text={formik.touched.name && formik.errors.name ? formik.errors.name : ''}
|
||||
/>
|
||||
<Input
|
||||
label='مدت زمان گارانتی'
|
||||
placeholder='مثال: 24 ماه'
|
||||
{...formik.getFieldProps('duration')}
|
||||
error_text={formik.touched.duration && formik.errors.duration ? formik.errors.duration : ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* فایلها */}
|
||||
<div className='w-80 space-y-6'>
|
||||
<div className='text-sm bg-white py-8 px-6 rounded-3xl'>
|
||||
<h2 className='text-lg font-medium mb-6'>فایلها</h2>
|
||||
|
||||
<div className='space-y-6'>
|
||||
<div>
|
||||
<UploadBoxDraggble
|
||||
label='لوگو گارانتی'
|
||||
isMultiple={false}
|
||||
onChange={(files) => setLogoFile(files)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CreateWarranty
|
||||
@@ -0,0 +1,117 @@
|
||||
import { type FC, useState } from 'react'
|
||||
import { useGetWarranties, useDeleteWarranty } from './hooks/useWarrantyData'
|
||||
import { type Warranty } from './types/Types'
|
||||
import PageLoading from '@/components/PageLoading'
|
||||
import Error from '@/components/Error'
|
||||
import PaginationUi from '@/components/PaginationUi'
|
||||
import Td from '@/components/Td'
|
||||
import TrashWithConfrim from '@/components/TrashWithConfrim'
|
||||
import Button from '@/components/Button'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { Pages } from '@/config/Pages'
|
||||
|
||||
const WarrantyList: FC = () => {
|
||||
|
||||
const navigate = useNavigate()
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const { data: warrantiesData, isLoading, error, refetch } = useGetWarranties(currentPage)
|
||||
const deleteWarrantyMutation = useDeleteWarranty();
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex justify-center items-center min-h-[400px]">
|
||||
<PageLoading />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="flex justify-center items-center min-h-[400px]">
|
||||
<Error errorText="خطا در بارگذاری گارانتیها" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const handleDeleteWarranty = async (warrantyId: string) => {
|
||||
await deleteWarrantyMutation.mutateAsync(warrantyId);
|
||||
refetch()
|
||||
};
|
||||
|
||||
const warranties = warrantiesData?.results?.warranties || [];
|
||||
const pager = warrantiesData?.results?.pager;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='flex justify-end mt-5'>
|
||||
<Button
|
||||
label='افزودن گارانتی'
|
||||
onClick={() => navigate(`${Pages.products.warranty.create}`)}
|
||||
className='w-fit'
|
||||
/>
|
||||
</div>
|
||||
<div className='relative overflow-x-auto rounded-3xl mt-5 w-full'>
|
||||
<table className='w-full text-sm'>
|
||||
<thead className='thead'>
|
||||
<tr>
|
||||
<Td text={'لوگو'} />
|
||||
<Td text={'نام'} />
|
||||
<Td text={'مدت زمان'} />
|
||||
<Td text={'وضعیت'} />
|
||||
<Td text={'عملیات'} />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{warranties.length === 0 ? (
|
||||
<tr className='tr'>
|
||||
<td colSpan={5} className="text-center py-8 text-gray-500">
|
||||
هیچ گارانتی یافت نشد
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
warranties.map((warranty: Warranty) => (
|
||||
<tr key={warranty._id} className='tr'>
|
||||
<Td text="">
|
||||
<div className="w-12 h-12 rounded-lg overflow-hidden">
|
||||
<img
|
||||
src={warranty.logoUrl || '/placeholder-image.png'}
|
||||
alt={warranty.name}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
</Td>
|
||||
<Td text={warranty.name} />
|
||||
<Td text={warranty.duration} />
|
||||
<Td text="">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={`px-2 py-1 rounded-full text-xs`}>
|
||||
{warranty.status}
|
||||
</span>
|
||||
</div>
|
||||
</Td>
|
||||
<Td text="">
|
||||
<div className="flex items-center gap-2">
|
||||
<TrashWithConfrim
|
||||
onDelete={() => handleDeleteWarranty(warranty._id.toString())}
|
||||
isLoading={deleteWarrantyMutation.isPending}
|
||||
/>
|
||||
</div>
|
||||
</Td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<PaginationUi
|
||||
pager={pager}
|
||||
onPageChange={(page) => {
|
||||
setCurrentPage(page);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default WarrantyList
|
||||
@@ -1,10 +1,22 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import * as api from "../service/WarrantyService";
|
||||
import type { WarrantyResponse } from "../types/Types";
|
||||
|
||||
export const useGetWarranties = () => {
|
||||
export const useGetWarranties = (page: number = 1, limit: number = 10) => {
|
||||
return useQuery<WarrantyResponse>({
|
||||
queryKey: ["warranties"],
|
||||
queryFn: () => api.getWarranties(),
|
||||
queryKey: ["warranties", page, limit],
|
||||
queryFn: () => api.getWarranties({ page, limit }),
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteWarranty = () => {
|
||||
return useMutation({
|
||||
mutationFn: (id: string) => api.deleteWarranty(id),
|
||||
});
|
||||
};
|
||||
|
||||
export const useCreateWarranty = () => {
|
||||
return useMutation({
|
||||
mutationFn: api.createWarranty,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import axios from "../../../config/axios";
|
||||
import type { GetWarrantiesParams, WarrantyResponse } from "../types/Types";
|
||||
import type {
|
||||
GetWarrantiesParams,
|
||||
WarrantyResponse,
|
||||
CreateWarrantyType,
|
||||
} from "../types/Types";
|
||||
|
||||
export const getWarranties = async (
|
||||
params?: GetWarrantiesParams
|
||||
@@ -7,3 +11,13 @@ export const getWarranties = async (
|
||||
const { data } = await axios.get("/warranty", { params });
|
||||
return data;
|
||||
};
|
||||
|
||||
export const deleteWarranty = async (id: string) => {
|
||||
const { data } = await axios.delete(`/admin/warranty/${id}`);
|
||||
return data;
|
||||
};
|
||||
|
||||
export const createWarranty = async (params: CreateWarrantyType) => {
|
||||
const { data } = await axios.post(`/admin/warranty`, params);
|
||||
return data;
|
||||
};
|
||||
|
||||
@@ -14,8 +14,8 @@ export interface Pager {
|
||||
limit: number;
|
||||
totalItems: number;
|
||||
totalPages: number;
|
||||
prevPage: boolean;
|
||||
nextPage: boolean;
|
||||
prevPage: boolean | null;
|
||||
nextPage: string | null;
|
||||
}
|
||||
|
||||
export interface WarrantyResults {
|
||||
@@ -33,3 +33,9 @@ export interface GetWarrantiesParams {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export type CreateWarrantyType = {
|
||||
name: string;
|
||||
duration: string;
|
||||
logoUrl: string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user