feat(frontend): add mui

This commit is contained in:
Sergey Krylov 2025-10-09 05:43:21 +03:00
parent 35291a103a
commit 021038f4ad
75 changed files with 979 additions and 481 deletions

View File

@ -1,5 +1,8 @@
import './normalize.css';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ru } from 'date-fns/locale/ru';
import { AuthContextProvider } from '@/shared/context/AuthContext';
@ -10,7 +13,9 @@ const queryClient = new QueryClient();
const App = () => (
<QueryClientProvider client={queryClient}>
<AuthContextProvider>
<Routing />
<LocalizationProvider adapterLocale={ru} dateAdapter={AdapterDateFns}>
<Routing />
</LocalizationProvider>
</AuthContextProvider>
</QueryClientProvider>
);

View File

@ -9,10 +9,11 @@ export { useEditBankCard } from './hooks/useEditBankCard';
export type { BankCard, BankCards } from './types';
export type { AddBankCardFormValues } from './ui/AddBankCardForm';
export type { AddBankCardFormProps, AddBankCardFormValues } from './ui/AddBankCardForm';
export { AddBankCardForm } from './ui/AddBankCardForm';
export type { DeleteBankCardFormProps } from './ui/DeleteBankCardForm';
export { DeleteBankCardForm } from './ui/DeleteBankCardForm';
export type { EditBankCardFormValues } from './ui/EditBankCardForm';
export type { EditBankCardFormProps, EditBankCardFormValues } from './ui/EditBankCardForm';
export { EditBankCardForm } from './ui/EditBankCardForm';

View File

@ -1,2 +1,3 @@
export type { AddBankCardFormValues } from './ui/AddBankCardForm.ui';
export type { AddBankCardFormProps } from './ui/AddBankCardForm.ui';
export { default as AddBankCardForm } from './ui/AddBankCardForm.ui';

View File

@ -5,7 +5,9 @@ import type {
RefObject,
} from 'react';
import { Input } from '@/shared/ui/Input';
import { Button, TextField, Typography } from '@mui/material';
import { DataTestId } from '@/shared/constants';
import classes from './AddBankCardForm.module.css';
@ -49,29 +51,41 @@ const AddBankCardForm: FC<AddBankCardFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.ADD_BANK_CARD_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...formProps}
>
<h2>Добавить карту</h2>
<Typography variant="h6">
Добавить карту
</Typography>
<Input
<TextField
disabled={disabled}
label="Название"
name="name"
required
size="small"
/>
<Input
<TextField
defaultValue={0}
disabled={disabled}
inputMode="numeric"
label="Баланс"
name="balance"
step="0.01"
type="number"
size="small"
/>
<button disabled={disabled} type="submit">Добавить</button>
<Button
data-testid={DataTestId.ADD_BANK_CARD_SUBMIT_BUTTON}
disabled={disabled}
sx={{ mt: 2 }}
type="submit"
variant="contained"
>
Добавить
</Button>
</form>
);
};

View File

@ -1 +1,2 @@
export type { DeleteBankCardFormProps } from './ui/DeleteBankCardForm.ui';
export { default as DeleteBankCardForm } from './ui/DeleteBankCardForm.ui';

View File

@ -5,6 +5,10 @@ import type {
RefObject,
} from 'react';
import { Button, Typography } from '@mui/material';
import { DataTestId } from '@/shared/constants';
import type { BankCard } from '../../../types';
export type DeleteBankCardFormProps = BaseFormProps & {
@ -31,10 +35,17 @@ const DeleteBankCardForm: FC<DeleteBankCardFormProps> = (props) => {
};
return (
<form onSubmit={onFormSubmitHandler} ref={ref} {...restProps}>
<h2>Удалить список расходов</h2>
<form
data-testid={DataTestId.DELETE_BANK_CARD_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<Typography variant="h6">
Удалить список расходов
</Typography>
<p>
<Typography variant="body1">
Вы действительно хотите удалить банковскую карту
{' '}
@ -44,9 +55,19 @@ const DeleteBankCardForm: FC<DeleteBankCardFormProps> = (props) => {
{' '}
?
</p>
</Typography>
<button disabled={disabled} type="submit">Удалить</button>
<Button
color="error"
data-testid={DataTestId.DELETE_BANK_CARD_SUBMIT_BUTTON}
disabled={disabled}
fullWidth
sx={{ mt: 2 }}
type="submit"
variant="contained"
>
Удалить
</Button>
</form>
);
};

View File

@ -1,2 +1,3 @@
export type { EditBankCardFormValues } from './ui/EditBankCardForm.ui';
export type { EditBankCardFormProps } from './ui/EditBankCardForm.ui';
export { default as EditBankCardForm } from './ui/EditBankCardForm.ui';

View File

@ -5,9 +5,11 @@ import type {
RefObject,
} from 'react';
import { Button, TextField, Typography } from '@mui/material';
import type { BankCard } from '@/entity/cards';
import { Input } from '@/shared/ui/Input';
import { DataTestId } from '@/shared/constants';
import classes from './EditBankCardForm.module.css';
@ -53,30 +55,42 @@ const EditBankCardForm: FC<EditBankCardFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.EDIT_BANK_CARD_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<h2>Добавить карту</h2>
<Typography variant="h6">
Добавить карту
</Typography>
<Input
<TextField
defaultValue={bankCard.name}
disabled={disabled}
label="Название"
name="name"
required
size="small"
/>
<Input
<TextField
defaultValue={bankCard.balance}
disabled={disabled}
inputMode="numeric"
label="Баланс"
name="balance"
step="0.01"
type="number"
size="small"
/>
<button disabled={disabled} type="submit">Сохранить</button>
<Button
data-testid={DataTestId.EDIT_BANK_CARD_SUBMIT_BUTTON}
disabled={disabled}
fullWidth
type="submit"
variant="contained"
>
Сохранить
</Button>
</form>
);
};

View File

@ -10,9 +10,10 @@ export { useEditCash } from './hooks/useEditCash';
export type { CashItem, CashList } from './types';
export { AddCashForm } from './ui/AddCashForm';
export type { AddCashFormValues } from './ui/AddCashForm';
export type { AddCashFormProps, AddCashFormValues } from './ui/AddCashForm';
export type { DeleteCashFormProps } from './ui/DeleteCashForm';
export { DeleteCashForm } from './ui/DeleteCashForm';
export { EditCashForm } from './ui/EditCashForm';
export type { EditCashFormValues } from './ui/EditCashForm';
export type { EditCashFormProps, EditCashFormValues } from './ui/EditCashForm';

View File

@ -1,2 +1,2 @@
export type { AddCashFormValues } from './ui/AddCashForm.ui';
export type { AddCashFormProps, AddCashFormValues } from './ui/AddCashForm.ui';
export { default as AddCashForm } from './ui/AddCashForm.ui';

View File

@ -5,7 +5,9 @@ import type {
RefObject,
} from 'react';
import { Input } from '@/shared/ui/Input';
import { Button, TextField, Typography } from '@mui/material';
import { DataTestId } from '@/shared/constants';
import classes from './AddCashForm.module.css';
@ -49,29 +51,40 @@ const AddCashForm: FC<AddCashFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.ADD_CASH_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...formProps}
>
<h2>Добавить наличные</h2>
<Typography variant="h6">
Добавить наличные
</Typography>
<Input
<TextField
disabled={disabled}
label="Название"
name="name"
required
size="small"
/>
<Input
<TextField
defaultValue={0}
disabled={disabled}
inputMode="numeric"
label="Баланс"
name="balance"
step="0.01"
type="number"
size="small"
/>
<button disabled={disabled} type="submit">Добавить</button>
<Button
data-testid={DataTestId.ADD_CASH_SUBMIT_BUTTON}
disabled={disabled}
type="submit"
variant="contained"
>
Добавить
</Button>
</form>
);
};

View File

@ -1 +1,2 @@
export type { DeleteCashFormProps } from './ui/DeleteCashForm.ui';
export { default as DeleteCashForm } from './ui/DeleteCashForm.ui';

View File

