diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f4df4eec..fc77746d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -462,7 +462,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", @@ -2067,7 +2066,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "peer": true, "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -5174,6 +5172,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -5189,6 +5188,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -5205,6 +5205,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -5217,6 +5218,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "peer": true, "engines": { "node": ">=8" } @@ -5226,6 +5228,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -5422,7 +5425,8 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -5576,7 +5580,6 @@ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", "dev": true, - "peer": true, "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -5646,7 +5649,6 @@ "version": "20.14.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", - "peer": true, "dependencies": { "undici-types": "~5.26.4" } @@ -5667,7 +5669,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "devOptional": true, - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5687,7 +5688,6 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", "devOptional": true, - "peer": true, "dependencies": { "@types/react": "*" } @@ -5779,7 +5779,6 @@ "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6255,7 +6254,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001629", "electron-to-chromium": "^1.4.796", @@ -7238,7 +7236,6 @@ "version": "8.57.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -8299,7 +8296,6 @@ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, - "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -10691,7 +10687,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", @@ -10955,7 +10950,6 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -10993,7 +10987,6 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -11027,14 +11020,12 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "peer": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-redux": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", - "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -11234,8 +11225,7 @@ "node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "peer": true + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -11830,7 +11820,6 @@ "version": "3.4.4", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", - "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -11999,7 +11988,6 @@ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz", "integrity": "sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q==", "dev": true, - "peer": true, "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", @@ -12056,7 +12044,6 @@ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "devOptional": true, - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -12140,7 +12127,6 @@ "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -12365,7 +12351,6 @@ "version": "5.2.13", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.13.tgz", "integrity": "sha512-SSq1noJfY9pR3I1TUENL3rQYDQCFqgD+lM6fTRAM8Nv6Lsg5hDLaXkjETVeBt+7vZBCMoibD+6IWnT2mJ+Zb/A==", - "peer": true, "dependencies": { "esbuild": "^0.20.1", "postcss": "^8.4.38", diff --git a/frontend/src/components/HomeComponents/Tasks/Task-Skeleton.tsx b/frontend/src/components/HomeComponents/Tasks/Task-Skeleton.tsx new file mode 100644 index 00000000..6b722d62 --- /dev/null +++ b/frontend/src/components/HomeComponents/Tasks/Task-Skeleton.tsx @@ -0,0 +1,26 @@ +import { TableCell, TableRow } from '@/components/ui/table'; + +export const Taskskeleton = ({ count }: { count: number }) => { + return ( + <> + {Array.from({ length: count }).map((_, i) => ( + + +
+
+ + +
+
+
+
+
+
+ +
+
+
+ ))} + + ); +}; diff --git a/frontend/src/components/HomeComponents/Tasks/Tasks.tsx b/frontend/src/components/HomeComponents/Tasks/Tasks.tsx index bd87921b..140288db 100644 --- a/frontend/src/components/HomeComponents/Tasks/Tasks.tsx +++ b/frontend/src/components/HomeComponents/Tasks/Tasks.tsx @@ -70,6 +70,7 @@ import { import { debounce } from '@/components/utils/utils'; import { DatePicker } from '@/components/ui/date-picker'; import { format } from 'date-fns'; +import { Taskskeleton } from './Task-Skeleton'; const db = new TasksDatabase(); export let syncTasksWithTwAndDb: () => any; @@ -266,6 +267,8 @@ export const Tasks = ( } catch (error) { console.error('Error syncing tasks:', error); toast.error(`Failed to sync tasks. Please try again.`); + } finally { + props.setIsLoading(false); } }, [props.email, props.encryptionSecret, props.UUID]); // Add dependencies @@ -805,7 +808,13 @@ export const Tasks = (
-
@@ -852,105 +861,209 @@ export const Tasks = ( {/* Display tasks */} - {currentTasks.map((task: Task, index: number) => ( - - handleDialogOpenChange(_isDialogOpen, task) - } - key={index} - > - - - {/* Display task details */} - - - {task.id} - - - - {task.priority === 'H' && ( -
- )} - {task.priority === 'M' && ( -
- )} - {task.priority != 'H' && - task.priority != 'M' && ( -
+ {props.isLoading ? ( + + ) : ( + currentTasks.map((task: Task, index: number) => ( + + handleDialogOpenChange(_isDialogOpen, task) + } + key={index} + > + + + {/* Display task details */} + + + {task.id} + + + + {task.priority === 'H' && ( +
)} - - {task.description} - - {task.project != '' && ( - - - {task.project === '' ? '' : task.project} - - )} -
- - + )} + {task.priority != 'H' && + task.priority != 'M' && ( +
+ )} + + {task.description} + + {task.project != '' && ( + + + {task.project === '' ? '' : task.project} + + )} +
+ + + {task.status === 'completed' + ? 'C' : task.status === 'deleted' - ? 'destructive' - : 'default' - } - > - {task.status === 'completed' - ? 'C' - : task.status === 'deleted' - ? 'D' - : 'P'} - - -
-
- - - - - - Task{' '} + ? 'D' + : 'P'} + +
+
+
+ + + + + + Task{' '} + + Details - Details - - - + + - {/* Scrollable content */} -
- - - - - ID: - {task.id} - - - Description: - - {isEditing ? ( - <> -
- - setEditedDescription( - e.target.value + {/* Scrollable content */} +
+ +
+ + + ID: + {task.id} + + + Description: + + {isEditing ? ( + <> +
+ + setEditedDescription( + e.target.value + ) + } + className="flex-grow mr-2" + /> + + +
+ + ) : ( + <> + {task.description} + + + )} +
+
+ + Due: + + {formattedDate(task.due)} + + + + Start: + + {formattedDate(task.start)} + + + + End: + + {formattedDate(task.end)} + + + + Wait: + + {formattedDate(task.wait)} + + + + Depends: + {task.depends} + + + Recur: + {task.recur} + + + RType: + {task.rtype} + + + Priority: + + {isEditingPriority ? ( +
+
- - ) : ( - <> - {task.description} - - - )} -
-
- - Due: - - {formattedDate(task.due)} - - - - Start: - - {formattedDate(task.start)} - - - - End: - - {formattedDate(task.end)} - - - - Wait: - - {formattedDate(task.wait)} - - - - Depends: - {task.depends} - - - Recur: - {task.recur} - - - RType: - {task.rtype} - - - Priority: - - {isEditingPriority ? ( -
- - - -
- ) : ( -
- - {task.priority - ? task.priority === 'H' - ? 'High (H)' - : task.priority === 'M' - ? 'Medium (M)' - : task.priority === 'L' - ? 'Low (L)' - : task.priority - : 'None'} - - -
- )} -
-
- - Project: - - {isEditingProject ? ( - <> + ) : ( +
+ + {task.priority + ? task.priority === 'H' + ? 'High (H)' + : task.priority === 'M' + ? 'Medium (M)' + : task.priority === 'L' + ? 'Low (L)' + : task.priority + : 'None'} + + +
+ )} +
+
+ + Project: + + {isEditingProject ? ( + <> +
+ + setEditedProject( + e.target.value + ) + } + className="flex-grow mr-2" + /> + + +
+ + ) : ( + <> + {task.project} + + + )} +
+
+ + Status: + {task.status} + + + Tags: + + {isEditingTags ? (
- setEditedProject( + setEditedTags( e.target.value + .split(',') + .map((tag) => tag.trim()) ) } className="flex-grow mr-2" @@ -1110,226 +1184,171 @@ export const Tasks = ( variant="ghost" size="icon" onClick={() => - handleProjectSaveClick(task) + handleSaveTags(task) } > + +
+ ) : ( +
+ {task.tags !== null && + task.tags.length >= 1 ? ( + task.tags.map((tag, index) => ( + + + {tag} + + )) + ) : ( + No Tags + )}
- - ) : ( - <> - {task.project} - - - )} -
-
- - Status: - {task.status} - - - Tags: - - {isEditingTags ? ( -
- - setEditedTags( - e.target.value - .split(',') - .map((tag) => tag.trim()) - ) - } - className="flex-grow mr-2" - /> - - -
- ) : ( -
- {task.tags !== null && - task.tags.length >= 1 ? ( - task.tags.map((tag, index) => ( - - - {tag} - - )) - ) : ( - No Tags - )} - -
- )} -
-
- - Urgency: - {task.urgency} - - - UUID: - - {task.uuid} - handleCopy('Task UUID')} - > - - - - -
-
-
-
+ )} + + + + Urgency: + {task.urgency} + + + UUID: + + {task.uuid} + + handleCopy('Task UUID') + } + > + + + + +
+ + + - {/* Non-scrollable footer */} - - {task.status == 'pending' ? ( - - - - - - - - - Are you{' '} + {/* Non-scrollable footer */} + + {task.status == 'pending' ? ( + + + + + + + + + Are you{' '} + + sure? - sure? - - - - - - - - - - - - - ) : null} + + + + + + + + + + + + ) : null} - {task.status != 'deleted' ? ( - - - - - - - - - Are you{' '} + {task.status != 'deleted' ? ( + + + + + + + + + Are you{' '} + + sure? - sure? - - - - - - - - - - - - - ) : null} - - - - - - - ))} + + + + + + + + + + + + ) : null} + + + + + + + )) + )} {/* Display empty rows */} - {emptyRows > 0 && ( + {!props.isLoading && emptyRows > 0 && (