setting and ui change password
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
VITE_TOKEN_NAME = 'dsc_token'
|
VITE_TOKEN_NAME = 'dsc_token'
|
||||||
VITE_REFRESH_TOKEN_NAME = 'dsc_refresh_token'
|
VITE_REFRESH_TOKEN_NAME = 'dsc_refresh_token'
|
||||||
VITE_BASE_URL = 'https://danak-dsc-api.run.danakcorp.com'
|
VITE_BASE_URL = 'https://danak-dsc-api.run.danakcorp.com'
|
||||||
|
# VITE_BASE_URL = 'http://192.168.0.207:3500'
|
||||||
@@ -2,6 +2,7 @@ import { FC, InputHTMLAttributes, useState } from 'react'
|
|||||||
import { clx } from '../helpers/utils';
|
import { clx } from '../helpers/utils';
|
||||||
import EyeIcon from '../assets/images/eye.svg'
|
import EyeIcon from '../assets/images/eye.svg'
|
||||||
import { SearchNormal } from 'iconsax-react';
|
import { SearchNormal } from 'iconsax-react';
|
||||||
|
import Error from './Error';
|
||||||
|
|
||||||
type Variant = "floating_outlined" | "primary" | "search";
|
type Variant = "floating_outlined" | "primary" | "search";
|
||||||
|
|
||||||
@@ -46,7 +47,16 @@ const Input: FC<Props> = (props: Props) => {
|
|||||||
props.variant === 'search' &&
|
props.variant === 'search' &&
|
||||||
<SearchNormal size={20} color='#8C90A3' className='absolute top-0 w-5 bottom-0 my-auto right-3' />
|
<SearchNormal size={20} color='#8C90A3' className='absolute top-0 w-5 bottom-0 my-auto right-3' />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
props.error_text &&
|
||||||
|
<Error
|
||||||
|
errorText={props.error_text}
|
||||||
|
/>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -42,7 +42,8 @@
|
|||||||
"enter_mobile_number": "شماره موبایل خود را وارد کنید"
|
"enter_mobile_number": "شماره موبایل خود را وارد کنید"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"required": "این فیلد اجباری می باشد"
|
"required": "این فیلد اجباری می باشد",
|
||||||
|
"password_not_match": "رمز عبور با تکرار آن مطابقت ندارد"
|
||||||
},
|
},
|
||||||
"description": "توضیحات",
|
"description": "توضیحات",
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
@@ -109,6 +110,7 @@
|
|||||||
"write_your_comment": "نظر خود را راجع به این سرویس بنویسید",
|
"write_your_comment": "نظر خود را راجع به این سرویس بنویسید",
|
||||||
"users_comments": "نظرات کاربران"
|
"users_comments": "نظرات کاربران"
|
||||||
},
|
},
|
||||||
|
"loading": "در حال بارگذاری",
|
||||||
"footer": {
|
"footer": {
|
||||||
"home": "صفحه اصلی",
|
"home": "صفحه اصلی",
|
||||||
"other_services": "سایر سرویس ها",
|
"other_services": "سایر سرویس ها",
|
||||||
@@ -254,7 +256,8 @@
|
|||||||
"min-8": "حداقل 8 کاراکتر باشد",
|
"min-8": "حداقل 8 کاراکتر باشد",
|
||||||
"mix_charachter_number": "ترکیبی از حروف کوچک و بزرگ باشد",
|
"mix_charachter_number": "ترکیبی از حروف کوچک و بزرگ باشد",
|
||||||
"exsist_number": "شامل اعداد باشد",
|
"exsist_number": "شامل اعداد باشد",
|
||||||
"exsist_special_character": "شامل کاراکتر های خاص (نماد ها) باشد"
|
"exsist_special_character": "شامل کاراکتر های خاص (نماد ها) باشد",
|
||||||
|
"password_changed": "رمز عبور با موفقیت تغییر یافت"
|
||||||
},
|
},
|
||||||
"wallet": {
|
"wallet": {
|
||||||
"increese_wallet": "افزایش موجودی حساب اعتباری",
|
"increese_wallet": "افزایش موجودی حساب اعتباری",
|
||||||
|
|||||||
+41
-166
@@ -2,13 +2,16 @@ import { FC, useState } from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Tabs from '../../components/Tabs'
|
import Tabs from '../../components/Tabs'
|
||||||
import { KeySquare, Notification1 } from 'iconsax-react'
|
import { KeySquare, Notification1 } from 'iconsax-react'
|
||||||
import SwitchComponent from '../../components/Switch'
|
import { useGetSettings } from './hooks/useSettingData'
|
||||||
import Input from '../../components/Input'
|
import PageLoading from '../../components/PageLoading'
|
||||||
import Button from '../../components/Button'
|
import Email from './components/Email'
|
||||||
|
import Sms from './components/Sms'
|
||||||
|
import ChangePassword from './components/ChangePassword'
|
||||||
|
|
||||||
const Setting: FC = () => {
|
const Setting: FC = () => {
|
||||||
|
|
||||||
const { t } = useTranslation('global')
|
const { t } = useTranslation('global')
|
||||||
|
const getSettings = useGetSettings()
|
||||||
const [activeTab, setActiveTab] = useState<string>('notification')
|
const [activeTab, setActiveTab] = useState<string>('notification')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -43,173 +46,45 @@ const Setting: FC = () => {
|
|||||||
{t('setting.setting_email_message')}
|
{t('setting.setting_email_message')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex xl:flex-row flex-col gap-6 text-sm mt-8'>
|
<div className='flex xl:flex-row flex-wrap flex-col gap-6 text-sm mt-8'>
|
||||||
<div className='flex-1 border border-border px-4 rounded-2xl min-h-14 items-center flex justify-between'>
|
{
|
||||||
<div className='xl:text-[13px] text-xs'>
|
getSettings.isPending ?
|
||||||
{t('setting.notification_announcement')}
|
<div className='w-full'>
|
||||||
</div>
|
<PageLoading />
|
||||||
<div className='flex xl:gap-4 gap-2'>
|
|
||||||
<div className='flex gap-2 text-xs items-center text-description'>
|
|
||||||
<div>
|
|
||||||
{t('setting.email')}
|
|
||||||
</div>
|
|
||||||
<SwitchComponent
|
|
||||||
active={true}
|
|
||||||
onChange={() => { }}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='flex gap-2 text-xs items-center text-description'>
|
:
|
||||||
<div>
|
getSettings.data?.data?.settings?.map((item: any) => {
|
||||||
{t('setting.sms')}
|
return (
|
||||||
</div>
|
<div key={item.id} className='flex-1 min-w-[40%] border border-border px-4 rounded-2xl min-h-14 items-center flex justify-between'>
|
||||||
<SwitchComponent
|
<div className='xl:text-[13px] text-xs'>
|
||||||
active={false}
|
{item?.notifSetting.title_fa}
|
||||||
onChange={() => { }}
|
</div>
|
||||||
/>
|
<div className='flex xl:gap-4 gap-2'>
|
||||||
</div>
|
<div className='flex gap-2 text-xs items-center text-description'>
|
||||||
</div>
|
<div>
|
||||||
</div>
|
{t('setting.email')}
|
||||||
<div className='flex-1 border border-border px-4 rounded-2xl min-h-14 items-center flex justify-between'>
|
</div>
|
||||||
<div className='xl:text-[13px] text-xs'>
|
<Email id={item.id} email={item.email} />
|
||||||
{t('setting.notification_announcement')}
|
</div>
|
||||||
</div>
|
<div className='flex gap-2 text-xs items-center text-description'>
|
||||||
<div className='flex xl:gap-4 gap-2'>
|
<div>
|
||||||
<div className='flex gap-2 text-xs items-center text-description'>
|
{t('setting.sms')}
|
||||||
<div>
|
</div>
|
||||||
{t('setting.email')}
|
<Sms
|
||||||
</div>
|
sms={item.sms}
|
||||||
<SwitchComponent
|
id={item.id}
|
||||||
active={true}
|
/>
|
||||||
onChange={() => { }}
|
</div>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex gap-2 text-xs items-center text-description'>
|
)
|
||||||
<div>
|
})
|
||||||
{t('setting.sms')}
|
}
|
||||||
</div>
|
<div className='flex-1 px-4'></div>
|
||||||
<SwitchComponent
|
|
||||||
active={false}
|
|
||||||
onChange={() => { }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='flex xl:flex-row flex-col gap-6 text-sm mt-6'>
|
|
||||||
<div className='flex-1 border border-border px-4 rounded-2xl min-h-14 items-center flex justify-between'>
|
|
||||||
<div className='xl:text-[13px] text-xs'>
|
|
||||||
{t('setting.notification_announcement')}
|
|
||||||
</div>
|
|
||||||
<div className='flex xl:gap-4 gap-2'>
|
|
||||||
<div className='flex gap-2 text-xs items-center text-description'>
|
|
||||||
<div>
|
|
||||||
{t('setting.email')}
|
|
||||||
</div>
|
|
||||||
<SwitchComponent
|
|
||||||
active={true}
|
|
||||||
onChange={() => { }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='flex gap-2 text-xs items-center text-description'>
|
|
||||||
<div>
|
|
||||||
{t('setting.sms')}
|
|
||||||
</div>
|
|
||||||
<SwitchComponent
|
|
||||||
active={false}
|
|
||||||
onChange={() => { }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='flex-1 border border-border px-4 rounded-2xl min-h-14 items-center flex justify-between'>
|
|
||||||
<div className='xl:text-[13px] text-xs'>
|
|
||||||
{t('setting.notification_announcement')}
|
|
||||||
</div>
|
|
||||||
<div className='flex xl:gap-4 gap-2'>
|
|
||||||
<div className='flex gap-2 text-xs items-center text-description'>
|
|
||||||
<div>
|
|
||||||
{t('setting.email')}
|
|
||||||
</div>
|
|
||||||
<SwitchComponent
|
|
||||||
active={true}
|
|
||||||
onChange={() => { }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='flex gap-2 text-xs items-center text-description'>
|
|
||||||
<div>
|
|
||||||
{t('setting.sms')}
|
|
||||||
</div>
|
|
||||||
<SwitchComponent
|
|
||||||
active={false}
|
|
||||||
onChange={() => { }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div className='mt-10 bg-white p-8 rounded-3xl'>
|
<ChangePassword />
|
||||||
<div>
|
|
||||||
{t('setting.change_password')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='flex xl:flex-row flex-col xl:gap-10 gap-4'>
|
|
||||||
<div className='flex-1'>
|
|
||||||
<Input
|
|
||||||
type='password'
|
|
||||||
className='mt-6'
|
|
||||||
placeholder={t('setting.current_password')}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
type='password'
|
|
||||||
className='mt-6'
|
|
||||||
placeholder={t('setting.new_password')}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
type='password'
|
|
||||||
className='mt-6'
|
|
||||||
placeholder={t('setting.reapeat_password')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className='mt-9 xl:block hidden'>
|
|
||||||
<Button
|
|
||||||
label={t('setting.save_change')}
|
|
||||||
className='w-32'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='flex-1 xl:p-8 p-4 bg-[#EEF0F7] rounded-3xl text-sm'>
|
|
||||||
<div>
|
|
||||||
{t('setting.password_is')}
|
|
||||||
</div>
|
|
||||||
<ul className='list-disc ps-4 flex flex-col gap-2 text-xs mt-4'>
|
|
||||||
<li>
|
|
||||||
{t('setting.min-8')}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
{t('setting.mix_charachter_number')}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
{t('setting.exsist_number')}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
{t('setting.exsist_special_character')}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className=' xl:hidden block'>
|
|
||||||
<Button
|
|
||||||
label={t('setting.save_change')}
|
|
||||||
className='w-32'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='h-14'></div>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import { FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Input from '../../../components/Input'
|
||||||
|
import Button from '../../../components/Button'
|
||||||
|
import { useFormik } from 'formik'
|
||||||
|
import { ChangePasswordType } from '../types/SettingTypes'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { useChangePassword } from '../hooks/useSettingData'
|
||||||
|
import { ErrorType } from '../../../helpers/types'
|
||||||
|
|
||||||
|
const ChangePassword: FC = () => {
|
||||||
|
|
||||||
|
const changePassword = useChangePassword()
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
|
||||||
|
const formik = useFormik<ChangePasswordType>({
|
||||||
|
initialValues: {
|
||||||
|
password: '',
|
||||||
|
newPassword: '',
|
||||||
|
repeatPassword: ''
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
password: Yup.string()
|
||||||
|
.required(t('errors.required')),
|
||||||
|
newPassword: Yup.string()
|
||||||
|
.required(t('errors.required')),
|
||||||
|
repeatPassword: Yup.string()
|
||||||
|
.required(t('errors.required'))
|
||||||
|
}),
|
||||||
|
onSubmit: (values) => {
|
||||||
|
if (values.newPassword !== values.repeatPassword) {
|
||||||
|
toast.error(t('errors.password_not_match'))
|
||||||
|
} else {
|
||||||
|
changePassword.mutate(values, {
|
||||||
|
onSuccess: () => {
|
||||||
|
toast.success(t('setting.password_changed'))
|
||||||
|
formik.resetForm()
|
||||||
|
},
|
||||||
|
onError: (error: ErrorType) => {
|
||||||
|
toast.error(error.response?.data?.error?.message[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mt-10 bg-white p-8 rounded-3xl'>
|
||||||
|
<div>
|
||||||
|
{t('setting.change_password')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex xl:flex-row flex-col xl:gap-10 gap-4'>
|
||||||
|
<div className='flex-1'>
|
||||||
|
<Input
|
||||||
|
type='password'
|
||||||
|
className='mt-6'
|
||||||
|
placeholder={t('setting.current_password')}
|
||||||
|
name='password'
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
error_text={formik.touched.password && formik.errors.password ? formik.errors.password : ''}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
type='password'
|
||||||
|
className='mt-6'
|
||||||
|
placeholder={t('setting.new_password')}
|
||||||
|
name='newPassword'
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
error_text={formik.touched.newPassword && formik.errors.newPassword ? formik.errors.newPassword : ''}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
type='password'
|
||||||
|
className='mt-6'
|
||||||
|
placeholder={t('setting.reapeat_password')}
|
||||||
|
name='repeatPassword'
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
error_text={formik.touched.repeatPassword && formik.errors.repeatPassword ? formik.errors.repeatPassword : ''}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className='mt-9 xl:block hidden'>
|
||||||
|
<Button
|
||||||
|
label={t('setting.save_change')}
|
||||||
|
className='w-32'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex-1 xl:p-8 p-4 bg-[#EEF0F7] rounded-3xl text-sm'>
|
||||||
|
<div>
|
||||||
|
{t('setting.password_is')}
|
||||||
|
</div>
|
||||||
|
<ul className='list-disc ps-4 flex flex-col gap-2 text-xs mt-4'>
|
||||||
|
<li>
|
||||||
|
{t('setting.min-8')}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
{t('setting.mix_charachter_number')}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
{t('setting.exsist_number')}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
{t('setting.exsist_special_character')}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className=' xl:hidden block'>
|
||||||
|
<Button
|
||||||
|
label={t('setting.save_change')}
|
||||||
|
className='w-32'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='h-14'></div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ChangePassword
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { FC, useState } from 'react'
|
||||||
|
import SwitchComponent from '../../../components/Switch'
|
||||||
|
import { useUpdateSetting } from '../hooks/useSettingData'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
email: boolean,
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const Email: FC<Props> = (props: Props) => {
|
||||||
|
const updateSetting = useUpdateSetting()
|
||||||
|
const [email, setEmail] = useState<boolean>(props.email)
|
||||||
|
|
||||||
|
const handleChange = (value: boolean) => {
|
||||||
|
setEmail(value)
|
||||||
|
updateSetting.mutate({ email: value, id: props.id })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SwitchComponent
|
||||||
|
active={email}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Email
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { FC, useState } from 'react'
|
||||||
|
import SwitchComponent from '../../../components/Switch'
|
||||||
|
import { useUpdateSetting } from '../hooks/useSettingData'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
sms: boolean,
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sms: FC<Props> = (props: Props) => {
|
||||||
|
const updateSetting = useUpdateSetting()
|
||||||
|
const [sms, setSms] = useState<boolean>(props.sms)
|
||||||
|
|
||||||
|
const handleChange = (value: boolean) => {
|
||||||
|
setSms(value)
|
||||||
|
updateSetting.mutate({ sms: value, id: props.id })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SwitchComponent
|
||||||
|
active={sms}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Sms
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
import * as api from "../service/SettingService";
|
||||||
|
import { ChangePasswordType, UpdateSettingType } from "../types/SettingTypes";
|
||||||
|
|
||||||
|
export const useGetSettings = () => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["settings"],
|
||||||
|
queryFn: () => api.getSettings(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateSetting = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (variables: UpdateSettingType) => api.updateSettings(variables),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useChangePassword = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (variables: ChangePasswordType) =>
|
||||||
|
api.changePassword(variables),
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import axios from "../../../config/axios";
|
||||||
|
import { ChangePasswordType, UpdateSettingType } from "../types/SettingTypes";
|
||||||
|
|
||||||
|
export const getSettings = async () => {
|
||||||
|
const { data } = await axios.get(`/settings`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateSettings = async (params: UpdateSettingType) => {
|
||||||
|
await axios.patch(`/settings/${params.id}/update`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const changePassword = async (params: ChangePasswordType) => {
|
||||||
|
await axios.post(`/settings/password`, params);
|
||||||
|
};
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export type UpdateSettingType = {
|
||||||
|
id: string;
|
||||||
|
email?: boolean;
|
||||||
|
sms?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ChangePasswordType = {
|
||||||
|
password: string;
|
||||||
|
newPassword: string;
|
||||||
|
repeatPassword: string;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user