@ -5,6 +5,10 @@ import type {
RefObject,
} from 'react';
import { Button, Typography } from '@mui/material';
import { DataTestId } from '@/shared/constants';
import type { CashItem } from '../../../types';
export type DeleteCashFormProps = BaseFormProps & {
@ -31,10 +35,17 @@ const DeleteCashForm: FC<DeleteCashFormProps> = (props) => {
};
return (
<form onSubmit={onFormSubmitHandler} ref={ref} {...restProps}>
<h2>Удалить наличные</h2>
<form
data-testid={DataTestId.DELETE_CASH_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<Typography variant="h6">
Удалить наличные
</Typography>
<p>
<Typography variant="body1">
Вы действительно хотите удалить наличные
{' '}
@ -44,9 +55,19 @@ const DeleteCashForm: FC<DeleteCashFormProps> = (props) => {
{' '}
?
</p>
</Typography>
<button disabled={disabled} type="submit">Удалить</button>
<Button
color="error"
data-testid={DataTestId.DELETE_CASH_SUBMIT_BUTTON}
disabled={disabled}
fullWidth
sx={{ mt: 2 }}
type="submit"
variant="contained"
>
Удалить
</Button>
</form>
);
};

View File

@ -1,2 +1,2 @@
export type { EditCashFormValues } from './ui/EditCashForm.ui';
export type { EditCashFormProps, EditCashFormValues } from './ui/EditCashForm.ui';
export { default as EditCashForm } from './ui/EditCashForm.ui';

View File

@ -5,9 +5,11 @@ import type {
RefObject,
} from 'react';
import { Button, TextField, Typography } from '@mui/material';
import type { CashItem } from '@/entity/cash';
import { Input } from '@/shared/ui/Input';
import { DataTestId } from '@/shared/constants';
import classes from './EditCashForm.module.css';
@ -53,30 +55,41 @@ const EditCashForm: FC<EditCashFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.EDIT_CASH_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<h2>Редактировать наличные</h2>
<Typography variant="h6">
Редактировать наличные
</Typography>
<Input
<TextField
defaultValue={cash.name}
disabled={disabled}
label="Название"
name="name"
required
size="small"
/>
<Input
<TextField
defaultValue={cash.balance}
disabled={disabled}
inputMode="numeric"
label="Баланс"
name="balance"
step="0.01"
type="number"
size="small"
/>
<button disabled={disabled} type="submit">Сохранить</button>
<Button
data-testid={DataTestId.EDIT_CASH_SUBMIT_BUTTON}
disabled={disabled}
type="submit"
variant="contained"
>
Сохранить
</Button>
</form>
);
};

View File

@ -7,11 +7,12 @@ export { useDeleteExpenseItem } from './hooks/useDeleteExpenseItem';
export { useEditExpenseItem } from './hooks/useEditExpenseItem';
export type { ExpenseListItem } from './types';
export type { AddExpenseItemFormValues } from './ui/AddExpenseItemForm/AddExpenseItemForm.ui';
export type { AddExpenseItemFormProps, AddExpenseItemFormValues } from './ui/AddExpenseItemForm/AddExpenseItemForm.ui';
export { default as AddExpenseItemForm } from './ui/AddExpenseItemForm/AddExpenseItemForm.ui';
export type { DeleteExpenseItemFormProps } from './ui/DeleteExpenseItemForm/DeleteExpenseItemForm.ui';
export { default as DeleteExpenseItemForm } from './ui/DeleteExpenseItemForm/DeleteExpenseItemForm.ui';
export type { EditExpenseItemFormValues } from './ui/EditExpenseItemForm/EditExpenseItemForm.ui';
export type { EditExpenseItemFormProps, EditExpenseItemFormValues } from './ui/EditExpenseItemForm/EditExpenseItemForm.ui';
export { default as EditExpenseItemForm } from './ui/EditExpenseItemForm/EditExpenseItemForm.ui';

View File

