Skip to content

kelly-eugenia/task-manager-app

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 

Repository files navigation

README.md

Task Manager

A personal task management app (think to-do lists) built with Laravel (API) and React + Vite (frontend). Authentication is handled with Laravel Sanctum using Bearer tokens.

Users can create, complete, edit, and delete tasks. Tasks may be optionally grouped into projects. Users can view the progress of each project based on percentage of project tasks completed. Users can only view tasks belonging to them.


Tech Stack

  • Backend: PHP 8.2+, Laravel 10+, Sanctum
  • Frontend: React 18, Vite, Axios, React Router, Typescript, TailwindCSS (CDN)
  • DB: MySQL/MariaDB (or SQLite)
  • Auth: Sanctum Personal Access Tokens (Bearer)

Prerequisites

  • PHP 8.2+, Composer 2.x
  • Node 18+ with npm/yarn/pnpm
  • MySQL/MariaDB or SQLite
  • Git

Project Structure

task-manager-app/
├─ backend/        # Laravel API
│  ├─ app/
│  ├─ database/
│  ├─ routes/api.php
│  └─ ...
└─ frontend/       # React + Vite client
   ├─ src/
   ├─ index.html
   └─ ...

Backend Setup (Laravel API)

  1. Install & configure
git clone https://github.com/kelly-eugenia/task-manager-app.git
cd task-manager-app/backend
composer install
cp .env.example .env
  1. Configure .env
APP_NAME=Laravel
APP_ENV=local
APP_KEY=           # will be generated
APP_DEBUG=true
APP_URL=http://localhost

# IMPORTANT: set app timezone for "today/overdue" to match local day
APP_TIMEZONE=Australia/Melbourne

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=task-manager
DB_USERNAME=root
DB_PASSWORD=

Verify that timezone config is read from env in config/app.php:

'timezone' => env('APP_TIMEZONE', 'UTC'),

Then clear caches:

php artisan config:clear
php artisan cache:clear
  1. Configure CORS

In config/cors.php, allow:

'allowed_origins' => [
  'http://localhost:5173',
  'http://127.0.0.1:5173',
  'http://localhost:8000',
  'http://127.0.0.1:8000',
],
'supports_credentials' => false, // fine for Bearer tokens
  1. Generate key, migrate, seed
php artisan key:generate
php artisan migrate --seed

This seeds one demo user (with some tasks and projects):

  1. Run the API
php artisan serve
# -> http://127.0.0.1:8000

Frontend Setup (React + Vite)

  1. Install & configure
cd ../frontend
npm install          # or yarn / pnpm
cp .env.example .env
  1. Set API base URL
VITE_API_BASE_URL=http://127.0.0.1:8000/api
  1. Run the dev server
npm run dev          # or yarn dev / pnpm dev
# -> http://127.0.0.1:5173

Frontend Auth & API

src/contexts/AuthContext.tsx

  • Holds user, token, and a ready flag
  • Bootstraps auth on app load:
    • Reads auth_token / auth_user from localStorage
    • If a token exists, calls GET /api/user to validate and refresh the user
    • On failure (expired/invalid), clears storage and resets auth state
  • Exposes login, register, logout
    • On success: saves { user, token } to state + localStorage, navigate to /
    • On logout: best-effort /api/logout, then clear storage and navigate to /login

Global 401 handling:
If any request returns 401, a response interceptor logs the user out and redirects to /login automatically,

src/api.ts

  • Central Axios instance with baseURL from .env (VITE_API_BASE_URL)
  • Request interceptor injects Authorization: Bearer <token> from localStorage (if present)

Protected routes

  • App routes are wrapped by a ProtectedRoute that checks token If absent → redirect to /login

API Overview

All protected routes require Authorization: Bearer <token>.

