Skip to content

Commit

Permalink
feat(skeleton): replace dialog controller component with hook
Browse files Browse the repository at this point in the history
  • Loading branch information
DASPRiD committed Apr 25, 2024
1 parent e030570 commit 9fe4339
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 78 deletions.
48 changes: 0 additions & 48 deletions skeleton/base/src/components/DialogController/DialogController.tsx

This file was deleted.

1 change: 0 additions & 1 deletion skeleton/base/src/components/DialogController/index.ts

This file was deleted.

47 changes: 47 additions & 0 deletions skeleton/base/src/hooks/useDialogController.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { TransitionProps } from "@mui/material/transitions";
import { useCallback, useMemo, useState } from "react";

export type ControlledDialogProps = {
open: boolean;
onClose: () => void;
TransitionProps: TransitionProps;
};

type DialogController = {
open: () => void;
mount: boolean;
dialogProps: ControlledDialogProps;
};

const useDialogController = (): DialogController => {
const [open, setOpen] = useState(false);
const [mounted, setMounted] = useState(false);

const handleOpen = useCallback(() => {
setMounted(true);
setOpen(true);
}, []);

const onClose = useCallback(() => {
setOpen(false);
}, []);

return useMemo(
() => ({
open: handleOpen,
mount: mounted,
dialogProps: {
open,
onClose,
TransitionProps: {
onExited: () => {
setMounted(false);
},
},
},
}),
[open, handleOpen, onClose, mounted],
);
};

export default useDialogController;
10 changes: 5 additions & 5 deletions skeleton/base/src/pages/ArticlesPage/ArticleFormDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { RenderDialogProps } from "@/components/DialogController/index.ts";
import { zodResolver } from "@hookform/resolvers/zod";
import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Stack } from "@mui/material";
import { RhfTextField } from "mui-rhf-integration";
import type { ReactNode } from "react";
import { useEffect } from "react";
import { type DefaultValues, useForm } from "react-hook-form";
import { z } from "zod";
import type { ControlledDialogProps } from "@/hooks/useDialogController.tsx";

