Skip to content

Commit b414b99

Browse files
authored
refactor: breakdown Tasks component to Dialogs (#236)
* seperated addtaskdialog && edittaskdialog * moved interfaces to types.ts * added tests for useEditTask.tsx * added tests for new files * fixed changes * resolved conflicts * changed names to TaskDialog * fixed name of testfile
1 parent ca48131 commit b414b99

10 files changed

Lines changed: 2940 additions & 1901 deletions

File tree

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
import { Badge } from '@/components/ui/badge';
2+
import { Button } from '@/components/ui/button';
3+
import { DatePicker } from '@/components/ui/date-picker';
4+
import {
5+
Dialog,
6+
DialogContent,
7+
DialogDescription,
8+
DialogFooter,
9+
DialogHeader,
10+
DialogTitle,
11+
DialogTrigger,
12+
} from '@/components/ui/dialog';
13+
import { Input } from '@/components/ui/input';
14+
import { Key } from '@/components/ui/key-button';
15+
import { Label } from '@/components/ui/label';
16+
import {
17+
Select,
18+
SelectContent,
19+
SelectItem,
20+
SelectTrigger,
21+
SelectValue,
22+
} from '@/components/ui/select';
23+
import { AddTaskDialogProps } from '@/components/utils/types';
24+
import { format } from 'date-fns';
25+
26+
export const AddTaskdialog = ({
27+
isOpen,
28+
setIsOpen,
29+
newTask,
30+
setNewTask,
31+
tagInput,
32+
setTagInput,
33+
onSubmit,
34+
isCreatingNewProject,
35+
setIsCreatingNewProject,
36+
uniqueProjects = [],
37+
}: AddTaskDialogProps) => {
38+
const handleAddTag = () => {
39+
if (tagInput && !newTask.tags.includes(tagInput, 0)) {
40+
setNewTask({ ...newTask, tags: [...newTask.tags, tagInput] });
41+
setTagInput('');
42+
}
43+
};
44+
45+
const handleRemoveTag = (tagToRemove: string) => {
46+
setNewTask({
47+
...newTask,
48+
tags: newTask.tags.filter((tag) => tag !== tagToRemove),
49+
});
50+
};
51+
52+
return (
53+
<Dialog open={isOpen} onOpenChange={setIsOpen}>
54+
<DialogTrigger asChild>
55+
<Button
56+
id="add-new-task"
57+
variant="outline"
58+
onClick={() => setIsOpen(true)}
59+
>
60+
Add Task
61+
<Key lable="a" />
62+
</Button>
63+
</DialogTrigger>
64+
<DialogContent>
65+
<DialogHeader>
66+
<DialogTitle>
67+
<span className="ml-0 mb-0 mr-0 text-2xl mt-0 md:text-2xl font-bold">
68+
<span className="inline bg-gradient-to-r from-[#F596D3] to-[#D247BF] text-transparent bg-clip-text">
69+
Add a{' '}
70+
</span>
71+
new task
72+
</span>
73+
</DialogTitle>
74+
<DialogDescription>
75+
Fill in the details below to add a new task.
76+
</DialogDescription>
77+
</DialogHeader>
78+
<div className="space-y-4">
79+
<div className="grid grid-cols-4 items-center gap-4">
80+
<Label htmlFor="description" className="text-right">
81+
Description
82+
</Label>
83+
<Input
84+
id="description"
85+
name="description"
86+
type="text"
87+
value={newTask.description}
88+
onChange={(e) =>
89+
setNewTask({
90+
...newTask,
91+
description: e.target.value,
92+
})
93+
}
94+
required
95+
className="col-span-3"
96+
/>
97+
</div>
98+
<div className="grid grid-cols-4 items-center gap-4">
99+
<Label htmlFor="priority" className="text-right">
100+
Priority
101+
</Label>
102+
<div className="col-span-1 flex items-center">
103+
<select
104+
id="priority"
105+
name="priority"
106+
value={newTask.priority}
107+
onChange={(e) =>
108+
setNewTask({
109+
...newTask,
110+
priority: e.target.value,
111+
})
112+
}
113+
className="border rounded-md px-2 py-1 w-full bg-white text-black dark:bg-black dark:text-white transition-colors"
114+
>
115+
<option value="H">H</option>
116+
<option value="M">M</option>
117+
<option value="L">L</option>
118+
</select>
119+
</div>
120+
</div>
121+
122+
<div className="grid grid-cols-4 items-center gap-4">
123+
<Label htmlFor="project" className="text-right">
124+
Project
125+
</Label>
126+
<div className="col-span-3 space-y-2">
127+
<Select
128+
value={newTask.project}
129+
onValueChange={(value) => {
130+
if (value === '__CREATE_NEW__') {
131+
setIsCreatingNewProject(true);
132+
setNewTask({ ...newTask, project: '' });
133+
} else {
134+
setIsCreatingNewProject(false);
135+
setNewTask({ ...newTask, project: value });
136+
}
137+
}}
138+
>
139+
<SelectTrigger id="project" data-testid="project-select">
140+
<SelectValue
141+
placeholder={
142+
uniqueProjects.length
143+
? 'Select a project'
144+
: 'No projects yet'
145+
}
146+
/>
147+
</SelectTrigger>
148+
<SelectContent>
149+
<SelectItem value="__NONE__">No project</SelectItem>
150+
{uniqueProjects.map((project: string) => (
151+
<SelectItem key={project} value={project}>
152+
{project}
153+
</SelectItem>
154+
))}
155+
<SelectItem value="__CREATE_NEW__">
156+
+ Create new project…
157+
</SelectItem>
158+
</SelectContent>
159+
</Select>
160+
161+
{isCreatingNewProject && (
162+
<Input
163+
id="project-name"
164+
placeholder="New project name"
165+
value={newTask.project}
166+
autoFocus
167+
onChange={(e) =>
168+
setNewTask({ ...newTask, project: e.target.value })
169+
}
170+
/>
171+
)}
172+
</div>
173+
</div>
174+
<div className="grid grid-cols-4 items-center gap-4">
175+
<Label htmlFor="due" className="text-right">
176+
Due
177+
</Label>
178+
<div className="col-span-3">
179+
<DatePicker
180+
date={newTask.due ? new Date(newTask.due) : undefined}
181+
onDateChange={(date) => {
182+
setNewTask({
183+
...newTask,
184+
due: date ? format(date, 'yyyy-MM-dd') : '',
185+
});
186+
}}
187+
placeholder="Select a due date"
188+
/>
189+
</div>
190+
</div>
191+
<div className="grid grid-cols-4 items-center gap-4">
192+
<Label htmlFor="description" className="text-right">
193+
Tags
194+
</Label>
195+
<Input
196+
id="tags"
197+
name="tags"
198+
placeholder="Add a tag"
199+
value={tagInput}
200+
onChange={(e) => setTagInput(e.target.value)}
201+
onKeyDown={(e) => e.key === 'Enter' && handleAddTag()}
202+
required
203+
className="col-span-3"
204+
/>
205+
</div>
206+
207+
<div className="mt-2">
208+
{newTask.tags.length > 0 && (
209+
<div className="grid grid-cols-4 items-center">
210+
<div> </div>
211+
<div className="flex flex-wrap gap-2 col-span-3">
212+
{newTask.tags.map((tag, index) => (
213+
<Badge key={index}>
214+
<span>{tag}</span>
215+
<button
216+
type="button"
217+
className="ml-2 text-red-500"
218+
onClick={() => handleRemoveTag(tag)}
219+
>
220+
221+
</button>
222+
</Badge>
223+
))}
224+
</div>
225+
</div>
226+
)}
227+
</div>
228+
</div>
229+
<DialogFooter>
230+
<Button
231+
className="dark:bg-white/5 bg-black hover:bg-black text-white"
232+
variant="secondary"
233+
onClick={() => setIsOpen(false)}
234+
>
235+
Cancel
236+
</Button>
237+
<Button
238+
className="mb-1"
239+
variant="default"
240+
onClick={() => onSubmit(newTask)}
241+
>
242+
Add Task
243+
</Button>
244+
</DialogFooter>
245+
</DialogContent>
246+
</Dialog>
247+
);
248+
};

0 commit comments

Comments
 (0)