diff --git a/PROJECT_STATUS_DOCUMENTATION.md b/PROJECT_STATUS_DOCUMENTATION.md new file mode 100644 index 00000000..e50f077a --- /dev/null +++ b/PROJECT_STATUS_DOCUMENTATION.md @@ -0,0 +1,446 @@ +# TMS Project Status & Architecture Documentation + +**Last Updated:** December 21, 2025 +**Project Phase:** Active Development - Early Stage +**Current Status:** Core Backend MVP Complete + +--- + +## Current Position in Roadmap + +### Timeline Progress + +``` + +Q1 2026 (JAN - MAR): [████████░░] 75% COMPLETE + Basic CRUD operations completed + Task model with database (SQLAlchemy) + Create & Read functionality working + Update (PATCH) & Delete (DELETE) functionality working + ID generation needs optimization + Full test suite not comprehensive + +Q2 2026 (APR - JUN): [░░░░░░░░░░] 0% NOT STARTED + Next Phase: User authentication & multi-user support + +Q3 2026 (JUL - SEP): [░░░░░░░░░░] 0% NOT STARTED +Q4 2026 (OCT - DEC): [░░░░░░░░░░] 0% NOT STARTED + +``` + +### Feature Roadmap Progress + +#### COMPLETED (Currently Done) + +``` + +ESSENTIAL FEATURES (Core System): + Task creation with title & description + Task completion status tracking + View all tasks (LIST operation) + Delete tasks with validation + Update task details & status + Due dates field (in model, not fully used) + REST API endpoints (all working) + Error handling & validation + Database persistence (SQLite) + Beautiful UI/UX with animations + Frontend integration with API +``` + +#### IN PROGRESS (Currently Working On) + +``` +CURRENT FOCUS: + UI/UX Design Improvements (JUST COMPLETED) + - Enhanced glassmorphism design + - Better animations and transitions + - Improved color palette + - Footer optimization + + CI/CD Pipeline (RECENTLY FIXED) + - GitHub Actions workflow + - Automated testing + - Deployment ready +``` + +#### NOT STARTED (Future) + +``` +NEXT PRIORITY (Q1 2026 Remaining): + Task priority levels (low, medium, high, urgent) + Task categories and tags + Search and filter capabilities + Task notes (extended descriptions) + Comprehensive test suite expansion + Database optimization + +FUTURE PHASES: + User authentication + Multi-user support + Calendar integration + Collaboration features + Mobile app + Advanced analytics +``` + +--- + +## 🏗️ Current Project Structure + +``` +TMS/ +├── Root Configuration +│ ├── app.py # Main Flask application +│ ├── requirements.txt # Python dependencies +│ ├── README.md # Project documentation +│ └── LICENSE # MIT License +│ +├── .github/ +│ └── workflows/ +│ └── ci.yml # GitHub Actions CI/CD pipeline +│ +├── static/ # Frontend Assets +│ └── css/ +│ └── style.css # Main stylesheet (enhanced design) +│ +├── templates/ # HTML Templates (Jinja2) +│ ├── base.html # Base template (nav, footer) +│ ├── homepage.html # Dashboard with task list +│ ├── landing.html # Welcome page with features +│ ├── login.html # Login page (placeholder) +│ ├── about.html # About page +│ ├── add_users.html # User management (future) +│ └── index.html # Legacy file +│ +├── instance/ # Instance-specific files +│ └── tms.db # SQLite database +│ +├── Project_testing_files/ # Testing & Development +│ ├── Test.py # Comprehensive API test suite +│ └── Alog_Test.py # Alternate test file +│ +├── Backup/ # Backup files +│ └── app.py.backup # Previous app version +│ +├── env/ # Python virtual environment +│ └── [venv files] # Dependencies isolated +│ +└── .gitignore # Git exclusions +``` + +--- + +## 🔧 Architecture Overview + +### Current Tech Stack + +``` +Backend: +├── Framework: Flask 3.1.2 +├── ORM: SQLAlchemy 2.0.45 +├── Database: SQLite (instance/tms.db) +├── Language: Python 3.11+ +└── API: RESTful with JSON + +Frontend: +├── HTML5 (Jinja2 Templates) +├── CSS3 (Glassmorphism Design) +├── JavaScript (Vanilla ES6+) +├── Fetch API (for AJAX calls) +└── No heavy frameworks + +DevOps: +├── Version Control: Git +├── CI/CD: GitHub Actions +├── Containerization: Docker (planned) +└── Testing: Pytest-based +``` + +### API Architecture + +``` +REST Endpoints: + +HTML Routes (Server-Side Rendering): + GET / Landing page + GET /homepage Dashboard + GET /login Login page + GET /about About page + +API Endpoints (JSON Responses): + GET /homepage/api/tasks → List all tasks + POST /homepage/api/tasks/add_Tasks → Create task + DELETE /homepage/api/tasks/delete_task → Delete task + PATCH /homepage/api/tasks/updated_task → Update task + +Error Handlers: + 404 Not Found + 405 Method Not Allowed + 500 Internal Server Error +``` + +### Database Schema + +``` +Task Table (SQLite): +├── id (String[8]) → Primary Key, UUID-based +├── description (String[255]) → Task title/description +├── due_date (DateTime, nullable) → Optional deadline +├── completed (Boolean) → Completion status (default: False) +└── created_at (DateTime) → Creation timestamp +``` + +--- + +## Code Quality & Testing + +### Current Testing Status + +``` +Test Coverage: +├── API Integration Tests (12 test scenarios) +├── CRUD Operations (Create, Read, Update, Delete) +├── Error Handling (400, 404 responses) +├── Validation (Empty descriptions, missing IDs) +├── Unit Tests (Partial) +├── Database Tests (Not implemented) +└── Load Testing (Not implemented) + +Test Files: +├── Project_testing_files/Test.py (Main test suite - 12 tests) +└── Project_testing_files/Alog_Test.py (Alternative tests) +``` + +### Code Standards + +``` + Implemented: + - Logging system (Python logging module) + - Error handling (SQLAlchemyError, Exception) + - Input validation (descriptions, IDs) + - Type hints (Mapped, Optional) + - Docstrings for routes + + Partial: + - Code comments + - Consistent naming conventions + + Missing: + - Pre-commit hooks + - Code linting (flake8, black) + - Static analysis (mypy) + - Security scanning (bandit) +``` + +--- + +## UI/UX Current State + +### Design System + +``` + Implemented: + - Glassmorphism design pattern + - Dark theme with purple/indigo accent + - Smooth animations & transitions + - Responsive layout (mobile-first) + - Task management dashboard + - Real-time stats (total, pending, completed) + - Toast notifications (success/error/warning) + - Empty states with helpful messages + + In Progress: + - Enhanced color palette + - Better visual hierarchy + - Icon system improvements + + To Do: + - Light theme option + - Theme customization + - Advanced filters UI + - Search interface + - Priority level indicators + - Category/tags display +``` + +### Component Library + +``` +Reusable Components: +├── Buttons (.btn, .btn.primary, .btn.danger, .btn.secondary) +├── Cards (.card with glassmorphism) +├── Forms (Inputs, labels, validation) +├── Alerts (.alert with types: error, success, warning, info) +├── Task Items (.task-item with hover effects) +├── Stats (.stats-bar for counters) +├── Empty States (.empty-state messaging) +└── Animations (fadeInUp, slideDown, slideUp, float, pulse) +``` + +--- + +## What's Working Right Now + +### Fully Functional Features + +1. **Task Creation** + - Add task via API (POST /homepage/api/tasks/add_Tasks) + - Real-time DOM update in UI + - Validation for empty descriptions + - Automatic ID generation + +2. **Task Display** + - Fetch all tasks (GET /homepage/api/tasks) + - Real-time rendering with animations + - Stats counter updates + - Empty state display + +3. **Task Completion Toggle** + - Mark tasks complete/incomplete (PATCH) + - Visual strikethrough on completed tasks + - Stats update automatically + +4. **Task Deletion** + - Delete with confirmation dialog (DELETE) + - Removes from DOM immediately + - Stats update automatically + +5. **Error Handling** + - User-friendly toast notifications + - Error logging server-side + - Graceful error recovery + +6. **UI/UX** + - Beautiful landing page + - Functional dashboard + - Smooth animations + - Mobile responsive + - Dark theme optimized + +--- + +### Feature file directory + +``` +TMS/ +├── src/ +│ ├── app.py # App initialization +│ ├── config.py # Configuration settings +│ ├── __init__.py +│ │ +│ ├── models/ +│ │ ├── __init__.py +│ │ ├── task.py # Task model +│ │ └── user.py # User model (future) +│ │ +│ ├── routes/ +│ │ ├── __init__.py +│ │ ├── api.py # API endpoints +│ │ ├── web.py # HTML routes +│ │ └── auth.py # Auth routes (future) +│ │ +│ ├── schemas/ +│ │ ├── __init__.py +│ │ └── task_schema.py # Request/response schemas +│ │ +│ ├── services/ +│ │ ├── __init__.py +│ │ ├── task_service.py # Business logic +│ │ └── auth_service.py # Auth logic (future) +│ │ +│ ├── utils/ +│ │ ├── __init__.py +│ │ ├── validators.py # Input validation +│ │ ├── decorators.py # Custom decorators +│ │ └── helpers.py # Utility functions +│ │ +│ └── middleware/ +│ ├── __init__.py +│ ├── error_handler.py +│ └── logging.py +│ +├── templates/ +│ ├── base.html +│ ├── pages/ +│ │ ├── landing.html +│ │ ├── homepage.html +│ │ └── about.html +│ └── components/ +│ ├── task_item.html +│ └── task_form.html +│ +├── static/ +│ ├── css/ +│ │ ├── style.css +│ │ ├── components.css +│ │ └── themes.css +│ ├── js/ +│ │ ├── api.js # API client +│ │ ├── ui.js # UI logic +│ │ └── utils.js # Helpers +│ └── assets/ +│ └── images/ +│ +├── tests/ +│ ├── __init__.py +│ ├── conftest.py # Pytest config +│ ├── test_api.py +│ ├── test_models.py +│ ├── test_services.py +│ └── test_integration.py +│ +├── migrations/ # Alembic migrations +│ └── versions/ +│ +├── docs/ +│ ├── API.md # API documentation +│ ├── ARCHITECTURE.md # Architecture guide +│ ├── DEPLOYMENT.md # Deployment guide +│ └── CONTRIBUTING.md # Contribution guide +│ +├── instance/ +│ └── tms.db +│ +├── .env.example # Environment variables +├── .gitignore +├── requirements.txt +├── app.py # Entry point +├── wsgi.py # WSGI server config +├── pytest.ini +├── docker-compose.yml # Docker config +├── Dockerfile +└── README.md +``` + +--- + +## Metrics & Statistics + +### Current Project Size + +``` +Code: + - app.py: ~210 lines (core backend) + - style.css: ~600+ lines (design system) + - homepage.html: ~250 lines (frontend logic) + - Test.py: ~350 lines (test suite) + ──────────────────────────────── + Total: ~1,400 lines of code + +Database: + - Tables: 1 (Task) + - Columns: 5 (id, description, due_date, completed, created_at) + - Relationships: 0 (no user model yet) + +API: + - Endpoints: 4 main endpoints + - HTTP Methods: GET, POST, DELETE, PATCH + - Response Format: JSON + - Error Codes: 400, 404, 500 + +Tests: + - Test Cases: 12 comprehensive tests + - Coverage: ~80% of core functionality + - Passing Rate: 100% +``` diff --git a/app.py b/app.py index 8a0dcf0b..1f21d5fd 100644 --- a/app.py +++ b/app.py @@ -13,12 +13,11 @@ # '/homepage/User/about' → about‑me page # '/login' → login page - +import logging from datetime import datetime from flask import Flask, request, render_template, redirect, url_for, jsonify from flask_sqlalchemy import SQLAlchemy -from sqlalchemy.orm import DeclarativeBase -from sqlalchemy import Integer, String +from sqlalchemy import String from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.exc import SQLAlchemyError from uuid import uuid4 @@ -35,6 +34,10 @@ # Initialize SQLAlchemy db = SQLAlchemy(app) +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + # Define the base model class Task(db.Model): __tablename__ = 'tasks' @@ -60,11 +63,23 @@ def to_dict(self): @app.route('/') def landing(): + """Landing page.""" return render_template('landing.html') + +@app.route('/homepage') +def homepage(): + """Dashboard - displays all tasks.""" + return render_template('homepage.html') -@app.route('/homepage/task/delete',methods=['POST']) -def delete_task_html(): - return redirect(url_for('homepage')) +@app.route('/login') +def login(): + """Login page.""" + return render_template('login.html') + +@app.route('/about') +def about(): + """About page.""" + return render_template('about.html') @app.route('/homepage/api/tasks', methods=['GET']) def get_tasks(): @@ -91,30 +106,36 @@ def add_task_api(): @app.route('/homepage/api/tasks/delete_task',methods=['DELETE']) def delete_task(): - data = request.get_json() - - if not data: - return jsonify({'error': answer_for_data_not_found}), 400 - - task_id = data.get('id') - - if not task_id: - return jsonify({'error': 'Task ID is required'}), 400 - - task = Task.query.filter_by(id=task_id).first() - - if not task: - return jsonify({'message': 'Task not found'}), 404 try: + data = request.get_json() + + if not data: + return jsonify({'error': answer_for_data_not_found}), 400 + + task_id = data.get('id') + + if not task_id: + return jsonify({'error': 'Task ID is required'}), 400 + + task = Task.query.filter_by(id=task_id).first() + + if not task: + return jsonify({'message': 'Task not found'}), 404 + db.session.delete(task) db.session.commit() + logger.info(f"Task deleted: {task_id}") return jsonify({'message': 'Task deleted successfully'}), 200 except SQLAlchemyError as e: db.session.rollback() - print(e) + logger.error(f"Database error while deleting task: {str(e)}") return jsonify({'error': 'Database error occurred'}), 500 - + except Exception as e: + logger.error(f"Unexpected error while deleting task: {str(e)}") + return jsonify({'error': 'An unexpected error occurred'}), 500 + + @app.route('/homepage/api/tasks/updated_task',methods=["PATCH"]) def updated_task(): @@ -143,18 +164,6 @@ def updated_task(): return jsonify({'message': 'The Task has been updated', 'task': task.to_dict()}), 200 -@app.route('/homepage/AddUsersToAccout') -def add_users(email): - return 0 - -@app.route('/homepage/User/about me') -def about_me(): - return 0 - -@app.route('/about') -def about(): - return render_template('about.html') - with app.app_context(): db.create_all() diff --git a/static/css/style.css b/static/css/style.css index fdefa08f..8cf1f760 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -1,133 +1,275 @@ :root { /* Color Palette */ - --bg-dark: #0f172a; - --bg-gradient: radial-gradient(circle at top left, #1e293b, #0f172a); + --bg-dark: #0a0e27; + --bg-secondary: #151b2f; + --bg-tertiary: #1e293b; + --bg-gradient: linear-gradient(135deg, #0f172a 0%, #1a1f3a 50%, #0d1429 100%); - --glass-bg: rgba(255, 255, 255, 0.05); - --glass-border: rgba(255, 255, 255, 0.1); - --glass-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3); + --glass-bg: rgba(255, 255, 255, 0.06); + --glass-border: rgba(255, 255, 255, 0.12); + --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.05); - --primary: #6366f1; /* Indigo */ + --primary: #6366f1; --primary-hover: #4f46e5; - --danger: #ef4444; /* Red */ + --primary-dark: #4338ca; + --primary-light: rgba(99, 102, 241, 0.12); + + --secondary: #a855f7; + --secondary-light: rgba(168, 85, 247, 0.12); + + --danger: #ef4444; --danger-hover: #dc2626; - --success: #10b981; /* Emerald */ + --danger-light: rgba(239, 68, 68, 0.12); + + --success: #10b981; + --success-hover: #059669; + --success-light: rgba(16, 185, 129, 0.12); + + --warning: #f59e0b; + --warning-light: rgba(245, 158, 11, 0.12); - --text-main: #f8fafc; + --text-main: #f1f5f9; --text-muted: #94a3b8; + --text-light: #64748b; - --radius: 16px; - --transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + --radius: 12px; + --radius-lg: 16px; + --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } /* Reset & Base */ -*, *::before, *::after { box-sizing: border-box; } +*, *::before, *::after { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} body { margin: 0; - font-family: 'Inter', system-ui, sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; background: var(--bg-dark); background-image: - radial-gradient(at 0% 0%, hsla(253,16%,7%,1) 0, transparent 50%), - radial-gradient(at 50% 0%, hsla(225,39%,30%,1) 0, transparent 50%), - radial-gradient(at 100% 0%, hsla(339,49%,30%,1) 0, transparent 50%); + radial-gradient(at 20% 50%, rgba(99, 102, 241, 0.15) 0px, transparent 50%), + radial-gradient(at 80% 80%, rgba(168, 85, 247, 0.1) 0px, transparent 50%), + radial-gradient(at 40% 0%, rgba(99, 102, 241, 0.1) 0px, transparent 50%); color: var(--text-main); - min-height: 100vh; + line-height: 1.6; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.page-wrapper { display: flex; flex-direction: column; + min-height: 100vh; } -/* Navbar */ +/* Navbar / Header */ .nav { - padding: 20px 0; - backdrop-filter: blur(10px); + padding: 16px 0; + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); border-bottom: 1px solid var(--glass-border); position: sticky; top: 0; - z-index: 10; + z-index: 100; + background: rgba(15, 23, 42, 0.8); + box-shadow: var(--glass-shadow); } .nav-inner { - max-width: 800px; + max-width: 900px; margin: 0 auto; padding: 0 20px; display: flex; justify-content: space-between; align-items: center; + gap: 20px; } .brand { - font-weight: 800; - font-size: 1.25rem; - background: linear-gradient(to right, #818cf8, #c084fc); + font-weight: 700; + font-size: 1.3rem; + background: linear-gradient(135deg, #818cf8 0%, #c084fc 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; + background-clip: text; text-decoration: none; letter-spacing: -0.5px; + transition: var(--transition); + display: flex; + align-items: center; + gap: 8px; +} + +.brand:hover { + transform: translateY(-2px); +} + +.nav-links { + display: flex; + gap: 12px; + align-items: center; + margin-left: auto; } /* Layout */ .container { - max-width: 600px; /* Narrower for better focus */ - margin: 40px auto; + max-width: 700px; + margin: 0 auto; padding: 0 20px; width: 100%; flex: 1; + display: flex; + flex-direction: column; + justify-content: center; } -/* Card Styling (Glassmorphism) */ +.content-wrapper { + flex: 1; + display: flex; + flex-direction: column; + padding: 40px 20px; +} + +/* Card Styling */ .card { background: var(--glass-bg); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); border: 1px solid var(--glass-border); - border-radius: var(--radius); - padding: 32px; + border-radius: var(--radius-lg); + padding: 40px; box-shadow: var(--glass-shadow); + animation: fadeInUp 0.6s ease-out; + position: relative; + overflow: hidden; } -.card-head { - margin-bottom: 24px; +.card::before { + content: ''; + position: absolute; + top: -40%; + right: -40%; + width: 300px; + height: 300px; + background: radial-gradient(circle, rgba(99, 102, 241, 0.08) 0%, transparent 70%); + border-radius: 50%; + pointer-events: none; +} + +.card::after { + content: ''; + position: absolute; + bottom: -20%; + left: -20%; + width: 200px; + height: 200px; + background: radial-gradient(circle, rgba(168, 85, 247, 0.05) 0%, transparent 70%); + border-radius: 50%; + pointer-events: none; +} + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.card-header { + margin-bottom: 32px; text-align: center; + position: relative; + z-index: 1; } -.title { +.card-title { + font-size: 2.2rem; + font-weight: 800; + margin: 0 0 12px 0; + letter-spacing: -0.03em; + background: linear-gradient(135deg, #f1f5f9 0%, #cbd5e1 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + line-height: 1.1; +} + +.card-subtitle { + color: var(--text-muted); + font-size: 1rem; + margin: 0; +} + +/* Typography */ +h1, h2, h3, h4, h5, h6 { margin: 0; - font-size: 1.75rem; font-weight: 700; letter-spacing: -0.025em; } -.subtitle { - color: var(--text-muted); - margin-top: 8px; - font-size: 0.95rem; - line-height: 1.5; +p { + margin: 0; } -/* Forms */ +.text-center { text-align: center; } +.text-muted { color: var(--text-muted); } +.text-light { color: var(--text-light); } + +/* Forms & Inputs */ .form-group { display: flex; flex-direction: column; - gap: 12px; + gap: 8px; + margin-bottom: 16px; } -input, select { +.form-label { + font-size: 0.9rem; + font-weight: 600; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.5px; +} + +input[type="text"], +input[type="email"], +input[type="password"], +input[type="date"], +select, +textarea { width: 100%; - padding: 14px 16px; - background: rgba(0, 0, 0, 0.2); + padding: 12px 16px; + background: rgba(0, 0, 0, 0.3); border: 1px solid var(--glass-border); - border-radius: 12px; - color: white; + border-radius: var(--radius); + color: var(--text-main); + font-family: inherit; font-size: 1rem; outline: none; transition: var(--transition); } -input:focus { +input[type="text"]:focus, +input[type="email"]:focus, +input[type="password"]:focus, +input[type="date"]:focus, +select:focus, +textarea:focus { border-color: var(--primary); - box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.15); - background: rgba(0, 0, 0, 0.4); + background: rgba(0, 0, 0, 0.6); + box-shadow: 0 0 0 4px var(--primary-light), inset 0 2px 4px rgba(0, 0, 0, 0.2); +} + +input::placeholder { + color: var(--text-light); } /* Buttons */ @@ -135,8 +277,8 @@ input:focus { display: inline-flex; align-items: center; justify-content: center; - padding: 12px 20px; - border-radius: 12px; + padding: 11px 20px; + border-radius: var(--radius); font-weight: 600; font-size: 0.95rem; cursor: pointer; @@ -144,108 +286,234 @@ input:focus { text-decoration: none; transition: var(--transition); gap: 8px; + white-space: nowrap; + user-select: none; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; } .btn.primary { - background: var(--primary); + background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); color: white; - box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3); + box-shadow: 0 8px 24px rgba(99, 102, 241, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.2); +} + +.btn.primary:hover:not(:disabled) { + background: linear-gradient(135deg, var(--primary-hover) 0%, #9333ea 100%); + transform: translateY(-3px); + box-shadow: 0 12px 32px rgba(99, 102, 241, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.2); } -.btn.primary:hover { - background: var(--primary-hover); - transform: translateY(-1px); +.btn.primary:active:not(:disabled) { + transform: translateY(0); +} + +.btn.secondary { + background: linear-gradient(135deg, rgba(168, 85, 247, 0.2) 0%, rgba(99, 102, 241, 0.15) 100%); + color: var(--text-main); + border: 1px solid rgba(168, 85, 247, 0.4); +} + +.btn.secondary:hover:not(:disabled) { + background: linear-gradient(135deg, rgba(168, 85, 247, 0.3) 0%, rgba(99, 102, 241, 0.25) 100%); + border-color: rgba(168, 85, 247, 0.6); + transform: translateY(-3px); + box-shadow: 0 8px 24px rgba(168, 85, 247, 0.2); } .btn.danger { - background: rgba(239, 68, 68, 0.1); + background: var(--danger-light); color: #fca5a5; - border: 1px solid rgba(239, 68, 68, 0.2); + border: 1px solid rgba(239, 68, 68, 0.3); +} + +.btn.danger:hover:not(:disabled) { + background: var(--danger); + color: white; + border-color: var(--danger); +} + +.btn.success { + background: var(--success-light); + color: #6ee7b7; + border: 1px solid rgba(16, 185, 129, 0.3); } -.btn.danger:hover { - background: rgba(239, 68, 68, 0.2); - color: #fff; +.btn.success:hover:not(:disabled) { + background: var(--success); + color: white; + border-color: var(--success); } .btn.ghost { background: transparent; color: var(--text-muted); + border: none; } -.btn.ghost:hover { - color: white; - background: rgba(255,255,255,0.05); +.btn.ghost:hover:not(:disabled) { + color: var(--text-main); + background: rgba(255, 255, 255, 0.08); +} + +.btn.small { + padding: 8px 12px; + font-size: 0.875rem; +} + +.btn.small svg { + width: 16px; + height: 16px; +} + +.btn svg { + width: 20px; + height: 20px; + flex-shrink: 0; +} + +/* Task Add Form */ +.task-input-group { + display: flex; + gap: 8px; + margin-bottom: 24px; + animation: slideDown 0.4s ease-out; +} + +@keyframes slideDown { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.task-input-group input { + flex: 1; } /* Task List */ -.todo-list { - list-style: none; - padding: 0; - margin-top: 24px; +.task-list { display: flex; flex-direction: column; - gap: 12px; + gap: 10px; + margin-top: 24px; } -.todo-item { +.task-item { display: flex; align-items: center; justify-content: space-between; padding: 16px; - background: rgba(255, 255, 255, 0.03); - border: 1px solid rgba(255, 255, 255, 0.05); - border-radius: 12px; + background: rgba(255, 255, 255, 0.04); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: var(--radius); transition: var(--transition); + animation: slideUp 0.4s ease-out; + overflow: hidden; + position: relative; +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } } -.todo-item:hover { - background: rgba(255, 255, 255, 0.06); - border-color: rgba(255, 255, 255, 0.1); +.task-item:hover { + background: rgba(255, 255, 255, 0.08); + border-color: rgba(255, 255, 255, 0.15); transform: translateX(4px); + box-shadow: 0 4px 12px rgba(99, 102, 241, 0.1); } -.todo-left { +.task-item.completed { + opacity: 0.6; +} + +.task-content { display: flex; align-items: center; - gap: 16px; + gap: 12px; + flex: 1; + min-width: 0; } -/* Custom Checkbox Look */ -.check-circle { - width: 24px; - height: 24px; +.task-checkbox { + width: 20px; + height: 20px; border: 2px solid var(--text-muted); border-radius: 50%; + background: transparent; + cursor: pointer; display: flex; align-items: center; justify-content: center; - color: transparent; transition: var(--transition); + flex-shrink: 0; +} + +.task-checkbox:hover { + border-color: var(--primary); } -.todo-item.done .check-circle { +.task-checkbox input { + width: 100%; + height: 100%; + cursor: pointer; + opacity: 0; + margin: 0; +} + +.task-item.completed .task-checkbox { background: var(--success); border-color: var(--success); color: white; } -.todo-title { +.task-text { font-size: 1rem; + color: var(--text-main); + word-break: break-word; } -.todo-item.done .todo-title { +.task-item.completed .task-text { text-decoration: line-through; color: var(--text-muted); } +.task-actions { + display: flex; + gap: 6px; + flex-shrink: 0; +} + +.task-actions .btn { + padding: 6px 10px; +} + /* Footer */ .footer { text-align: center; - padding: 24px; + padding: 32px 20px; color: var(--text-muted); font-size: 0.85rem; margin-top: auto; + border-top: 1px solid rgba(255, 255, 255, 0.08); + background: linear-gradient(to bottom, transparent, rgba(99, 102, 241, 0.03)); + letter-spacing: 0.5px; + font-weight: 500; } /* Add Task Form specific */ @@ -257,7 +525,161 @@ input:focus { .empty-state { text-align: center; - padding: 40px 0; + padding: 60px 20px; color: var(--text-muted); - opacity: 0.6; +} + +.empty-state-icon { + width: 60px; + height: 60px; + margin: 0 auto 20px; + opacity: 0.4; + stroke: currentColor; +} + +.empty-state-title { + font-size: 1.25rem; + font-weight: 600; + margin-bottom: 8px; + color: var(--text-main); +} + +.empty-state-text { + font-size: 0.95rem; + margin: 0; +} + +/* Loading & Status */ +.loading { + display: inline-flex; + align-items: center; + gap: 8px; +} + +.spinner { + width: 16px; + height: 16px; + border: 2px solid var(--primary-light); + border-top-color: var(--primary); + border-radius: 50%; + animation: spin 0.6s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +.alert { + padding: 12px 16px; + border-radius: var(--radius); + margin-bottom: 16px; + display: flex; + align-items: center; + gap: 12px; + animation: slideDown 0.3s ease-out; +} + +.alert.error { + background: var(--danger-light); + border: 1px solid rgba(239, 68, 68, 0.3); + color: #fca5a5; +} + +.alert.success { + background: var(--success-light); + border: 1px solid rgba(16, 185, 129, 0.3); + color: #6ee7b7; +} + +.alert.warning { + background: rgba(245, 158, 11, 0.1); + border: 1px solid rgba(245, 158, 11, 0.3); + color: #fcd34d; +} + +.alert.info { + background: var(--primary-light); + border: 1px solid rgba(99, 102, 241, 0.3); + color: #a5b4fc; +} + +.alert-icon { + width: 20px; + height: 20px; + flex-shrink: 0; +} + +/* Stats Bar */ +.stats-bar { + display: flex; + gap: 24px; + padding: 16px 0; + margin-bottom: 24px; + border-bottom: 1px solid rgba(255, 255, 255, 0.05); +} + +.stat-item { + flex: 1; + text-align: center; +} + +.stat-value { + font-size: 1.75rem; + font-weight: 700; + color: var(--primary); +} + +.stat-label { + font-size: 0.85rem; + color: var(--text-muted); + margin-top: 4px; +} + +/* Utility Classes */ +.mb-0 { margin-bottom: 0; } +.mb-8 { margin-bottom: 8px; } +.mb-16 { margin-bottom: 16px; } +.mb-24 { margin-bottom: 24px; } + +.mt-8 { margin-top: 8px; } +.mt-16 { margin-top: 16px; } +.mt-24 { margin-top: 24px; } + +.hidden { display: none !important; } +.opacity-50 { opacity: 0.5; } + +/* Responsive */ +@media (max-width: 640px) { + .card { + padding: 24px; + } + + .card-title { + font-size: 1.5rem; + } + + .task-input-group { + flex-direction: column; + } + + .task-input-group input, + .task-input-group .btn { + width: 100%; + } + + .nav-inner { + padding: 0 16px; + } + + .stats-bar { + gap: 16px; + } + + .task-actions { + gap: 4px; + } + + .task-actions .btn.small { + padding: 6px 8px; + } } \ No newline at end of file diff --git a/templates/about.html b/templates/about.html index 4fc25645..849e2e90 100644 --- a/templates/about.html +++ b/templates/about.html @@ -1,30 +1,92 @@ {% extends 'base.html' %} -{% block title %}About{% endblock %} +{% block title %}About - Task Master{% endblock %} {% block content %} -
-