const schema = z.object({
title: z.string().trim().min(1),
Expand All @@ -20,10 +20,10 @@ type Props = {
title: string;
defaultValues?: DefaultValues<FieldValues>;
onSubmit: (values: TransformedValues) => Promise<void>;
DialogProps: RenderDialogProps;
dialogProps: ControlledDialogProps;
};

const ArticleFormDialog = ({ title, defaultValues, onSubmit, DialogProps }: Props): ReactNode => {
const ArticleFormDialog = ({ title, defaultValues, onSubmit, dialogProps }: Props): ReactNode => {
const form = useForm<FieldValues, unknown, TransformedValues>({
resolver: zodResolver(schema),
defaultValues,
Expand All @@ -35,7 +35,7 @@ const ArticleFormDialog = ({ title, defaultValues, onSubmit, DialogProps }: Prop

return (
<Dialog
{...DialogProps}
{...dialogProps}
PaperProps={{
component: "form",
onSubmit: form.handleSubmit(onSubmit),
Expand All @@ -52,7 +52,7 @@ const ArticleFormDialog = ({ title, defaultValues, onSubmit, DialogProps }: Prop
</DialogContent>

<DialogActions>
<Button color="secondary" onClick={DialogProps.onClose}>
<Button color="secondary" onClick={dialogProps.onClose}>
Cancel
</Button>
<Button type="submit">Save</Button>
Expand Down
25 changes: 17 additions & 8 deletions skeleton/base/src/pages/ArticlesPage/ArticleListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import ConfirmDialog from "@/components/ConfirmDialog/index.ts";
import DialogController from "@/components/DialogController/index.ts";
import { useDeleteArticleMutation } from "@/mutations/article.ts";
import EditArticleFormDialog from "@/pages/ArticlesPage/EditArticleFormDialog.tsx";
import type { ListArticle } from "@/queries/article.ts";
Expand All @@ -9,6 +8,7 @@ import { bindMenu, bindTrigger, usePopupState } from "material-ui-popup-state/ho
import { useSnackbar } from "notistack";
import type { ReactNode } from "react";
import { useConfirm } from "react-confirm-hook";
import useDialogController from "@/hooks/useDialogController.js";

type Props = {
article: ListArticle;
Expand All @@ -22,6 +22,7 @@ const ArticleListItem = ({ article }: Props): ReactNode => {
const deleteMutation = useDeleteArticleMutation();
const { enqueueSnackbar } = useSnackbar();
const confirm = useConfirm(ConfirmDialog);
const editDialogController = useDialogController();

const handleDelete = () => {
confirm({
Expand All @@ -48,19 +49,27 @@ const ArticleListItem = ({ article }: Props): ReactNode => {
<MoreVertIcon />
</IconButton>
<Menu {...bindMenu(popupState)}>
<DialogController
controller={(props) => <MenuItem {...props}>Edit</MenuItem>}
dialog={(props) => (
<EditArticleFormDialog articleId={article.id} DialogProps={props} />
)}
/>

<MenuItem
onClick={() => {
editDialogController.open();
popupState.close();
}}
>
Edit
</MenuItem>
<MenuItem onClick={handleDelete}>Delete</MenuItem>
</Menu>
</>
}
>
<ListItemText>{article.title}</ListItemText>

{editDialogController.mount && (
<EditArticleFormDialog
articleId={article.id}
dialogProps={editDialogController.dialogProps}
/>
)}
</ListItem>
);
};
Expand Down
18 changes: 14 additions & 4 deletions skeleton/base/src/pages/ArticlesPage/ArticlesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { ReactNode } from "react";
import { useState } from "react";
import ArticleListItem from "./ArticleListItem.tsx";
import CreateArticleFormDialog from "./CreateArticleFormDialog.tsx";
import useDialogController from "@/hooks/useDialogController.js";

type PaginationButtonProps = {
label: string;
Expand Down Expand Up @@ -85,16 +86,25 @@ const ArticleList = (): ReactNode => {
};

const ArticlesPage = (): ReactNode => {
const createDialogController = useDialogController();

return (
<Container>
<Typography variant="h6" gutterBottom>
Articles
</Typography>

<DialogController
controller={(props) => <Button {...props}>Create article</Button>}
dialog={(props) => <CreateArticleFormDialog DialogProps={props} />}
/>
<Button
onClick={() => {
createDialogController.open();
}}
>
Create article
</Button>

{createDialogController.mount && (
<CreateArticleFormDialog dialogProps={createDialogController.props} />
)}

<ArticleList />
</Container>
Expand Down
10 changes: 5 additions & 5 deletions skeleton/base/src/pages/ArticlesPage/CreateArticleFormDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { RenderDialogProps } from "@/components/DialogController/index.ts";
import { useCreateWorldMutation } from "@/mutations/article.ts";
import { useSnackbar } from "notistack";
import type { ReactNode } from "react";
import ArticleFormDialog, { type ArticleFormValues } from "./ArticleFormDialog.tsx";
import type { ControlledDialogProps } from "@/hooks/useDialogController.tsx";

type Props = {
DialogProps: RenderDialogProps;
dialogProps: ControlledDialogProps;
};

const CreateArticleFormDialog = ({ DialogProps }: Props): ReactNode => {
const CreateArticleFormDialog = ({ dialogProps }: Props): ReactNode => {
const { enqueueSnackbar } = useSnackbar();
const createMutation = useCreateWorldMutation();

Expand All @@ -23,14 +23,14 @@ const CreateArticleFormDialog = ({ DialogProps }: Props): ReactNode => {
}

enqueueSnackbar("Article has been created", { variant: "success" });
DialogProps.onClose();
dialogProps.onClose();
};

return (
<ArticleFormDialog
title="Create article"
onSubmit={handleSubmit}
DialogProps={DialogProps}
dialogProps={dialogProps}
/>
);
};
Expand Down
10 changes: 5 additions & 5 deletions skeleton/base/src/pages/ArticlesPage/EditArticleFormDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import type { RenderDialogProps } from "@/components/DialogController/index.ts";
import { useUpdateArticleMutation } from "@/mutations/article.ts";
import { useArticleQuery } from "@/queries/article.ts";
import { Backdrop, CircularProgress } from "@mui/material";
import { useSnackbar } from "notistack";
import { useEffect } from "react";
import type { ReactNode } from "react";
import ArticleFormDialog, { type ArticleFormValues } from "./ArticleFormDialog.tsx";
import type { ControlledDialogProps } from "@/hooks/useDialogController.tsx";

type Props = {
articleId: string;
DialogProps: RenderDialogProps;
dialogProps: ControlledDialogProps;
};

const EditArticleFormDialog = ({ articleId, DialogProps }: Props): ReactNode => {
const EditArticleFormDialog = ({ articleId, dialogProps }: Props): ReactNode => {
const { enqueueSnackbar } = useSnackbar();
const articleQuery = useArticleQuery(articleId);
const updateMutation = useUpdateArticleMutation();
Expand All @@ -29,7 +29,7 @@ const EditArticleFormDialog = ({ articleId, DialogProps }: Props): ReactNode =>
}

enqueueSnackbar("Article has been updated", { variant: "success" });
DialogProps.onClose();
dialogProps.onClose();
};

useEffect(() => {
Expand Down Expand Up @@ -60,7 +60,7 @@ const EditArticleFormDialog = ({ articleId, DialogProps }: Props): ReactNode =>
content: article.content,
}}
onSubmit={handleSubmit}
DialogProps={DialogProps}
DialogProps={dialogProps}
/>
);
};
Expand Down
4 changes: 2 additions & 2 deletions skeleton/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
"@mui/material": "^5.15.10",
"@tanstack/react-query": "^5.20.5",
"caught-object-report-json": "^7.1.7",
"jsonapi-zod-query": "^1.2.3",
"jsonapi-zod-query": "^1.5.0",
"material-ui-popup-state": "^5.0.10",
"mui-rhf-integration": "^3.4.0",
"mui-rhf-integration": "^4.0.3",
"notistack": "^3.0.1",
"react": "^18.2.0",
"react-confirm-hook": "^1.0.4",
Expand Down

0 comments on commit 9fe4339

Please sign in to comment.