VORKOUT-9 #6
@ -24,7 +24,7 @@
|
|||||||
work correctly both with client-side routing and a non-root public URL.
|
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`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>React App</title>
|
<title>VORKOUT</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Drawer } from 'antd';
|
import { Drawer } from 'antd';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Avatar, Typography } from 'antd';
|
import { Avatar, Typography } from 'antd';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
interface ContentDrawerProps {
|
interface ContentDrawerProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -15,6 +16,7 @@ export default function ContentDrawer({
|
|||||||
children,
|
children,
|
||||||
type,
|
type,
|
||||||
}: ContentDrawerProps) {
|
}: ContentDrawerProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [width, setWidth] = useState<number | string>('30%');
|
const [width, setWidth] = useState<number | string>('30%');
|
||||||
|
|
||||||
const calculateWidths = () => {
|
const calculateWidths = () => {
|
||||||
@ -123,7 +125,7 @@ export default function ContentDrawer({
|
|||||||
fontSize: '20px',
|
fontSize: '20px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Новая учетная запись
|
{t('newAccount')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@ -133,6 +135,7 @@ export default function ContentDrawer({
|
|||||||
height: '24px',
|
height: '24px',
|
||||||
width: '24px',
|
width: '24px',
|
||||||
}}
|
}}
|
||||||
|
onClick={closeDrawer}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src="./icons/drawer/delete.svg"
|
src="./icons/drawer/delete.svg"
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
UploadProps,
|
UploadProps,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ const getBase64 = (file: FileType): Promise<string> =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
export default function UserCreate() {
|
export default function UserCreate() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [previewOpen, setPreviewOpen] = useState(false);
|
const [previewOpen, setPreviewOpen] = useState(false);
|
||||||
const [previewImage, setPreviewImage] = useState('');
|
const [previewImage, setPreviewImage] = useState('');
|
||||||
|
|
||||||
@ -64,7 +66,9 @@ export default function UserCreate() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span style={{ fontSize: '14px', color: '#8c8c8c' }}>Выбрать фото</span>
|
<span style={{ fontSize: '14px', color: '#8c8c8c' }}>
|
||||||
|
{t('selectPhoto')}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -135,54 +139,54 @@ export default function UserCreate() {
|
|||||||
style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
|
style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
|
||||||
>
|
>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Имя"
|
label={t('name')}
|
||||||
name="name"
|
name="name"
|
||||||
rules={[{ required: true, message: 'Введите имя' }]}
|
rules={[{ required: true, message: t('nameMessage') }]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Логин"
|
label={t('login')}
|
||||||
name="login"
|
name="login"
|
||||||
rules={[{ required: true, message: 'Введите логин' }]}
|
rules={[{ required: true, message: t('loginMessage') }]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Пароль"
|
label={t('password')}
|
||||||
name="password"
|
name="password"
|
||||||
rules={[{ required: true, message: 'Введите пароль' }]}
|
rules={[{ required: true, message: t('passwordMessage') }]}
|
||||||
>
|
>
|
||||||
<Input.Password />
|
<Input.Password />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="E-mail"
|
label={t('email')}
|
||||||
name="email"
|
name="email"
|
||||||
rules={[
|
rules={[
|
||||||
{ required: true, message: 'Введите имейл' },
|
{ required: true, message: t('emailMessage') },
|
||||||
{ type: 'email', message: 'Некорректный имейл' },
|
{ type: 'email', message: t('emailErrorMessage') },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Привязка"
|
label={t('tenant')}
|
||||||
name="tenant"
|
name="tenant"
|
||||||
rules={[{ required: true, message: 'Введите привязку' }]}
|
rules={[{ required: true, message: t('tenantMessage') }]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Роль"
|
label={t('role')}
|
||||||
name="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>
|
<Option value="Менеджер">Менеджер</Option>
|
||||||
<Option value="Кассир">Кассир</Option>
|
<Option value="Кассир">Кассир</Option>
|
||||||
@ -190,11 +194,11 @@ export default function UserCreate() {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Статус"
|
label={t('status')}
|
||||||
name="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="ACTIVE">Активен</Option>
|
||||||
<Option value="DISABLED">Неактивен</Option>
|
<Option value="DISABLED">Неактивен</Option>
|
||||||
<Option value="BLOCKED">Заблокирован</Option>
|
<Option value="BLOCKED">Заблокирован</Option>
|
||||||
@ -216,7 +220,7 @@ export default function UserCreate() {
|
|||||||
alt="save"
|
alt="save"
|
||||||
style={{ height: '18px', width: '18px' }}
|
style={{ height: '18px', width: '18px' }}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
Добавить аккаунт
|
{t('addAccount')}
|
||||||
</Button>
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { Button, Form, Input, Select } from 'antd';
|
import { Button, Form, Input, Select } from 'antd';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
export default function UserEdit() {
|
export default function UserEdit() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||||
<Form
|
<Form
|
||||||
@ -21,54 +23,54 @@ export default function UserEdit() {
|
|||||||
style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
|
style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
|
||||||
>
|
>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Имя"
|
label={t('name')}
|
||||||
name="name"
|
name="name"
|
||||||
rules={[{ required: true, message: 'Введите имя' }]}
|
rules={[{ required: true, message: t('nameMessage') }]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Логин"
|
label={t('login')}
|
||||||
name="login"
|
name="login"
|
||||||
rules={[{ required: true, message: 'Введите логин' }]}
|
rules={[{ required: true, message: t('loginMessage') }]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Пароль (последний ввод)"
|
label={t('password')}
|
||||||
name="password"
|
name="password"
|
||||||
rules={[{ required: true, message: 'Введите пароль' }]}
|
rules={[{ required: true, message: t('passwordMessage') }]}
|
||||||
>
|
>
|
||||||
<Input.Password />
|
<Input.Password />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="E-mail"
|
label={t('email')}
|
||||||
name="email"
|
name="email"
|
||||||
rules={[
|
rules={[
|
||||||
{ required: true, message: 'Введите имейл' },
|
{ required: true, message: t('emailMessage') },
|
||||||
{ type: 'email', message: 'Некорректный имейл' },
|
{ type: 'email', message: t('emailErrorMessage') },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Привязка"
|
label={t('tenant')}
|
||||||
name="tenant"
|
name="tenant"
|
||||||
rules={[{ required: true, message: 'Введите привязку' }]}
|
rules={[{ required: true, message: t('tenantMessage') }]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Роль"
|
label={t('role')}
|
||||||
name="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>
|
<Option value="Менеджер">Менеджер</Option>
|
||||||
<Option value="Кассир">Кассир</Option>
|
<Option value="Кассир">Кассир</Option>
|
||||||
@ -76,11 +78,11 @@ export default function UserEdit() {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Статус"
|
label={t('status')}
|
||||||
name="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="ACTIVE">Активен</Option>
|
||||||
<Option value="DISABLED">Неактивен</Option>
|
<Option value="DISABLED">Неактивен</Option>
|
||||||
<Option value="BLOCKED">Заблокирован</Option>
|
<Option value="BLOCKED">Заблокирован</Option>
|
||||||
@ -102,7 +104,7 @@ export default function UserEdit() {
|
|||||||
alt="save"
|
alt="save"
|
||||||
style={{ height: '18px', width: '18px' }}
|
style={{ height: '18px', width: '18px' }}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
Сохранить изменения
|
{t('save')}
|
||||||
</Button>
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</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';
|
import Header from '../components/Header';
|
||||||
|
|
||||||
export default function ConfigurationPage() {
|
export default function ConfigurationPage() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header title="Конфигурация" />
|
<Header title={t('configuration')} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import Header from '../components/Header';
|
import Header from '../components/Header';
|
||||||
|
|
||||||
export default function EventsListPage() {
|
export default function EventsListPage() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header title="Справочник событий" />
|
<Header title={t('eventsList')} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import Header from '../components/Header';
|
import Header from '../components/Header';
|
||||||
|
|
||||||
export default function ProcessDiagramPage() {
|
export default function ProcessDiagramPage() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header title="Схемы процессов" />
|
<Header title={t('processDiagrams')} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import Header from '../components/Header';
|
import Header from '../components/Header';
|
||||||
|
|
||||||
export default function RunningProcessesPage() {
|
export default function RunningProcessesPage() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header title="Запущенные процессы" />
|
<Header title={t('runningProcesses')} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user