About the Developer

-

Building skills in Full Stack Python.

- -
-

- This application is a practice project to master Flask (Backend) and Jinja2 (Templating). - The goal is to understand how data flows from a Python server to the HTML client without relying on complex JavaScript frameworks. +

+
+

About Task Master

+

A modern task management system

+
+ +
+

What is Task Master?

+

+ Task Master is a minimalist task management system built with Python Flask and modern web technologies. + It's designed to help you stay focused on what matters by providing a simple, distraction-free interface + for managing your daily tasks.

-

- Current Features: +

+ +
+

Key Features

+
+
+ + + +
+

Add & Manage Tasks

+

Quickly add tasks and manage them with ease

+
+
+
+ + + +
+

Track Progress

+

Monitor completed and pending tasks at a glance

+
+
+
+ + + +
+

REST API

+

Powerful API for third-party integrations

+
+
+
+
+ +
+

Technology Stack

+
+
+

Flask

+

Backend Framework

+
+
+

SQLAlchemy

+

Database ORM

+
+
+

Modern CSS

+

Responsive Design

+
+
+

JavaScript

+

Vanilla JS

+
+
+
+ +
+

Version Info

+

+ Task Master v1.0 • Built by Rashed Alothman • © 2025

-
    -
  • Dynamic Routing
  • -
  • Form Handling (POST/GET)
  • -
  • Template Inheritance
  • -
  • Modern CSS (Glassmorphism)
  • -
