Skip to content

Commit

Permalink
Refactored page input dialog to use AppDialog
Browse files Browse the repository at this point in the history
  • Loading branch information
pkirilin committed Oct 28, 2023
1 parent 00be9da commit 898c480
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 180 deletions.
2 changes: 1 addition & 1 deletion src/frontend/src/components/AppDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const AppDialog: FC<AppDialogProps> = ({
sx={theme => ({
padding: `0 ${theme.spacing(3)} ${theme.spacing(2)}`,

'& > :not(:first-child)': {
'& > :not(:first-of-type)': {
marginLeft: theme.spacing(2),
},
})}
Expand Down
4 changes: 3 additions & 1 deletion src/frontend/src/features/__shared__/hooks/useDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ export interface DialogHookResult<TConfirmedData>
show: DialogActionFn;
}

// TODO: make centralized redux modals, remove modal hook
/**
@deprecated
*/
export default function useDialog<TConfirmedData = unknown>(
confirmAction: DialogConfirmActionFn<TConfirmedData>,
): DialogHookResult<TConfirmedData> {
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { create } from 'src/test-utils';
import { PageCreateEdit } from '../../models';
import PageInputDialog from './PageInputDialog';

describe('when initial date is specified', () => {
test('should create new page with that date', async () => {
const submitFn = vi.fn();
const ui = create
.component(
<PageInputDialog
title="Test dialog"
submitText="Create"
isOpened
initialDate={new Date('2023-10-22')}
onSubmit={submitFn}
onClose={vi.fn()}
/>,
)
.please();

render(ui);
const createButton = await screen.findByRole('button', { name: /create/i });
await userEvent.click(createButton);

expect(submitFn).toHaveBeenCalledWith<[PageCreateEdit]>({ date: '2023-10-22' });
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Button } from '@mui/material';
import { FC, useEffect } from 'react';
import { AppDialog, DatePicker } from 'src/components';
import { useInput } from 'src/hooks';
import { formatDate } from 'src/utils';
import { mapToDateInputProps } from 'src/utils/inputMapping';
import { validateDate } from 'src/utils/validation';
import { PageCreateEdit } from '../../models';

type PageInputDialogProps = {
title: string;
isOpened: boolean;
submitText: string;
initialDate: Date;
onClose: () => void;
onSubmit: (page: PageCreateEdit) => void;
};

const PageInputDialog: FC<PageInputDialogProps> = ({
title,
isOpened,
submitText,
initialDate,
onClose,
onSubmit,
}) => {
const dateInput = useInput({
initialValue: initialDate,
errorHelperText: 'Date is required',
validate: validateDate,
mapToInputProps: mapToDateInputProps,
});

const setDate = dateInput.setValue;

useEffect(() => {
if (isOpened && initialDate) {
setDate(initialDate);
}
}, [initialDate, isOpened, setDate]);

const handleSubmitClick = (): void => {
if (dateInput.value) {
onSubmit({
date: formatDate(dateInput.value),
});
}
};

return (
<AppDialog
title={title}
isOpened={isOpened}
onClose={onClose}
content={
<DatePicker
{...dateInput.inputProps}
autoFocus
label="Page date"
placeholder="Select page date"
/>
}
actionSubmit={
<Button
variant="contained"
color="primary"
onClick={handleSubmitClick}
disabled={dateInput.isInvalid || !dateInput.isTouched}
>
{submitText}
</Button>
}
actionCancel={
<Button variant="text" onClick={onClose}>
Cancel
</Button>
}
/>
);
};

export default PageInputDialog;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import PageInputDialog from './PageInputDialog';

export { PageInputDialog };
62 changes: 37 additions & 25 deletions src/frontend/src/features/pages/components/PagesTableRow.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,53 @@
import EditIcon from '@mui/icons-material/Edit';
import { TableRow, TableCell, Checkbox, Tooltip, IconButton, Link } from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import dateFnsFormat from 'date-fns/format';
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { useAppDispatch, useDialog, useAppSelector } from '../../__shared__/hooks';
import { formatDate } from 'src/utils';
import { useAppDispatch, useAppSelector } from '../../__shared__/hooks';
import { PageCreateEdit, PageItem } from '../models';
import { pageSelected } from '../slice';
import { editPage } from '../thunks';
import PageCreateEditDialog from './PageCreateEditDialog';
import { PageInputDialog } from './PageInputDialog';

type PagesTableRowProps = {
page: PageItem;
};

const useStyles = makeStyles(() => ({
pageDateLink: {
// TODO: use theme value after Material 5 migration
fontWeight: 'bold',
},
}));

const PagesTableRow: React.FC<PagesTableRowProps> = ({ page }: PagesTableRowProps) => {
const classes = useStyles();
const pageDate = dateFnsFormat(new Date(page.date), 'dd.MM.yyyy');
const pageDate = new Date(page.date);

const operationStatus = useAppSelector(state => state.pages.operationStatus);

const isPageSelected = useAppSelector(state =>
state.pages.selectedPageIds.some(id => id === page.id),
);

const dispatch = useAppDispatch();

const pageEditDialog = useDialog<PageCreateEdit>(pageInfo => {
const [isDialogOpened, setIsDialogOpened] = useState(false);

useEffect(() => {
if (operationStatus === 'succeeded') {
setIsDialogOpened(false);
}
}, [operationStatus]);

const handleOpenDialog = () => {
setIsDialogOpened(true);
};

const handleCloseDialog = () => {
setIsDialogOpened(false);
};

const handleEditPage = ({ date }: PageCreateEdit) => {
dispatch(
editPage({
id: page.id,
page: pageInfo,
page: { date },
}),
);
});
};

const handleSelectPage = (): void => {
dispatch(
Expand All @@ -49,13 +58,16 @@ const PagesTableRow: React.FC<PagesTableRowProps> = ({ page }: PagesTableRowProp
);
};

const handleEditClick = (): void => {
pageEditDialog.show();
};

return (
<TableRow hover>
<PageCreateEditDialog {...pageEditDialog.binding} page={page} />
<PageInputDialog
title="Edit page"
submitText="Save"
isOpened={isDialogOpened}
initialDate={pageDate}
onClose={handleCloseDialog}
onSubmit={handleEditPage}
/>
<TableCell padding="checkbox">
<Checkbox color="primary" checked={isPageSelected} onChange={handleSelectPage} />
</TableCell>
Expand All @@ -65,17 +77,17 @@ const PagesTableRow: React.FC<PagesTableRowProps> = ({ page }: PagesTableRowProp
to={`/pages/${page.id}`}
variant="body1"
color="primary"
className={classes.pageDateLink}
underline="hover"
fontWeight="bold"
>
{pageDate}
{formatDate(pageDate)}
</Link>
</TableCell>
<TableCell align="right">{page.countCalories}</TableCell>
<TableCell align="right">{page.countNotes}</TableCell>
<TableCell width="30px">
<Tooltip title="Edit page">
<IconButton onClick={handleEditClick} size="large">
<IconButton onClick={handleOpenDialog} size="large">
<EditIcon />
</IconButton>
</Tooltip>
Expand Down
Loading

0 comments on commit 898c480

Please sign in to comment.