@ -1,11 +1,21 @@
import type { SelectChangeEvent } from '@mui/material';
import type {
ChangeEventHandler,
FC,
FormEventHandler,
FormHTMLAttributes,
RefObject,
} from 'react';
import {
Button,
FormControl,
InputLabel,
MenuItem,
Select,
TextField,
Typography,
} from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import {
useMemo,
useState,
@ -15,9 +25,8 @@ import type { ExpenseListItem } from '@/entity/expenses/item';
import { useBankCards } from '@/entity/cards';
import { useCash } from '@/entity/cash';
import { Input } from '@/shared/ui/Input';
import { Select } from '@/shared/ui/Select';
import { formatRub } from '@/shared/utils';
import { DataTestId } from '@/shared/constants';
import { formatRub, getUTCDate } from '@/shared/utils';
import classes from './AddExpenseItemForm.module.css';
@ -89,7 +98,7 @@ const AddExpenseItemForm: FC<AddExpenseItemFormProps> = (props) => {
amount: Number(amount),
count: Number(count),
currency: 'RUB',
date: new Date(date).toISOString(),
date: getUTCDate(date),
description,
// @ts-ignore todo
payment: getPayment(),
@ -100,31 +109,33 @@ const AddExpenseItemForm: FC<AddExpenseItemFormProps> = (props) => {
const { data: bankCards } = useBankCards();
const { data: cash } = useCash();
const bankCardOptions = bankCards?.map((card) => ({
label: `${card.name} (${formatRub(card.balance)})`,
value: card.id,
}));
const bankCardOptions = bankCards?.map((card) => (
<MenuItem key={card.id} value={card.id}>
{`${card.name} (${formatRub(card.balance)})`}
</MenuItem>
));
const cashOptions = cash?.map((cashItem) => ({
label: `${cashItem.name} (${formatRub(cashItem.balance)})`,
value: cashItem.id,
}));
const cashOptions = cash?.map((cashItem) => (
<MenuItem key={cashItem.id} value={cashItem.id}>
{`${cashItem.name} (${formatRub(cashItem.balance)})`}
</MenuItem>
));
const paymentOptions = useMemo(() => {
const options = [{ label: 'Без оплаты', value: 'none' }];
const options = [<MenuItem key="none" value="none">Без оплаты</MenuItem>];
if (bankCardOptions && bankCardOptions.length > 0) {
options.push({ label: 'Банковская карта', value: 'BANK_CARD' });
options.push(<MenuItem key="BANK_CARD" value="BANK_CARD">Банковская карта</MenuItem>);
}
if (cashOptions && cashOptions.length > 0) {
options.push({ label: 'Наличные', value: 'CASH' });
options.push(<MenuItem key="CASH" value="CASH">Наличные</MenuItem>);
}
return options;
}, [bankCardOptions, cashOptions]);
const onChangePaymentHandler: ChangeEventHandler<HTMLSelectElement> = (event) => {
const onChangePaymentHandler = (event: SelectChangeEvent<'BANK_CARD' | 'CASH' | 'none'>) => {
const { value } = event.target;
if (value === 'none') {
setPaymentType(null);
@ -135,80 +146,126 @@ const AddExpenseItemForm: FC<AddExpenseItemFormProps> = (props) => {
};
const renderCardSelect = () => (
<Select
label="Карта"
name="bank-card"
options={bankCardOptions ?? []}
/>
<FormControl fullWidth>
<InputLabel id="bank-card-label">Карта</InputLabel>
<Select
data-testid="bank-card-select"
defaultValue={bankCards?.[0].id}
disabled={disabled}
inputProps={{ 'data-testid': 'bank-card-select-input' }}
labelId="bank-card-label"
name="bank-card"
size="small"
>
{bankCardOptions}
</Select>
</FormControl>
);
const renderCashSelect = () => (
<Select
label="Наличные"
name="cash"
options={cashOptions ?? []}
/>
<FormControl fullWidth>
<InputLabel id="cash-label">Наличные</InputLabel>
<Select
data-testid="cash-select"
defaultValue={cash?.[0].id}
disabled={disabled}
inputProps={{ 'data-testid': 'cash-select-input' }}
labelId="cash-label"
name="cash"
size="small"
>
{cashOptions ?? []}
</Select>
</FormControl>
);
return (
<form
className={classes.form}
data-testid={DataTestId.ADD_EXPENSE_ITEM_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...formProps}
>
<h2>Добавить список расходов</h2>
<Typography variant="h6">
Добавить список расходов
</Typography>
<Input
<TextField
disabled={disabled}
label="Название"
name="title"
required
size="small"
/>
<Input
<TextField
disabled={disabled}
label="Описание"
name="description"
size="small"
/>
<Input
defaultValue={new Date().toISOString().split('T')[0]}
<DatePicker
defaultValue={new Date()}
disabled={disabled}
label="Дата"
name="date"
required
type="date"
slotProps={{ textField: { required: true, size: 'small' } }}
/>
<Input
<TextField
disabled={disabled}
inputMode="numeric"
label="Сумма"
name="amount"
required
step="0.01"
size="small"
type="number"
/>
<Input
<TextField
defaultValue={1}
disabled={disabled}
inputMode="numeric"
label="Количество"
name="count"
size="small"
type="number"
/>
<Select
label="Способ оплаты"
name="paymentMethod"
onChange={onChangePaymentHandler}
options={paymentOptions}
/>
<FormControl fullWidth>
<InputLabel id="payment-type-label">Способ оплаты</InputLabel>
<Select
data-testid="payment-type-select"
defaultValue="none"
disabled={disabled}
inputProps={{ 'data-testid': 'payment-type-select-input' }}
labelId="payment-type-label"
name="paymentMethod"
onChange={onChangePaymentHandler}
size="small"
>
{paymentOptions}
</Select>
</FormControl>
{paymentType === 'BANK_CARD' && renderCardSelect()}
{paymentType === 'CASH' && renderCashSelect()}
<button disabled={disabled} type="submit">Добавить</button>
<Button
data-testid={DataTestId.ADD_EXPENSE_ITEM_SUBMIT_BUTTON}
disabled={disabled}
size="small"
type="submit"
variant="contained"
>
Добавить
</Button>
</form>
);
};

View File

@ -5,6 +5,10 @@ import type {
RefObject,
} from 'react';
import { Button, Typography } from '@mui/material';
import { DataTestId } from '@/shared/constants';
import type { ExpenseListItem } from '../../types';
export type DeleteExpenseItemFormProps = BaseFormProps & {
@ -30,10 +34,27 @@ const DeleteExpenseItemForm: FC<DeleteExpenseItemFormProps> = (props) => {
};
return (
<form onSubmit={onFormSubmitHandler} ref={ref} {...restProps}>
<h2>Удалить элемент ?</h2>
<form
data-testid={DataTestId.DELETE_EXPENSE_ITEM_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<Typography variant="h6">
Удалить элемент ?
</Typography>
<button disabled={disabled} type="submit">Удалить</button>
<Button
color="error"
data-testid={DataTestId.DELETE_EXPENSE_ITEM_SUBMIT_BUTTON}
disabled={disabled}
fullWidth
sx={{ mt: 2 }}
type="submit"
variant="contained"
>
Удалить
</Button>
</form>
);
};

View File

@ -5,7 +5,11 @@ import type {
RefObject,
} from 'react';
import { Input } from '@/shared/ui/Input';
import { Button, TextField, Typography } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DataTestId } from '@/shared/constants';
import { getUTCDate } from '@/shared/utils';
import type { ExpenseListItem } from '../../types';
@ -53,7 +57,7 @@ const EditExpenseItemForm: FC<EditExpenseItemFormProps> = (props) => {
amount: Number(amount),
count: Number(count),
currency: 'RUB',
date: new Date(date).toISOString(),
date: getUTCDate(date),
description,
title,
});
@ -63,52 +67,67 @@ const EditExpenseItemForm: FC<EditExpenseItemFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.EDIT_EXPENSE_ITEM_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...formProps}
>
<h2>Добавить список расходов</h2>
<Typography variant="h6">
Добавить список расходов
</Typography>
<Input
<TextField
defaultValue={item.title}
disabled={disabled}
label="Название"
name="title"
required
size="small"
/>
<Input
<TextField
defaultValue={item.description ?? ''}
disabled={disabled}
label="Описание"
name="description"
size="small"
/>
<Input
defaultValue={new Date(item.date).toISOString().split('T')[0]}
<DatePicker
defaultValue={new Date(item.date)}
disabled={disabled}
label="Дата"
name="date"
type="date"
slotProps={{ textField: { required: true, size: 'small' } }}
/>
<Input
<TextField
defaultValue={item.amount}
disabled={disabled}
inputMode="numeric"
label="Сумма"
name="amount"
step="0.01"
type="number"
required
size="small"
/>
<Input
<TextField
defaultValue={item.count ?? 1}
disabled={disabled}
label="Количество"
name="count"
size="small"
type="number"
/>
<button disabled={disabled} type="submit">Сохранить</button>
<Button
data-testid={DataTestId.EDIT_EXPENSE_ITEM_SUBMIT_BUTTON}
disabled={disabled}
type="submit"
variant="contained"
>
Сохранить
</Button>
</form>
);
};

View File

@ -10,10 +10,11 @@ export { useExpensesList } from './hooks/useExpensesList';
export type { ExpenseList } from './types';
export type { AddExpenseListFormValues } from './ui/AddExpensesListForm/ui/AddExpensesListForm.ui';
export type { AddExpenseListFormProps, AddExpenseListFormValues } from './ui/AddExpensesListForm/ui/AddExpensesListForm.ui';
export { default as AddExpensesListForm } from './ui/AddExpensesListForm/ui/AddExpensesListForm.ui';
export type { DeleteExpenseListFormProps } from './ui/DeleteExpensesListForm/ui/DeleteExpensesListForm.ui';
export { default as DeleteExpensesListForm } from './ui/DeleteExpensesListForm/ui/DeleteExpensesListForm.ui';
export type { EditExpenseListFormValues } from './ui/EditExpensesListForm/ui/EditExpensesListForm.ui';
export type { EditExpenseListFormValues, EditExpensesListFormProps } from './ui/EditExpensesListForm/ui/EditExpensesListForm.ui';
export { default as EditExpensesListForm } from './ui/EditExpensesListForm/ui/EditExpensesListForm.ui';

View File

@ -5,7 +5,9 @@ import type {
RefObject,
} from 'react';
import { Input } from '@/shared/ui/Input';
import { Button, TextField, Typography } from '@mui/material';
import { DataTestId } from '@/shared/constants';
import classes from './AddExpenseListForm.module.css';
@ -46,15 +48,32 @@ const AddExpensesListForm: FC<AddExpenseListFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.ADD_EXPENSES_LIST_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<h2>Добавить список расходов</h2>
<Typography variant="h6">
Добавить список расходов
</Typography>
<Input disabled={disabled} label="Название" name="title" />
<TextField
disabled={disabled}
label="Название"
name="title"
required
size="small"
/>
<button disabled={disabled} type="submit">Добавить</button>
<Button
data-testid={DataTestId.ADD_EXPENSES_LIST_SUBMIT_BUTTON}
disabled={disabled}
size="small"
type="submit"
variant="contained"
>
Добавить
</Button>
</form>
);
};

View File

@ -5,8 +5,12 @@ import type {
RefObject,
} from 'react';
import { Button, Typography } from '@mui/material';
import type { ExpenseList } from '@/entity/expenses/list';
import { DataTestId } from '@/shared/constants';
export type DeleteExpenseListFormProps = BaseFormProps & {
disabled?: boolean;
list: ExpenseList;
@ -31,10 +35,17 @@ const DeleteExpensesListForm: FC<DeleteExpenseListFormProps> = (props) => {
};
return (
<form onSubmit={onFormSubmitHandler} ref={ref} {...restProps}>
<h2>Удалить список расходов</h2>
<form
data-testid={DataTestId.DELETE_EXPENSES_LIST_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<Typography variant="h6">
Удалить список расходов
</Typography>
<p>
<Typography sx={{ mt: 2 }} variant="body2">
Вы действительно хотите удалить список расходов
{' '}
@ -44,12 +55,12 @@ const DeleteExpensesListForm: FC<DeleteExpenseListFormProps> = (props) => {
{' '}
?
</p>
</Typography>
{
list.items && list.items.length > 0
? (
<p>
<Typography sx={{ mt: 1 }} variant="body2">
В нем содержится
{' '}
@ -59,12 +70,23 @@ const DeleteExpensesListForm: FC<DeleteExpenseListFormProps> = (props) => {
{' '}
расходов
</p>
</Typography>
)
: null
}
<button disabled={disabled} type="submit">Удалить</button>
<Button
color="error"
data-testid={DataTestId.DELETE_EXPENSES_LIST_SUBMIT_BUTTON}
disabled={disabled}
fullWidth
size="small"
sx={{ mt: 2 }}
type="submit"
variant="contained"
>
Удалить
</Button>
</form>
);
};

View File

@ -5,9 +5,11 @@ import type {
RefObject,
} from 'react';
import { Button, TextField, Typography } from '@mui/material';
import type { ExpenseList } from '@/entity/expenses/list';
import { Input } from '@/shared/ui/Input';
import { DataTestId } from '@/shared/constants';
import classes from './EditExpenseListForm.module.css';
@ -48,20 +50,32 @@ const EditExpensesListForm: FC<EditExpensesListFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.EDIT_EXPENSES_LIST_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<h2>Редактировать список расходов</h2>
<Typography variant="h6">
Редактировать список расходов
</Typography>
<Input
<TextField
defaultValue={list.title}
disabled={disabled}
label="Название"
name="title"
required
/>
<button disabled={disabled} type="submit">Сохранить</button>
<Button
data-testid={DataTestId.EDIT_EXPENSES_LIST_SUBMIT_BUTTON}
disabled={disabled}
size="small"
type="submit"
variant="contained"
>
Сохранить
</Button>
</form>
);
};

View File

@ -9,9 +9,11 @@ export { useEditIncomeItem } from './hooks/useEditIncomeItem';
export type { IncomeListItem } from './types';
export type { AddIncomeItemFormValues } from './ui/AddIncomeItemForm/AddIncomeItemForm.ui';
export type { AddIncomeItemFormProps } from './ui/AddIncomeItemForm/AddIncomeItemForm.ui';
export { default as AddIncomeItemForm } from './ui/AddIncomeItemForm/AddIncomeItemForm.ui';
export type { DeleteIncomeItemFormProps } from './ui/DeleteIncomeItemForm/DeleteIncomeItemForm.ui';
export { default as DeleteIncomeItemForm } from './ui/DeleteIncomeItemForm/DeleteIncomeItemForm.ui';
export type { EditIncomeItemFormValues } from './ui/EditIncomeItemForm/EditIncomeItemForm.ui';
export type { EditIncomeItemFormProps, EditIncomeItemFormValues } from './ui/EditIncomeItemForm/EditIncomeItemForm.ui';
export { default as EditIncomeItemForm } from './ui/EditIncomeItemForm/EditIncomeItemForm.ui';

View File

@ -5,7 +5,11 @@ import type {
RefObject,
} from 'react';
import { Input } from '@/shared/ui/Input';
import { Button, TextField, Typography } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DataTestId } from '@/shared/constants';
import { getUTCDate } from '@/shared/utils';
import classes from './AddIncomeItemForm.module.css';
@ -47,7 +51,7 @@ const AddIncomeItemForm: FC<AddIncomeItemFormProps> = (props) => {
onSubmit?.({
amount: Number(amount),
currency: 'RUB',
date: new Date(date).toISOString(),
date: getUTCDate(date),
description,
title,
});
@ -57,43 +61,57 @@ const AddIncomeItemForm: FC<AddIncomeItemFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.ADD_INCOME_ITEM_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...formProps}
>
<h2>Добавить список доходов</h2>
<Typography variant="h6">
Добавить список доходов
</Typography>
<Input
<TextField
disabled={disabled}
label="Название"
name="title"
required
size="small"
/>
<Input
<TextField
disabled={disabled}
label="Описание"
name="description"
size="small"
/>
<Input
<DatePicker
disabled={disabled}
disableFuture
format="dd.MM.yyyy"
label="Дата"
name="date"
required
type="date"
slotProps={{ textField: { required: true, size: 'small' } }}
/>
<Input
<TextField
disabled={disabled}
inputMode="numeric"
label="Сумма"
name="amount"
required
step="0.01"
size="small"
type="number"
/>
<button disabled={disabled} type="submit">Добавить</button>
<Button
data-testid={DataTestId.ADD_INCOME_ITEM_SUBMIT_BUTTON}
disabled={disabled}
type="submit"
variant="contained"
>
Добавить
</Button>
</form>
);
};

