├── public
├── robots.txt
├── favicon.ico
├── logo192.png
├── logo512.png
├── index.html
└── manifest.json
├── src
├── setupTests.js
├── App.test.js
├── index.js
├── reportWebVitals.js
├── index.css
├── components
│ └── Navbar.js
├── App.js
├── pages
│ ├── Settings.js
│ ├── Dashboard.js
│ └── Tasks.js
├── context
│ └── TaskContext.js
├── logo.svg
└── App.css
├── .gitignore
├── package.json
└── README.md
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NaveenKumar71/Task-Management-App/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NaveenKumar71/Task-Management-App/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NaveenKumar71/Task-Management-App/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | test('renders learn react link', () => {
5 | render();
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 |
6 | const root = createRoot(document.getElementById('root'));
7 | root.render(
8 |
9 |
10 |
11 | );
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Task Management App
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | * {
11 | box-sizing: border-box;
12 | }
13 |
14 | h1, h2, h3, h4, h5, h6 {
15 | margin-top: 0;
16 | }
17 |
18 | button {
19 | cursor: pointer;
20 | }
--------------------------------------------------------------------------------
/src/components/Navbar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router-dom';
3 |
4 | function Navbar() {
5 | return (
6 |
19 | );
20 | }
21 |
22 | export default Navbar;
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
3 | import Navbar from './components/Navbar';
4 | import Dashboard from './pages/Dashboard';
5 | import Tasks from './pages/Tasks';
6 | import Settings from './pages/Settings';
7 | import { TaskProvider } from './context/TaskContext';
8 | import './App.css';
9 |
10 | function App() {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 | } />
19 | } />
20 | } />
21 |
22 |
23 |
24 |
25 |
26 | );
27 | }
28 |
29 | export default App;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "new-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/dom": "^10.4.0",
7 | "@testing-library/jest-dom": "^6.6.3",
8 | "@testing-library/react": "^16.2.0",
9 | "@testing-library/user-event": "^13.5.0",
10 | "chart.js": "^4.4.8",
11 | "date-fns": "^4.1.0",
12 | "react": "^19.1.0",
13 | "react-beautiful-dnd": "^13.1.1",
14 | "react-chartjs-2": "^5.3.0",
15 | "react-dom": "^19.1.0",
16 | "react-router-dom": "^7.4.1",
17 | "react-scripts": "5.0.1",
18 | "web-vitals": "^2.1.4"
19 | },
20 | "scripts": {
21 | "start": "react-scripts start",
22 | "build": "react-scripts build",
23 | "test": "react-scripts test",
24 | "eject": "react-scripts eject"
25 | },
26 | "eslintConfig": {
27 | "extends": [
28 | "react-app",
29 | "react-app/jest"
30 | ]
31 | },
32 | "browserslist": {
33 | "production": [
34 | ">0.2%",
35 | "not dead",
36 | "not op_mini all"
37 | ],
38 | "development": [
39 | "last 1 chrome version",
40 | "last 1 firefox version",
41 | "last 1 safari version"
42 | ]
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/pages/Settings.js:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import { TaskContext } from '../context/TaskContext';
3 |
4 | function Settings() {
5 | const { darkMode, setDarkMode } = useContext(TaskContext);
6 |
7 | return (
8 |
9 |
Settings
10 |
11 |
Theme
12 |
13 |
14 |
15 | setDarkMode(!darkMode)}
19 | id="dark-mode-toggle"
20 | />
21 |
22 |
23 |
24 |
25 |
26 |
About
27 |
Task Management App v1.0.0
28 |
A simple and efficient way to manage your daily tasks.
29 |
30 |
31 |
Contact
32 |
For support or feedback, please email: support@taskapp.com
33 |
34 |
35 | );
36 | }
37 |
38 | export default Settings;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Task Management App
2 |
3 | This project is a simple **Task Management App** built using **React.js**.
4 |
5 | ## Tech Stack
6 | - React.js
7 | - HTML
8 | - CSS
9 | - JavaScript
10 |
11 | ## Getting Started
12 |
13 | ### Prerequisites
14 | Ensure you have **Node.js** and **npm** installed on your system. You can check by running:
15 | ```bash
16 | node -v
17 | npm -v
18 | ```
19 | If not installed, download them from [Node.js Official Website](https://nodejs.org/).
20 |
21 | ### Installation
22 | 1. Clone the repository:
23 | ```bash
24 | git clone https://github.com/NaveenKumar71/Task-Management-App-.git
25 | ```
26 | 2. Navigate into the project directory:
27 | ```bash
28 | cd Task-Management-App
29 | ```
30 | 3. Install dependencies:
31 | ```bash
32 | npm install
33 | ```
34 |
35 | ## Available Scripts
36 |
37 | In the project directory, you can run:
38 |
39 | ### `npm start`
40 | Runs the app in development mode. Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
41 | The page reloads when you make changes, and lint errors are displayed in the console.
42 |
43 | ### `npm run build`
44 | Builds the app for production in the `build` folder. It optimizes React for best performance.
45 |
46 | ### `npm test`
47 | Launches the test runner in interactive watch mode.
48 |
49 | ### `npm run eject`
50 | **Warning:** This is a one-way operation. Once you `eject`, you can't go back!
51 |
52 | ## Features
53 | - Add, edit, and delete tasks
54 | - Mark tasks as completed
55 | - No sign-up required
56 |
57 | ## Deployment
58 | Refer to the [React Deployment Guide](https://facebook.github.io/create-react-app/docs/deployment) for deployment options.
59 |
60 | ## Learn More
61 | To learn more about React, visit the [React Documentation](https://reactjs.org/).
62 |
63 | ## License
64 | This project is licensed under the MIT License.
65 |
66 | ---
67 | ### 🚀 Happy Coding! 🎯
--------------------------------------------------------------------------------
/src/context/TaskContext.js:
--------------------------------------------------------------------------------
1 | import React, { createContext, useState, useEffect } from 'react';
2 |
3 | export const TaskContext = createContext();
4 |
5 | export const TaskProvider = ({ children }) => {
6 | const [tasks, setTasks] = useState(() => {
7 | const savedTasks = localStorage.getItem('tasks');
8 | return savedTasks ? JSON.parse(savedTasks) : [];
9 | });
10 | const [darkMode, setDarkMode] = useState(() => {
11 | const savedMode = localStorage.getItem('darkMode');
12 | return savedMode ? JSON.parse(savedMode) : false;
13 | });
14 |
15 | useEffect(() => {
16 | localStorage.setItem('tasks', JSON.stringify(tasks));
17 | }, [tasks]);
18 |
19 | useEffect(() => {
20 | localStorage.setItem('darkMode', JSON.stringify(darkMode));
21 | if (darkMode) {
22 | document.body.classList.add('dark-mode');
23 | } else {
24 | document.body.classList.remove('dark-mode');
25 | }
26 | }, [darkMode]);
27 |
28 | const addTask = (task) => {
29 | setTasks([...tasks, { ...task, id: Date.now(), completed: false }]);
30 | };
31 |
32 | const toggleTask = (id) => {
33 | setTasks(tasks.map(task =>
34 | task.id === id ? { ...task, completed: !task.completed } : task
35 | ));
36 | };
37 |
38 | const deleteTask = (id) => {
39 | setTasks(tasks.filter(task => task.id !== id));
40 | };
41 |
42 | const editTask = (id, updatedTask) => {
43 | setTasks(tasks.map(task =>
44 | task.id === id ? { ...task, ...updatedTask } : task
45 | ));
46 | };
47 |
48 | const reorderTasks = (startIndex, endIndex) => {
49 | const newTasks = Array.from(tasks);
50 | const [removed] = newTasks.splice(startIndex, 1);
51 | newTasks.splice(endIndex, 0, removed);
52 | setTasks(newTasks);
53 | };
54 |
55 | return (
56 |
66 | {children}
67 |
68 | );
69 | };
--------------------------------------------------------------------------------
/src/pages/Dashboard.js:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import { TaskContext } from '../context/TaskContext';
3 | import { Chart as ChartJS, ArcElement, Tooltip, Legend, CategoryScale, LinearScale, BarElement } from 'chart.js';
4 | import { Pie, Bar } from 'react-chartjs-2';
5 |
6 | ChartJS.register(ArcElement, Tooltip, Legend, CategoryScale, LinearScale, BarElement);
7 |
8 | function Dashboard() {
9 | const { tasks } = useContext(TaskContext);
10 |
11 | const completedTasks = tasks.filter(task => task.completed).length;
12 | const pendingTasks = tasks.length - completedTasks;
13 |
14 | const pieData = {
15 | labels: ['Completed', 'Pending'],
16 | datasets: [{
17 | data: [completedTasks, pendingTasks],
18 | backgroundColor: ['#4CAF50', '#FF5722'],
19 | }]
20 | };
21 |
22 | const priorityData = {
23 | labels: ['High', 'Medium', 'Low'],
24 | datasets: [{
25 | label: 'Tasks by Priority',
26 | data: [
27 | tasks.filter(task => task.priority === 'high').length,
28 | tasks.filter(task => task.priority === 'medium').length,
29 | tasks.filter(task => task.priority === 'low').length,
30 | ],
31 | backgroundColor: ['#f44336', '#ff9800', '#4caf50'],
32 | }]
33 | };
34 |
35 | return (
36 |
37 |
Dashboard
38 |
39 |
40 |
Total Tasks
41 |
{tasks.length}
42 |
43 |
44 |
Completed Tasks
45 |
{completedTasks}
46 |
47 |
48 |
Pending Tasks
49 |
{pendingTasks}
50 |
51 |
52 |
53 |
54 |
Task Status
55 |
56 |
57 |
58 |
Tasks by Priority
59 |
60 |
61 |
62 |
63 | );
64 | }
65 |
66 | export default Dashboard;
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/pages/Tasks.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useContext, useEffect } from 'react';
2 | import { TaskContext } from '../context/TaskContext';
3 | import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
4 | import { format, isValid, parseISO } from 'date-fns';
5 |
6 | function Tasks() {
7 | const { tasks, addTask, toggleTask, deleteTask, editTask, reorderTasks } = useContext(TaskContext);
8 | const [newTask, setNewTask] = useState({
9 | title: '',
10 | description: '',
11 | priority: 'medium',
12 | dueDate: format(new Date(), 'yyyy-MM-dd')
13 | });
14 | const [editingTask, setEditingTask] = useState(null);
15 | const [isFormVisible, setIsFormVisible] = useState(false);
16 | const [filter, setFilter] = useState('all');
17 |
18 | // ✅ Motivational quotes logic inside component
19 | const motivationalQuotes = [
20 | "Stay focused and never give up.",
21 | "Your only limit is your mind.",
22 | "Push yourself, because no one else is going to do it for you.",
23 | "Dream it. Wish it. Do it.",
24 | "Don’t watch the clock; do what it does — keep going.",
25 | "Great things never come from comfort zones.",
26 | "Success doesn’t come to you. You go to it.",
27 | "Believe in yourself and all that you are.",
28 | ];
29 |
30 | const [quoteIndex, setQuoteIndex] = useState(0);
31 |
32 | useEffect(() => {
33 | const interval = setInterval(() => {
34 | setQuoteIndex(prevIndex => (prevIndex + 1) % motivationalQuotes.length);
35 | }, 3000);
36 |
37 | return () => clearInterval(interval);
38 | }, []);
39 |
40 | const formatDate = (dateString) => {
41 | try {
42 | const date = parseISO(dateString);
43 | if (isValid(date)) {
44 | return format(date, 'MMM dd, yyyy');
45 | }
46 | return 'No due date';
47 | } catch {
48 | return 'No due date';
49 | }
50 | };
51 |
52 | const handleSubmit = (e) => {
53 | e.preventDefault();
54 | if (editingTask) {
55 | editTask(editingTask.id, newTask);
56 | setEditingTask(null);
57 | } else {
58 | addTask(newTask);
59 | }
60 | setNewTask({
61 | title: '',
62 | description: '',
63 | priority: 'medium',
64 | dueDate: format(new Date(), 'yyyy-MM-dd')
65 | });
66 | setIsFormVisible(false);
67 | };
68 |
69 | const startEdit = (task) => {
70 | setEditingTask(task);
71 | setNewTask({
72 | title: task.title,
73 | description: task.description,
74 | priority: task.priority,
75 | dueDate: task.dueDate || format(new Date(), 'yyyy-MM-dd')
76 | });
77 | setIsFormVisible(true);
78 | };
79 |
80 | const handleDragEnd = (result) => {
81 | if (!result.destination) return;
82 | reorderTasks(result.source.index, result.destination.index);
83 | };
84 |
85 | const filteredTasks = tasks.filter(task => {
86 | switch(filter) {
87 | case 'completed':
88 | return task.completed;
89 | case 'pending':
90 | return !task.completed;
91 | default:
92 | return true;
93 | }
94 | });
95 |
96 | return (
97 |
98 |
99 |
Tasks
100 |
101 |
110 |
116 |
117 |
118 |
119 |
152 |
153 | {/* ✅ Quote Display Section */}
154 |
155 |
{motivationalQuotes[quoteIndex]}
156 |
157 |
158 |
159 |
160 | {(provided) => (
161 |
166 | {filteredTasks.map((task, index) => (
167 |
172 | {(provided) => (
173 |
179 |
180 |
181 | {task.title}
182 |
183 |
184 | {task.priority}
185 |
186 |
187 |
{task.description}
188 |
Due: {formatDate(task.dueDate)}
189 |
190 |
193 |
194 |
195 |
196 |
197 | )}
198 |
199 | ))}
200 | {provided.placeholder}
201 |
202 | )}
203 |
204 |
205 |
206 | );
207 | }
208 |
209 | export default Tasks;
210 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | /* General Styles */
2 | :root {
3 | --bg-primary: #f5f5f5;
4 | --bg-secondary: #ffffff;
5 | --text-primary: #333333;
6 | --text-secondary: #666666;
7 | --accent-primary: #1a237e;
8 | --accent-secondary: #0d47a1;
9 | --success: #4caf50;
10 | --warning: #ff9800;
11 | --error: #f44336;
12 | --card-shadow: 0 4px 15px rgba(0,0,0,0.05);
13 | }
14 |
15 | .dark-mode {
16 | --bg-primary: #121212;
17 | --bg-secondary: #1e1e1e;
18 | --text-primary: #ffffff;
19 | --text-secondary: #b0b0b0;
20 | --accent-primary: #64ffda;
21 | --accent-secondary: #00b4d8;
22 | --card-shadow: 0 4px 15px rgba(0,0,0,0.2);
23 | }
24 |
25 | body {
26 | background-color: var(--bg-primary);
27 | color: var(--text-primary);
28 | transition: background-color 0.3s ease, color 0.3s ease;
29 | }
30 |
31 | .app {
32 | min-height: 100vh;
33 | }
34 |
35 | .main-content {
36 | padding: 20px;
37 | margin-top: 70px;
38 | }
39 |
40 | /* Navbar Styles */
41 | .navbar {
42 | position: fixed;
43 | top: 0;
44 | width: 100%;
45 | background: linear-gradient(135deg, var(--accent-primary) 0%, var(--accent-secondary) 100%);
46 | padding: 15px 30px;
47 | display: flex;
48 | justify-content: space-between;
49 | align-items: center;
50 | color: white;
51 | box-shadow: var(--card-shadow);
52 | z-index: 1000;
53 | }
54 |
55 | .nav-brand {
56 | display: flex;
57 | align-items: center;
58 | }
59 |
60 | .nav-brand h1 {
61 | margin: 0;
62 | font-size: 1.8rem;
63 | font-weight: 700;
64 | }
65 |
66 | .nav-brand h1 span:first-child {
67 | color: #cf4efe;
68 | }
69 |
70 | .nav-brand h1 span:last-child {
71 | color: #d0f001;
72 | }
73 |
74 | .nav-links {
75 | display: flex;
76 | list-style: none;
77 | margin: 0;
78 | padding: 0;
79 | gap: 30px;
80 | }
81 |
82 | .nav-links li a {
83 | color: white;
84 | text-decoration: none;
85 | font-weight: 500;
86 | font-size: 1.1rem;
87 | transition: color 0.3s ease;
88 | padding: 8px 16px;
89 | border-radius: 20px;
90 | }
91 |
92 | .nav-links li a:hover {
93 | color: #64ffda;
94 | background: rgba(255, 255, 255, 0.1);
95 | }
96 |
97 | /* Tasks Page Styles */
98 | .tasks-header {
99 | display: flex;
100 | justify-content: space-between;
101 | align-items: center;
102 | margin-bottom: 20px;
103 | }
104 |
105 | .tasks-controls {
106 | display: flex;
107 | gap: 15px;
108 | }
109 |
110 | .filter-select {
111 | padding: 10px 20px;
112 | border-radius: 20px;
113 | border: 2px solid var(--accent-primary);
114 | background: var(--bg-secondary);
115 | color: var(--text-primary);
116 | font-size: 1rem;
117 | cursor: pointer;
118 | }
119 |
120 | .task-form {
121 | background: var(--bg-secondary);
122 | color: var(--text-primary);
123 | padding: 25px;
124 | border-radius: 15px;
125 | margin-bottom: 30px;
126 | box-shadow: 0 4px 15px rgba(0,0,0,0.05);
127 | display: none;
128 | }
129 |
130 | .task-form.visible {
131 | display: block;
132 | animation: slideDown 0.3s ease;
133 | }
134 |
135 | @keyframes slideDown {
136 | from {
137 | opacity: 0;
138 | transform: translateY(-20px);
139 | }
140 | to {
141 | opacity: 1;
142 | transform: translateY(0);
143 | }
144 | }
145 |
146 | .task-form input,
147 | .task-form textarea,
148 | .task-form select {
149 | width: 100%;
150 | padding: 12px;
151 | margin-bottom: 15px;
152 | border: 2px solid #e0e0e0;
153 | border-radius: 8px;
154 | font-size: 1rem;
155 | transition: border-color 0.3s ease;
156 | }
157 |
158 | .task-form input:focus,
159 | .task-form textarea:focus,
160 | .task-form select:focus {
161 | border-color: #1a237e;
162 | outline: none;
163 | }
164 |
165 | .task-form button {
166 | background: #1a237e;
167 | color: white;
168 | border: none;
169 | padding: 12px 24px;
170 | border-radius: 8px;
171 | font-size: 1rem;
172 | cursor: pointer;
173 | transition: all 0.3s ease;
174 | }
175 |
176 | .task-form button:hover {
177 | background: #0d47a1;
178 | transform: translateY(-2px);
179 | }
180 |
181 | .task-card {
182 | background: var(--bg-secondary);
183 | color: var(--text-primary);
184 | cursor: grab;
185 | padding: 20px;
186 | border-radius: 15px;
187 | box-shadow: var(--card-shadow);
188 | transition: transform 0.3s ease;
189 | }
190 |
191 | .task-card:active {
192 | cursor: grabbing;
193 | }
194 |
195 | .task-card:hover {
196 | transform: translateY(-5px);
197 | }
198 |
199 | .task-card.completed {
200 | background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
201 | }
202 |
203 | .completed-title {
204 | text-decoration: line-through;
205 | color: var(--text-secondary);
206 | }
207 |
208 | .due-date {
209 | color: var(--text-secondary);
210 | font-size: 0.9rem;
211 | margin: 10px 0;
212 | }
213 |
214 | .task-header {
215 | display: flex;
216 | justify-content: space-between;
217 | align-items: center;
218 | margin-bottom: 15px;
219 | }
220 |
221 | .task-header h3 {
222 | margin: 0;
223 | color: var(--accent-primary);
224 | }
225 |
226 | .priority {
227 | padding: 6px 12px;
228 | border-radius: 20px;
229 | font-size: 0.9rem;
230 | font-weight: 500;
231 | text-transform: capitalize;
232 | }
233 |
234 | .priority.high {
235 | background: #ffebee;
236 | color: #c62828;
237 | }
238 |
239 | .priority.medium {
240 | background: #fff3e0;
241 | color: #ef6c00;
242 | }
243 |
244 | .priority.low {
245 | background: #e8f5e9;
246 | color: #2e7d32;
247 | }
248 |
249 | .task-actions {
250 | display: flex;
251 | gap: 10px;
252 | margin-top: 15px;
253 | }
254 |
255 | .task-actions button {
256 | flex: 1;
257 | padding: 8px 16px;
258 | border: none;
259 | border-radius: 20px;
260 | cursor: pointer;
261 | font-weight: 500;
262 | transition: all 0.3s ease;
263 | }
264 |
265 | .task-actions button:nth-child(1) {
266 | background: var(--success);
267 | color: white;
268 | }
269 |
270 | .task-actions button:nth-child(2) {
271 | background: var(--accent-secondary);
272 | color: white;
273 | }
274 |
275 | .task-actions button:nth-child(3) {
276 | background: var(--error);
277 | color: white;
278 | }
279 |
280 | .task-actions button:hover {
281 | transform: translateY(-2px);
282 | box-shadow: 0 4px 8px rgba(0,0,0,0.1);
283 | }
284 |
285 | /* Toggle Switch Styles */
286 | .toggle-switch {
287 | position: relative;
288 | width: 60px;
289 | height: 34px;
290 | }
291 |
292 | .toggle-switch input {
293 | opacity: 0;
294 | width: 0;
295 | height: 0;
296 | }
297 |
298 | .toggle-switch label {
299 | position: absolute;
300 | cursor: pointer;
301 | top: 0;
302 | left: 0;
303 | right: 0;
304 | bottom: 0;
305 | background-color: #ccc;
306 | transition: .4s;
307 | border-radius: 34px;
308 | }
309 |
310 | .toggle-switch label:before {
311 | position: absolute;
312 | content: "";
313 | height: 26px;
314 | width: 26px;
315 | left: 4px;
316 | bottom: 4px;
317 | background-color: white;
318 | transition: .4s;
319 | border-radius: 50%;
320 | }
321 |
322 | .toggle-switch input:checked + label {
323 | background-color: var(--accent-primary);
324 | }
325 |
326 | .toggle-switch input:checked + label:before {
327 | transform: translateX(26px);
328 | }
329 |
330 | /* Settings Page Styles */
331 | .settings-page {
332 | max-width: 800px;
333 | margin: 0 auto;
334 | padding: 20px;
335 | }
336 |
337 | .settings-section {
338 | background: var(--bg-secondary);
339 | padding: 25px;
340 | border-radius: 15px;
341 | margin-bottom: 30px;
342 | box-shadow: var(--card-shadow);
343 | }
344 |
345 | .settings-section h2 {
346 | color: var(--accent-primary);
347 | margin-bottom: 20px;
348 | }
349 |
350 | .preference-item {
351 | display: flex;
352 | justify-content: space-between;
353 | align-items: center;
354 | padding: 15px 0;
355 | border-bottom: 1px solid var(--text-secondary);
356 | }
357 |
358 | .preference-item:last-child {
359 | border-bottom: none;
360 | }
361 |
362 | .preference-item select {
363 | padding: 8px 16px;
364 | border: 2px solid var(--text-secondary);
365 | border-radius: 8px;
366 | font-size: 1rem;
367 | transition: border-color 0.3s ease;
368 | background: var(--bg-secondary);
369 | color: var(--text-primary);
370 | }
371 |
372 | .preference-item select:focus {
373 | border-color: var(--accent-primary);
374 | outline: none;
375 | }
376 | /* Dashboard Specific Styles */
377 | .dashboard {
378 | padding: 20px;
379 | }
380 |
381 | .stats-container {
382 | display: flex;
383 | gap: 20px;
384 | flex-wrap: wrap;
385 | margin-bottom: 30px;
386 | }
387 |
388 | .stat-card {
389 | background: var(--bg-secondary);
390 | color: var(--text-primary);
391 | flex: 1;
392 | min-width: 200px;
393 | padding: 20px;
394 | border-radius: 15px;
395 | box-shadow: var(--card-shadow);
396 | text-align: center;
397 | transition: transform 0.3s ease;
398 | }
399 |
400 | .stat-card:hover {
401 | transform: translateY(-5px);
402 | }
403 |
404 | .stat-card h3 {
405 | margin: 0 0 10px;
406 | color: var(--accent-primary);
407 | font-size: 1.2rem;
408 | }
409 |
410 | .stat-card p {
411 | font-size: 1.8rem;
412 | font-weight: bold;
413 | margin: 0;
414 | }
415 |
416 | .charts-container {
417 | display: flex;
418 | flex-wrap: wrap;
419 | gap: 30px;
420 | justify-content: center;
421 | }
422 |
423 | .chart {
424 | background: var(--bg-secondary);
425 | padding: 20px;
426 | border-radius: 15px;
427 | box-shadow: var(--card-shadow);
428 | width: 100%;
429 | max-width: 400px;
430 | text-align: center;
431 | }
432 |
433 | .chart h3 {
434 | margin-bottom: 15px;
435 | color: var(--accent-primary);
436 | }
437 | /* Enhance Add Task Button */
438 | .add-task-button {
439 | padding: 10px 24px;
440 | background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));
441 | color: white;
442 | font-size: 1rem;
443 | font-weight: bold;
444 | border: none;
445 | border-radius: 30px;
446 | cursor: pointer;
447 | transition: all 0.3s ease;
448 | box-shadow: 0 4px 10px rgba(0,0,0,0.1);
449 | }
450 |
451 | .add-task-button:hover {
452 | transform: translateY(-2px);
453 | background: linear-gradient(135deg, var(--accent-secondary), var(--accent-primary));
454 | }
455 |
456 | /* Refined Dropdown Filter */
457 | .filter-select {
458 | padding: 10px 20px;
459 | border-radius: 30px;
460 | border: 2px solid var(--accent-primary);
461 | background: linear-gradient(145deg, var(--bg-secondary), #e0e0e0);
462 | color: var(--accent-primary);
463 | font-weight: 500;
464 | font-size: 1rem;
465 | cursor: pointer;
466 | transition: all 0.3s ease;
467 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
468 | }
469 |
470 | .filter-select:hover {
471 | border-color: var(--accent-secondary);
472 | }
473 |
474 | /* Shrink and Polish Task Card */
475 | .task-card {
476 | background: var(--bg-secondary);
477 | color: var(--text-primary);
478 | cursor: grab;
479 | padding: 16px;
480 | margin-bottom: 15px;
481 | border-radius: 12px;
482 | box-shadow: var(--card-shadow);
483 | transition: transform 0.3s ease, box-shadow 0.3s ease;
484 | max-width: 700px;
485 | margin-left: auto;
486 | margin-right: auto;
487 | }
488 |
489 | .task-card:hover {
490 | transform: scale(1.01);
491 | box-shadow: 0 6px 20px rgba(0, 0, 0, 0.07);
492 | }
493 |
494 | /* Optional: Style the Task Form Toggle */
495 | .task-form.visible {
496 | margin-top: 10px;
497 | animation: fadeIn 0.3s ease-in-out;
498 | }
499 |
500 | @keyframes fadeIn {
501 | from { opacity: 0; transform: scale(0.98); }
502 | to { opacity: 1; transform: scale(1); }
503 | }
504 |
505 | /* Better spacing in task list */
506 | .tasks-list {
507 | display: flex;
508 | flex-direction: column;
509 | gap: 15px;
510 | margin-top: 10px;
511 | }
512 | /* Container with two-column layout */
513 | .tasks-page {
514 | display: flex;
515 | gap: 30px;
516 | align-items: flex-start;
517 | flex-wrap: wrap;
518 | padding: 20px;
519 | }
520 |
521 | /* Left: Task List */
522 | .tasks-list {
523 | flex: 2;
524 | display: flex;
525 | flex-direction: column;
526 | gap: 15px;
527 | min-width: 300px;
528 | }
529 |
530 | /* Right: Task Form */
531 | .task-form {
532 | flex: 1;
533 | max-width: 400px;
534 | position: sticky;
535 | top: 100px;
536 | align-self: flex-start;
537 | }
538 |
539 | /* Make sure form always shows when visible */
540 | .task-form.visible {
541 | display: block;
542 | animation: slideInRight 0.3s ease;
543 | }
544 |
545 | @keyframes slideInRight {
546 | from {
547 | opacity: 0;
548 | transform: translateX(20px);
549 | }
550 | to {
551 | opacity: 1;
552 | transform: translateX(0);
553 | }
554 | }
555 |
556 | /* Header styles: make filters + add button stand out */
557 | .tasks-header {
558 | width: 100%;
559 | display: flex;
560 | justify-content: space-between;
561 | align-items: center;
562 | flex-wrap: wrap;
563 | background: var(--bg-secondary);
564 | padding: 15px 20px;
565 | border-radius: 12px;
566 | box-shadow: var(--card-shadow);
567 | margin-bottom: 20px;
568 | }
569 |
570 | /* Adjust task card width */
571 | .task-card {
572 | width: 100%;
573 | }
574 |
575 | /* Responsive behavior */
576 | @media (max-width: 768px) {
577 | .tasks-page {
578 | flex-direction: column;
579 | }
580 |
581 | .task-form {
582 | position: static;
583 | max-width: 100%;
584 | width: 100%;
585 | }
586 | }
587 | /* Motivation Quote Section */
588 | .motivation-quote {
589 | flex: 1;
590 | max-width: 400px;
591 | padding: 40px 20px;
592 | text-align: center;
593 | background: linear-gradient(135deg, rgba(255, 0, 150, 0.1), rgba(0, 229, 255, 0.1));
594 | border-radius: 20px;
595 | box-shadow: var(--card-shadow);
596 | animation: fadeIn 1s ease-in-out;
597 | }
598 |
599 | .motivation-quote h2 {
600 | font-size: 2rem;
601 | font-weight: bold;
602 | background: linear-gradient(to right, rgb(0,255,164), rgb(166,0,255));
603 | -webkit-background-clip: text;
604 | -webkit-text-fill-color: transparent;
605 | text-shadow: 2px 2px rgba(0,0,0,0.1);
606 | }
607 |
608 | /* Responsive - hide on mobile */
609 | @media (max-width: 768px) {
610 | .motivation-quote {
611 | display: none;
612 | }
613 | }
614 |
--------------------------------------------------------------------------------