Skip to content

Repository files navigation

Timesheet + Reflection

A full-stack time tracking and daily reflection application built with React, Express, and MongoDB. Features local-first caching, JWT authentication, group management with team leads, and Docker containerization for easy deployment.

Features

  • Time Tracking: Log work entries with project, category, description, and tags
  • Daily Reflections: Record mood, energy, focus levels along with wins, challenges, and learnings
  • Week Calendar View: Visual overview of time entries by day
  • Reports: Aggregated views of time by project and recent reflections
  • Group Management: Organize users into groups with designated team leads
  • Team Lead Reports: Group leads can view all entries and reflections from their team members
  • Local-First Architecture: Data cached locally with server sync
  • User Management: Admin can bulk import users with group assignments and lead status
  • CSV Export: Export time entries for external reporting (with optional group filter)

Tech Stack

Frontend (apps/web)

  • React 19 with Vite 7
  • React Router DOM 7 for navigation
  • date-fns for date manipulation
  • UUID for client-side ID generation
  • ESLint with React hooks plugin

Backend (services/api)

  • Express 5 REST API
  • MongoDB with Mongoose 9 ODM
  • JWT authentication with bcrypt password hashing
  • Morgan for request logging
  • CORS configured for development

Infrastructure

  • Docker Compose for local development
  • MongoDB 7 container with health checks
  • Hot-reload enabled for both frontend and backend

Project Structure

timesheet/
├── apps/
│   └── web/                    # React frontend
│       ├── src/
│       │   ├── api/            # API client
│       │   ├── app/            # Route definitions
│       │   ├── components/     # Reusable UI components
│       │   ├── pages/          # Page components
│       │   ├── store/          # State management (Context + hooks)
│       │   └── utils/          # Helper functions
│       └── package.json
├── services/
│   └── api/                    # Express backend
│       ├── src/
│       │   ├── middleware/     # Auth middleware
│       │   ├── models/         # Mongoose schemas
│       │   ├── routes/         # API endpoints
│       │   ├── db.js           # Database connection
│       │   └── server.js       # App entry point
│       └── package.json
├── docker-compose.yml          # Container orchestration
└── import_users.py             # Bulk user import script

Getting Started

Prerequisites

  • Docker and Docker Compose
  • Node.js 20+ (for local development without Docker)

Quick Start with Docker

  1. Clone the repository:

    git clone <repository-url>
    cd timesheet
  2. Start all services:

    docker-compose up
  3. Access the application:

Local Development (without Docker)

  1. Start MongoDB locally or use a cloud instance

  2. Configure the API:

    cd services/api
    cp .env.example .env  # Create and configure .env
    npm install
    npm run dev
  3. Configure the frontend:

    cd apps/web
    npm install
    npm run dev

Environment Variables

API (services/api/.env)

PORT=8080
MONGO_URI=mongodb://localhost:27017/timesheet_reflection
CORS_ORIGIN=http://localhost:5173,http://127.0.0.1:5173
JWT_SECRET=your-secret-key-here
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin123!ChangeMe

Web (apps/web)

VITE_API_URL=http://localhost:8080

API Endpoints

Authentication

Method Endpoint Description
POST /api/auth/login User login (returns group & isGroupLead)
GET /api/auth/me Get current user
POST /api/auth/change-password Change password

Time Entries (requires auth)

Method Endpoint Description
GET /api/entries List entries (with filters)
POST /api/entries Create entry
PUT /api/entries/:id Update entry
DELETE /api/entries/:id Delete entry

Reflections (requires auth)

Method Endpoint Description
GET /api/reflections List reflections
PUT /api/reflections/:date Upsert reflection by date
DELETE /api/reflections/:id Delete reflection

Settings (requires auth)

Method Endpoint Description
GET /api/settings Get user settings
PUT /api/settings Update settings

Group (requires auth)

Method Endpoint Description
GET /api/group/info Get current user's group info
GET /api/group/members List group members (lead only)
GET /api/group/entries Get group's time entries (lead only)
GET /api/group/reflections Get group's reflections (lead only)
GET /api/group/reports/summary Get group summary report (lead only)
GET /api/group/reports/user/:userId Get detailed report for a member (lead only)

Admin - User Management (requires admin role)

Method Endpoint Description
POST /api/admin/import-users Bulk import users with group/lead
GET /api/admin/users List all users
GET /api/admin/users/:id Get single user
PUT /api/admin/users/:id Update user (group, isGroupLead, role)
DELETE /api/admin/users/:id Delete user and their data

Admin - Group Management (requires admin role)