View File

@ -5,6 +5,10 @@ import type {
RefObject,
} from 'react';
import { Button, Typography } from '@mui/material';
import { DataTestId } from '@/shared/constants';
import type { IncomeListItem } from '../../types';
export type DeleteIncomeItemFormProps = BaseFormProps & {
@ -30,10 +34,25 @@ const DeleteIncomeItemForm: FC<DeleteIncomeItemFormProps> = (props) => {
};
return (
<form onSubmit={onFormSubmitHandler} ref={ref} {...restProps}>
<h2>Удалить элемент ?</h2>
<form
data-testid={DataTestId.DELETE_INCOME_ITEM_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<Typography variant="h6">
Удалить элемент ?
</Typography>
<button disabled={disabled} type="submit">Удалить</button>
<Button
color="error"
data-testid={DataTestId.DELETE_INCOME_ITEM_SUBMIT_BUTTON}
disabled={disabled}
type="submit"
variant="contained"
>
Удалить
</Button>
</form>
);
};

View File

@ -5,7 +5,11 @@ import type {
RefObject,
} from 'react';
import { Input } from '@/shared/ui/Input';
import { Button, TextField, Typography } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DataTestId } from '@/shared/constants';
import { getUTCDate } from '@/shared/utils';
import type { IncomeListItem } from '../../types';
@ -50,7 +54,7 @@ const EditIncomeItemForm: FC<EditIncomeItemFormProps> = (props) => {
await onSubmit?.({
amount: Number(amount),
currency: 'RUB',
date: new Date(date).toISOString(),
date: getUTCDate(date),
description,
title,
});
@ -60,44 +64,58 @@ const EditIncomeItemForm: FC<EditIncomeItemFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.EDIT_INCOME_ITEM_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...formProps}
>
<h2>Изменить доход</h2>
<Typography variant="h6">
Изменить доход
</Typography>
<Input
<TextField
defaultValue={item.title}
disabled={disabled}
label="Название"
name="title"
required
size="small"
/>
<Input
<TextField
defaultValue={item.description ?? ''}
disabled={disabled}
label="Описание"
name="description"
size="small"
/>
<Input
defaultValue={new Date(item.date).toISOString().split('T')[0]}
<DatePicker
defaultValue={new Date(item.date)}
disabled={disabled}
label="Дата"
name="date"
type="date"
slotProps={{ textField: { required: true, size: 'small' } }}
/>
<Input
<TextField
defaultValue={item.amount}
disabled={disabled}
inputMode="numeric"
label="Сумма"
name="amount"
step="0.01"
size="small"
type="number"
/>
<button disabled={disabled} type="submit">Сохранить</button>
<Button
data-testid={DataTestId.EDIT_INCOME_ITEM_SUBMIT_BUTTON}
disabled={disabled}
type="submit"
variant="contained"
>
Сохранить
</Button>
</form>
);
};

View File

