diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6b665aa --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} diff --git a/web/package-lock.json b/web/package-lock.json index e5f013a..f7da801 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -24,7 +24,6 @@ "eslint-plugin-react-refresh": "^0.4.16", "globals": "^15.14.0", "prettier": "^3.4.2", - "sass": "^1.83.4", "vite": "^6.0.5" }, "engines": { @@ -1020,6 +1019,7 @@ "hasInstallScript": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", @@ -1062,6 +1062,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1083,6 +1084,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1104,6 +1106,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1125,6 +1128,7 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1146,6 +1150,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1167,6 +1172,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1188,6 +1194,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1209,6 +1216,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1230,6 +1238,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1251,6 +1260,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1272,6 +1282,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1293,6 +1304,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1314,6 +1326,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1948,6 +1961,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -2092,6 +2106,8 @@ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -2280,6 +2296,7 @@ "dev": true, "license": "Apache-2.0", "optional": true, + "peer": true, "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -2859,6 +2876,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3202,7 +3220,9 @@ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -3458,6 +3478,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=0.12.0" } @@ -3824,6 +3845,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -3884,7 +3906,8 @@ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/node-releases": { "version": "2.0.19", @@ -4122,6 +4145,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=8.6" }, @@ -4277,6 +4301,8 @@ "integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 14.18.0" }, @@ -4457,6 +4483,8 @@ "integrity": "sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -4810,6 +4838,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "is-number": "^7.0.0" }, @@ -4976,11 +5005,10 @@ } }, "node_modules/vite": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.7.tgz", - "integrity": "sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==", + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", + "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", "dev": true, - "license": "MIT", "dependencies": { "esbuild": "^0.24.2", "postcss": "^8.4.49", diff --git a/web/src/App.jsx b/web/src/App.jsx index 34be849..b4ab92f 100644 --- a/web/src/App.jsx +++ b/web/src/App.jsx @@ -1,9 +1,40 @@ import { TaskList } from './components/domains/task/TaskList/TaskList'; +const taskItems = [ + { + name: 'Re-work UI/UX', + priority: 'Low', + releaseDate: '12/05/2025', + designers: ['Said', 'Rachael'], + projectName: 'Time App', + }, + { + name: 'Dark mode toggle', + priority: 'High', + releaseDate: '09/03/2025', + designers: ['Umair', 'Precious'], + projectName: 'ASA Darkmode Feature', + }, + { + name: 'Accessibility checks', + priority: 'Medium', + releaseDate: '15/04/2025', + designers: ['Michael', 'Ricardo'], + projectName: 'Time App', + }, + { + name: 'Notification integration', + priority: 'High', + releaseDate: '11/03/2025', + designers: ['Ebtesam', 'Deborah'], + projectName: 'Time App', + }, +]; + function App() { return ( <> - + ); } diff --git a/web/src/components/domains/task/TaskItem/TaskItem.jsx b/web/src/components/domains/task/TaskItem/TaskItem.jsx index a1832ec..07d477c 100644 --- a/web/src/components/domains/task/TaskItem/TaskItem.jsx +++ b/web/src/components/domains/task/TaskItem/TaskItem.jsx @@ -1,11 +1,30 @@ import styles from './TaskItem.module.css'; +import PropTypes from 'prop-types'; -/* -Please create the component following the design from the Figma file. -Please make sure to add styles using CSS Modules. -Add the necessary props to the component. -*/ - -export function TaskItem(props) { - return
; +export function TaskItem({ + name, + priority, + releaseDate, + designers, + projectName, +}) { + return ( +
  • +

    {name}

    +

    {priority}

    +

    {releaseDate}

    +

    {designers.join(', ')}

    +

    + {projectName} +

    +
  • + ); } + +TaskItem.propTypes = { + name: PropTypes.string.isRequired, + priority: PropTypes.string.isRequired, + releaseDate: PropTypes.string.isRequired, + designers: PropTypes.arrayOf(PropTypes.string).isRequired, + projectName: PropTypes.string.isRequired, +}; diff --git a/web/src/components/domains/task/TaskItem/TaskItem.module.css b/web/src/components/domains/task/TaskItem/TaskItem.module.css index e69de29..8cdde11 100644 --- a/web/src/components/domains/task/TaskItem/TaskItem.module.css +++ b/web/src/components/domains/task/TaskItem/TaskItem.module.css @@ -0,0 +1,14 @@ +.taskItem { + display: grid; + grid-template-columns: 1.5fr 0.5fr 1fr 1fr 1fr; + align-items: center; + gap: 10px; + padding: 10px; + background-color: #e0e4ea; + border-radius: 10px; + margin: 1rem; +} + +.section { + text-align: left; +} diff --git a/web/src/components/domains/task/TaskList/TaskList.jsx b/web/src/components/domains/task/TaskList/TaskList.jsx index 624be89..3581140 100644 --- a/web/src/components/domains/task/TaskList/TaskList.jsx +++ b/web/src/components/domains/task/TaskList/TaskList.jsx @@ -1,14 +1,106 @@ +import { useState } from 'react'; import styles from './TaskList.module.css'; +import PropTypes from 'prop-types'; +import { TaskItem } from '../TaskItem/TaskItem'; -/* -Please create the component following the design from the Figma file. -Please make sure to add styles using CSS Modules. -Create a taskItems array and return a list of components. -*/ +export function TaskList({ initialTaskItems }) { + const [taskItems, setTaskItems] = useState(initialTaskItems); + const [newTask, setNewTask] = useState({ + name: '', + priority: '', + releaseDate: '', + designers: '', + projectName: '', + }); -export function TaskList() { - // create some task items here and return one task list for each item you have - const taskItems = []; + const handleInputChange = (e) => { + const { name, value } = e.target; + setNewTask({ ...newTask, [name]: value }); + }; - return
    ; + const handleAddTask = () => { + setTaskItems([ + ...taskItems, + { + ...newTask, + designers: newTask.designers + .split(',') + .map((designer) => designer.trim()), + }, + ]); + setNewTask({ + name: '', + priority: '', + releaseDate: '', + designers: '', + projectName: '', + }); + }; + + return ( +
    +
      + {taskItems.map((task, index) => ( + + ))} +
    +
    + + + + + + +
    +
    + ); } + +TaskList.propTypes = { + initialTaskItems: PropTypes.arrayOf( + PropTypes.shape({ + name: PropTypes.string.isRequired, + priority: PropTypes.string.isRequired, + releaseDate: PropTypes.string.isRequired, + designers: PropTypes.arrayOf(PropTypes.string).isRequired, + projectName: PropTypes.string.isRequired, + }), + ).isRequired, +};