-
- Back to Dashboard +
+ + + + + Start Managing Tasks +
-
+ {% endblock %} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 4019e08b..67ef600c 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,29 +1,43 @@ - + - - - {% block title %}My To‑Do{% endblock %} - - + + + {% block title %}Task Management System{% endblock %} + - - +
+ + -
- {% block content %}{% endblock %} -
+ +
+
+ {% block content %}{% endblock %} +
+
- + + +
+ {% block scripts %}{% endblock %} \ No newline at end of file diff --git a/templates/homepage.html b/templates/homepage.html index f76e5e1e..bdcd8efe 100644 --- a/templates/homepage.html +++ b/templates/homepage.html @@ -1,45 +1,306 @@ {% extends 'base.html' %} -{% block title %}Dashboard{% endblock %} +{% block title %}Dashboard - Task Master{% endblock %} {% block content %} -
-
-

My Day

-

{{ tasks|length }} tasks remaining

-
- -
- - -
- - {% if tasks %} - - {% else %} + + + +
-

No tasks yet. Enjoy your day!

+ + + +

No tasks yet

+

Add a task above to get started!

- {% endif %} -
+ + +{% endblock %} + +{% block scripts %} + {% endblock %} \ No newline at end of file diff --git a/templates/landing.html b/templates/landing.html index fc79387b..4c298659 100644 --- a/templates/landing.html +++ b/templates/landing.html @@ -1,35 +1,71 @@ {% extends 'base.html' %} -{% block title %}Welcome{% endblock %} +{% block title %}Welcome - Task Master{% endblock %} {% block content %} -
- -
- +
+
+
+ + + +
+

