Skip to content

Commit

Permalink
Merge pull request #504 from bobrov-site/AppearanceFrontend
Browse files Browse the repository at this point in the history
Appearance frontend
  • Loading branch information
HelenOne authored Jun 20, 2024
2 parents e006d60 + b1bf035 commit 822a53d
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 3 deletions.
96 changes: 96 additions & 0 deletions frontend/src/components/Forms/AppearanceForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { useFormik } from 'formik';
import { Button } from 'react-bootstrap';
import Form from 'react-bootstrap/Form';
import { useTranslation } from 'react-i18next';
import { useTernaryDarkMode } from 'usehooks-ts';
import { useState } from 'react';
import { useLanguage } from '../../hooks';
import FormAlert from './FormAlert.jsx';

function LanguageItem({ value, language }) {
const { t } = useTranslation();
if (value !== language) {
return <option value={value}>{t(`profileSettings.${value}`)}</option>;
}
}

function ThemeItem({ value, theme }) {
const { t } = useTranslation();
if (value !== theme) {
return <option value={value}>{t(`settings.themes.${value}`)}</option>;
}
}

function ApperearanceForm() {
const { t } = useTranslation();
const { language, availableLanguages, setLanguage } = useLanguage();
const { ternaryDarkMode, setTernaryDarkMode } = useTernaryDarkMode();
const themes = ['system', 'light', 'dark'];
const initialFormState = { state: 'initial', message: '' };
const [formState, setFormState] = useState(initialFormState);
const initialValues = {
selectedLanguage: '',
selectedTheme: '',
};
const formik = useFormik({
initialValues,
onSubmit: (values) => {
const { selectedLanguage, selectedTheme } = values;
setFormState(initialFormState);
setLanguage(selectedLanguage !== '' ? selectedLanguage : language);
setTernaryDarkMode(
selectedTheme !== '' ? selectedTheme : ternaryDarkMode,
);
setFormState({
state: 'success',
message: 'profileSettings.updateSuccessful',
});
formik.resetForm();
},
});
return (
<Form className="d-flex flex-column gap-3" onSubmit={formik.handleSubmit}>
<h5>{t('profileSettings.appearance')}</h5>
<FormAlert
onClose={() => setFormState(initialFormState)}
state={formState.state}
>
{t(formState.message)}
</FormAlert>
<Form.Group>
<Form.Label>{t('profileSettings.language')}</Form.Label>
<Form.Select name="selectedLanguage" onChange={formik.handleChange}>
<option defaultValue={language}>
{t(`profileSettings.${language}`)}
</option>
{availableLanguages.map((lang) => {
return <LanguageItem key={lang} language={language} value={lang} />;
})}
</Form.Select>
</Form.Group>
<Form.Group>
<Form.Label>{t('profileSettings.theme')}</Form.Label>
<Form.Select name="selectedTheme" onChange={formik.handleChange}>
<option defaultValue={ternaryDarkMode}>
{t(`settings.themes.${ternaryDarkMode}`)}
</option>
{themes.map((item) => {
return (
<ThemeItem key={item} theme={ternaryDarkMode} value={item} />
);
})}
</Form.Select>
</Form.Group>
<Button
className="ms-auto"
disabled={!formik.dirty || formik.isSubmitting}
type="submit"
variant="primary"
>
{t('profileSettings.changeButton')}
</Button>
</Form>
);
}

export default ApperearanceForm;
5 changes: 5 additions & 0 deletions frontend/src/components/Navigation/LanguageSelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ import { useTranslation } from 'react-i18next';
import Dropdown from 'react-bootstrap/Dropdown';
import Button from 'react-bootstrap/Button';

import { useEffect } from 'react';
import { useLanguage } from '../../hooks';

function LanguageSelector() {
const { t, i18n } = useTranslation();

const { language, availableLanguages, setLanguage } = useLanguage();

useEffect(() => {
setLanguage(language);
}, [setLanguage, language]);

return (
<Dropdown align="end" as="li" className="nav-item">
<Dropdown.Toggle
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/hooks/useLanguage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useTranslation } from 'react-i18next';
import { useLayoutEffect, useState } from 'react';
import { useEffect, useLayoutEffect, useState } from 'react';

import { AVAILABLE_LANGUAGES } from '../initI18next';

Expand All @@ -8,6 +8,10 @@ const useLanguage = () => {
const { resolvedLanguage, changeLanguage } = i18n;
const [language, setLanguage] = useState(resolvedLanguage);

useEffect(() => {
setLanguage(resolvedLanguage);
}, [setLanguage, resolvedLanguage]);

useLayoutEffect(() => {
changeLanguage(language);
}, [language, changeLanguage]);
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@
"signUp": "Sign Up"
},
"profileSettings": {
"appearance": "Appearance",
"changeButton": "Change",
"changePassword": "Change Password",
"currentPassword": "Current Password",
Expand All @@ -274,7 +275,11 @@
"updateButton": "Update",
"updateFailed": "Failed to update account data. Try again later",
"updateSuccessful": "Profile has been updated successfully",
"usernameLabel": "Username"
"usernameLabel": "Username",
"language": "UI Language",
"theme": "Theme",
"ru": "Russian",
"en": "English"
},
"forgotPass": {
"pageHeader": "Forgot password?",
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@
"signUp": "Регистрация"
},
"profileSettings": {
"appearance": "Внешний вид",
"changeButton": "Изменить",
"changePassword": "Изменить пароль",
"currentPassword": "Текущий пароль",
Expand All @@ -407,7 +408,11 @@
"updateButton": "Изменить",
"updateFailed": "Не удалось обновить данные. Попробуйте позже",
"updateSuccessful": "Данные аккаунта были обновлены",
"usernameLabel": "Имя пользователя"
"usernameLabel": "Имя пользователя",
"language": "Язык интерфейса",
"theme": "Тема",
"ru": "Русский",
"en": "English"
},
"forgotPass": {
"pageHeader": "Забыли пароль?",
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/pages/settings/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { actions as modalActions } from '../../slices/modalSlice.js';
import AvatarChangeForm from '../../components/Forms/AvatarChangeForm.jsx';
import ChangePasswordForm from '../../components/Forms/ChangePasswordForm.jsx';
import UpdateAccountForm from '../../components/Forms/UpdateAccountForm.jsx';
import ApperearanceForm from '../../components/Forms/AppearanceForm.jsx';

function SettingsPage() {
const { t } = useTranslation();
Expand Down Expand Up @@ -40,6 +41,8 @@ function SettingsPage() {
<UpdateAccountForm />
<hr className="border-secondary-subtle" />
<ChangePasswordForm />
<hr className="border-secondary-subtle" />
<ApperearanceForm />
</Stack>
</div>
</div>
Expand Down

0 comments on commit 822a53d

Please sign in to comment.