Method Endpoint Description
GET /api/admin/groups List all groups with member counts
GET /api/admin/groups/:name Get group details with members
PUT /api/admin/groups/:name Bulk assign users to group
DELETE /api/admin/groups/:name Remove all users from group
POST /api/admin/groups/:name/set-lead Set/unset group lead

Admin - Export (requires admin role)

Method Endpoint Description
GET /api/admin/export/entries.csv Export entries (optional group filter)

Data Models

User

{
  username: String,
  passwordHash: String,
  role: String,                 // "admin" | "user"
  mustChangePassword: Boolean,
  group: String,                // Group name/identifier (nullable)
  isGroupLead: Boolean          // Can view group members' reports
}

TimeEntry

{
  userId: ObjectId,
  date: String,        // yyyy-MM-dd
  start: String,       // HH:mm
  end: String,         // HH:mm
  project: String,
  category: String,
  description: String,
  tags: [String]
}

Reflection

{
  userId: ObjectId,
  date: String,        // yyyy-MM-dd (unique per user)
  mood: Number,        // 1-5
  energy: Number,      // 1-5
  focus: Number,       // 1-5
  wins: String,
  challenges: String,
  learned: String,
  nextSteps: String,
  gratitude: String,
  notes: String
}

Settings

{
  userId: ObjectId,
  projects: [String],           // Default: Research, Teaching, Dev, Admin
  categories: [String],         // Default: Build, Meetings, Writing, Study, Support
  reflectionPrompts: [String]
}

Bulk User Import

Use the Python script to import users from a file with group assignments:

# Set environment variables
export API_URL=http://localhost:8080
export ADMIN_USER=admin
export ADMIN_PASS=admin123!ChangeMe
export DEFAULT_PASSWORD=TempPass123!
export INPUT_PATH=users.csv

# Run the import
python import_users.py

Input File Formats

Simple TXT format (usernames.txt) - one username per line:

user1
user2
user3

CSV format with groups (users.csv):

username,group,isGroupLead
alice,Engineering,true
bob,Engineering,false
carol,Engineering,false
dave,Marketing,true
eve,Marketing,false

The script will display a summary before importing:

Loaded 5 users from users.csv

Group summary:
  Engineering: 3 users (leads: alice)
  Marketing: 2 users (leads: dave)

Import result:
  Created: 5
  Skipped: 0
  Errors: 0

API Import Format

You can also import users directly via API:

curl -X POST http://localhost:8080/api/admin/import-users \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "users": [
      {"username": "alice", "group": "Engineering", "isGroupLead": true},
      {"username": "bob", "group": "Engineering", "isGroupLead": false}
    ],
    "defaultPassword": "TempPass123!",
    "mustChangePassword": true
  }'

Group Lead Features

Group leads have access to view their team's data:

  1. View team members: /api/group/members
  2. View team entries: /api/group/entries?from=2024-01-01&to=2024-12-31
  3. View team reflections: /api/group/reflections
  4. Get summary report: /api/group/reports/summary
  5. Get individual reports: /api/group/reports/user/:userId

Example summary response:

{
  "group": "Engineering",
  "memberCount": 3,
  "dateRange": { "from": "2024-01-01", "to": "2024-12-31" },
  "timeByUser": [
    { "username": "alice", "totalEntries": 150, "projectCount": 4 },
    { "username": "bob", "totalEntries": 120, "projectCount": 3 }
  ],
  "timeByProject": [
    { "_id": "Development", "entryCount": 200 },
    { "_id": "Meetings", "entryCount": 50 }
  ],
  "reflectionStats": [
    { "username": "alice", "reflectionCount": 30, "avgMood": 4.2, "avgEnergy": 3.8, "avgFocus": 4.0 }
  ]
}

Development

Available Scripts

Frontend (apps/web):

  • npm run dev - Start development server
  • npm run build - Build for production
  • npm run lint - Run ESLint
  • npm run preview - Preview production build

Backend (services/api):

  • npm run dev - Start with nodemon (hot reload)
  • npm start - Start production server

Docker Commands

# Start all services
docker-compose up

# Start in background
docker-compose up -d

# Stop all services
docker-compose down

# Rebuild containers
docker-compose up --build

# View logs
docker-compose logs -f [service-name]

# Reset database
docker-compose down -v

Architecture Notes

  • Local-First: The frontend maintains a local cache (localStorage) and syncs with the server
  • Optimistic Updates: UI updates immediately, then syncs with API
  • JWT Authentication: Tokens stored in localStorage, included in Authorization header
  • First-Login Flow: Users imported by admin must change password on first login
  • Group Hierarchy: Users belong to groups, group leads can view their team's data, admins can view everything

License

ISC

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages