v2.0.0: Complete rewrite — React + Express + PostgreSQL + Docker
BREAKING: Full rewrite from static HTML to production-grade stack. Features: - React 18 + Vite + Tailwind CSS (mobile-first) - Express + Prisma + PostgreSQL backend - JWT authentication with role-based access - Weekly Mon-Sun timesheets with auto-save - Multiple homeowner entries per day - Submit → Approve/Reject workflow - Server-side PDF generation - SMTP email integration - Admin panel with reporting & filters - Dark mode (system-aware) - Docker Compose one-command deploy - Non-root containers, Helmet, bcrypt, Zod validation
This commit is contained in:
@@ -1,189 +1,287 @@
|
||||
# Coastal Contracting Timesheet App
|
||||
<p align="center">
|
||||
<img src="docs/screenshots/01-login-mobile.png" alt="Coastal Timesheet" width="200" />
|
||||
</p>
|
||||
|
||||
A modern, responsive timesheet application built with React for tracking work hours and generating professional PDF timesheets. Features comprehensive validation, dynamic field layouts, and seamless data management.
|
||||
<h1 align="center">Coastal Timesheet v2</h1>
|
||||
|
||||

|
||||
*Screenshot showing the timesheet interface with validation, dynamic fields, and professional layout*
|
||||
<p align="center">
|
||||
<strong>A modern, mobile-first time tracking application for Coastal Contracting of FL</strong>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/React-18-61DAFB?logo=react&logoColor=white" alt="React 18" />
|
||||
<img src="https://img.shields.io/badge/Express-4-000000?logo=express&logoColor=white" alt="Express" />
|
||||
<img src="https://img.shields.io/badge/PostgreSQL-16-4169E1?logo=postgresql&logoColor=white" alt="PostgreSQL" />
|
||||
<img src="https://img.shields.io/badge/Prisma-ORM-2D3748?logo=prisma&logoColor=white" alt="Prisma" />
|
||||
<img src="https://img.shields.io/badge/Docker-Compose-2496ED?logo=docker&logoColor=white" alt="Docker" />
|
||||
<img src="https://img.shields.io/badge/TailwindCSS-3-06B6D4?logo=tailwindcss&logoColor=white" alt="Tailwind" />
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## ✨ Features
|
||||
|
||||
### 📊 **Time Tracking & Management**
|
||||
- **Weekly Time Tracking**: Track work hours for each day of the week with multiple entries per day
|
||||
- **Dynamic Date Navigation**: Navigate between weeks with intuitive date picker controls
|
||||
- **Flexible Entry Management**: Add, remove, and modify time entries as needed
|
||||
- **Auto-saving**: Automatically saves all data to browser localStorage
|
||||
- **📱 Mobile-first design** — Built for field workers, optimized for phones
|
||||
- **🔐 JWT authentication** — Secure login with access/refresh tokens + rate limiting
|
||||
- **📅 Weekly timesheets** — Monday–Sunday pay period with auto-save
|
||||
- **🏠 Multiple homeowners per day** — Track work at different job sites
|
||||
- **✅ Submit → Approve workflow** — Employees submit, admins approve or reject
|
||||
- **📄 PDF generation** — Professional server-side PDF export
|
||||
- **📧 Email integration** — Send timesheets via email with SMTP
|
||||
- **👥 Admin panel** — Manage employees, homeowners, review timesheets
|
||||
- **📊 Reporting** — Filter by employee, date range, status with summary stats
|
||||
- **🌙 Dark mode** — System-aware with manual toggle
|
||||
- **🐳 One-command deploy** — Single `docker compose up` for the entire stack
|
||||
|
||||
### 🏠 **Homeowner Management**
|
||||
- **Pre-loaded Homeowners**: Comprehensive list of default homeowner names and addresses
|
||||
- **Custom Homeowners**: Add and save custom homeowner names that persist across sessions
|
||||
- **Smart Dropdown**: Searchable dropdown with autocomplete functionality
|
||||
---
|
||||
|
||||
### ✅ **Smart Validation System**
|
||||
- **Required Employee Name**: Employee name must be entered before exporting timesheets
|
||||
- **Complete Entry Validation**: When any field is filled, all three fields (homeowner, hours, work description) become required
|
||||
- **Visual Feedback**: Red borders, asterisks, and warning messages guide users to complete entries
|
||||
- **Export Protection**: PDF generation disabled until all validation requirements are met
|
||||
## 📸 Screenshots
|
||||
|
||||
### 📝 **Enhanced User Interface**
|
||||
- **Dynamic Work Description Fields**: Auto-resizing text areas that expand to show all content without scrolling
|
||||
- **Optimized Field Layout**: Homeowner → Hours → Work Description order with maximum space for descriptions
|
||||
- **Today Highlighting**: Current day is visually highlighted for easy identification
|
||||
- **Dark/Light Mode**: Toggle between themes with persistent user preference
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><strong>Timesheet Entry</strong></td>
|
||||
<td align="center"><strong>Entry Form</strong></td>
|
||||
<td align="center"><strong>Dark Mode</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="docs/screenshots/02-timesheet-mobile.png" width="250" /></td>
|
||||
<td><img src="docs/screenshots/03-entry-form-mobile.png" width="250" /></td>
|
||||
<td><img src="docs/screenshots/07-dark-mode-mobile.png" width="250" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### 📄 **Professional PDF Export**
|
||||
- **Download PDF**: Generate and download professional timesheet PDFs
|
||||
- **Email Integration**: Share PDFs via device share sheet or download with pre-filled email subject
|
||||
- **Optimized Layout**: PDF layout matches UI with proper field sizing and professional formatting
|
||||
- **Validation Integration**: Only complete, valid timesheets can be exported
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><strong>Admin Panel</strong></td>
|
||||
<td align="center"><strong>Reports & Filters</strong></td>
|
||||
<td align="center"><strong>History</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="docs/screenshots/05-admin-mobile.png" width="250" /></td>
|
||||
<td><img src="docs/screenshots/06-admin-reports-mobile.png" width="250" /></td>
|
||||
<td><img src="docs/screenshots/04-history-mobile.png" width="250" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### 💾 **Data Management**
|
||||
- **Import/Export**: Backup and restore timesheet data with JSON export/import
|
||||
- **Week-based Storage**: Each week's data stored separately for better organization
|
||||
- **Custom Homeowner Persistence**: Added homeowners saved across all sessions
|
||||
- **Cross-device Compatibility**: Works on desktop, tablet, and mobile devices
|
||||
### Desktop
|
||||
|
||||
### 📱 **Responsive Design**
|
||||
- **Mobile-first**: Optimized for touch interfaces and small screens
|
||||
- **Adaptive Layouts**: Fields reorganize appropriately for different screen sizes
|
||||
- **Touch-friendly**: Large buttons and touch targets for mobile users
|
||||
<img src="docs/screenshots/02-timesheet-desktop.png" width="700" />
|
||||
<img src="docs/screenshots/06-admin-reports-desktop.png" width="700" />
|
||||
|
||||
## 🚀 Getting Started
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js (version 16 or higher)
|
||||
- npm or yarn
|
||||
- [Docker](https://docs.docker.com/get-docker/) and Docker Compose
|
||||
- That's it. Everything else runs in containers.
|
||||
|
||||
### Installation
|
||||
|
||||
1. Clone or download the project files
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. Start the development server:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
4. Open [http://localhost:5173](http://localhost:5173) in your browser
|
||||
|
||||
### Building for Production
|
||||
### Deploy
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
# Clone the repo
|
||||
git clone https://git.bizzle.lol/bizzle/coastal_timesheet.git
|
||||
cd coastal_timesheet
|
||||
git checkout v2
|
||||
|
||||
# Configure environment
|
||||
cp .env.example .env
|
||||
# Edit .env with your secrets (see Configuration below)
|
||||
|
||||
# Launch
|
||||
cd docker
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
The built files will be in the `dist/` directory, ready for web hosting.
|
||||
The app will be available at `http://localhost` (port 80).
|
||||
|
||||
### Preview Production Build
|
||||
### Default Admin Account
|
||||
|
||||
```bash
|
||||
npm run preview
|
||||
| Field | Value |
|
||||
|----------|-------------------------|
|
||||
| Email | `admin@coastal.com` |
|
||||
| Password | `CoastalAdmin2026!` |
|
||||
|
||||
> ⚠️ **Change the admin password after first login.**
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
Copy `.env.example` to `.env` and configure:
|
||||
|
||||
```env
|
||||
# Database (auto-configured in Docker)
|
||||
DB_PASSWORD=your-secure-db-password
|
||||
|
||||
# JWT Secrets (CHANGE THESE!)
|
||||
JWT_SECRET=your-jwt-secret-min-32-chars
|
||||
JWT_REFRESH_SECRET=your-refresh-secret-min-32-chars
|
||||
|
||||
# CORS (add your domain)
|
||||
CORS_ORIGINS=https://timesheets.yourdomain.com
|
||||
|
||||
# Email (optional — for sending timesheets)
|
||||
SMTP_HOST=smtp.gmail.com
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=your-email@gmail.com
|
||||
SMTP_PASS=your-app-password
|
||||
SMTP_FROM=timesheets@yourdomain.com
|
||||
ADMIN_EMAIL=admin@yourdomain.com
|
||||
```
|
||||
|
||||
## 📖 Usage Guide
|
||||
### Email Setup (Gmail)
|
||||
|
||||
### 1. **Setup**
|
||||
- Enter your **Employee Name** (required for all exports)
|
||||
- Select the week you want to track using the date picker
|
||||
1. Enable 2FA on your Google account
|
||||
2. Go to [App Passwords](https://myaccount.google.com/apppasswords)
|
||||
3. Generate a new app password for "Mail"
|
||||
4. Use that as `SMTP_PASS`
|
||||
|
||||
### 2. **Adding Time Entries**
|
||||
- Click "Add Entry" for any day to create multiple entries
|
||||
- Fill in all three fields for each entry:
|
||||
- **Homeowner**: Select from dropdown or add custom names
|
||||
- **Hours Worked**: Enter decimal hours (e.g., 2.5 for 2 hours 30 minutes)
|
||||
- **Work Description**: Detailed description of work performed (auto-expanding field)
|
||||
---
|
||||
|
||||
### 3. **Validation & Completion**
|
||||
- **Red asterisks (*)** indicate required fields
|
||||
- **Warning messages** appear for incomplete entries
|
||||
- **Export buttons** are disabled until all requirements are met
|
||||
## 🏗️ Architecture
|
||||
|
||||
### 4. **Export Options**
|
||||
- **Download PDF**: Save a printable PDF to your device
|
||||
- **Share/Email PDF**: Use device share functionality or download with email setup
|
||||
- **Import/Export Data**: Backup/restore your timesheet data
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ Nginx │
|
||||
│ (reverse proxy) │
|
||||
│ /api/* → backend:3001 │
|
||||
│ /* → static frontend │
|
||||
├──────────────────┬──────────────────────────┤
|
||||
│ Frontend │ Backend │
|
||||
│ React + Vite │ Express + Prisma │
|
||||
│ Tailwind CSS │ JWT Auth │
|
||||
│ Lucide Icons │ @react-pdf/renderer │
|
||||
│ │ Nodemailer │
|
||||
│ ├──────────────────────────┤
|
||||
│ │ PostgreSQL 16 │
|
||||
│ │ (persistent volume) │
|
||||
└──────────────────┴──────────────────────────┘
|
||||
```
|
||||
|
||||
### 5. **Additional Features**
|
||||
- **Theme Toggle**: Switch between light and dark modes
|
||||
- **Office Contact**: Download contact card for easy email setup
|
||||
### Tech Stack
|
||||
|
||||
## 🗂️ Data Storage
|
||||
| Layer | Technology |
|
||||
|-----------|-----------------------------------------------|
|
||||
| Frontend | React 18, Vite 6, Tailwind CSS 3, Lucide |
|
||||
| Backend | Express 4, Prisma ORM, bcryptjs, jsonwebtoken |
|
||||
| Database | PostgreSQL 16 (Alpine) |
|
||||
| PDF | @react-pdf/renderer (server-side) |
|
||||
| Email | Nodemailer + SMTP |
|
||||
| Proxy | Nginx 1.27 (Alpine) |
|
||||
| Container | Docker Compose v3.9 |
|
||||
|
||||
- **Local Browser Storage**: All data stored locally, no external servers
|
||||
- **Weekly Organization**: Each week stored as separate dataset
|
||||
- **Persistent Settings**: Theme preferences and custom homeowners preserved
|
||||
- **Privacy-focused**: Your data never leaves your device
|
||||
|
||||
## 🛠️ Tech Stack
|
||||
|
||||
- **Frontend Framework**: React 18 with Vite
|
||||
- **Styling**: Tailwind CSS with responsive design
|
||||
- **PDF Generation**: @react-pdf/renderer for professional documents
|
||||
- **Icons**: Lucide React icon library
|
||||
- **Storage**: Browser localStorage API
|
||||
- **Build Tool**: Vite for fast development and optimized builds
|
||||
---
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── components/ # React components
|
||||
│ ├── TimeSheet.jsx # Main timesheet interface
|
||||
│ ├── DayEntries.jsx # Day-specific entry management
|
||||
│ ├── TimeEntryRow.jsx # Individual entry row (legacy)
|
||||
│ ├── DatePicker.jsx # Week navigation
|
||||
│ ├── HomeownerDropdown.jsx # Homeowner selection
|
||||
│ ├── ThemeToggle.jsx # Dark/light mode toggle
|
||||
│ ├── PDFExport.jsx # PDF download functionality
|
||||
│ ├── EmailPDF.jsx # PDF sharing functionality
|
||||
│ ├── TimesheetPDF.jsx # PDF document structure
|
||||
│ ├── ImportExport.jsx # Data backup/restore
|
||||
│ └── MiniCalendar.jsx # Calendar widget
|
||||
├── hooks/ # Custom React hooks
|
||||
│ ├── useTimeSheet.js # Timesheet state & validation
|
||||
│ └── useTheme.js # Theme management
|
||||
├── utils/ # Utility functions
|
||||
│ └── dateUtils.js # Date manipulation helpers
|
||||
├── App.jsx # Main application component
|
||||
├── main.jsx # Application entry point
|
||||
└── index.css # Global styles
|
||||
.
|
||||
├── frontend/ # React SPA
|
||||
│ ├── src/
|
||||
│ │ ├── api/ # Axios client with token refresh
|
||||
│ │ ├── components/ # Reusable UI components
|
||||
│ │ ├── contexts/ # Auth context (JWT)
|
||||
│ │ ├── hooks/ # Custom hooks (theme, swipe, auto-save)
|
||||
│ │ └── pages/ # Route pages
|
||||
│ └── vite.config.js
|
||||
├── backend/ # Express API
|
||||
│ ├── prisma/
|
||||
│ │ ├── schema.prisma # Database schema
|
||||
│ │ └── seed.js # Seed admin + homeowners
|
||||
│ └── src/
|
||||
│ ├── middleware/ # Auth middleware
|
||||
│ ├── routes/ # API routes
|
||||
│ └── utils/ # PDF, email, validation
|
||||
├── docker/ # Deployment
|
||||
│ ├── docker-compose.yml
|
||||
│ ├── backend/Dockerfile
|
||||
│ ├── frontend/Dockerfile
|
||||
│ └── nginx/default.conf
|
||||
└── docs/screenshots/ # App screenshots
|
||||
```
|
||||
|
||||
## 🔧 Configuration Files
|
||||
|
||||
- `vite.config.js` - Vite build configuration
|
||||
- `tailwind.config.js` - Tailwind CSS customization
|
||||
- `postcss.config.js` - PostCSS processing
|
||||
- `package.json` - Dependencies and scripts
|
||||
|
||||
## 🌐 Deployment
|
||||
|
||||
The built application is a static site that can be deployed to any web hosting service:
|
||||
|
||||
1. Run `npm run build`
|
||||
2. Upload the contents of the `dist/` directory to your web server
|
||||
3. Ensure your server serves `index.html` for all routes (SPA configuration)
|
||||
|
||||
Compatible with: Netlify, Vercel, GitHub Pages, traditional web hosting, and more.
|
||||
|
||||
## 📋 Features Summary
|
||||
|
||||
✅ **Employee name validation**
|
||||
✅ **Complete entry validation (all fields required when any field has input)**
|
||||
✅ **Dynamic auto-resizing work description fields**
|
||||
✅ **Optimized field order (Homeowner → Hours → Work Description)**
|
||||
✅ **Professional PDF generation with validation**
|
||||
✅ **Email/share functionality**
|
||||
✅ **Data import/export**
|
||||
✅ **Dark/light theme support**
|
||||
✅ **Mobile-responsive design**
|
||||
✅ **Local data persistence**
|
||||
✅ **Multiple entries per day**
|
||||
✅ **Custom homeowner management**
|
||||
|
||||
---
|
||||
|
||||
*Built for Coastal Contracting of FL - Making timesheet management simple and professional.*
|
||||
## 🔒 Security
|
||||
|
||||
- **bcrypt** password hashing (12 rounds)
|
||||
- **JWT** access tokens (15min) + refresh tokens (7 days)
|
||||
- **Helmet** security headers
|
||||
- **Rate limiting** on auth endpoints (50 req / 15 min)
|
||||
- **Zod** input validation on all endpoints
|
||||
- **Prisma ORM** — parameterized queries (no SQL injection)
|
||||
- **Non-root Docker** containers
|
||||
- **CORS** origin whitelist
|
||||
|
||||
---
|
||||
|
||||
## 📡 API Endpoints
|
||||
|
||||
### Auth
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------------------|----------------------|
|
||||
| POST | `/api/auth/login` | Login, get tokens |
|
||||
| POST | `/api/auth/refresh` | Refresh access token |
|
||||
| GET | `/api/auth/me` | Current user info |
|
||||
|
||||
### Entries
|
||||
| Method | Endpoint | Description |
|
||||
|--------|---------------------|------------------------|
|
||||
| GET | `/api/entries` | List entries (by week) |
|
||||
| POST | `/api/entries` | Create entry |
|
||||
| PUT | `/api/entries/:id` | Update entry |
|
||||
| DELETE | `/api/entries/:id` | Delete entry |
|
||||
|
||||
### Timesheets
|
||||
| Method | Endpoint | Description |
|
||||
|--------|------------------------------|----------------------|
|
||||
| GET | `/api/timesheets` | Get current week |
|
||||
| GET | `/api/timesheets/history` | All user timesheets |
|
||||
| POST | `/api/timesheets/submit` | Submit for approval |
|
||||
| GET | `/api/timesheets/:id/pdf` | Download PDF |
|
||||
|
||||
### Admin
|
||||
| Method | Endpoint | Description |
|
||||
|--------|-------------------------------------|-------------------------|
|
||||
| GET | `/api/admin/timesheets` | All timesheets (filter) |
|
||||
| GET | `/api/admin/timesheets/:id` | Timesheet detail |
|
||||
| PUT | `/api/admin/timesheets/:id/approve` | Approve timesheet |
|
||||
| PUT | `/api/admin/timesheets/:id/reject` | Reject timesheet |
|
||||
| PUT | `/api/admin/timesheets/:id/reopen` | Reopen for editing |
|
||||
| GET | `/api/admin/users` | List employees |
|
||||
| POST | `/api/admin/users` | Create employee |
|
||||
| GET | `/api/admin/homeowners` | List homeowners |
|
||||
| POST | `/api/admin/homeowners` | Add homeowner |
|
||||
| GET | `/api/admin/reports` | Reporting with filters |
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Upgrading from v1
|
||||
|
||||
v2 is a complete rewrite. Key differences:
|
||||
|
||||
| Feature | v1 | v2 |
|
||||
|-----------------|-----------------------------|----------------------------------|
|
||||
| Storage | Browser localStorage | PostgreSQL database |
|
||||
| Auth | None | JWT with roles |
|
||||
| Multi-user | No | Yes — unlimited employees |
|
||||
| Approval flow | No | Submit → Approve/Reject |
|
||||
| PDF | Client-side (jsPDF) | Server-side (@react-pdf) |
|
||||
| Email | mailto: link | SMTP with PDF attachment |
|
||||
| Deploy | Static HTML | Docker Compose (one command) |
|
||||
| Admin panel | No | Full admin with reporting |
|
||||
| Dark mode | No | System-aware + manual toggle |
|
||||
|
||||
---
|
||||
|
||||
## 📝 License
|
||||
|
||||
Private — Coastal Contracting of FL. All rights reserved.
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
Built with ☀️ in Florida
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user