This repository has no description
4.0 kB
160 lines
1'use client';
2
3import { Dispatch, SetStateAction, useState } from 'react';
4import useRemoveCardFromLibrary from '../../lib/mutations/useRemoveCardFromLibrary';
5import { notifications } from '@mantine/notifications';
6import {
7 Button,
8 Card,
9 Flex,
10 Group,
11 Input,
12 Stack,
13 Text,
14 Textarea,
15 VisuallyHidden,
16} from '@mantine/core';
17
18interface Props {
19 note?: string;
20 noteId?: string;
21 onUpdateNote: Dispatch<SetStateAction<string | undefined>>;
22 onClose: () => void;
23}
24
25export default function AddCardActions(props: Props) {
26 const [showDeleteWarning, setShowDeleteWarning] = useState(false);
27 const [noteMode, setNoteMode] = useState(false);
28 const [note, setNote] = useState(props.note);
29 const MAX_NOTE_LENGTH = 500;
30
31 const removeNote = useRemoveCardFromLibrary();
32
33 const handleDeleteNote = () => {
34 if (!props.noteId) return;
35
36 removeNote.mutate(props.noteId, {
37 onError: () => {
38 notifications.show({
39 message: 'Could not delete note.',
40 position: 'top-center',
41 });
42 },
43 onSettled: () => {
44 props.onClose();
45 },
46 });
47 };
48
49 if (noteMode) {
50 return (
51 <Card
52 withBorder
53 component="article"
54 p={'xs'}
55 radius={'lg'}
56 style={{ cursor: 'pointer' }}
57 >
58 <Stack gap={'xs'}>
59 <Stack gap={0}>
60 <Flex justify="space-between">
61 <Input.Label size="md" htmlFor="note">
62 Your note
63 </Input.Label>
64 <Text c={'gray'} aria-hidden>
65 {note?.length ?? 0} / {MAX_NOTE_LENGTH}
66 </Text>
67 </Flex>
68
69 <Textarea
70 id="note"
71 placeholder="Add a note about this card"
72 variant="filled"
73 size="md"
74 rows={3}
75 maxLength={500}
76 value={note}
77 onChange={(e) => setNote(e.currentTarget.value)}
78 />
79 <VisuallyHidden id="note-char-remaining" aria-live="polite">
80 {`${MAX_NOTE_LENGTH - (note?.length ?? 0)} characters remaining`}
81 </VisuallyHidden>
82 </Stack>
83 <Group gap={'xs'} grow>
84 <Button
85 variant="light"
86 color="gray"
87 onClick={() => {
88 setNoteMode(false);
89 setNote(props.note);
90 }}
91 >
92 Cancel
93 </Button>
94 <Button
95 onClick={() => {
96 props.onUpdateNote(note);
97 setNoteMode(false);
98 }}
99 disabled={note?.trimEnd() === ''}
100 >
101 Ok
102 </Button>
103 </Group>
104 </Stack>
105 </Card>
106 );
107 }
108
109 return (
110 <Stack gap={'xs'}>
111 {showDeleteWarning ? (
112 <Group justify="space-between" gap={'xs'}>
113 <Text>Delete note?</Text>
114 <Group gap={'xs'}>
115 <Button
116 color="red"
117 onClick={handleDeleteNote}
118 loading={removeNote.isPending}
119 >
120 Delete
121 </Button>
122 <Button
123 variant="light"
124 color="gray"
125 onClick={() => setShowDeleteWarning(false)}
126 >
127 Cancel
128 </Button>
129 </Group>
130 </Group>
131 ) : (
132 <Group gap={'xs'}>
133 <Button
134 variant="light"
135 size="xs"
136 color="gray"
137 onClick={(e) => {
138 e.stopPropagation();
139 setNoteMode(true);
140 }}
141 >
142 {note ? 'Edit note' : 'Add note'}
143 </Button>
144 {props.noteId && (
145 <Button
146 variant="light"
147 color="red"
148 onClick={(e) => {
149 e.stopPropagation();
150 setShowDeleteWarning(true);
151 }}
152 >
153 Delete note
154 </Button>
155 )}
156 </Group>
157 )}
158 </Stack>
159 );
160}