diff --git a/Frontend/App.js b/Frontend/App.js new file mode 100644 index 0000000..dad7805 --- /dev/null +++ b/Frontend/App.js @@ -0,0 +1,213 @@ +import { useEffect, useState } from 'react'; + +function App() { + const [tasks, setTasks] = useState([]); + const [form, setForm] = useState({ + title: '', + description: '', + status: 'pending', + due_date: '' + }); + const [search, setSearch] = useState(''); + const [editingId, setEditingId] = useState(null); + + const loadTasks = () => { + fetch('http://localhost:8082/api/tasks') + .then(res => res.json()) + .then(data => setTasks(data)) + .catch(err => console.error(err)); + }; + + useEffect(() => { + loadTasks(); + }, []); + + const handleChange = e => { + setForm({ ...form, [e.target.name]: e.target.value }); + }; + + const handleSubmit = e => { + e.preventDefault(); + const method = editingId ? 'PUT' : 'POST'; + const url = editingId + ? `http://localhost:8082/api/tasks/${editingId}` + : 'http://localhost:8082/api/tasks'; + + fetch(url, { + method, + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(form), + }) + .then(res => res.json()) + .then(() => { + setForm({ title: '', description: '', status: 'pending', due_date: '' }); + setEditingId(null); + loadTasks(); + }) + .catch(err => console.error(err)); + }; + + const handleDelete = id => { + fetch(`http://localhost:8082/api/tasks/${id}`, { method: 'DELETE' }) + .then(() => loadTasks()) + .catch(err => console.error(err)); + }; + + const handleEdit = task => { + setEditingId(task.id); + setForm({ + title: task.title, + description: task.description || '', + status: task.status, + due_date: task.due_date || '', + }); + }; + + const filtered = tasks.filter(t => + t.title.toLowerCase().includes(search.toLowerCase()) + ); + + return ( +
+

Task Manager

+ + setSearch(e.target.value)} + style={{ + marginBottom: '15px', + padding: '8px 10px', + width: '100%', + maxWidth: '400px', + display: 'block', + border: '1px solid #d1d5db', + borderRadius: '6px' + }} + /> + +
+ + + + + +
+ + + + + + + + + + + + + {filtered.map(t => ( + + + + + + + + ))} + +
TitleDescriptionStatusDue DateActions
{t.title}{t.description}{t.status}{t.due_date} + + +
+
+ ); +} + +export default App; diff --git a/Frontend/Components/AddTaskView.js b/Frontend/Components/AddTaskView.js deleted file mode 100644 index 3732a2d..0000000 --- a/Frontend/Components/AddTaskView.js +++ /dev/null @@ -1,83 +0,0 @@ -import React, { useState } from "react"; -import { useNavigate } from "react-router-dom"; -import "./style.css"; - -function AddTaskView({ addTask }) { - const [taskTitle, setTaskTitle] = useState(""); - const [description, setDescription] = useState(""); - const [priority, setPriority] = useState("Low"); - const navigate = useNavigate(); - - const handleSubmit = (e) => { - e.preventDefault(); - - if (!taskTitle.trim()) { - alert("Please enter a task title"); - return; - } - - // Add a timestamp field here - addTask({ - title: taskTitle, - description: description, - priority: priority, - dateCreated: new Date().toLocaleString(), - }); - - setTaskTitle(""); - setDescription(""); - setPriority("Low"); - navigate("/"); - }; - - return ( -
-

Add Task

-
-
- - setTaskTitle(e.target.value)} - required - /> - - - - - - - -
- - -
-
-
-
- ); -} - -export default AddTaskView; diff --git a/Frontend/Components/TaskContext.js b/Frontend/Components/TaskContext.js deleted file mode 100644 index 0e09e27..0000000 --- a/Frontend/Components/TaskContext.js +++ /dev/null @@ -1,29 +0,0 @@ -import React, { createContext, useContext, useState } from "react"; - -const TaskContext = createContext(); - -export const useTaskContext = () => { - const context = useContext(TaskContext); - if (!context) { - throw new Error("useTaskContext must be used within TaskProvider"); - } - return context; -}; - -export const TaskProvider = ({ children }) => { - const [tasks, setTasks] = useState([]); - - const addTask = (task) => { - setTasks([...tasks, { ...task, id: Date.now() }]); - }; - - const deleteTask = (id) => { - setTasks(tasks.filter((task) => task.id !== id)); - }; - - return ( - - {children} - - ); -}; diff --git a/Frontend/Components/TaskListView.js b/Frontend/Components/TaskListView.js deleted file mode 100644 index abbff8f..0000000 --- a/Frontend/Components/TaskListView.js +++ /dev/null @@ -1,92 +0,0 @@ -import React from "react"; -import "./style.css"; - -function TaskListView({ tasks, deleteTask }) { - return ( - <> - {/* ===== Task List Container ===== */} -
-

Task List

- - {tasks.length === 0 ? ( -
-

- No tasks available. Add a task to get started! -

-
- ) : ( - - - - - - - - - - - - - {tasks.map((task, index) => ( - - - - - - - - - ))} - -
IDTask TitleDescriptionPriorityDate Created
{index + 1}{task.title}{task.description} - - {task.priority} - - {task.dateCreated} - -
- )} -
- - ); -} - -export default TaskListView; diff --git a/Frontend/Components/style.css b/Frontend/Components/style.css deleted file mode 100644 index 7748d72..0000000 --- a/Frontend/Components/style.css +++ /dev/null @@ -1,382 +0,0 @@ -@import url("https://fonts.googleapis.com/css2?family=Gloria+Hallelujah&display=swap"); -@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap"); - -/* ===== Base Layout ===== */ -body { - font-family: "Poppins", sans-serif; - background-image: url("/public/nav.png"); - background-position: center; - background-repeat: no-repeat; - background-size: cover; - background-attachment: fixed; - background-color: #1f2937; - color: #f9fafb; - margin: 0; - padding: 0; - letter-spacing: 0.2px; -} - -/* ===== Containers ===== */ -.container, -.add-task-container { - max-width: 720px; - margin: 3rem auto; - padding: 2rem; - background: #ffffff; - border: 1px solid #e5e7eb; - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.06); - border-radius: 12px; -} - -/* ===== Headings ===== */ -h2 { - text-align: center; - font-size: 1.7rem; - margin-bottom: 1.5rem; - color: #4d4d4d; - letter-spacing: 0.3px; - font-weight: 600; -} - -/* ===== Navbar ===== */ -.navbar { - font-family: "Gloria Hallelujah", cursive; - background-color: #ffc067; - padding: 0.9rem 2rem; - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 3px solid #374151; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); - position: sticky; - top: 0; - z-index: 50; -} - -.navbar-left { - display: flex; - align-items: center; - gap: 0.2rem; -} - -.navbar-left img { - width: 40px; - height: 40px; - object-fit: contain; - border-radius: 6px; -} - -.navbar-title { - color: #4d4d4d; - font-size: 1.5rem; - font-weight: 600; - letter-spacing: 0.5px; -} - -.navbar-right { - display: flex; - align-items: center; - gap: 0.6rem; -} - -/* ===== Navbar Buttons ===== */ -.btn-home, -.btn-add { - background-color: #ffffff; - color: #4d4d4d; - font-weight: 600; - font-size: 1.1rem; - text-decoration: none; - padding: 0.5rem 1.2rem; - border-radius: 8px; - border: 2px solid transparent; - transition: all 0.25s ease; - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); -} - -.btn-home:hover { - background-color: #0e68dd; - color: #ffffff; - border-color: transparent; - transform: translateY(-1px); -} - -.btn-add:hover { - background-color: #0edd5a; - color: #ffffff; - border-color: transparent; - transform: translateY(-1px); -} - -/* ===== Table ===== */ -.table { - width: 100%; - border-collapse: collapse; - margin-top: 1rem; - font-size: 0.94rem; - border: 1px solid #e5e7eb; -} - -.table th { - background: #f3f4f6; - color: #1f2937; - text-transform: uppercase; - font-size: 0.75rem; - letter-spacing: 0.5px; -} - -.table th, -.table td { - padding: 0.75rem 1rem; - border-bottom: 1px solid #e5e7eb; - text-align: left; -} - -.table tr:hover td { - background-color: #f9fafb; -} - -/* ===== Card ===== */ -.card { - background: #ffffff; - border: 1px solid #e5e7eb; - padding: 1.25rem; - margin-top: 1rem; - box-shadow: 0 3px 8px rgba(0, 0, 0, 0.04); - border-radius: 10px; - transition: transform 0.2s ease, box-shadow 0.2s ease; -} - -.card-text { - color: #6b7280; - text-align: center; - margin: 0.5rem 0; - font-size: 0.95rem; -} - -/* ===== Buttons ===== */ -.btn { - padding: 0.45rem 0.9rem; - border: none; - cursor: pointer; - font-size: 0.9rem; - font-weight: 500; - border-radius: 8px; - transition: all 0.2s ease; -} - -.btn:hover { - opacity: 0.9; -} - -.btn-primary { - background: #4d4d4d; - color: #ffffff; -} - -.btn-primary:hover { - background: #0edd5a; - color: #ffffff; -} - -.btn-secondary { - background-color: #f9fafb; - color: #4d4d4d; - border: 1px solid #d1d5db; -} - -.btn-secondary:hover { - background-color: #c70c0c; - color: #ffffff; -} - -.btn-danger { - background-color: #ef4444; - color: #ffffff; -} - -.btn-danger:hover { - background-color: #dc2626; -} - -/* ===== Icon Buttons ===== */ -.icon-btn { - background: none; - border: none; - padding: 0.4rem; - cursor: pointer; - display: inline-flex; - align-items: center; - justify-content: center; - transition: all 0.2s ease; - border-radius: 6px; -} - -.btn-danger.icon-btn svg { - color: #dc2626; - transition: color 0.2s ease, transform 0.2s ease; -} - -.btn-danger.icon-btn:hover { - background-color: #dc2626; -} - -.btn-danger.icon-btn:hover svg { - color: #ffffff; - transform: scale(1.05); -} - -.btn-danger.icon-btn:active svg { - transform: scale(0.95); -} - -/* ===== Badges ===== */ -.badge { - display: inline-block; - padding: 0.3em 0.6em; - font-size: 0.75rem; - font-weight: 500; - color: #fff; - border-radius: 6px; -} - -.bg-danger { - background: #7a0000; -} - -.bg-warning { - background: #ffc067; -} - -.bg-success { - background: #41ab6d; -} - -/* ===== Forms ===== */ -form { - display: flex; - flex-direction: column; - gap: 1rem; - margin-top: 1.2rem; -} - -form label { - font-weight: 500; - font-size: 0.9rem; - color: #374151; - text-transform: uppercase; - letter-spacing: 0.5px; -} - -form input, -form textarea, -form select { - width: 100%; - padding: 0.55rem 0.7rem; - border: 1px solid #d1d5db; - font-size: 0.9rem; - background-color: #fafafa; - border-radius: 6px; - transition: border-color 0.2s ease, background-color 0.2s ease; -} - -form input:focus, -form textarea:focus, -form select:focus { - background-color: #ffffff; - border-color: #111827; - outline: none; -} - -form button { - align-self: flex-start; -} - -/* Buttons container inside Add Task form */ -.add-task-container form > div:last-child { - display: flex; - justify-content: center; - gap: 1rem; - margin-top: 1.5rem; -} - -/* ===== Responsive Design ===== */ -@media (max-width: 1024px) { - .container, - .add-task-container { - max-width: 90%; - padding: 1.5rem; - } -} - -@media (max-width: 768px) { - .navbar { - flex-direction: column; - gap: 0.75rem; - text-align: center; - padding: 1rem; - } - - .navbar-left { - flex-direction: column; - } - - .navbar-right { - width: 100%; - justify-content: center; - } - - .btn-home { - width: 100%; - max-width: 200px; - } - - .table th, - .table td { - padding: 0.6rem; - font-size: 0.85rem; - } - - .btn { - font-size: 0.85rem; - padding: 0.4rem 0.8rem; - } -} - -@media (max-width: 600px) { - .table thead { - display: none; - } - - .table, - .table tbody, - .table tr, - .table td { - display: block; - width: 100%; - } - - .table tr { - margin-bottom: 1rem; - border: 1px solid #e5e7eb; - padding: 0.75rem; - border-radius: 8px; - } - - .table td { - text-align: right; - position: relative; - padding-left: 50%; - } - - .table td::before { - content: attr(data-label); - position: absolute; - left: 0.75rem; - top: 0.6rem; - font-weight: 600; - text-transform: uppercase; - font-size: 0.7rem; - color: #6b7280; - } -} diff --git a/Frontend/Main.js b/Frontend/Main.js deleted file mode 100644 index cc3ce14..0000000 --- a/Frontend/Main.js +++ /dev/null @@ -1,48 +0,0 @@ -import React, { useState } from "react"; -import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom"; -import TaskListView from "./Task-Management-Application/TaskListView"; -import AddTaskView from "./Task-Management-Application/AddTaskView"; -import "./Task-Management-Application/style.css"; - -function Main() { - const [tasks, setTasks] = useState([]); - - const addTask = (taskDetails) => { - setTasks([...tasks, { ...taskDetails, id: Date.now() }]); - }; - - const deleteTask = (taskId) => { - setTasks(tasks.filter((task) => task.id !== taskId)); - }; - - return ( - - {/* ===== Navbar ===== */} - - - {/* ===== Routes ===== */} - - } - /> - } /> - - - ); -} - -export default Main; diff --git a/Frontend/README.md b/Frontend/README.md deleted file mode 100644 index 3139781..0000000 --- a/Frontend/README.md +++ /dev/null @@ -1 +0,0 @@ -"# Task-Management-Application" diff --git a/Frontend/index.js b/Frontend/index.js deleted file mode 100644 index 080d017..0000000 --- a/Frontend/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import 'bootstrap/dist/css/bootstrap.min.css'; -import Main from './Main'; - -const root = ReactDOM.createRoot(document.getElementById('root')); -root.render( - -
- -); \ No newline at end of file