Skip to content

Commit cd58387

Browse files
authored
Merge branch 'main' into fix/issue-210-reusable-tags
2 parents 1bbd628 + bf7b859 commit cd58387

20 files changed

Lines changed: 1312 additions & 109 deletions

File tree

.github/workflows/backend-test.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ on:
33
push:
44
branches:
55
- main
6+
pull_request:
7+
branches:
8+
- main
9+
- dev
10+
611
jobs:
712
build:
813
runs-on: ubuntu-latest

assets/02_home.png

4.42 KB
Loading

frontend/src/components/HomeComponents/Footer/Footer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export const Footer = () => {
9090

9191
<section className="container pb-14 text-center">
9292
<h3>
93-
&copy; 2025{' '}
93+
&copy; 2026{' '}
9494
<a
9595
rel="noreferrer noopener"
9696
target="_blank"

frontend/src/components/HomeComponents/Footer/__tests__/__snapshots__/Footer.test.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ exports[`Footer component using Snapshot renders correctly 1`] = `
149149
class="container pb-14 text-center"
150150
>
151151
<h3>
152-
© 2025
152+
© 2026
153153
<a
154154
class="text-red transition-all border-secondary hover:border-b-2"
155155
rel="noreferrer noopener"

frontend/src/components/HomeComponents/Tasks/AddTaskDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export const AddTaskdialog = ({
111111
onClick={() => setIsOpen(true)}
112112
>
113113
Add Task
114-
<Key lable="a" />
114+
<Key label="a" />
115115
</Button>
116116
</DialogTrigger>
117117
<DialogContent>

frontend/src/components/HomeComponents/Tasks/ReportChart.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ export const ReportChart: React.FC<ReportChartProps> = ({
2323
}) => {
2424
const [isExporting, setIsExporting] = useState(false);
2525

26+
const isDark =
27+
typeof document !== 'undefined' &&
28+
document.documentElement.classList.contains('dark');
29+
30+
const labelColor = isDark ? '#ffffff' : '#111111';
31+
2632
const handleCSVExport = () => {
2733
exportReportToCSV(data, title);
2834
};
@@ -90,19 +96,19 @@ export const ReportChart: React.FC<ReportChartProps> = ({
9096
dataKey="completed"
9197
fill="#E776CB"
9298
name="Completed"
93-
label={{ position: 'top', fill: 'white', fontSize: 12 }}
99+
label={{ position: 'top', fill: labelColor, fontSize: 12 }}
94100
/>
95101
<Bar
96102
dataKey="ongoing"
97103
fill="#5FD9FA"
98104
name="Ongoing"
99-
label={{ position: 'top', fill: 'white', fontSize: 12 }}
105+
label={{ position: 'top', fill: labelColor, fontSize: 12 }}
100106
/>
101107
<Bar
102108
dataKey="overdue"
103109
fill="#F33434"
104110
name="Overdue"
105-
label={{ position: 'top', fill: 'white', fontSize: 12 }}
111+
label={{ position: 'top', fill: labelColor, fontSize: 12 }}
106112
/>
107113
</BarChart>
108114
</ResponsiveContainer>

frontend/src/components/HomeComponents/Tasks/TaskDialog.tsx

Lines changed: 99 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import {
2828
CopyIcon,
2929
Folder,
3030
PencilIcon,
31+
Pin,
32+
PinOff,
3133
Tag,
3234
Trash2Icon,
3335
XIcon,
@@ -72,6 +74,8 @@ export const TaskDialog = ({
7274
onMarkDeleted,
7375
isOverdue,
7476
isUnsynced,
77+
isPinned,
78+
onTogglePin,
7579
}: EditTaskDialogProps) => {
7680
const editButtonRef = useRef<
7781
Partial<Record<FieldKey, HTMLButtonElement | null>>
@@ -201,7 +205,10 @@ export const TaskDialog = ({
201205
onSelectTask(task, index);
202206
}}
203207
>
204-
<TableCell className="py-2" onClick={(e) => e.stopPropagation()}>
208+
<TableCell
209+
className="py-3 md:py-2 align-top"
210+
onClick={(e) => e.stopPropagation()}
211+
>
205212
<input
206213
type="checkbox"
207214
checked={selectedTaskUUIDs.includes(task.uuid)}
@@ -213,59 +220,77 @@ export const TaskDialog = ({
213220
/>
214221
</TableCell>
215222

216-
{/* Display task details */}
217-
<TableCell className="py-2">
218-
<span
219-
className={`px-3 py-1 rounded-md font-semibold ${
220-
task.status === 'pending' && isOverdue(task.due)
221-
? 'bg-red-600/80 text-white'
222-
: 'dark:text-white text-black'
223-
}`}
224-
>
225-
{task.id}
226-
</span>
227-
</TableCell>
228-
<TableCell className="flex items-center space-x-2 py-2">
229-
{task.priority === 'H' && (
230-
<div className="flex items-center justify-center w-3 h-3 bg-red-500 rounded-full border-0 min-w-3"></div>
231-
)}
232-
{task.priority === 'M' && (
233-
<div className="flex items-center justify-center w-3 h-3 bg-yellow-500 rounded-full border-0 min-w-3"></div>
234-
)}
235-
{task.priority != 'H' && task.priority != 'M' && (
236-
<div className="flex items-center justify-center w-3 h-3 bg-green-500 rounded-full border-0 min-w-3"></div>
237-
)}
238-
<span className="text-s text-foreground">{task.description}</span>
239-
{task.project != '' && (
240-
<Badge variant={'secondary'}>
241-
<Folder className="pr-2" />
242-
{task.project === '' ? '' : task.project}
243-
</Badge>
244-
)}
245-
</TableCell>
246-
<TableCell className="py-2">
247-
<Badge
248-
className={
249-
task.status === 'pending' && isOverdue(task.due)
250-
? 'bg-orange-500 text-white'
251-
: ''
252-
}
253-
variant={
254-
task.status === 'deleted'
255-
? 'destructive'
256-
: task.status === 'completed'
257-
? 'default'
258-
: 'secondary'
259-
}
260-
>
261-
{task.status === 'pending' && isOverdue(task.due)
262-
? 'O'
263-
: task.status === 'completed'
264-
? 'C'
265-
: task.status === 'deleted'
266-
? 'D'
267-
: 'P'}
268-
</Badge>
223+
{/* Desktop: single row layout, Mobile: 2-row layout */}
224+
<TableCell className="py-2" colSpan={3}>
225+
<div className="flex items-center gap-4">
226+
<span
227+
className={`px-3 py-1 rounded-md font-semibold ${
228+
task.status === 'pending' && isOverdue(task.due)
229+
? 'bg-red-600/80 text-white'
230+
: 'dark:text-white text-black'
231+
}`}
232+
>
233+
{task.id}
234+
</span>
235+
<div className="flex items-center space-x-2 flex-1 min-w-0">
236+
{task.priority === 'H' && (
237+
<div className="flex items-center justify-center w-3 h-3 bg-red-500 rounded-full border-0 min-w-3"></div>
238+
)}
239+
{task.priority === 'M' && (
240+
<div className="flex items-center justify-center w-3 h-3 bg-yellow-500 rounded-full border-0 min-w-3"></div>
241+
)}
242+
{task.priority != 'H' && task.priority != 'M' && (
243+
<div className="flex items-center justify-center w-3 h-3 bg-green-500 rounded-full border-0 min-w-3"></div>
244+
)}
245+
<span className="text-s text-foreground">
246+
{task.description}
247+
</span>
248+
{task.project != '' && (
249+
<Badge variant={'secondary'}>
250+
<Folder className="pr-2" />
251+
{task.project === '' ? '' : task.project}
252+
</Badge>
253+
)}
254+
</div>
255+
<div className="flex items-center gap-2">
256+
<Badge
257+
className={
258+
task.status === 'pending' && isOverdue(task.due)
259+
? 'bg-orange-500 text-white'
260+
: ''
261+
}
262+
variant={
263+
task.status === 'deleted'
264+
? 'destructive'
265+
: task.status === 'completed'
266+
? 'default'
267+
: 'secondary'
268+
}
269+
>
270+
{task.status === 'pending' && isOverdue(task.due)
271+
? 'O'
272+
: task.status === 'completed'
273+
? 'C'
274+
: task.status === 'deleted'
275+
? 'D'
276+
: 'P'}
277+
</Badge>
278+
<button
279+
onClick={(e) => {
280+
e.stopPropagation();
281+
onTogglePin(task.uuid);
282+
}}
283+
className="p-1 hover:bg-muted rounded transition-colors"
284+
aria-label={isPinned ? 'Unpin task' : 'Pin task'}
285+
>
286+
{isPinned ? (
287+
<Pin className="h-4 w-4 text-amber-500 fill-amber-500" />
288+
) : (
289+
<Pin className="h-4 w-4 text-muted-foreground" />
290+
)}
291+
</button>
292+
</div>
293+
</div>
269294
</TableCell>
270295
</TableRow>
271296
</DialogTrigger>
@@ -1610,14 +1635,32 @@ export const TaskDialog = ({
16101635
</div>
16111636

16121637
<DialogFooter className="flex flex-row justify-end pt-4">
1638+
<Button
1639+
variant="outline"
1640+
onClick={() => onTogglePin(task.uuid)}
1641+
className="mr-auto"
1642+
aria-label={isPinned ? 'Unpin task' : 'Pin task'}
1643+
>
1644+
{isPinned ? (
1645+
<>
1646+
<PinOff className="h-4 w-4 mr-1" />
1647+
Unpin
1648+
</>
1649+
) : (
1650+
<>
1651+
<Pin className="h-4 w-4 mr-1" />
1652+
Pin
1653+
</>
1654+
)}
1655+
</Button>
16131656
{task.status == 'pending' ? (
16141657
<Dialog>
16151658
<DialogTrigger asChild className="mr-5">
16161659
<Button
16171660
id={`mark-task-complete-${task.id}`}
16181661
aria-label="complete task"
16191662
>
1620-
Mark As Completed <Key lable="c" />
1663+
Mark As Completed <Key label="c" />
16211664
</Button>
16221665
</DialogTrigger>
16231666
<DialogContent>
@@ -1659,7 +1702,7 @@ export const TaskDialog = ({
16591702
aria-label="delete task"
16601703
>
16611704
<Trash2Icon />
1662-
<Key lable="d" />
1705+
<Key label="d" />
16631706
</Button>
16641707
</DialogTrigger>
16651708
<DialogContent>

0 commit comments

Comments
 (0)