review
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
VITE_TOKEN_NAME = 'dsc_token'
|
||||
VITE_REFRESH_TOKEN_NAME = 'dsc_refresh_token'
|
||||
VITE_BASE_URL = 'https://api.danakcorp.com'
|
||||
# VITE_BASE_URL = 'http://192.168.0.216:4000'
|
||||
# VITE_BASE_URL = 'http://192.168.1.124:4000'
|
||||
@@ -15,6 +15,7 @@ import AuthRouter from './router/Auth'
|
||||
import { Pages } from './config/Pages'
|
||||
import useConvertNumbers from './hooks/useConvertNumbers';
|
||||
import { Helmet, HelmetProvider } from 'react-helmet-async';
|
||||
import moment from 'moment-jalaali';
|
||||
|
||||
i18next.init({
|
||||
interpolation: { escapeValue: false },
|
||||
@@ -47,6 +48,7 @@ const App: FC = () => {
|
||||
|
||||
// useNumberFont()
|
||||
useConvertNumbers()
|
||||
moment.loadPersian({ usePersianDigits: true, dialect: "persian-modern" });
|
||||
|
||||
const [isLogin, setIsLogin] = useState<'checking' | 'isLogin' | 'isNotLogin'>('checking')
|
||||
useEffect(() => {
|
||||
|
||||
+54
-17
@@ -18,11 +18,57 @@ type Props = {
|
||||
onChangeSearchFinal?: (value: string) => void;
|
||||
} & InputHTMLAttributes<HTMLInputElement>
|
||||
|
||||
const formatNumber = (value: string | number): string => {
|
||||
if (!value) return '';
|
||||
const inputValue = String(value).replace(/,/g, '');
|
||||
return inputValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
};
|
||||
|
||||
const Input: FC<Props> = (props: Props) => {
|
||||
|
||||
const [formattedValue, setFormattedValue] = useState<string>(
|
||||
props.value ? formatNumber(props.value as string) : ''
|
||||
);
|
||||
|
||||
const [showPassword, setShowPassword] = useState<boolean>(false)
|
||||
const [search, setSearch] = useState<string>('')
|
||||
|
||||
const inputClass = clx(
|
||||
'w-full h-10 text-black block px-4 text-xs rounded-xl border border-border',
|
||||
props.readOnly && 'bg-gray-100 border-0 text-description',
|
||||
props.variant === 'search' && 'bg-[#EEF0F7] border-0 ps-10',
|
||||
props.className
|
||||
);
|
||||
|
||||
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (props.seprator) {
|
||||
const inputValue = event.target.value.replace(/,/g, ''); // حذف کاماها
|
||||
const formatted = formatNumber(inputValue);
|
||||
|
||||
// بهروزرسانی مقدار قالببندیشده
|
||||
setFormattedValue(formatted);
|
||||
|
||||
// ارسال مقدار خام به `onChange` والد
|
||||
props.onChange?.({
|
||||
...event,
|
||||
target: {
|
||||
...event.target,
|
||||
value: inputValue,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
props.onChange?.(event);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (props.value) {
|
||||
setFormattedValue(formatNumber(props.value as string));
|
||||
} else {
|
||||
setFormattedValue('');
|
||||
}
|
||||
}, [props.value])
|
||||
|
||||
useEffect(() => {
|
||||
if (props.variant === 'search' && props.onChangeSearchFinal) {
|
||||
const timeout = setTimeout(() => {
|
||||
@@ -32,13 +78,6 @@ const Input: FC<Props> = (props: Props) => {
|
||||
}
|
||||
}, [search, props])
|
||||
|
||||
const inputClass = clx(
|
||||
'w-full h-10 text-black block px-4 text-xs rounded-xl border border-border',
|
||||
props.readOnly && 'bg-gray-100 border-0 text-description',
|
||||
props.variant === 'search' && 'bg-[#EEF0F7] border-0 ps-10',
|
||||
props.className
|
||||
);
|
||||
|
||||
|
||||
return (
|
||||
<div className='w-full'>
|
||||
@@ -49,8 +88,8 @@ const Input: FC<Props> = (props: Props) => {
|
||||
<div className='w-full relative mt-1'>
|
||||
<input {...props} onChange={(e) => {
|
||||
setSearch(e.target.value)
|
||||
props.onChange?.(e)
|
||||
}} type={props.type === 'password' && showPassword ? 'text' : props.type === 'password' ? 'password' : undefined} className={inputClass} />
|
||||
handleInputChange(e)
|
||||
}} value={props.seprator ? formattedValue : props.value} type={props.type === 'password' && showPassword ? 'text' : props.type === 'password' ? 'password' : undefined} className={inputClass} />
|
||||
|
||||
{
|
||||
props.type === 'password' &&
|
||||
@@ -62,15 +101,13 @@ const Input: FC<Props> = (props: Props) => {
|
||||
<SearchNormal size={20} color='#8C90A3' className='absolute top-0 w-5 bottom-0 my-auto right-3' />
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
props.error_text &&
|
||||
<Error
|
||||
errorText={props.error_text}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
||||
{
|
||||
props.error_text &&
|
||||
<Error
|
||||
errorText={props.error_text}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
+2
-1
@@ -443,7 +443,8 @@
|
||||
"failed": "پرداخت ناموفق!",
|
||||
"desc_failed": "متأسفیم! پرداخت شما انجام نشد. لطفاً دوباره تلاش کنید یا روش پرداخت دیگری انتخاب کنید.",
|
||||
"pending": "وضعیت پرداخت نامشخص است!",
|
||||
"desc_pending": "اگر مبلغی از حساب شما کسر شده ولی سفارش شما بعد از ۷۲ ساعت تأیید نشد، لطفاً با پشتیبانی تماس بگیرید."
|
||||
"desc_pending": "اگر مبلغی از حساب شما کسر شده ولی سفارش شما بعد از ۷۲ ساعت تأیید نشد، لطفاً با پشتیبانی تماس بگیرید.",
|
||||
"home": "صفحه اصلی"
|
||||
},
|
||||
"discount": {
|
||||
"number": "شماره",
|
||||
|
||||
@@ -38,7 +38,7 @@ const Notifications: FC = () => {
|
||||
<div ref={ref}>
|
||||
<div onClick={() => setShowModal(!showModal)} className='relative cursor-pointer'>
|
||||
<Notification size={18} color="black" />
|
||||
<div className="absolute top-0 right-0 -mt-1 -mr-1 rounded-full bg-red-500 text-white text-[8px] size-3 flex justify-center items-center">
|
||||
<div className="absolute top-0 right-0 -mt-1 -mr-1 rounded-full bg-red-500 text-white text-[8px] size-3 flex pt-0.5 pl-[1px] justify-center items-center">
|
||||
{getDashboard.data?.data?.notificationCount}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -93,11 +93,18 @@ const CallBack: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
label={t('callback.back')}
|
||||
className='xl:max-w-[560px] mt-8'
|
||||
onClick={() => navigate(Pages.transactions)}
|
||||
/>
|
||||
<div className='flex xl:max-w-[560px] w-full gap-2.5'>
|
||||
<Button
|
||||
label={t('callback.home')}
|
||||
className='w-full mt-8 bg-transparent border border-black text-black'
|
||||
onClick={() => navigate(Pages.dashboard)}
|
||||
/>
|
||||
<Button
|
||||
label={t('callback.back')}
|
||||
className='w-full mt-8'
|
||||
onClick={() => navigate(Pages.transactions)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { FC, Fragment } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '../../components/Button'
|
||||
import Rate from 'rc-rate'
|
||||
import ServiceImages from './components/ServiceImages'
|
||||
import Input from '../../components/Input'
|
||||
import Textarea from '../../components/Textarea'
|
||||
import AvatarImage from '../../assets/images/Avatar.png'
|
||||
import AvatarImage from '../../assets/images/avatar_image.png'
|
||||
import ServiceHeader from './components/ServiceHeader'
|
||||
import { useGetDetailService } from './hooks/useServiceData'
|
||||
import { useParams } from 'react-router-dom'
|
||||
@@ -13,6 +10,8 @@ import PageLoading from '../../components/PageLoading'
|
||||
import moment from 'moment-jalaali'
|
||||
import { useGetAds } from '../ads/hooks/useAdsData'
|
||||
import { AdsDisplayLocation } from '../ads/types/AdsTypes'
|
||||
import CreateReview from './components/CreateReview'
|
||||
import { ReviewItemType } from './types/ServiecTypes'
|
||||
|
||||
const DetailService: FC = () => {
|
||||
|
||||
@@ -74,8 +73,9 @@ const DetailService: FC = () => {
|
||||
<Rate
|
||||
count={5}
|
||||
style={{ fontSize: 15 }}
|
||||
value={4}
|
||||
value={getDetailService?.data?.data?.averageRating}
|
||||
disabled
|
||||
allowHalf
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -92,111 +92,51 @@ const DetailService: FC = () => {
|
||||
</div>
|
||||
|
||||
<div className='mt-8 flex xl:flex-row flex-col gap-8 items-start'>
|
||||
<div className='bg-white p-6 rounded-3xl xl:w-[360px] w-full'>
|
||||
<div>
|
||||
{t('service.submit_comment')}
|
||||
</div>
|
||||
<div className='text-xs mt-4'>
|
||||
{t('service.hint_comment')}
|
||||
</div>
|
||||
|
||||
<div className='mt-6 text-description text-sm'>
|
||||
<div>
|
||||
{t('service.score')}
|
||||
</div>
|
||||
<div className='mt-2 dltr flex justify-end'>
|
||||
<Rate
|
||||
count={5}
|
||||
style={{ fontSize: 22 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-6'>
|
||||
<Input
|
||||
label={t('service.title')}
|
||||
placeholder={t('service.enter_title_comment')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-6'>
|
||||
<Textarea
|
||||
label={t('service.your_comment')}
|
||||
placeholder={t('service.write_your_comment')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-6'>
|
||||
<Button
|
||||
label={t('service.submit_comment')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
getDetailService.data?.data?.purchased &&
|
||||
<CreateReview refetch={() => getDetailService.refetch()} />
|
||||
}
|
||||
<div className='flex-1 max-w-full bg-white p-6 rounded-3xl'>
|
||||
<div className='text-sm'>
|
||||
{t('service.users_comments')}
|
||||
</div>
|
||||
|
||||
<div className='mt-5 border border-border rounded-3xl p-6'>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<img src={AvatarImage} className='size-6 rounded-full object-cover' />
|
||||
<div className='text-description text-xs'>
|
||||
فروغ براتی
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
getDetailService.data?.data?.danakService?.reviews?.map((item: ReviewItemType) => {
|
||||
return (
|
||||
<div className='mt-5 border border-border rounded-3xl p-6'>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<img src={item.user.profilePic || AvatarImage} className='size-6 rounded-full object-cover' />
|
||||
<div className='text-description text-xs'>
|
||||
{item.user?.firstName + ' ' + item.user?.lastName}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-4 flex justify-between'>
|
||||
<div className='text-sm max-w-[70%] truncate'>
|
||||
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ
|
||||
</div>
|
||||
<div className='text-xs text-description'>
|
||||
۳ روز پیش
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-4 flex justify-between'>
|
||||
<div className='text-sm max-w-[70%] truncate'>
|
||||
{item.title}
|
||||
</div>
|
||||
<div className='text-xs text-description'>
|
||||
{moment(item.createdAt).fromNow()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-2'>
|
||||
<Rate
|
||||
disabled
|
||||
value={5}
|
||||
count={5}
|
||||
style={{ fontSize: 14 }}
|
||||
/>
|
||||
</div>
|
||||
<div className='mt-2'>
|
||||
<Rate
|
||||
disabled
|
||||
value={item.rating}
|
||||
count={5}
|
||||
style={{ fontSize: 14 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-4 text-[11px] leading-6'>
|
||||
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را ...
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-5 border border-border rounded-3xl p-6'>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<img src={AvatarImage} className='size-6 rounded-full object-cover' />
|
||||
<div className='text-description text-xs'>
|
||||
فروغ براتی
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-4 flex justify-between'>
|
||||
<div className='text-sm max-w-[70%] truncate'>
|
||||
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ
|
||||
</div>
|
||||
<div className='text-xs text-description'>
|
||||
۳ روز پیش
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='mt-2'>
|
||||
<Rate
|
||||
disabled
|
||||
value={5}
|
||||
count={5}
|
||||
style={{ fontSize: 14 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-4 text-[11px] leading-6'>
|
||||
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را ...
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-4 text-[11px] leading-6'>
|
||||
{item.comment}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
import Rate from 'rc-rate'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Input from '../../../components/Input'
|
||||
import Textarea from '../../../components/Textarea'
|
||||
import Button from '../../../components/Button'
|
||||
import { useFormik } from 'formik'
|
||||
import { CreateReviewType } from '../types/ServiecTypes'
|
||||
import * as Yup from 'yup'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useCreateReview } from '../hooks/useServiceData'
|
||||
import { ErrorType } from '../../../helpers/types'
|
||||
import { toast } from 'react-toastify'
|
||||
import Error from '../../../components/Error'
|
||||
|
||||
type Props = {
|
||||
refetch: () => void
|
||||
}
|
||||
|
||||
const CreateReview: FC<Props> = ({ refetch }) => {
|
||||
|
||||
const { id } = useParams()
|
||||
const { t } = useTranslation('global')
|
||||
|
||||
const createReview = useCreateReview()
|
||||
|
||||
const formik = useFormik<CreateReviewType>({
|
||||
initialValues: {
|
||||
title: '',
|
||||
comment: '',
|
||||
rating: undefined,
|
||||
id: id ? id : ''
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
title: Yup.string().required(t('errors.required')),
|
||||
comment: Yup.string().required(t('errors.required')),
|
||||
rating: Yup.string().required(t('errors.required')),
|
||||
}),
|
||||
onSubmit: (values) => {
|
||||
createReview.mutate(values, {
|
||||
onSuccess: () => {
|
||||
formik.resetForm()
|
||||
refetch()
|
||||
},
|
||||
onError: (error: ErrorType) => {
|
||||
toast.error(error.response?.data?.error.message[0])
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
return (
|
||||
<div className='bg-white p-6 rounded-3xl xl:w-[360px] w-full'>
|
||||
<div>
|
||||
{t('service.submit_comment')}
|
||||
</div>
|
||||
<div className='text-xs mt-4'>
|
||||
{t('service.hint_comment')}
|
||||
</div>
|
||||
|
||||
<div className='mt-6 text-description text-sm'>
|
||||
<div>
|
||||
{t('service.score')}
|
||||
</div>
|
||||
<div className='mt-2 dltr flex justify-end'>
|
||||
<Rate
|
||||
count={5}
|
||||
style={{ fontSize: 22 }}
|
||||
value={formik.values.rating}
|
||||
onChange={(value) => formik.setFieldValue('rating', value)}
|
||||
/>
|
||||
</div>
|
||||
{formik.errors.rating && formik.touched.rating && <Error errorText={formik.errors.rating} />}
|
||||
|
||||
<div className='mt-6'>
|
||||
<Input
|
||||
label={t('service.title')}
|
||||
placeholder={t('service.enter_title_comment')}
|
||||
{...formik.getFieldProps('title')}
|
||||
error_text={formik.touched.title && formik.errors.title ? formik.errors.title : ''}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-6'>
|
||||
<Textarea
|
||||
label={t('service.your_comment')}
|
||||
placeholder={t('service.write_your_comment')}
|
||||
{...formik.getFieldProps('comment')}
|
||||
error_text={formik.touched.comment && formik.errors.comment ? formik.errors.comment : ''}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-6'>
|
||||
<Button
|
||||
label={t('service.submit_comment')}
|
||||
onClick={() => formik.handleSubmit()}
|
||||
isLoading={createReview.isPending}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CreateReview
|
||||
@@ -82,13 +82,13 @@ const ServiceHeader: FC<Props> = (props: Props) => {
|
||||
<div className='flex gap-4 mt-5 xl:mt-0 items-center justify-between xl:justify-normal'>
|
||||
<div className='text-xs whitespace-nowrap flex gap-1 items-center'>
|
||||
<div className='flex gap-2'>
|
||||
{
|
||||
{/* {
|
||||
finalPrice !== price &&
|
||||
<div className='line-through text-xs text-description'>
|
||||
{NumberFormat(Number(price))}
|
||||
</div>
|
||||
}
|
||||
<div>{NumberFormat(Number(finalPrice))}</div>
|
||||
} */}
|
||||
<div>{NumberFormat(Number(price))}</div>
|
||||
</div>
|
||||
<span>{planText}</span>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import * as api from "../service/ServiceService";
|
||||
import { BuyServiceType } from "../types/ServiecTypes";
|
||||
import { BuyServiceType, CreateReviewType } from "../types/ServiecTypes";
|
||||
|
||||
export const useGetSuggestedServices = () => {
|
||||
return useQuery({
|
||||
@@ -44,3 +44,9 @@ export const useGetMyServices = (search: string) => {
|
||||
queryFn: () => api.getMyServices(search),
|
||||
});
|
||||
};
|
||||
|
||||
export const useCreateReview = () => {
|
||||
return useMutation({
|
||||
mutationFn: (variables: CreateReviewType) => api.createReview(variables),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import axios from "../../../config/axios";
|
||||
import { BuyServiceType } from "../types/ServiecTypes";
|
||||
import { BuyServiceType, CreateReviewType } from "../types/ServiecTypes";
|
||||
|
||||
export const getServiceSuggestedDanak = async () => {
|
||||
const { data } = await axios.get(`/danak-services/suggested`);
|
||||
@@ -32,3 +32,11 @@ export const getMyServices = async (search: string) => {
|
||||
const { data } = await axios.get(`/subscriptions/user?q=${search}`);
|
||||
return data;
|
||||
};
|
||||
|
||||
export const createReview = async (params: CreateReviewType) => {
|
||||
const { data } = await axios.post(
|
||||
`/danak-services/${params.id}/reviews`,
|
||||
params
|
||||
);
|
||||
return data;
|
||||
};
|
||||
|
||||
@@ -119,3 +119,25 @@ export type BuyServiceType = {
|
||||
description: string;
|
||||
serviceId: string;
|
||||
};
|
||||
|
||||
export type CreateReviewType = {
|
||||
id: string;
|
||||
comment: string;
|
||||
rating?: number;
|
||||
title: string;
|
||||
};
|
||||
|
||||
export type ReviewItemType = {
|
||||
comment: string;
|
||||
createdAt: string;
|
||||
id: string;
|
||||
rating: number;
|
||||
status: "APPROVED" | "PENDING" | "REJECTED";
|
||||
title: string;
|
||||
user: {
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
profilePic: string | null;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -81,10 +81,16 @@ const ChangePassword: FC = () => {
|
||||
|
||||
<div className='mt-9 xl:block hidden'>
|
||||
<Button
|
||||
label={t('setting.save_change')}
|
||||
className='w-32'
|
||||
className='w-fit px-4'
|
||||
onClick={() => formik.handleSubmit()}
|
||||
/>
|
||||
>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<TickCircle size={20} color='white' />
|
||||
<div>
|
||||
{t('setting.save_change')}
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -110,10 +116,16 @@ const ChangePassword: FC = () => {
|
||||
|
||||
<div className=' xl:hidden block'>
|
||||
<Button
|
||||
label={t('setting.save_change')}
|
||||
className='w-32'
|
||||
className='w-32 hidden xl:block'
|
||||
onClick={() => formik.handleSubmit()}
|
||||
/>
|
||||
>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<TickCircle size={20} color='white' />
|
||||
<div>
|
||||
{t('setting.save_change')}
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className='justify-end xl:hidden flex'>
|
||||
|
||||
@@ -4,7 +4,7 @@ import Input from '../../components/Input'
|
||||
import Textarea from '../../components/Textarea'
|
||||
import UploadBox from '../../components/UploadBox'
|
||||
import Button from '../../components/Button'
|
||||
import { CloseCircle, InfoCircle, Paperclip2 } from 'iconsax-react'
|
||||
import { CloseCircle, InfoCircle, Paperclip2, Send2 } from 'iconsax-react'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { useAddMessageTicket, useCloseTicket, useGetMessages, useMultiUpload } from './hooks/useTicketData'
|
||||
import PageLoading from '../../components/PageLoading'
|
||||
@@ -212,11 +212,17 @@ const TicketDetail: FC = () => {
|
||||
|
||||
<div className='flex justify-end mt-6'>
|
||||
<Button
|
||||
label={t('ticket.send')}
|
||||
className='max-w-[100px]'
|
||||
className='xl:max-w-[100px]'
|
||||
onClick={() => formik.handleSubmit()}
|
||||
isLoading={addMessage.isPending || multiUpload.isPending}
|
||||
/>
|
||||
>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<Send2 size={20} color='white' />
|
||||
<div>
|
||||
{t('ticket.send')}
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</Fragment>
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ const CardtoCard: FC = () => {
|
||||
name='amount'
|
||||
onChange={formik.handleChange}
|
||||
error_text={formik.touched.amount && formik.errors.amount ? formik.errors.amount : ''}
|
||||
seprator
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ const Online: FC = () => {
|
||||
placeholder={t('wallet.enter_your_price')}
|
||||
onChange={(e) => setDesiredAmount(Number(e.target.value))}
|
||||
value={desiredAmount}
|
||||
seprator
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ const CardtoCard: FC = () => {
|
||||
name='amount'
|
||||
onChange={formik.handleChange}
|
||||
error_text={formik.touched.amount && formik.errors.amount ? formik.errors.amount : ''}
|
||||
seprator
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user