Auth

  • POST /api/register

    Body:

    { "name": "string", "email": "string", "password": "string", "password_confirmation": "string" }

    Returns:

    { "token": "...", "user": { ... } }
  • POST /api/login

    Body:

    { "email": "string", "password": "string" }

    Returns:

    { "token": "...", "user": { ... } }
  • POST /api/logout (auth required) Revokes/Deletes the current token.

  • GET /api/user (auth required) Returns the authenticated user


Tasks

(auth required)

  • GET /api/tasks List tasks for the user.

    Query params

    • project_id — only tasks in that project

    • status=completed — only completed tasks

    • due=today | scheduled | overdue

      • today: tasks with due_date equal to today
      • scheduled: tasks with a non-null due_date
      • overdue: non-completed tasks with due_date before today
    • sort=due_date | created_at | priority (default due_date)

    • dir=asc | desc (default asc)

    Ordering rules

    • Incomplete tasks are always shown first
    • When sorting by due_date, NULL due dates are pushed to the bottom
    • Priority order (ascending): null < low < medium < high
  • POST /api/tasks Create task for the user. Body:

    {
      "title": "required|string|max:100",
      "description": "string|null|max:255",
      "due_date": "YYYY-MM-DD|null",
      "priority": "low|medium|high|null",
      "project_id": "number|null"
    }
  • GET /api/tasks/{id} Show task (ownership enforced).

  • PUT /api/tasks/{id} Update task. If is_completed is toggled:

    • false → true → backend sets completed_at = now()
    • true → false → backend clears completed_at
  • DELETE /api/tasks/{id} Delete task.


Projects

(auth required)

  • GET /api/projects List user’s projects. Each includes:

    • tasks_count
    • completed_tasks_count
    • progress (computed)
  • POST /api/projects Create project for the user. Body:

    {
      "title": "required|string|max:100",
      "description": "required|string|max:255",
      "end_date": "YYYY-MM-DD|null"
    }
  • GET /api/projects/{id} Show project, with counts & computed progress. Also retrieve tasks under the project, ordered by due date then created_at (can be filtered and sorted too).

  • PUT /api/projects/{id} Update project: title, description, end_date.

  • DELETE /api/projects/{id} Deletes the project and all its tasks (via cascadeOnDelete).


Assumptions

  • Auth: Sanctum Personal Access Tokens; frontend stores token in localStorage and sends Authorization: Bearer <token>. Logout revokes the current token.
  • Ownership: Every read/write query is scoped by user_id (server-side). Tasks and projects can only belong or assigned to one user -- no other users can access them.
  • Dates: due_date and end_date are date-only (YYYY-MM-DD). Overdue/today use date comparisons at local midnight. The UI uses helpers in src/utils/dates.ts to normalize values for <input type="date">, format display, and compute “today/overdue” using the configured app timezone.
  • Projects/Tasks: project_id on tasks is nullable, but the FK is configured with cascadeOnDelete(). Deleting a project will delete all its tasks.
  • Computed: completed_at is managed by backend when is_completed changes. Project progress is computed from counts (not stored).

Seed Data

Running:

php artisan migrate:fresh --seed

creates one demo user with several projects and tasks:

  • Email: test@example.com
  • Password: testPassword

Login example:

curl -X POST http://127.0.0.1:8000/api/login \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","password":"testPassword"}'

CURL Examples

Register

curl -X POST http://127.0.0.1:8000/api/register \
  -H "Content-Type: application/json" \
  -d '{"name":"John Smith","email":"john@example.com","password":"secret1234","password_confirmation":"secret1234"}'

Login

curl -X POST http://127.0.0.1:8000/api/login \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","password":"testPassword"}'

List project tasks

curl "http://127.0.0.1:8000/api/projects/1" \
  -H "Authorization: Bearer <TOKEN>"

Create a task

curl -X POST http://127.0.0.1:8000/api/tasks \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"title":"Buy milk","due_date":"2025-10-20","priority":"medium","project_id":null}'

About

A personal task management app (think to-do lists) built with Laravel (API) and React + Vite (frontend). Authentication is handled with Laravel Sanctum using Bearer tokens.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors