add: settings page locales
This commit is contained in:
@@ -7,12 +7,23 @@ import { TabHeader } from '@/components/tab/TabHeader'
|
|||||||
import { Switch } from '@/components/ui/switch';
|
import { Switch } from '@/components/ui/switch';
|
||||||
import Accordion from '@/components/utils/Accordion';
|
import Accordion from '@/components/utils/Accordion';
|
||||||
import Seperator from '@/components/utils/Seperator';
|
import Seperator from '@/components/utils/Seperator';
|
||||||
import { Key, KeySquare, Notification1, ArrowLeft, MedalStar, TickCircle } from 'iconsax-react'
|
import { SmartIcon } from '@/components/utils/SmartIcon';
|
||||||
|
import { getI18nObject } from '@/lib/i18n';
|
||||||
|
import { SettingsData } from '@/types/i18n/settings';
|
||||||
|
import { Key, KeySquare, Notification1, ArrowLeft, TickCircle } from 'iconsax-react'
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import React from 'react'
|
import React, { Fragment } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
function UserSettingsIndex() {
|
function UserSettingsIndex() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { t } = useTranslation('settings');
|
||||||
|
const data: SettingsData = getI18nObject(t, "data");
|
||||||
|
|
||||||
|
const onSwitched = (e: React.MouseEvent) => {
|
||||||
|
const target = e.target as HTMLElement;
|
||||||
|
console.log('Save changed setting?', target.id);
|
||||||
|
}
|
||||||
|
|
||||||
const notifsTab = () => {
|
const notifsTab = () => {
|
||||||
|
|
||||||
@@ -22,106 +33,46 @@ function UserSettingsIndex() {
|
|||||||
className="bg-container rounded-container shadow-container p-4">
|
className="bg-container rounded-container shadow-container p-4">
|
||||||
|
|
||||||
<div className="flex justify-between items-center pb-[25px]">
|
<div className="flex justify-between items-center pb-[25px]">
|
||||||
<h2 className='text-sm leading-5'>تنظیمات نوتیفیکیشن</h2>
|
<h2 className='text-sm leading-5'>{data.TabNotifications.Heading}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='p-2 pt-0'>
|
<div className='p-2 pt-0'>
|
||||||
|
{data.TabNotifications.Accordions.map((accordion, i) => {
|
||||||
|
return (
|
||||||
|
<Fragment key={i}>
|
||||||
<Accordion
|
<Accordion
|
||||||
title='حساب'
|
title={accordion.Heading}
|
||||||
group='1'
|
group={'accordions'}
|
||||||
|
icon={accordion.Icon}
|
||||||
>
|
>
|
||||||
<div
|
<div className='grid gap-4 mb-3'>
|
||||||
|
{accordion.Items.map((item, j) => {
|
||||||
|
return (
|
||||||
|
<label
|
||||||
|
key={j}
|
||||||
|
htmlFor={item.HtmlName}
|
||||||
className="flex w-full h-11 items-center justify-between gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 focus:outline-none focus:ring-2 focus:ring-black"
|
className="flex w-full h-11 items-center justify-between gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 focus:outline-none focus:ring-2 focus:ring-black"
|
||||||
>
|
>
|
||||||
<span className="inline-flex items-center gap-2.5 text-sm2">
|
|
||||||
<MedalStar size="16" color="#333333" />
|
|
||||||
ورود به حساب
|
|
||||||
</span>
|
|
||||||
<Switch className="w-12 h-6 scale-[0.9]" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="flex w-full my-3 h-11 items-center justify-between gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 focus:outline-none focus:ring-2 focus:ring-black"
|
|
||||||
>
|
|
||||||
<span className="inline-flex items-center gap-2.5 text-sm2">
|
<span className="inline-flex items-center gap-2.5 text-sm2">
|
||||||
<MedalStar size="16" color="#333333" />
|
<SmartIcon icon={item.Icon} />
|
||||||
تغییر رمز عبور
|
{item.Label}
|
||||||
</span>
|
</span>
|
||||||
<Switch className="w-12 h-6 scale-[0.9]" />
|
<Switch
|
||||||
</div>
|
onClick={onSwitched}
|
||||||
</Accordion>
|
id={item.HtmlName}
|
||||||
<Seperator />
|
name={item.HtmlName}
|
||||||
|
className="w-12 h-6 scale-[0.9]"
|
||||||
<Accordion
|
/>
|
||||||
title='کیف پول'
|
</label>
|
||||||
group='1'
|
)
|
||||||
>
|
})}
|
||||||
<div
|
|
||||||
className="flex w-full h-11 items-center justify-between gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 focus:outline-none focus:ring-2 focus:ring-black"
|
|
||||||
>
|
|
||||||
<span className="inline-flex items-center gap-2.5 text-sm2">
|
|
||||||
<MedalStar size="16" color="#333333" />
|
|
||||||
افزایش شارژ
|
|
||||||
</span>
|
|
||||||
<Switch className="w-12 h-6 scale-[0.9]" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="flex w-full my-3 h-11 items-center justify-between gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 focus:outline-none focus:ring-2 focus:ring-black"
|
|
||||||
>
|
|
||||||
<span className="inline-flex items-center gap-2.5 text-sm2">
|
|
||||||
<MedalStar size="16" color="#333333" />
|
|
||||||
برداشت از کیف
|
|
||||||
</span>
|
|
||||||
<Switch className="w-12 h-6 scale-[0.9]" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="flex w-full my-3 h-11 items-center justify-between gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 focus:outline-none focus:ring-2 focus:ring-black"
|
|
||||||
>
|
|
||||||
<span className="inline-flex items-center gap-2.5 text-sm2">
|
|
||||||
<MedalStar size="16" color="#333333" />
|
|
||||||
استفاده از تخفیف
|
|
||||||
</span>
|
|
||||||
<Switch className="w-12 h-6 scale-[0.9]" />
|
|
||||||
</div>
|
|
||||||
</Accordion>
|
|
||||||
<Seperator />
|
|
||||||
|
|
||||||
<Accordion
|
|
||||||
title='سفارش'
|
|
||||||
group='1'
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="flex w-full h-11 items-center justify-between gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 focus:outline-none focus:ring-2 focus:ring-black"
|
|
||||||
>
|
|
||||||
<span className="inline-flex items-center gap-2.5 text-sm2">
|
|
||||||
<MedalStar size="16" color="#333333" />
|
|
||||||
<span className='mt-0.5'>وضعیت سفارش</span>
|
|
||||||
</span>
|
|
||||||
<Switch className="w-12 h-6 scale-[0.9]" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="flex w-full my-3 h-11 items-center justify-between gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 focus:outline-none focus:ring-2 focus:ring-black"
|
|
||||||
>
|
|
||||||
<span className="inline-flex items-center gap-2.5 text-sm2">
|
|
||||||
<MedalStar size="16" color="#333333" />
|
|
||||||
<span className='mt-0.5'>تحویل</span>
|
|
||||||
</span>
|
|
||||||
<Switch className="w-12 h-6 scale-[0.9]" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="flex w-full my-3 h-11 items-center justify-between gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 focus:outline-none focus:ring-2 focus:ring-black"
|
|
||||||
>
|
|
||||||
<span className="inline-flex items-center gap-2.5 text-sm2">
|
|
||||||
<MedalStar size="16" color="#333333" />
|
|
||||||
<span className='mt-0.5'>کنسلی</span>
|
|
||||||
</span>
|
|
||||||
<Switch className="w-12 h-6 scale-[0.9]" />
|
|
||||||
</div>
|
</div>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
<Seperator className='last:hidden' />
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
@@ -138,45 +89,49 @@ function UserSettingsIndex() {
|
|||||||
className="bg-container rounded-container shadow-container p-4">
|
className="bg-container rounded-container shadow-container p-4">
|
||||||
|
|
||||||
<div className="flex justify-between items-center pb-[25px]">
|
<div className="flex justify-between items-center pb-[25px]">
|
||||||
<h2 className='text-sm leading-5'>تغییر رمز عبور</h2>
|
<h2 className='text-sm leading-5'>{data.TabPassword.Heading}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => e.preventDefault()}
|
onSubmit={(e) => e.preventDefault()}
|
||||||
className='grid gap-6 p-2'
|
className='grid gap-6 p-2'
|
||||||
>
|
>
|
||||||
|
{data.TabPassword.Inputs.map((input, i) => {
|
||||||
|
return (
|
||||||
<PasswordField
|
<PasswordField
|
||||||
htmlFor='oldPassword'
|
labelText={input.Label}
|
||||||
placeholder='رمز عبور فعلی'
|
className='bg-container'
|
||||||
autoComplete='current-password'
|
key={i}
|
||||||
|
htmlFor={input.HtmlName ?? ''}
|
||||||
|
placeholder={input.Placeholder}
|
||||||
|
autoComplete={input.AutoComplete}
|
||||||
/>
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
<PasswordField
|
}
|
||||||
htmlFor='newPassowrd'
|
|
||||||
placeholder='رمز عبور جدید'
|
|
||||||
autoComplete='new-password'
|
|
||||||
/>
|
|
||||||
|
|
||||||
<PasswordField
|
{data.TabPassword.Rules.map((rule, i) => {
|
||||||
htmlFor='passwordRepeat'
|
return (
|
||||||
placeholder='تکرار رمز عبور'
|
<section
|
||||||
autoComplete='new-password'
|
key={i}
|
||||||
/>
|
className='bg-background rounded-normal p-4 text-xs flex flex-col gap-2 font-light'
|
||||||
|
>
|
||||||
<section className='bg-background rounded-normal p-4 text-xs flex flex-col gap-2 font-light'>
|
<h6 className='text-sm mb-2'>{rule.Heading}</h6>
|
||||||
<h6 className='text-sm'>رمز عبور میبایست:</h6>
|
{rule.Items.map((item, i) => {
|
||||||
<li className='mt-2'>حداقل 8 کاراکتر باشد</li>
|
return (
|
||||||
<li>ترکیبی از حروف موچک و بزرگ باشد</li>
|
<li key={i}>{item}</li>
|
||||||
<li>شامل اعداد باشد</li>
|
)
|
||||||
<li>شامل کاراکتر های خاص (نماد ها) باشد</li>
|
})}
|
||||||
</section>
|
</section>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
|
||||||
<Button className='mt-4'>
|
<Button className='mt-4'>
|
||||||
<div className='flex items-center justify-center gap-1'>
|
<div className='flex items-center justify-center gap-1'>
|
||||||
<TickCircle className='stroke-white' size={20} />
|
<TickCircle className='stroke-white' size={20} />
|
||||||
<span className='mt-0.5'>
|
<span className='mt-0.5'>
|
||||||
ذخیره تغییرات
|
{data.TabPassword.ButtonSubmit}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
@@ -194,8 +149,8 @@ function UserSettingsIndex() {
|
|||||||
className="bg-container rounded-container shadow-container p-4">
|
className="bg-container rounded-container shadow-container p-4">
|
||||||
|
|
||||||
<div className="pb-4">
|
<div className="pb-4">
|
||||||
<h2 className='text-sm leading-5'>راهاندازی احراز هویت دو مرحلهای</h2>
|
<h2 className='text-sm leading-5'>{data.TabAuthenticator.Heading}</h2>
|
||||||
<p className='text-xs mt-3 text-disabled-text font-light'>احراز هویت دو مرحلهای امنیت اکانت شما را افزایش میدهد</p>
|
<p className='text-xs mt-3 text-disabled-text font-light'>{data.TabAuthenticator.Description}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Seperator />
|
<Seperator />
|
||||||
@@ -205,7 +160,7 @@ function UserSettingsIndex() {
|
|||||||
<Key size={32} className='stroke-blue-500' />
|
<Key size={32} className='stroke-blue-500' />
|
||||||
</div>
|
</div>
|
||||||
<p className='text-sm2 mt-4 font-light place-self-center'>
|
<p className='text-sm2 mt-4 font-light place-self-center'>
|
||||||
برای شروع فرآیند راهاندازی احراز هویت دو مرحلهای، روی دکمه زیر کلیک کنید
|
{data.TabAuthenticator.Tip}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className='place-self-center mt-2'>
|
<div className='place-self-center mt-2'>
|
||||||
@@ -213,44 +168,46 @@ function UserSettingsIndex() {
|
|||||||
<div className='flex items-center justify-center gap-1'>
|
<div className='flex items-center justify-center gap-1'>
|
||||||
<TickCircle className='stroke-white' size={20} />
|
<TickCircle className='stroke-white' size={20} />
|
||||||
<span className='mt-0.5'>
|
<span className='mt-0.5'>
|
||||||
ذخیره تغییرات
|
{data.TabAuthenticator.ButtonSubmit}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section className='bg-background rounded-normal mt-14 p-4 text-xs flex flex-col gap-2 font-light'>
|
{data.TabAuthenticator.Guides.map((guide, i) => {
|
||||||
<h6 className='text-sm'>راهنمای احراز هویت دو مرحلهای</h6>
|
return (
|
||||||
<p className='text-disabled-text'>این قابلیت امنیت حساب شما را به شدت افزایش میدهد</p>
|
<section
|
||||||
<div>
|
key={i}
|
||||||
|
className='bg-background rounded-normal mt-14 p-4 text-xs flex flex-col gap-2 font-light'
|
||||||
|
>
|
||||||
|
<h6 className='text-sm'>{guide.Heading}</h6>
|
||||||
|
<p className='text-disabled-text'>{guide.Description}</p>
|
||||||
|
{guide.Items.map((item, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i}>
|
||||||
<div className='ml-2 mt-2 bg-blue-100 inline-block size-6 text-center pt-[5px] pr-[1px] text-blue-500 rounded-full'>
|
<div className='ml-2 mt-2 bg-blue-100 inline-block size-6 text-center pt-[5px] pr-[1px] text-blue-500 rounded-full'>
|
||||||
1
|
{item.Mark}
|
||||||
</div>
|
</div>
|
||||||
<span>
|
<span>
|
||||||
یک برنامه Authenticator مانند Google Authenticator نصب کنید
|
{item.Label}
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className='ml-2 mt-2 bg-blue-100 inline-block size-6 text-center pt-[5px] pr-[1px] text-blue-500 rounded-full'>
|
|
||||||
2
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
QR Code را اسکن کنید یا کد را به صورت دستی وارد کنید
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className='ml-2 mt-2 bg-blue-100 inline-block size-6 text-center pt-[5px] pr-[1px] text-blue-500 rounded-full'>
|
|
||||||
3
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
کد 6 رقمی تولید شده توسط برنامه را وارد کنید
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
|
||||||
<div className='mt-4 p-3 text-yellow-800 rounded-lg bg-yellow-50 border border-solid border-yellow-200'>
|
{guide.Notes.map((note, i) => {
|
||||||
توجه: کد های پشتیبان خود را در مکانی امن نگهداری کنید
|
return (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className='mt-4 p-3 text-yellow-800 rounded-lg bg-yellow-50 border border-solid border-yellow-200'
|
||||||
|
>
|
||||||
|
{note}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</section>
|
</section>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -262,7 +219,7 @@ function UserSettingsIndex() {
|
|||||||
<div className='overflow-y-auto h-full noscrollbar flex flex-col gap-6'>
|
<div className='overflow-y-auto h-full noscrollbar flex flex-col gap-6'>
|
||||||
<div className='grid grid-cols-3 items-center'>
|
<div className='grid grid-cols-3 items-center'>
|
||||||
<span></span>
|
<span></span>
|
||||||
<h1 className='text-sm2 place-self-center font-medium'>تنظیمات</h1>
|
<h1 className='text-sm2 place-self-center font-medium'>{data.Heading}</h1>
|
||||||
<ArrowLeft
|
<ArrowLeft
|
||||||
className='cursor-pointer place-self-end'
|
className='cursor-pointer place-self-end'
|
||||||
size='24'
|
size='24'
|
||||||
@@ -273,17 +230,17 @@ function UserSettingsIndex() {
|
|||||||
<TabContainer>
|
<TabContainer>
|
||||||
<TabHeader
|
<TabHeader
|
||||||
viewRenderer={notifsTab()}
|
viewRenderer={notifsTab()}
|
||||||
title='نوتیفیکیشن'
|
title={data.TabNotifications.Title}
|
||||||
icon={<Notification1 size={24} />}
|
icon={<Notification1 size={24} />}
|
||||||
/>
|
/>
|
||||||
<TabHeader
|
<TabHeader
|
||||||
viewRenderer={passwordTab()}
|
viewRenderer={passwordTab()}
|
||||||
title='رمز عبور'
|
title={data.TabPassword.Title}
|
||||||
icon={<KeySquare size={24} />}
|
icon={<KeySquare size={24} />}
|
||||||
/>
|
/>
|
||||||
<TabHeader
|
<TabHeader
|
||||||
viewRenderer={authenticatorTab()}
|
viewRenderer={authenticatorTab()}
|
||||||
title='دو مرحله ای'
|
title={data.TabAuthenticator.Title}
|
||||||
icon={<Key size={24} />}
|
icon={<Key size={24} />}
|
||||||
/>
|
/>
|
||||||
</TabContainer>
|
</TabContainer>
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ export const viewport: Viewport = {
|
|||||||
themeColor: '#F4F5F9',
|
themeColor: '#F4F5F9',
|
||||||
}
|
}
|
||||||
|
|
||||||
const i18nNamespaces = ['common', 'menu', 'orders', 'auth', "rating", "chat", "notifications", 'parallels'];
|
const i18nNamespaces = ['settings', 'common', 'menu', 'orders', 'auth', "rating", "chat", "notifications", 'parallels'];
|
||||||
|
|
||||||
export default async function RootLayout({
|
export default async function RootLayout({
|
||||||
children,
|
children,
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import useToggle from '@/hooks/helpers/useToggle';
|
import useToggle from '@/hooks/helpers/useToggle';
|
||||||
|
import { renderIcon } from '@/lib/helpers/smartIcon';
|
||||||
|
import { IconType } from '@/types/iconType';
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { Icon } from 'iconsax-react'
|
|
||||||
import { ChevronDown } from 'lucide-react';
|
import { ChevronDown } from 'lucide-react';
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
|
|
||||||
interface DropdownProps extends React.HTMLAttributes<HTMLDivElement> {
|
interface AccordionProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
initial?: boolean,
|
initial?: boolean
|
||||||
children?: React.ReactNode
|
children?: React.ReactNode
|
||||||
title?: string
|
title?: string
|
||||||
icon?: Icon
|
icon?: IconType;
|
||||||
group?: string
|
group?: string
|
||||||
};
|
};
|
||||||
|
|
||||||
function Accordion({ initial, group, title, icon: Icon, children, className, ...rest }: DropdownProps) {
|
function Accordion({ initial, group, title, icon, children, className, ...rest }: AccordionProps) {
|
||||||
const { state, toggle, set } = useToggle(initial);
|
const { state, toggle, set } = useToggle(initial);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -37,6 +38,7 @@ function Accordion({ initial, group, title, icon: Icon, children, className, ...
|
|||||||
}, [group, set, state]);
|
}, [group, set, state]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@@ -56,9 +58,7 @@ function Accordion({ initial, group, title, icon: Icon, children, className, ...
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
{Icon &&
|
{renderIcon(icon)}
|
||||||
<Icon size={16} className='stroke-foreground mb-0.5' />
|
|
||||||
}
|
|
||||||
<span className='text-sm2'>{title ?? ''}</span>
|
<span className='text-sm2'>{title ?? ''}</span>
|
||||||
</div>
|
</div>
|
||||||
<ChevronDown
|
<ChevronDown
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import * as Iconsax from "iconsax-react";
|
||||||
|
import { SmartIconType } from "@/types/iconType";
|
||||||
|
|
||||||
|
type IconsaxIconProps = {
|
||||||
|
size?: number;
|
||||||
|
color?: string;
|
||||||
|
className?: string;
|
||||||
|
variant?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type IconComponentType = React.FC<IconsaxIconProps>;
|
||||||
|
|
||||||
|
export interface SmartIconProps {
|
||||||
|
icon?: SmartIconType;
|
||||||
|
name?: string;
|
||||||
|
size?: number;
|
||||||
|
color?: string;
|
||||||
|
className?: string;
|
||||||
|
variant?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SmartIcon: React.FC<SmartIconProps> = ({
|
||||||
|
icon,
|
||||||
|
name,
|
||||||
|
size,
|
||||||
|
color,
|
||||||
|
className,
|
||||||
|
variant,
|
||||||
|
}) => {
|
||||||
|
const iconName = (icon?.Name || name || "").charAt(0).toUpperCase() + (icon?.Name || name || "").slice(1);
|
||||||
|
|
||||||
|
if (!iconName) return null;
|
||||||
|
|
||||||
|
const IconComponent = Iconsax[iconName as keyof typeof Iconsax] as IconComponentType | undefined;
|
||||||
|
|
||||||
|
if (!IconComponent) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IconComponent
|
||||||
|
variant={icon?.Variant ?? variant ?? 'lineat'}
|
||||||
|
size={icon?.Size ?? size ?? 20}
|
||||||
|
color={icon?.Color ?? color ?? "currentColor"}
|
||||||
|
className={icon?.ClassName ?? className}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { IconType, SmartIconType } from "@/types/iconType";
|
||||||
|
import { SmartIcon } from '@/components/utils/SmartIcon';
|
||||||
|
|
||||||
|
export function isSmartIconType(icon: unknown): icon is SmartIconType {
|
||||||
|
return (
|
||||||
|
typeof icon === 'object' &&
|
||||||
|
icon !== null &&
|
||||||
|
'Name' in icon &&
|
||||||
|
typeof (icon as SmartIconType).Name === 'string'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderIcon(icon: IconType) {
|
||||||
|
if (React.isValidElement(icon)) {
|
||||||
|
return icon; // It's a React node
|
||||||
|
} else if (typeof icon === 'function') {
|
||||||
|
const IconComponent = icon; // It's a functional component
|
||||||
|
|
||||||
|
// Create a ref to pass to the forwardRef component
|
||||||
|
const ref = React.createRef<SVGSVGElement>(); // Adjust the type based on your icon component
|
||||||
|
|
||||||
|
return <IconComponent ref={ref} size={20} className='stroke-foreground mb-0.5' />;
|
||||||
|
} else if (isSmartIconType(icon)) {
|
||||||
|
// Handle SmartIconType
|
||||||
|
return (
|
||||||
|
<SmartIcon icon={icon} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null; // No valid icon provided
|
||||||
|
}
|
||||||
@@ -3,6 +3,10 @@ import { initReactI18next } from 'react-i18next/initReactI18next';
|
|||||||
import resourcesToBackend from 'i18next-resources-to-backend';
|
import resourcesToBackend from 'i18next-resources-to-backend';
|
||||||
import i18nConfig from '../../i18nConfig';
|
import i18nConfig from '../../i18nConfig';
|
||||||
|
|
||||||
|
export const getI18nObject = (t, x) => {
|
||||||
|
return t(x, { returnObjects: true })
|
||||||
|
}
|
||||||
|
|
||||||
export default async function initTranslations(
|
export default async function initTranslations(
|
||||||
locale,
|
locale,
|
||||||
namespaces,
|
namespaces,
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"Heading": "تنظیمات",
|
||||||
|
"TabNotifications": {
|
||||||
|
"Title": "نوتیفیکیشن",
|
||||||
|
"Heading": "تنظیمات نوتیفیکیشن",
|
||||||
|
"Description": "",
|
||||||
|
"Accordions": [
|
||||||
|
{
|
||||||
|
"Heading": "حساب",
|
||||||
|
"Items": [
|
||||||
|
{
|
||||||
|
"Label": "ورود به حساب",
|
||||||
|
"HtmlName": "login-notif"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "تغییر رمز عبور",
|
||||||
|
"HtmlName": "password-notif"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Heading": "کیف پول",
|
||||||
|
"Items": [
|
||||||
|
{
|
||||||
|
"Label": "افزایش شارژ",
|
||||||
|
"HtmlName": "wallet-recharge"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "برداشت از کیف",
|
||||||
|
"HtmlName": "wallet-withdrawal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "استفاده از تخفیف",
|
||||||
|
"HtmlName": "redeem-discount"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Heading": "سفارش",
|
||||||
|
"Items": [
|
||||||
|
{
|
||||||
|
"Label": "وضعیت سفارش",
|
||||||
|
"HtmlName": "order-state"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "تحویل",
|
||||||
|
"HtmlName": "order-deliver"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "کنسلی",
|
||||||
|
"HtmlName": "order-canceled"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"TabPassword": {
|
||||||
|
"Title": "رمز عبور",
|
||||||
|
"Heading": "تغییر رمز عبور",
|
||||||
|
"Description": "",
|
||||||
|
"Inputs": [
|
||||||
|
{
|
||||||
|
"Label": "",
|
||||||
|
"Placeholder": "رمز عبور فعلی",
|
||||||
|
"HtmlName": "oldPassword",
|
||||||
|
"AutoComplete": "old-password"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "",
|
||||||
|
"Placeholder": "رمز عبور جدید",
|
||||||
|
"HtmlName": "newPassword",
|
||||||
|
"AutoComplete": "off"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "",
|
||||||
|
"Placeholder": "تکرار رمز عبور",
|
||||||
|
"HtmlName": "passwordRepeat",
|
||||||
|
"AutoComplete": "off"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Rules": [
|
||||||
|
{
|
||||||
|
"Heading": "رمز عبور میبایست:",
|
||||||
|
"Items": [
|
||||||
|
"حداقل 8 کاراکتر باشد",
|
||||||
|
"ترکیبی از حروف موچک و بزرگ باشد",
|
||||||
|
"شامل اعداد باشد",
|
||||||
|
"شامل کاراکتر های خاص (نماد ها) باشد"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ButtonSubmit": "ذخیره تغییرات"
|
||||||
|
},
|
||||||
|
"TabAuthenticator": {
|
||||||
|
"Title": "دو مرحله ای",
|
||||||
|
"Heading": "راهاندازی احراز هویت دو مرحلهای",
|
||||||
|
"Description": "احراز هویت دو مرحلهای امنیت اکانت شما را افزایش میدهد",
|
||||||
|
"Tip": "برای شروع فرآیند راهاندازی احراز هویت دو مرحلهای، روی دکمه زیر کلیک کنید",
|
||||||
|
"Guides": [
|
||||||
|
{
|
||||||
|
"Heading": "راهنمای احراز هویت دو مرحلهای",
|
||||||
|
"Description": "این قابلیت امنیت حساب شما را به شدت افزایش میدهد",
|
||||||
|
"Items": [
|
||||||
|
{
|
||||||
|
"Label": "یک برنامه Authenticator مانند Google Authenticator نصب کنید",
|
||||||
|
"Mark": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "QR Code را اسکن کنید یا کد را به صورت دستی وارد کنید",
|
||||||
|
"Mark": "2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "کد 6 رقمی تولید شده توسط برنامه را وارد کنید",
|
||||||
|
"Mark": "3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Notes": [
|
||||||
|
"توجه: کد های پشتیبان خود را در مکانی امن نگهداری کنید"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ButtonSubmit": "راهاندازی کد دو مرحلهای"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import { SmartIconType } from "../iconType";
|
||||||
|
|
||||||
|
export interface Item {
|
||||||
|
Label: string;
|
||||||
|
HtmlName: string;
|
||||||
|
Icon?: SmartIconType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Accordion {
|
||||||
|
Heading: string;
|
||||||
|
Icon?: SmartIconType;
|
||||||
|
Items: Item[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TabNotifications {
|
||||||
|
Title: string;
|
||||||
|
Heading: string;
|
||||||
|
Description?: string;
|
||||||
|
Accordions: Accordion[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InputField {
|
||||||
|
Label: string;
|
||||||
|
Placeholder?: string;
|
||||||
|
HtmlName?: string;
|
||||||
|
AutoComplete?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RuleGroup {
|
||||||
|
Heading: string;
|
||||||
|
Items: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TabPassword {
|
||||||
|
Title: string;
|
||||||
|
Heading: string;
|
||||||
|
Description?: string;
|
||||||
|
Inputs: InputField[];
|
||||||
|
Rules: RuleGroup[];
|
||||||
|
ButtonSubmit: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GuideItem {
|
||||||
|
Label: string;
|
||||||
|
Mark: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Guide {
|
||||||
|
Heading: string;
|
||||||
|
Description: string;
|
||||||
|
Items: GuideItem[];
|
||||||
|
Notes: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TabAuthenticator {
|
||||||
|
Title: string;
|
||||||
|
Heading: string;
|
||||||
|
Description?: string;
|
||||||
|
Tip: string;
|
||||||
|
Guides: Guide[];
|
||||||
|
ButtonSubmit: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SettingsData {
|
||||||
|
Heading: string;
|
||||||
|
TabNotifications: TabNotifications;
|
||||||
|
TabPassword: TabPassword;
|
||||||
|
TabAuthenticator: TabAuthenticator;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
export interface SmartIconType {
|
||||||
|
Name: string;
|
||||||
|
Size?: number;
|
||||||
|
Color?: string;
|
||||||
|
ClassName?: string;
|
||||||
|
Variant?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IconType =
|
||||||
|
React.ElementType |
|
||||||
|
React.ReactNode |
|
||||||
|
SmartIconType;
|
||||||
Reference in New Issue
Block a user