@ -9,7 +9,7 @@ export const useAddIncomesList = () => {
return useMutation({
mutationFn: addIncomeList,
mutationKey: [QueryKeys.ExpenseList],
mutationKey: [QueryKeys.IncomesList],
onSuccess: async () => {
await queryClient.invalidateQueries({ queryKey: [QueryKeys.IncomesList] });
},

View File

@ -10,10 +10,11 @@ export { useIncomesList } from './hooks/useIncomesList';
export type { IncomeList } from './types';
export type { AddIncomeListFormValues } from './ui/AddIncomeListForm/ui/AddIncomeListForm.ui';
export type { AddIncomeListFormProps, AddIncomeListFormValues } from './ui/AddIncomeListForm/ui/AddIncomeListForm.ui';
export { default as AddIncomeListForm } from './ui/AddIncomeListForm/ui/AddIncomeListForm.ui';
export type { DeleteIncomeListFormProps } from './ui/DeleteIncomeListForm/ui/DeleteIncomeListForm.ui';
export { default as DeleteIncomeListForm } from './ui/DeleteIncomeListForm/ui/DeleteIncomeListForm.ui';
export type { EditIncomeListFormValues } from './ui/EditIncomeListForm/ui/EditIncomeListForm.ui';
export type { EditIncomeListFormProps, EditIncomeListFormValues } from './ui/EditIncomeListForm/ui/EditIncomeListForm.ui';
export { default as EditIncomeListForm } from './ui/EditIncomeListForm/ui/EditIncomeListForm.ui';

View File

@ -5,7 +5,9 @@ import type {
RefObject,
} from 'react';
import { Input } from '@/shared/ui/Input';
import { Button, TextField, Typography } from '@mui/material';
import { DataTestId } from '@/shared/constants';
import classes from './AddIncomeListForm.module.css';
@ -46,15 +48,31 @@ const AddIncomeListForm: FC<AddIncomeListFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.ADD_INCOME_LIST_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<h2>Добавить список доходов</h2>
<Typography variant="h6">
Добавить список доходов
</Typography>
<Input disabled={disabled} label="Название" name="title" />
<TextField
disabled={disabled}
label="Название"
name="title"
required
size="small"
/>
<button disabled={disabled} type="submit">Добавить</button>
<Button
data-testid={DataTestId.ADD_INCOME_LIST_SUBMIT_BUTTON}
disabled={disabled}
type="submit"
variant="contained"
>
Добавить
</Button>
</form>
);
};

View File

@ -5,6 +5,10 @@ import type {
RefObject,
} from 'react';
import { Button, Typography } from '@mui/material';
import { DataTestId } from '@/shared/constants';
import type { IncomeList } from '../../../types';
export type DeleteIncomeListFormProps = BaseFormProps & {
@ -31,10 +35,17 @@ const DeleteIncomeListForm: FC<DeleteIncomeListFormProps> = (props) => {
};
return (
<form onSubmit={onFormSubmitHandler} ref={ref} {...restProps}>
<h2>Удалить список доходов</h2>
<form
data-testid={DataTestId.DELETE_INCOME_LIST_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<Typography variant="h6">
Удалить список доходов
</Typography>
<p>
<Typography sx={{ mt: 2 }} variant="body1">
Вы действительно хотите удалить список доходов
{' '}
@ -44,12 +55,12 @@ const DeleteIncomeListForm: FC<DeleteIncomeListFormProps> = (props) => {
{' '}
?
</p>
</Typography>
{
list.items && list.items.length > 0
? (
<p>
<Typography sx={{ mt: 1 }} variant="body1">
В нем содержится
{' '}
@ -59,12 +70,22 @@ const DeleteIncomeListForm: FC<DeleteIncomeListFormProps> = (props) => {
{' '}
доходов
</p>
</Typography>
)
: null
}
<button disabled={disabled} type="submit">Удалить</button>
<Button
color="error"
data-testid={DataTestId.DELETE_INCOME_LIST_SUBMIT_BUTTON}
disabled={disabled}
fullWidth
sx={{ mt: 2 }}
type="submit"
variant="contained"
>
Удалить
</Button>
</form>
);
};

View File

@ -5,13 +5,15 @@ import type {
RefObject,
} from 'react';
import { Input } from '@/shared/ui/Input';
import { Button, TextField, Typography } from '@mui/material';
import { DataTestId } from '@/shared/constants';
import type { IncomeList } from '../../../types';
import classes from './EditIncomeListForm.module.css';
export type EditExpensesListFormProps = BaseFormProps & {
export type EditIncomeListFormProps = BaseFormProps & {
disabled?: boolean;
list: IncomeList;
onSubmit: (data: EditIncomeListFormValues) => Promise<void> | void;
@ -24,7 +26,7 @@ export type EditIncomeListFormValues = {
type BaseFormProps = Omit<FormHTMLAttributes<HTMLFormElement>, 'onSubmit'>;
const EditExpensesListForm: FC<EditExpensesListFormProps> = (props) => {
const EditIncomeListForm: FC<EditIncomeListFormProps> = (props) => {
const {
disabled,
list,
@ -48,22 +50,34 @@ const EditExpensesListForm: FC<EditExpensesListFormProps> = (props) => {
return (
<form
className={classes.form}
data-testid={DataTestId.EDIT_INCOME_LIST_FORM}
onSubmit={onFormSubmitHandler}
ref={ref}
{...restProps}
>
<h2>Редактировать список доходов</h2>
<Typography variant="h6">
Редактировать список доходов
</Typography>
<Input
<TextField
defaultValue={list.title}
disabled={disabled}
label="Название"
name="title"
required
size="small"
/>
<button disabled={disabled} type="submit">Сохранить</button>
<Button
data-testid={DataTestId.EDIT_INCOME_LIST_SUBMIT_BUTTON}
disabled={disabled}
type="submit"
variant="contained"
>
Сохранить
</Button>
</form>
);
};
export default EditExpensesListForm;
export default EditIncomeListForm;

View File

@ -1,11 +1,15 @@
import type { ButtonHTMLAttributes, FC, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, Ref } from 'react';
import { Button } from '@mui/material';
import { AddBankCardForm } from '@/entity/cards';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useAddBankCardButton } from '../hooks/useAddBankCardButton';
type AddBankCardButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
type AddBankCardButtonProps = ButtonProps & {
ref?: Ref<HTMLButtonElement>;
};
@ -22,14 +26,15 @@ const AddBankCardButton: FC<AddBankCardButtonProps> = (props) => {
return (
<>
<button
<Button
data-testid={DataTestId.ADD_BANK_CARD_BUTTON}
onClick={onClickHandler}
ref={ref}
type="button"
variant="contained"
{...restProps}
>
Добавить
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<AddBankCardForm disabled={isPending} onSubmit={onFormSubmitHandler} />

View File

@ -1,13 +1,17 @@
import type { ButtonHTMLAttributes, FC, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, Ref } from 'react';
import { Button } from '@mui/material';
import type { BankCard } from '@/entity/cards';
import { DeleteBankCardForm } from '@/entity/cards';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useDeleteBankCardButton } from '../hooks/useDeleteBankCardButton';
export type DeleteBankCardButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
export type DeleteBankCardButtonProps = ButtonProps & {
bankCard: BankCard;
ref?: Ref<HTMLButtonElement>;
};
@ -30,9 +34,16 @@ const DeleteBankCardButton: FC<DeleteBankCardButtonProps> = (props) => {
return (
<>
<button onClick={onClickHandler} type="button" {...restProps}>
<Button
color="error"
data-testid={DataTestId.DELETE_BANK_CARD_BUTTON}
onClick={onClickHandler}
ref={ref}
size="small"
{...restProps}
>
Удалить
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<DeleteBankCardForm

View File

@ -1,13 +1,17 @@
import type { ButtonHTMLAttributes, FC, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, Ref } from 'react';
import { Button } from '@mui/material';
import type { BankCard } from '@/entity/cards';
import { EditBankCardForm } from '@/entity/cards';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useEditBankCardButton } from '../hooks/useEditBankCardButton';
export type EditBankCardButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
export type EditBankCardButtonProps = ButtonProps & {
bankCard: BankCard;
ref?: Ref<HTMLButtonElement>;
};
@ -29,9 +33,15 @@ const EditBankCardButton: FC<EditBankCardButtonProps> = (props) => {
return (
<>
<button onClick={onClickHandler} type="button" {...restProps}>
<Button
data-testid={DataTestId.EDIT_BANK_CARD_BUTTON}
onClick={onClickHandler}
ref={ref}
size="small"
{...restProps}
>
Редактировать
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<EditBankCardForm

View File

@ -1,11 +1,15 @@
import type { ButtonHTMLAttributes, FC, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, Ref } from 'react';
import { Button } from '@mui/material';
import { AddCashForm } from '@/entity/cash';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useAddCashButton } from '../hooks/useAddCashButton';
type AddCashButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
type AddCashButtonProps = ButtonProps & {
ref?: Ref<HTMLButtonElement>;
};
@ -22,14 +26,15 @@ const AddCashButton: FC<AddCashButtonProps> = (props) => {
return (
<>
<button
<Button
data-testid={DataTestId.ADD_CASH_BUTTON}
onClick={onClickHandler}
ref={ref}
type="button"
variant="contained"
{...restProps}
>
Добавить
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<AddCashForm disabled={isPending} onSubmit={onFormSubmitHandler} />

View File

@ -1,13 +1,17 @@
import type { ButtonHTMLAttributes, FC, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, Ref } from 'react';
import { Button } from '@mui/material';
import type { CashItem } from '@/entity/cash';
import { DeleteCashForm } from '@/entity/cash';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useDeleteCashButton } from '../hooks/useDeleteCashButton';
export type DeleteCashButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
export type DeleteCashButtonProps = ButtonProps & {
cash: CashItem;
ref?: Ref<HTMLButtonElement>;
};
@ -30,9 +34,16 @@ const DeleteCashButton: FC<DeleteCashButtonProps> = (props) => {
return (
<>
<button onClick={onClickHandler} type="button" {...restProps}>
<Button
color="error"
data-testid={DataTestId.DELETE_CASH_BUTTON}
onClick={onClickHandler}
ref={ref}
size="small"
{...restProps}
>
Удалить
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<DeleteCashForm

View File

@ -1,13 +1,17 @@
import type { ButtonHTMLAttributes, FC, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, Ref } from 'react';
import { Button } from '@mui/material';
import type { CashItem } from '@/entity/cash';
import { EditCashForm } from '@/entity/cash';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useEditCashButton } from '../hooks/useEditCashButton';
export type EditCashButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
export type EditCashButtonProps = ButtonProps & {
cash: CashItem;
ref?: Ref<HTMLButtonElement>;
};
@ -29,9 +33,15 @@ const EditCashButton: FC<EditCashButtonProps> = (props) => {
return (
<>
<button onClick={onClickHandler} type="button" {...restProps}>
<Button
data-testid={DataTestId.EDIT_CASH_BUTTON}
onClick={onClickHandler}
ref={ref}
size="small"
{...restProps}
>
Редактировать
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<EditCashForm

View File

@ -1,19 +1,21 @@
import type { ButtonHTMLAttributes, FC, RefObject } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, RefObject } from 'react';
import { Button } from '@mui/material';
import type { ExpenseList } from '@/entity/expenses/list';
import { AddExpenseItemForm } from '@/entity/expenses/item';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useAddExpenseItemButton } from '../hooks/useAddExpenseItemButton';
type AddExpenseItemButtonProps = BaseButtonProps & {
type AddExpenseItemButtonProps = ButtonProps & {
listId: ExpenseList['id'];
ref?: RefObject<HTMLButtonElement>;
};
type BaseButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
const AddExpenseItemButton: FC<AddExpenseItemButtonProps> = (props) => {
const {
listId,
@ -32,14 +34,15 @@ const AddExpenseItemButton: FC<AddExpenseItemButtonProps> = (props) => {
return (
<>
<button
<Button
data-testid={DataTestId.ADD_EXPENSE_ITEM_BUTTON}
onClick={onClickHandler}
ref={ref}
type="button"
variant="contained"
{...buttonProps}
>
Добавить элемент
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<AddExpenseItemForm disabled={isPending} onSubmit={onFormSubmitHandler} />

View File

@ -1,15 +1,17 @@
import type { ButtonHTMLAttributes, FC, RefObject } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, RefObject } from 'react';
import { Button } from '@mui/material';
import type { ExpenseListItem } from '@/entity/expenses/item';
import { DeleteExpenseItemForm } from '@/entity/expenses/item';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useDeleteExpenseItemButton } from '../hooks/useDeleteExpenseItemButton';
type BaseButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
type DeleteExpenseItemButtonProps = BaseButtonProps & {
type DeleteExpenseItemButtonProps = ButtonProps & {
item: ExpenseListItem;
ref?: RefObject<HTMLButtonElement>;
};
@ -30,14 +32,16 @@ const DeleteExpenseItemButton: FC<DeleteExpenseItemButtonProps> = (props) => {
return (
<>
<button
<Button
color="error"
data-testid={DataTestId.DELETE_EXPENSE_ITEM_BUTTON}
onClick={onClickHandler}
ref={ref}
type="button"
size="small"
{...restProps}
>
Удалить
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<DeleteExpenseItemForm disabled={isPending} item={item} onSubmit={onFormSubmitHandler} />

View File

@ -1,15 +1,17 @@
import type { ButtonHTMLAttributes, FC, RefObject } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, RefObject } from 'react';
import { Button } from '@mui/material';
import type { ExpenseListItem } from '@/entity/expenses/item';
import { EditExpenseItemForm } from '@/entity/expenses/item';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useEditExpenseItemButton } from '../hooks/useEditExpenseItemButton';
type BaseButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
type EditExpenseItemButtonProps = BaseButtonProps & {
type EditExpenseItemButtonProps = ButtonProps & {
item: ExpenseListItem;
ref?: RefObject<HTMLButtonElement>;
};
@ -32,15 +34,16 @@ const EditExpenseItemButton: FC<EditExpenseItemButtonProps> = (props) => {
return (
<>
<button
<Button
data-testid={DataTestId.EDIT_EXPENSE_ITEM_BUTTON}
disabled={isPending}
onClick={onClickHandler}
ref={ref}
type="button"
size="small"
{...restProps}
>
Редактировать
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<EditExpenseItemForm disabled={isPending} item={item} onSubmit={onFormSubmitHandler} />

View File

@ -1,11 +1,15 @@
import type { ButtonHTMLAttributes, FC, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, Ref } from 'react';
import { Button } from '@mui/material';
import { AddExpensesListForm } from '@/entity/expenses/list';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useAddExpensesListButton } from '../hooks/useAddExpensesListButton';
type AddExpensesListButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
type AddExpensesListButtonProps = ButtonProps & {
ref?: Ref<HTMLButtonElement>;
};
@ -22,9 +26,14 @@ const AddExpensesListButton: FC<AddExpensesListButtonProps> = (props) => {
return (
<>
<button onClick={onClickHandler} type="button" {...restProps}>
<Button
data-testid={DataTestId.ADD_EXPENSES_LIST_BUTTON}
onClick={onClickHandler}
variant="contained"
{...restProps}
>
Добавить
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<AddExpensesListForm disabled={isPending} onSubmit={onFormSubmitHandler} />

View File

@ -1,13 +1,18 @@
import type { ButtonHTMLAttributes, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { Ref } from 'react';
import DeleteIcon from '@mui/icons-material/Delete';
import { Button } from '@mui/material';
import type { ExpenseList } from '@/entity/expenses/list';
import { DeleteExpensesListForm } from '@/entity/expenses/list';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useDeleteExpensesListButton } from '../hooks/useDeleteExpensesListButton';
type DeleteExpensesListButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
type DeleteExpensesListButtonProps = ButtonProps & {
list: ExpenseList;
ref?: Ref<HTMLButtonElement>;
};
@ -25,9 +30,16 @@ const DeleteExpensesListButton = (props: DeleteExpensesListButtonProps) => {
return (
<>
<button onClick={onClickHandler} type="button" {...restProps}>
<Button
color="error"
data-testid={DataTestId.DELETE_EXPENSES_LIST_BUTTON}
onClick={onClickHandler}
size="small"
{...restProps}
>
<DeleteIcon fontSize="small" />
Удалить
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<DeleteExpensesListForm

View File

@ -1,13 +1,18 @@
import type { ButtonHTMLAttributes, FC, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, Ref } from 'react';
import EditIcon from '@mui/icons-material/Edit';
import { Button } from '@mui/material';
import type { ExpenseList } from '@/entity/expenses/list';
import { EditExpensesListForm } from '@/entity/expenses/list';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useEditExpensesListButton } from '../hooks/useEditExpensesListButton';
type EditExpensesListButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
type EditExpensesListButtonProps = ButtonProps & {
list: ExpenseList;
ref?: Ref<HTMLButtonElement>;
};
@ -25,9 +30,15 @@ const EditExpensesListButton: FC<EditExpensesListButtonProps> = (props) => {
return (
<>
<button onClick={onClickHandler} type="button" {...restProps}>
<Button
data-testid={DataTestId.EDIT_EXPENSES_LIST_BUTTON}
onClick={onClickHandler}
size="small"
{...restProps}
>
<EditIcon fontSize="small" />
Редактировать
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<EditExpensesListForm disabled={isPending} list={list} onSubmit={onFormSubmitHandler} />

View File

@ -1,19 +1,21 @@
import type { ButtonHTMLAttributes, FC, RefObject } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, RefObject } from 'react';
import { Button } from '@mui/material';
import type { IncomeList } from '@/entity/incomes/list';
import { AddIncomeItemForm } from '@/entity/incomes/item';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useAddIncomeItemButton } from '../hooks/useAddIncomeItemButton';
type AddIncomeItemButtonProps = BaseButtonProps & {
type AddIncomeItemButtonProps = ButtonProps & {
listId: IncomeList['id'];
ref?: RefObject<HTMLButtonElement>;
};
type BaseButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
const AddIncomeItemButton: FC<AddIncomeItemButtonProps> = (props) => {
const {
listId,
@ -32,14 +34,15 @@ const AddIncomeItemButton: FC<AddIncomeItemButtonProps> = (props) => {
return (
<>
<button
<Button
data-testid={DataTestId.ADD_INCOME_ITEM_BUTTON}
onClick={onClickHandler}
ref={ref}
type="button"
variant="contained"
{...buttonProps}
>
Добавить элемент
</button>
Добавить
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<AddIncomeItemForm disabled={isPending} onSubmit={onFormSubmitHandler} />

View File

@ -1,15 +1,17 @@
import type { ButtonHTMLAttributes, FC, RefObject } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, RefObject } from 'react';
import { Button } from '@mui/material';
import type { IncomeListItem } from '@/entity/incomes/item';
import { DeleteIncomeItemForm } from '@/entity/incomes/item';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useDeleteIncomeItemButton } from '../hooks/useDeleteIncomeItemButton';
type BaseButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
type DeleteIncomeItemButtonProps = BaseButtonProps & {
type DeleteIncomeItemButtonProps = ButtonProps & {
item: IncomeListItem;
ref?: RefObject<HTMLButtonElement>;
};
@ -30,14 +32,16 @@ const DeleteIncomeItemButton: FC<DeleteIncomeItemButtonProps> = (props) => {
return (
<>
<button
<Button
color="error"
data-testid={DataTestId.DELETE_INCOME_ITEM_BUTTON}
onClick={onClickHandler}
ref={ref}
type="button"
size="small"
{...restProps}
>
Удалить
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<DeleteIncomeItemForm disabled={isPending} item={item} onSubmit={onFormSubmitHandler} />

View File

@ -1,15 +1,17 @@
import type { ButtonHTMLAttributes, FC, RefObject } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, RefObject } from 'react';
import { Button } from '@mui/material';
import type { IncomeListItem } from '@/entity/incomes/item';
import { EditIncomeItemForm } from '@/entity/incomes/item';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useIncomeItemButton } from '../hooks/useIncomeItemButton';
type BaseButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
type EditIncomeItemButtonProps = BaseButtonProps & {
type EditIncomeItemButtonProps = ButtonProps & {
item: IncomeListItem;
ref?: RefObject<HTMLButtonElement>;
};
@ -32,15 +34,16 @@ const EditIncomeItemButton: FC<EditIncomeItemButtonProps> = (props) => {
return (
<>
<button
<Button
data-testid={DataTestId.EDIT_INCOME_ITEM_BUTTON}
disabled={isPending}
onClick={onClickHandler}
ref={ref}
type="button"
size="small"
{...restProps}
>
Редактировать
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<EditIncomeItemForm disabled={isPending} item={item} onSubmit={onFormSubmitHandler} />

View File

@ -1,11 +1,15 @@
import type { ButtonHTMLAttributes, FC, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, Ref } from 'react';
import { Button } from '@mui/material';
import { AddIncomeListForm } from '@/entity/incomes/list';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useAddIncomeListButton } from '../hooks/useAddIncomeListButton';
type AddIncomeListButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
type AddIncomeListButtonProps = ButtonProps & {
ref?: Ref<HTMLButtonElement>;
};
@ -22,9 +26,14 @@ const AddIncomeListButton: FC<AddIncomeListButtonProps> = (props) => {
return (
<>
<button onClick={onClickHandler} type="button" {...restProps}>
<Button
data-testid={DataTestId.ADD_INCOME_LIST_BUTTON}
onClick={onClickHandler}
variant="contained"
{...restProps}
>
Добавить
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<AddIncomeListForm disabled={isPending} onSubmit={onFormSubmitHandler} />

View File

@ -1,13 +1,17 @@
import type { ButtonHTMLAttributes, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { Ref } from 'react';
import { Button } from '@mui/material';
import type { IncomeList } from '@/entity/incomes/list';
import { DeleteIncomeListForm } from '@/entity/incomes/list';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useIncomeListButton } from '../hooks/useIncomeListButton';
type DeleteIncomeListButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
type DeleteIncomeListButtonProps = ButtonProps & {
list: IncomeList;
ref?: Ref<HTMLButtonElement>;
};
@ -25,9 +29,15 @@ const DeleteIncomeListButton = (props: DeleteIncomeListButtonProps) => {
return (
<>
<button onClick={onClickHandler} type="button" {...restProps}>
<Button
color="error"
data-testid={DataTestId.DELETE_INCOME_LIST_BUTTON}
onClick={onClickHandler}
size="small"
{...restProps}
>
Удалить
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<DeleteIncomeListForm

View File

@ -1,13 +1,17 @@
import type { ButtonHTMLAttributes, FC, Ref } from 'react';
import type { ButtonProps } from '@mui/material';
import type { FC, Ref } from 'react';
import { Button } from '@mui/material';
import type { IncomeList } from '@/entity/incomes/list';
import { EditIncomeListForm } from '@/entity/incomes/list';
import { DataTestId } from '@/shared/constants';
import { Modal } from '@/shared/ui/Modal';
import { useIncomeListButton } from '../hooks/useIncomeListButton';
type EditIncomeListButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
type EditIncomeListButtonProps = ButtonProps & {
list: IncomeList;
ref?: Ref<HTMLButtonElement>;
};
@ -25,9 +29,14 @@ const EditIncomeListButton: FC<EditIncomeListButtonProps> = (props) => {
return (
<>
<button onClick={onClickHandler} type="button" {...restProps}>
<Button
data-testid={DataTestId.EDIT_INCOME_LIST_BUTTON}
onClick={onClickHandler}
size="small"
{...restProps}
>
Редактировать
</button>
</Button>
<Modal onClose={onCloseModalHandler} open={isOpen}>
<EditIncomeListForm disabled={isPending} list={list} onSubmit={onFormSubmitHandler} />

View File

@ -2,6 +2,10 @@ import React from 'react';
import ReactDOM from 'react-dom/client';
import { App } from '@/app/App';
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';
const rootEl = document.getElementById('root');

View File

@ -1,5 +1,7 @@
import { Button, Typography } from '@mui/material';
import { NavLink } from 'react-router';
import { PAGES } from '@/shared/router';
import { LoginForm } from '@/widgets/auth/LoginForm';
import classes from './LoginPage.module.css';
@ -7,12 +9,16 @@ import classes from './LoginPage.module.css';
const LoginPage = () => (
<div className={classes.overlay}>
<div className={classes.contentWrapper}>
<h1>Вход в аккаунт</h1>
<Typography sx={{ mb: 2 }} variant="h4">
Вход в аккаунт
</Typography>
<LoginForm />
<NavLink end to="/register">
Регистрация
<NavLink end to={PAGES.Register}>
<Button size="small" sx={{ mt: 1 }}>
Регистрация
</Button>
</NavLink>
</div>
</div>

View File

@ -1,5 +1,7 @@
import { Button, Typography } from '@mui/material';
import { NavLink } from 'react-router';
import { PAGES } from '@/shared/router';
import { RegisterForm } from '@/widgets/auth/RegisterForm';
import classes from './RegisterPage.module.css';
@ -7,12 +9,16 @@ import classes from './RegisterPage.module.css';
const RegisterPage = () => (
<div className={classes.overlay}>
<div className={classes.contentWrapper}>
<h1>Регистрация аккаунта</h1>
<Typography sx={{ mb: 2 }} variant="h4">
Регистрация аккаунта
</Typography>
<RegisterForm />
<NavLink end to="/login">
Вход
<NavLink end to={PAGES.Login}>
<Button size="small" sx={{ mt: 1 }}>
Вход
</Button>
</NavLink>
</div>
</div>

View File

@ -1,5 +1,7 @@
import type { FC } from 'react';
import { Typography } from '@mui/material';
import { useBankCards } from '@/entity/cards';
import { AddBankCardButton } from '@/features/bank-cards/AddBankCardButton';
import { Spinner } from '@/shared/ui/Spinner';
@ -23,16 +25,14 @@ const BankCardsPage: FC = () => {
return (
<AppLayout>
<div>
<h1>Мои карты</h1>
<Typography variant="h4">
Мои карты
</Typography>
<div>
<AddBankCardButton />
</div>
<AddBankCardButton sx={{ mb: 2, mt: 2 }} />
{renderContent()}
{renderContent()}
</div>
</AppLayout>
);
};

View File

@ -1,5 +1,7 @@
import type { FC } from 'react';
import { Typography } from '@mui/material';
import { useCash } from '@/entity/cash';
import { AddCashButton } from '@/features/cash/AddCashButton';
import { Spinner } from '@/shared/ui/Spinner';
@ -23,16 +25,14 @@ const CashPage: FC = () => {
return (
<AppLayout>
<div>
<h1>Мои наличные</h1>
<Typography variant="h4">
Мои наличные
</Typography>
<div>
<AddCashButton />
</div>
<AddCashButton sx={{ mb: 2, mt: 2 }} />
{renderContent()}
{renderContent()}
</div>
</AppLayout>
);
};

View File

@ -1,3 +1,4 @@
import { Typography } from '@mui/material';
import { useParams } from 'react-router';
import type { ExpensePageParams } from '@/shared/router';
@ -30,14 +31,14 @@ const ExpensePage = () => {
return (
<AppLayout>
<div>
<h1>Списки расходов</h1>
<Typography variant="h4">
Списки расходов
</Typography>
<AddExpenseItemButton listId={id} />
<AddExpenseItemButton listId={id} sx={{ mb: 2, mt: 2 }} />
{renderContent()}
{renderContent()}
</div>
</AppLayout>
);
};

View File

@ -1,3 +1,5 @@
import { Typography } from '@mui/material';
import { useExpensesList } from '@/entity/expenses/list';
import { AddExpensesListButton } from '@/features/expenses/list/AddExpensesListButton';
import { Spinner } from '@/shared/ui/Spinner';
@ -21,16 +23,13 @@ const ExpensesPage = () => {
return (
<AppLayout>
<div>
<h1>Списки расходов</h1>
<Typography variant="h4">
Списки расходов
</Typography>
<div>
<AddExpensesListButton />
</div>
<AddExpensesListButton sx={{ mb: 2, mt: 2 }} />
{renderContent()}
</div>
{renderContent()}
</AppLayout>
);
};

View File

@ -1,10 +1,12 @@
import { Typography } from '@mui/material';
import { AppLayout } from '@/widgets/AppLayout';
const HomePage = () => (
<AppLayout>
<div>
<h1>Home Page</h1>
</div>
<Typography variant="h4">
Домашняя страница
</Typography>
</AppLayout>
);

View File

@ -1,3 +1,4 @@
import { Typography } from '@mui/material';
import { useParams } from 'react-router';
import type { IncomePageParams } from '@/shared/router';
@ -30,14 +31,14 @@ const IncomePage = () => {
return (
<AppLayout>
<div>
<h1>Списки расходов</h1>
<Typography variant="h4">
Списки расходов
</Typography>
<AddIncomeItemButton listId={id} />
<AddIncomeItemButton listId={id} sx={{ mb: 2, mt: 2 }} />
{renderContent()}
{renderContent()}
</div>
</AppLayout>
);
};

View File

@ -1,3 +1,5 @@
import { Typography } from '@mui/material';
import { useIncomesList } from '@/entity/incomes/list';
import { AddIncomeListButton } from '@/features/incomes/list/AddIncomeListButton';
import { Spinner } from '@/shared/ui/Spinner';
@ -21,16 +23,14 @@ const IncomesPage = () => {
return (
<AppLayout>
<div>
<h1>Списки дохода</h1>
<Typography variant="h4">
Списки дохода
</Typography>
<div>
<AddIncomeListButton />
</div>
<AddIncomeListButton sx={{ mb: 2, mt: 2 }} />
{renderContent()}
{renderContent()}
</div>
</AppLayout>
);
};

View File

@ -1 +0,0 @@
export { default as Input } from './ui/Input.ui';

View File

@ -1,4 +0,0 @@
.wrapper {
display: flex;
flex-direction: column;
}

View File

@ -1,24 +0,0 @@
import type { FC, HTMLProps } from 'react';
import classes from './Input.styles.module.css';
type InputProps = HTMLProps<HTMLInputElement> & {
label: string;
};
const Input: FC<InputProps> = (props) => {
const { id, label, ...rest } = props;
return (
<label className={classes.wrapper} htmlFor={id}>
{label}
<input
id={id}
{...rest}
/>
</label>
);
};
export default Input;

View File

@ -1,27 +0,0 @@
.wrapper {
display: flex;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.5);
justify-content: center;
align-items: center;
}
.content {
background-color: white;
z-index: 2;
border-radius: 10px;
position: relative;
padding: 30px;
}
.closeIcon {
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
font-size: 20px;
}

View File

@ -0,0 +1,13 @@
const modalStyle = {
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
left: '50%',
p: 4,
position: 'absolute',
top: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
};
export default modalStyle;

View File

@ -1,28 +1,33 @@
import type { ModalProps as MuiModalProps } from '@mui/material';
import type { FC, ReactNode } from 'react';
import classes from './Modal.module.css';
import { Box, Modal as MuiModal } from '@mui/material';
import Fade from '@mui/material/Fade';
type ModalProps = {
import modalStyle from './Modal.style';
type ModalProps = MuiModalProps & {
children: ReactNode;
onClose: () => void;
open: boolean;
};
const Modal: FC<ModalProps> = (props) => {
const { children, onClose, open } = props;
if (!open) {
return null;
}
const {
children, onClose, open, ...restProps
} = props;
return (
<div className={classes.wrapper} onClick={onClose} role="dialog">
<div className={classes.content} onClick={(e) => { e.stopPropagation(); }}>
<span className={classes.closeIcon} onClick={onClose}>&times;</span>
{children}
</div>
</div>
<MuiModal
closeAfterTransition
onClose={onClose}
open={open}
{...restProps}
>
<Fade in={open}>
<Box sx={modalStyle}>
{children}
</Box>
</Fade>
</MuiModal>
);
};

View File

@ -1 +0,0 @@
export { default as Select } from './ui/Select.ui';

View File

@ -1,4 +0,0 @@
.wrapper {
display: flex;
flex-direction: column;
}

View File

@ -1,45 +0,0 @@
import type { FC, HTMLProps, RefObject } from 'react';
import classes from './Select.module.css';
type Option = {
label: string;
value: string;
};
type SelectProps = HTMLProps<HTMLSelectElement> & {
label: string;
options: Option[];
ref?: RefObject<HTMLSelectElement>;
};
const Select: FC<SelectProps> = (props) => {
const {
id,
label,
options,
ref,
...refProps
} = props;
return (
<label className={classes.wrapper} htmlFor={id}>
{label}
<select
id={id}
ref={ref}
{...refProps}
>
{options.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
</label>
);
};
export default Select;

View File

@ -0,0 +1,13 @@
import { parse } from 'date-fns';
export function getUTCDate(date: string) {
const parsedDate = parse(date, 'dd.MM.yyyy', new Date());
return new Date(
Date.UTC(
parsedDate.getFullYear(),
parsedDate.getMonth(),
parsedDate.getDate(),
),
).toISOString();
}

View File

@ -4,3 +4,5 @@ export const wait = async (time: number) => new Promise((res) => {
export { formatRub } from './formatters/currency';
export { formatDate } from './formatters/date';
export { getUTCDate } from './helpers/getUTCDate';

View File

@ -4,4 +4,5 @@
.content {
flex-grow: 1;
padding: 20px;
}

View File

@ -1,42 +1,70 @@
import { NavLink } from 'react-router';
import type { ReactElement } from 'react';
import AddIcon from '@mui/icons-material/Add';
import CreditCardIcon from '@mui/icons-material/CreditCard';
import CurrencyRubleIcon from '@mui/icons-material/CurrencyRuble';
import HomeIcon from '@mui/icons-material/Home';
import RemoveIcon from '@mui/icons-material/Remove';
import {
List, ListItem, ListItemButton, ListItemIcon, ListItemText,
} from '@mui/material';
import { NavLink, useLocation } from 'react-router';
import { PAGES } from '@/shared/router';
import classes from './SideBar.module.css';
type ListItemLinkProps = {
icon?: ReactElement;
primary: string;
to: string;
};
const ListItemLink = (props: ListItemLinkProps) => {
const { icon, primary, to } = props;
const location = useLocation();
return (
<ListItemButton
component={NavLink}
selected={location.pathname === to}
to={to}
>
{icon
? (
<ListItemIcon>
{icon}
</ListItemIcon>
)
: null}
<ListItemText primary={primary} />
</ListItemButton>
);
};
type Element = {
icon?: ReactElement;
title: string;
to: string;
};
const elements: Element[] = [
{ icon: <HomeIcon />, title: 'Главная', to: PAGES.Home },
{ icon: <AddIcon />, title: 'Доходы', to: PAGES.Incomes },
{ icon: <RemoveIcon />, title: 'Расходы', to: PAGES.Expenses },
{ icon: <CreditCardIcon />, title: 'Карты', to: PAGES.BankCards },
{ icon: <CurrencyRubleIcon />, title: 'Наличные', to: PAGES.Cash },
];
const SideBar = () => (
<div className={classes.wrapper}>
<ul>
<li>
<NavLink to={PAGES.Home}>
Главная
</NavLink>
</li>
<li>
<NavLink to={PAGES.Incomes}>
Доходы
</NavLink>
</li>
<li>
<NavLink to={PAGES.Expenses}>
Расходы
</NavLink>
</li>
<li>
<NavLink to={PAGES.BankCards}>
Карты
</NavLink>
</li>
<li>
<NavLink to={PAGES.Cash}>
Наличные
</NavLink>
</li>
</ul>
<List>
{elements.map(({ icon, title, to }) => (
<ListItem disablePadding key={to}>
<ListItemLink icon={icon} primary={title} to={to} />
</ListItem>
))}
</List>
</div>
);

View File

@ -1,6 +1,6 @@
import type { FC } from 'react';
import { Input } from '@/shared/ui/Input';
import { Button, TextField } from '@mui/material';
import { useLoginForm } from './hooks/useLoginForm';
import classes from './LoginForm.module.css';
@ -10,28 +10,36 @@ const LoginForm: FC = () => {
return (
<form className={classes.form} onSubmit={onSubmitHandler}>
<Input
<TextField
disabled={isPending}
id="email"
inputMode="email"
label="Почта"
name="email"
type="text"
required
size="small"
variant="standard"
/>
<Input
<TextField
disabled={isPending}
id="password"
label="Пароль"
name="password"
required
size="small"
type="password"
variant="standard"
/>
<button
<Button
disabled={isPending}
size="small"
sx={{ mt: 2 }}
type="submit"
variant="contained"
>
Войти
</button>
</Button>
</form>
);
};

View File

@ -1,6 +1,6 @@
import type { FC } from 'react';
import { Input } from '@/shared/ui/Input';
import { Button, TextField } from '@mui/material';
import { useRegisterForm } from './hooks/useRegisterForm';
import classes from './RegisterForm.module.css';
@ -10,25 +10,36 @@ const RegisterForm: FC = () => {
return (
<form className={classes.form} onSubmit={onSubmitHandler}>
<Input
<TextField
disabled={isPending}
id="email"
inputMode="email"
label="Почта"
name="email"
type="text"
required
size="small"
variant="standard"
/>
<Input
<TextField
disabled={isPending}
id="password"
label="Пароль"
name="password"
required
size="small"
type="password"
variant="standard"
/>
<button disabled={isPending} type="submit">
<Button
disabled={isPending}
size="small"
sx={{ mt: 2 }}
type="submit"
variant="contained"
>
Зарегистрироваться
</button>
</Button>
</form>
);
};