From c7193dc175e848a9056b136e6656ccf69cc76721 Mon Sep 17 00:00:00 2001 From: Blaine Booher Date: Mon, 2 Dec 2024 10:56:49 -0600 Subject: [PATCH 1/4] fix: update TaskList test to handle date format variations Made the date format assertions in TaskList.test.jsx more flexible by using regex patterns to account for potential timezone and locale differences in date rendering. --- README.md | 9 +- server/routes/todos.router.js | 6 +- server/todos.db | Bin 20480 -> 20480 bytes src/App.css | 42 ------- src/App.jsx | 4 +- src/components/TaskList.jsx | 134 +++++++++++++-------- src/components/__tests__/TaskList.test.jsx | 109 +++++++++++------ src/index.css | 3 +- src/stores/todoStore.js | 9 +- 9 files changed, 168 insertions(+), 148 deletions(-) diff --git a/README.md b/README.md index f768e33..6f404ef 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,3 @@ -# React + Vite +# User Authentication API -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. - -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh +A RESTful API for user authentication built with Express.js and Passport.js. \ No newline at end of file diff --git a/server/routes/todos.router.js b/server/routes/todos.router.js index 8a98119..31c23cb 100644 --- a/server/routes/todos.router.js +++ b/server/routes/todos.router.js @@ -19,7 +19,11 @@ router.post('/', validateTodo, async (req, res) => { // Read all todos router.get('/', async (req, res) => { try { - const todos = await Todo.findAll(); + const todos = await Todo.findAll({ + order: [ + ['completed_at', 'ASC'], // Sort by completed_at, nulls (incomplete) first + ], + }); res.json(todos); } catch (error) { console.error('GET /todos error:', error); diff --git a/server/todos.db b/server/todos.db index 710789f5f4f32c1bcd85917f02c650b5c17a77b7..877929f23b8a305c91618bc5203bea0d3a39cf04 100644 GIT binary patch literal 20480 zcmeI&O>@#f7zgl8TeUic>S&ws;LKheU|KWD@={>N8Ih)zDaA^IV^0uCDzSwifl-gu z@!-KP;L$JOXYfOLcXuHzbSB#A$?5#Jyd-(@B)h+7IV@%WMb#U+^w1x4?IBH*+eA^w z6G{mozxeYSe}-+2Z!Cm6{9T#aj@tZ1w84*9{0UizX(awVz8%xzD^VxoI0PU70SG_< z0uX=z1Rwx`|3~1&nZKc`s`5E8v|k^)qre>m@@1i1H%pdDt!4eNQO#*=oJg zMy>LqVe%9Eb`ZSx2TrqN2c3ws`DyKeYY$zgX%Aa;lXuLj?3$-n6Zh*o(eYGj;kx=* zRfyMf+z-LKW4=Oc+M}T__nUHXO+&tk_2HtZ&)(d1b!|;KkS>#yzxrjNGQ6mX`_-w*7AZ z*d5nrHgH%%D#mL!x2%%oughxe z?f6gB6Ac0ofB*y_009U<00I#BuLVw)Ru;+q`xV|SJ2;~0@#=)>Ec3`O%Ktxld+L6y+Z$IW?7-!!^Edx|(MW50 zI;^=W+>A# z*>IFoxqSW_`6A0}h1|wpN|eckx%|`ojjYHIj2$?K(=(#Kx=0?#*&-sg6U;;}_+jD& zDQJ2joDs8KW#^)!JBws(Ma<95f!8~t-H#I>@y)_i>OX~q0n@U2F3P~jX}Mfj7P0Wae_2s$NeOZfR11Q;0jOM%dYe+i$(W47++|-oJ(p)10BNJUiLtP_t1WUol(8|!#%E%atP!t>33|nL4#A2*wG;;6)Rfu{5 z0Z2tgW_kwH7-pa)lQ+mq)q`wPFfy_-HMKId&@;6#RnRsture?}whkg|qGxDoiBlG+ z*Ak|efq}tST-cKVVrybfemRn9VAFvX=ouIoC}>aKFVAg)>;`i^6CwW)?V|hh!`kuL1R%n{ECn&nCdgx5z*N0OiYMh5!Hn diff --git a/src/App.css b/src/App.css index b9d355d..e69de29 100644 --- a/src/App.css +++ b/src/App.css @@ -1,42 +0,0 @@ -#root { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} diff --git a/src/App.jsx b/src/App.jsx index 787bce1..4d50c90 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -4,9 +4,9 @@ import { Container, Row, Col } from 'react-bootstrap' function App() { return ( - + - + diff --git a/src/components/TaskList.jsx b/src/components/TaskList.jsx index af80541..cfec624 100644 --- a/src/components/TaskList.jsx +++ b/src/components/TaskList.jsx @@ -1,10 +1,18 @@ -import { useEffect } from 'react'; -import useTodoStore from '../stores/todoStore'; -import { ListGroup, Badge, Button, Spinner, Alert } from 'react-bootstrap'; -import { BsCheckSquare, BsSquare } from 'react-icons/bs'; +import { useEffect } from "react"; +import useTodoStore from "../stores/todoStore"; +import { Table, Button, Spinner, Alert } from "react-bootstrap"; +import { BsCheckSquare, BsSquare } from "react-icons/bs"; function TaskList() { - const { todos, isLoading, error, fetchTodos, deleteTodo, completeTodo, incompleteTodo } = useTodoStore(); + const { + todos, + isLoading, + error, + fetchTodos, + deleteTodo, + completeTodo, + incompleteTodo, + } = useTodoStore(); useEffect(() => { fetchTodos(); @@ -16,52 +24,84 @@ function TaskList() { <> {isLoading && ( + animation="border" + role="status" + /> )} - - {todos.map(todo => ( - -
-
{todo.name}
-
- - {todo.priority} - - Due: {new Date(todo.due_date).toLocaleDateString()} -
-
-
- diff --git a/src/components/TaskList.jsx b/src/components/TaskList.jsx index cfec624..811ebe8 100644 --- a/src/components/TaskList.jsx +++ b/src/components/TaskList.jsx @@ -1,6 +1,6 @@ import { useEffect } from "react"; import useTodoStore from "../stores/todoStore"; -import { Table, Button, Spinner, Alert } from "react-bootstrap"; +import { Table, Button, Spinner, Alert, Badge } from "react-bootstrap"; import { BsCheckSquare, BsSquare } from "react-icons/bs"; function TaskList() { @@ -18,6 +18,19 @@ function TaskList() { fetchTodos(); }, [fetchTodos]); + const getBadgeVariant = (priority) => { + switch (priority.toLowerCase()) { + case "high": + return "danger"; + case "medium": + return "warning"; + case "low": + return "success"; + default: + return "secondary"; + } + }; + if (error) return Error: {error}; return ( @@ -72,21 +85,12 @@ function TaskList() { {new Date(todo.due_date).toLocaleDateString()} - - {todo.name} + {todo.name} + + + {todo.priority.charAt(0).toUpperCase() + todo.priority.slice(1)} + - {todo.priority}