VORKOUT-9 #6
@ -24,7 +24,7 @@
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
<title>VORKOUT</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Drawer } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Avatar, Typography } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface ContentDrawerProps {
|
||||
open: boolean;
|
||||
@ -15,6 +16,7 @@ export default function ContentDrawer({
|
||||
children,
|
||||
type,
|
||||
}: ContentDrawerProps) {
|
||||
const { t } = useTranslation();
|
||||
const [width, setWidth] = useState<number | string>('30%');
|
||||
|
||||
const calculateWidths = () => {
|
||||
@ -123,7 +125,7 @@ export default function ContentDrawer({
|
||||
fontSize: '20px',
|
||||
}}
|
||||
>
|
||||
Новая учетная запись
|
||||
{t('newAccount')}
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -133,6 +135,7 @@ export default function ContentDrawer({
|
||||
height: '24px',
|
||||
width: '24px',
|
||||
}}
|
||||
onClick={closeDrawer}
|
||||
>
|
||||
<img
|
||||
src="./icons/drawer/delete.svg"
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
UploadProps,
|
||||
} from 'antd';
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@ -24,6 +25,7 @@ const getBase64 = (file: FileType): Promise<string> =>
|
||||
});
|
||||
|
||||
export default function UserCreate() {
|
||||
const { t } = useTranslation();
|
||||
const [previewOpen, setPreviewOpen] = useState(false);
|
||||
const [previewImage, setPreviewImage] = useState('');
|
||||
|
||||
@ -64,7 +66,9 @@ export default function UserCreate() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span style={{ fontSize: '14px', color: '#8c8c8c' }}>Выбрать фото</span>
|
||||
<span style={{ fontSize: '14px', color: '#8c8c8c' }}>
|
||||
{t('selectPhoto')}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -135,54 +139,54 @@ export default function UserCreate() {
|
||||
style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
|
||||
>
|
||||
<Form.Item
|
||||
label="Имя"
|
||||
label={t('name')}
|
||||
name="name"
|
||||
rules={[{ required: true, message: 'Введите имя' }]}
|
||||
rules={[{ required: true, message: t('nameMessage') }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Логин"
|
||||
label={t('login')}
|
||||
name="login"
|
||||
rules={[{ required: true, message: 'Введите логин' }]}
|
||||
rules={[{ required: true, message: t('loginMessage') }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Пароль"
|
||||
label={t('password')}
|
||||
name="password"
|
||||
rules={[{ required: true, message: 'Введите пароль' }]}
|
||||
rules={[{ required: true, message: t('passwordMessage') }]}
|
||||
>
|
||||
<Input.Password />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="E-mail"
|
||||
label={t('email')}
|
||||
name="email"
|
||||
rules={[
|
||||
{ required: true, message: 'Введите имейл' },
|
||||
{ type: 'email', message: 'Некорректный имейл' },
|
||||
{ required: true, message: t('emailMessage') },
|
||||
{ type: 'email', message: t('emailErrorMessage') },
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Привязка"
|
||||
label={t('tenant')}
|
||||
name="tenant"
|
||||
rules={[{ required: true, message: 'Введите привязку' }]}
|
||||
rules={[{ required: true, message: t('tenantMessage') }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Роль"
|
||||
label={t('role')}
|
||||
name="role"
|
||||
rules={[{ required: true, message: 'Выберите роль' }]}
|
||||
rules={[{ required: true, message: t('roleMessage') }]}
|
||||
>
|
||||
<Select placeholder="Выберите роль">
|
||||
<Select placeholder={t('roleMessage')}>
|
||||
<Option value="Директор магазина">Директор магазина</Option>
|
||||
<Option value="Менеджер">Менеджер</Option>
|
||||
<Option value="Кассир">Кассир</Option>
|
||||
@ -190,11 +194,11 @@ export default function UserCreate() {
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Статус"
|
||||
label={t('status')}
|
||||
name="status"
|
||||
rules={[{ required: true, message: 'Выберите статус' }]}
|
||||
rules={[{ required: true, message: t('statusMessage') }]}
|
||||
>
|
||||
<Select placeholder="Выберите статус">
|
||||
<Select placeholder={t('statusMessage')}>
|
||||
<Option value="ACTIVE">Активен</Option>
|
||||
<Option value="DISABLED">Неактивен</Option>
|
||||
<Option value="BLOCKED">Заблокирован</Option>
|
||||
@ -216,7 +220,7 @@ export default function UserCreate() {
|
||||
alt="save"
|
||||
style={{ height: '18px', width: '18px' }}
|
||||
/>{' '}
|
||||
Добавить аккаунт
|
||||
{t('addAccount')}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { Button, Form, Input, Select } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
export default function UserEdit() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||
<Form
|
||||
@ -21,54 +23,54 @@ export default function UserEdit() {
|
||||
style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
|
||||
>
|
||||
<Form.Item
|
||||
label="Имя"
|
||||
label={t('name')}
|
||||
name="name"
|
||||
rules={[{ required: true, message: 'Введите имя' }]}
|
||||
rules={[{ required: true, message: t('nameMessage') }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Логин"
|
||||
label={t('login')}
|
||||
name="login"
|
||||
rules={[{ required: true, message: 'Введите логин' }]}
|
||||
rules={[{ required: true, message: t('loginMessage') }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Пароль (последний ввод)"
|
||||
label={t('password')}
|
||||
name="password"
|
||||
rules={[{ required: true, message: 'Введите пароль' }]}
|
||||
rules={[{ required: true, message: t('passwordMessage') }]}
|
||||
>
|
||||
<Input.Password />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="E-mail"
|
||||
label={t('email')}
|
||||
name="email"
|
||||
rules={[
|
||||
{ required: true, message: 'Введите имейл' },
|
||||
{ type: 'email', message: 'Некорректный имейл' },
|
||||
{ required: true, message: t('emailMessage') },
|
||||
{ type: 'email', message: t('emailErrorMessage') },
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Привязка"
|
||||
label={t('tenant')}
|
||||
name="tenant"
|
||||
rules={[{ required: true, message: 'Введите привязку' }]}
|
||||
rules={[{ required: true, message: t('tenantMessage') }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Роль"
|
||||
label={t('role')}
|
||||
name="role"
|
||||
rules={[{ required: true, message: 'Выберите роль' }]}
|
||||
rules={[{ required: true, message: t('roleMessage') }]}
|
||||
>
|
||||
<Select placeholder="Выберите роль">
|
||||
<Select placeholder={t('roleMessage')}>
|
||||
<Option value="Директор магазина">Директор магазина</Option>
|
||||
<Option value="Менеджер">Менеджер</Option>
|
||||
<Option value="Кассир">Кассир</Option>
|
||||
@ -76,11 +78,11 @@ export default function UserEdit() {
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Статус"
|
||||
label={t('status')}
|
||||
name="status"
|
||||
rules={[{ required: true, message: 'Выберите статус' }]}
|
||||
rules={[{ required: true, message: t('statusMessage') }]}
|
||||
>
|
||||
<Select placeholder="Выберите статус">
|
||||
<Select placeholder={t('statusMessage')}>
|
||||
<Option value="ACTIVE">Активен</Option>
|
||||
<Option value="DISABLED">Неактивен</Option>
|
||||
<Option value="BLOCKED">Заблокирован</Option>
|
||||
@ -102,7 +104,7 @@ export default function UserEdit() {
|
||||
alt="save"
|
||||
style={{ height: '18px', width: '18px' }}
|
||||
/>{' '}
|
||||
Сохранить изменения
|
||||
{t('save')}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
24
client/src/config/AppWrapper.tsx
Normal file
24
client/src/config/AppWrapper.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import './i18n';
|
||||
import { ConfigProvider } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { theme } from './customTheme';
|
||||
|
||||
import en from 'antd/locale/en_US';
|
||||
import ru from 'antd/locale/ru_RU';
|
||||
|
||||
const antdLocales = {
|
||||
en: en,
|
||||
ru: ru,
|
||||
};
|
||||
|
||||
export default function AppWrapper({ children }: any) {
|
||||
const { i18n } = useTranslation();
|
||||
const currentLang = i18n.language.split('-')[0] as 'en' | 'ru';
|
||||
|
||||
return (
|
||||
<ConfigProvider locale={antdLocales[currentLang]} theme={theme}>
|
||||
{children}
|
||||
</ConfigProvider>
|
||||
);
|
||||
}
|
74
client/src/config/i18n.ts
Normal file
74
client/src/config/i18n.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
|
||||
i18n
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
fallbackLng: 'en',
|
||||
supportedLngs: ['en', 'ru'],
|
||||
interpolation: { escapeValue: false },
|
||||
resources: {
|
||||
en: {
|
||||
translation: {
|
||||
accounts: 'Accounts',
|
||||
processDiagrams: 'Process diagrams',
|
||||
runningProcesses: 'Running processes',
|
||||
settings: 'Settings',
|
||||
eventsList: 'Events list',
|
||||
configuration: 'Configuration',
|
||||
selectPhoto: 'Select photo',
|
||||
name: 'Name',
|
||||
login: 'Login',
|
||||
password: 'Password',
|
||||
email: 'Email',
|
||||
tenant: 'Tenant',
|
||||
role: 'Role',
|
||||
status: 'Status',
|
||||
nameMessage: 'Enter name',
|
||||
loginMessage: 'Enter login',
|
||||
passwordMessage: 'Enter password',
|
||||
emailMessage: 'Enter email',
|
||||
emailErrorMessage: 'Incorrect email',
|
||||
tenantMessage: 'Enter tenant',
|
||||
roleMessage: 'Choose role',
|
||||
statusMessage: 'Choose status',
|
||||
addAccount: 'Add account',
|
||||
save: 'Save changes',
|
||||
newAccount: 'New account',
|
||||
},
|
||||
},
|
||||
ru: {
|
||||
translation: {
|
||||
accounts: 'Учетные записи',
|
||||
processDiagrams: 'Схемы процессов',
|
||||
runningProcesses: 'Запущенные процессы',
|
||||
settings: 'Настройки',
|
||||
eventsList: 'Справочкин событий',
|
||||
configuration: 'Конфигурация',
|
||||
selectPhoto: 'Выбрать фото',
|
||||
name: 'Имя',
|
||||
login: 'Логин',
|
||||
password: 'Пароль',
|
||||
email: 'Имейл',
|
||||
tenant: 'Привязка',
|
||||
role: 'Роль',
|
||||
status: 'Статус',
|
||||
nameMessage: 'Введите имя',
|
||||
loginMessage: 'Введите логин',
|
||||
passwordMessage: 'Введите пароль',
|
||||
emailMessage: 'Введите имейл',
|
||||
emailErrorMessage: 'Некорректный имейл',
|
||||
tenantMessage: 'Введите привязку',
|
||||
roleMessage: 'Выберите роль',
|
||||
statusMessage: 'Выберите статус',
|
||||
addAccount: 'Добавить аккаунт',
|
||||
save: 'Сохранить изменения',
|
||||
newAccount: 'Новая учетная запись',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
@ -1,9 +1,11 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Header from '../components/Header';
|
||||
|
||||
export default function ConfigurationPage() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Header title="Конфигурация" />
|
||||
<Header title={t('configuration')} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Header from '../components/Header';
|
||||
|
||||
export default function EventsListPage() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Header title="Справочник событий" />
|
||||
<Header title={t('eventsList')} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Header from '../components/Header';
|
||||
|
||||
export default function ProcessDiagramPage() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Header title="Схемы процессов" />
|
||||
<Header title={t('processDiagrams')} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Header from '../components/Header';
|
||||
|
||||
export default function RunningProcessesPage() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Header title="Запущенные процессы" />
|
||||
<Header title={t('runningProcesses')} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user