Skip to content

Commit 8c6677a

Browse files
committed
feat: add dialogs
1 parent 8e39b80 commit 8c6677a

File tree

4 files changed

+137
-22
lines changed

4 files changed

+137
-22
lines changed

web/src/hooks/alert.tsx

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import {
2+
createContext,
3+
useContext,
4+
useState,
5+
PropsWithChildren,
6+
ReactNode,
7+
useRef
8+
} from "react";
9+
10+
import {
11+
AlertDialog,
12+
AlertDialogBody,
13+
AlertDialogFooter,
14+
AlertDialogHeader,
15+
AlertDialogContent,
16+
AlertDialogOverlay,
17+
useDisclosure,
18+
Button,
19+
ButtonProps,
20+
} from '@chakra-ui/react'
21+
22+
export interface DialogProps {
23+
title?: string | ReactNode;
24+
accept?: {
25+
title?: string;
26+
onClick?: () => void;
27+
options?: ButtonProps
28+
},
29+
decline?: {
30+
title?: string;
31+
onClick?: () => void;
32+
options?: ButtonProps
33+
},
34+
content?: ReactNode;
35+
}
36+
37+
interface DialogContextData {
38+
show: (content: DialogProps) => void;
39+
}
40+
41+
const DialogContext = createContext<DialogContextData>({} as DialogContextData);
42+
43+
export const DialogProvider = ({ children }: PropsWithChildren) => {
44+
const { isOpen, onOpen, onClose } = useDisclosure()
45+
46+
const cancelRef = useRef()
47+
const [dialog, setDialog] = useState<DialogProps | null>(null);
48+
49+
const show = (content: DialogProps) => {
50+
setDialog(content);
51+
onOpen();
52+
}
53+
54+
return (
55+
<DialogContext.Provider value={{ show }}>
56+
{children}
57+
{dialog && (
58+
<AlertDialog
59+
isOpen={isOpen}
60+
leastDestructiveRef={cancelRef as any}
61+
onClose={onClose}
62+
>
63+
<AlertDialogOverlay>
64+
<AlertDialogContent>
65+
{typeof dialog.title === 'string' ? (
66+
<AlertDialogHeader fontSize='lg' fontWeight='bold'>
67+
{dialog.title}
68+
</AlertDialogHeader>
69+
) : dialog.title}
70+
71+
<AlertDialogBody>
72+
{dialog.content}
73+
</AlertDialogBody>
74+
75+
<AlertDialogFooter>
76+
<Button
77+
ref={cancelRef as any}
78+
onClick={() => {
79+
onClose();
80+
dialog?.decline?.onClick && dialog?.decline?.onClick()
81+
}}
82+
{...dialog?.decline?.options}>
83+
{dialog.decline?.title || 'Yes'}
84+
</Button>
85+
<Button
86+
colorScheme='red'
87+
ml={3}
88+
onClick={() => {
89+
onClose()
90+
dialog?.accept?.onClick && dialog?.accept?.onClick()
91+
}}
92+
{...dialog?.accept?.options}>
93+
{dialog.accept?.title || 'No'}
94+
</Button>
95+
</AlertDialogFooter>
96+
</AlertDialogContent>
97+
</AlertDialogOverlay>
98+
</AlertDialog>
99+
)}
100+
</DialogContext.Provider>
101+
);
102+
}
103+
104+
export function useDialog(): DialogContextData {
105+
const context = useContext(DialogContext);
106+
107+
if (!context) {
108+
throw new Error("o useDialog deve ser utilizado dentro de um DialogProvider");
109+
}
110+
111+
return context;
112+
}

web/src/hooks/index.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { ChakraProvider } from "@chakra-ui/react";
2+
import { PropsWithChildren } from "react";
3+
import { DialogProvider } from "./alert";
4+
5+
export const Providers = ({ children }: PropsWithChildren) => (
6+
<ChakraProvider>
7+
<DialogProvider>
8+
{children}
9+
</DialogProvider>
10+
</ChakraProvider>
11+
)

web/src/main.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import { ChakraProvider } from '@chakra-ui/react';
44

55
import { App } from './App';
66
import { BrowserRouter } from 'react-router-dom';
7+
import { Providers } from './hooks';
78

89
const element = document.getElementById('root') as Element;
910
const root = createRoot(element);
1011

1112
root.render(
1213
<BrowserRouter>
13-
<ChakraProvider>
14+
<Providers>
1415
<App />
15-
</ChakraProvider>
16+
</Providers>
1617
</BrowserRouter>
1718
);

web/src/pages/users/index.tsx

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ import { Column } from "../../components/table/types";
2323

2424
import { Roles } from "./components/roles";
2525
import { Status } from "./components/status";
26+
import { useDialog } from "../../hooks/alert";
2627

2728
export const Users = () => {
2829

29-
const { isOpen, onOpen, onClose } = useDisclosure()
30+
const { show } = useDialog();
3031

3132
const [{ page, size, totalPages }, setPagination] = useState<PaginationProps>({
3233
page: 0,
@@ -101,29 +102,19 @@ export const Users = () => {
101102
edit: { options: { disabled: loading } },
102103
remove: {
103104
options: { disabled: loading },
104-
onClick: onOpen
105+
onClick: (row) => show({
106+
title: 'Delete user',
107+
content: 'Are you sure? You can\'t undo this action afterwards.',
108+
accept: {
109+
title: 'Delete',
110+
onClick: () => console.log('remove: ', row?.name)
111+
},
112+
decline: { title: 'Cancel' }
113+
})
105114
},
106115
})
107116
]}
108117
/>
109-
110-
<Modal isOpen={isOpen} onClose={onClose}>
111-
<ModalOverlay />
112-
<ModalContent>
113-
<ModalHeader>Modal Title</ModalHeader>
114-
<ModalCloseButton />
115-
<ModalBody>
116-
bla bla bla
117-
</ModalBody>
118-
119-
<ModalFooter>
120-
<Button colorScheme='blue' mr={3} onClick={onClose}>
121-
Close
122-
</Button>
123-
<Button variant='ghost'>Secondary Action</Button>
124-
</ModalFooter>
125-
</ModalContent>
126-
</Modal>
127118
</Template>
128119
)
129120
}

0 commit comments

Comments
 (0)