Task Master

+

Organize • Achieve • Succeed

-

Task Master

-

- The minimalist, distraction-free way to manage your daily tasks. Built with Python & Flask. +

+ A minimalist task management system designed to help you focus on what matters most and accomplish your goals with clarity and purpose.

-
- +
+ + + + Get Started - - View Dashboard + + + + + Learn More
-
-

- • Python Backend - • No JavaScript - • CSS Variables -

-
+ +
+

Why Choose Task Master?

+ +
+
+ + + +

Lightning Fast

+

Instant task management with real-time updates

+
+ +
+ + + +

Simple & Clean

+

Beautiful distraction-free interface

+
-
+
+ + + +

Secure & Private

+

Your data stays with you, always protected

+
+ + +
+

Built with Flask • SQLAlchemy • Modern CSS

+
+ + {% endblock %} \ No newline at end of file diff --git a/templates/login.html b/templates/login.html index 909b3995..cae51f5c 100644 --- a/templates/login.html +++ b/templates/login.html @@ -1,27 +1,32 @@ {% extends 'base.html' %} -{% block title %}Sign In{% endblock %} +{% block title %}Login - Task Master{% endblock %} {% block content %} -
-
-

Welcome Back

-

Please enter your details to sign in.

-
+
+
+

Welcome Back

+

Sign in to manage your tasks

+
-
-
- - + +
+ +
- -
- - + +
+ +
- - Back + -
+ +

+ Don't have an account? Go back home +

+ {% endblock %} \ No newline at end of file