criticisms

This commit is contained in:
hamid zarghami
2025-10-25 12:05:23 +03:30
parent 9a90f96170
commit 8e81321add
9 changed files with 445 additions and 7 deletions
+7 -1
View File
@@ -7,6 +7,8 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
// import { getToken } from './config/func'
import MainRouter from './router/MainRouter'
// import AuthRouter from './router/AuthRouter'
import ToastContainer from './components/Toast'
import { HelmetProvider } from 'react-helmet-async';
const queryClient = new QueryClient()
@@ -18,7 +20,11 @@ const App: FC = () => {
<QueryClientProvider client={queryClient}>
<BrowserRouter>
{/* {isLoggedIn ? <MainRouter /> : <AuthRouter />} */}
<MainRouter />
<HelmetProvider>
<MainRouter />
</HelmetProvider>
<ToastContainer />
</BrowserRouter>
</QueryClientProvider>
)
+9
View File
@@ -99,6 +99,15 @@ export const fa = {
description: "توضیحات",
attach: "پیوست",
success: "موفقیت‌آمیز",
criticisms: {
criticisms: "انتقادات",
submit_your_criticisms: "انتقاد خود را ارسال کنید",
description_criticisms: "نظرات و انتقادات خود را با ما در میان بگذارید",
subject: "موضوع",
enter_your_subject: "موضوع خود را وارد کنید",
description: "توضیحات",
enter_description: "توضیحات خود را وارد کنید",
},
errors: {
required: "این فیلد الزامی است",
},
+176
View File
@@ -0,0 +1,176 @@
import { type FC } from 'react'
import Input from '../../components/Input'
import Textarea from '../../components/Textarea'
import UploadBox from '../../components/UploadBox'
import Button from '../../components/Button'
import { TickCircle, TickSquare } from 'iconsax-react'
// import { useMultiUpload } from '../ticket/hooks/useTicketData'
import { useFormik } from 'formik'
import type { CreateCriticismsTypes } from './types/CriticismsTypes'
import * as Yup from 'yup'
import { toast } from '../../shared/toast'
// import type { ErrorType } from '../../helpers/types'
// import { useCreateCriticisms } from './hooks/useCriticismsData'
import { Helmet } from 'react-helmet-async'
import { t } from '../../locale'
const AddCriticisms: FC = () => {
// const [files, setFiles] = useState<File[]>([])
// const [percent, setPercent] = useState<number>(0)
// const multiUpload = useMultiUpload(setPercent)
// const createCriticisms = useCreateCriticisms()
const formik = useFormik<CreateCriticismsTypes>({
initialValues: {
content: '',
files: [],
title: '',
},
validationSchema: Yup.object({
title: Yup.string().required(t('errors.required')),
content: Yup.string().required(t('errors.required')),
}),
onSubmit: async (values: CreateCriticismsTypes) => {
// کامنت شده - بخش ارتباط با سرور
console.log('Form submitted:', values)
toast(t('success'), 'success')
formik.resetForm()
// if (files.length > 0) {
// const images = new FormData()
// files.forEach(file => {
// images.append('files', file)
// })
// await multiUpload.mutateAsync(images, {
// onSuccess: async (data) => {
// values.files = await data.data.map((item: { url: string }) => item?.url)
// },
// onError: (error: ErrorType) => {
// toast(error.response?.data?.error?.message[0], 'error')
// }
// })
// } else {
// delete values.files
// }
// createCriticisms.mutate(values, {
// onSuccess: () => {
// toast(t('success'), 'success')
// formik.resetForm()
// setTimeout(() => {
// window.location.reload()
// }, 1000);
// },
// onError: (error: ErrorType) => {
// toast(error.response?.data?.error?.message[0], 'error')
// }
// })
}
})
return (
<div className='mt-4 text-sm'>
<Helmet>
<title>
داناک | انتقادات
</title>
</Helmet>
<div>
{t('criticisms.criticisms')}
</div>
<div className='flex gap-6 xl:mt-8 mt-5'>
<div className='flex-1 bg-white py-8 xl:px-10 px-5 rounded-3xl'>
<div>
{t('criticisms.submit_your_criticisms')}
</div>
<div className='mt-3 text-xs text-description'>
{t('criticisms.description_criticisms')}
</div>
<div className='mt-10'>
<Input
label={t('criticisms.subject')}
placeholder={t('criticisms.enter_your_subject')}
{...formik.getFieldProps('title')}
error_text={formik.touched.title && formik.errors.title ? formik.errors.title : ''}
/>
</div>
<div className='mt-7'>
<Textarea
label={t('criticisms.description')}
placeholder={t('criticisms.enter_description')}
{...formik.getFieldProps('content')}
error_text={formik.touched.content && formik.errors.content ? formik.errors.content : ''}
/>
</div>
<div className='mt-7'>
<UploadBox
label={t('attach')}
isMultiple
onChange={() => { }}
/>
</div>
<div className='mt-20 flex justify-end'>
<Button
className='xl:max-w-[100px]'
onClick={() => formik.handleSubmit()}
isLoading={false}
percentage={0}
>
<div className='flex gap-2 items-center'>
<TickCircle size={20} color='black' />
<div>
{t('ticket.send')}
</div>
</div>
</Button>
</div>
</div>
<div className='bg-white w-[300px] hidden xl:block py-10 px-5 h-fit rounded-3xl'>
<div className='text-sm'>
انتقادات و پیشنهادهای شما برای ما راه گشاست:
</div>
<div className='mt-6'>
<div className='flex items-start gap-2 border-b border-border 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 border-border 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'>
تمامی نظرات توسط داناک بررسی و پردازش شده و در صورت نیاز شما را در جریان پردازش اطلاعات قرار خواهیم داد، ممکن است همکاران ما در واحد تجربه مشتری با شما تماس گرفته و جزییات بیشتری را پیرامون نقد و نظر شما جویا شوند.
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default AddCriticisms
@@ -0,0 +1,10 @@
import { useMutation } from "@tanstack/react-query";
import { CreateCriticismsTypes } from "../types/CriticismsTypes";
import * as api from "../service/CriticismsService";
export const useCreateCriticisms = () => {
return useMutation({
mutationFn: (variables: CreateCriticismsTypes) =>
api.createCriticisms(variables),
});
};
@@ -0,0 +1,7 @@
import axios from "../../../config/axios";
import { CreateCriticismsTypes } from "../types/CriticismsTypes";
export const createCriticisms = async (params: CreateCriticismsTypes) => {
const { data } = await axios.post(`/criticisms`, params);
return data;
};
@@ -0,0 +1,5 @@
export type CreateCriticismsTypes = {
title: string;
content: string;
files?: string[];
};
+2
View File
@@ -13,6 +13,7 @@ import CreateTicket from '@/pages/ticket/CreateTicket'
import TicketDetail from '@/pages/ticket/Detail'
import AnnouncementList from '@/pages/annoncement/List'
import AnnouncementDetail from '@/pages/annoncement/Detail'
import AddCriticisms from '@/pages/criticisms/Add'
const MainRouter: FC = () => {
return (
@@ -35,6 +36,7 @@ const MainRouter: FC = () => {
<Route path={`${Paths.tickets.detail}:id`} element={<TicketDetail />} />
<Route path={Paths.announcement.list} element={<AnnouncementList />} />
<Route path={`${Paths.announcement.detail}:id`} element={<AnnouncementDetail />} />
<Route path={Paths.criticisms} element={<AddCriticisms />} />
</Routes>
</div>
</div>