Scaffold full-stack volunteer scheduling application

Go backend with domain-based packages (volunteer, schedule, timeoff,
checkin, notification), SQLite storage, JWT auth, and chi router.
React TypeScript frontend with routing, auth context, and pages for
all core features. Multi-stage Dockerfile and docker-compose included.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 11:25:02 -04:00
parent 64f4563bfa
commit 4989ff1061
49 changed files with 19996 additions and 12 deletions

27
internal/db/db.go Normal file
View File

@@ -0,0 +1,27 @@
package db
import (
"database/sql"
"fmt"
_ "modernc.org/sqlite"
)
func Open(dsn string) (*sql.DB, error) {
db, err := sql.Open("sqlite", dsn)
if err != nil {
return nil, fmt.Errorf("open db: %w", err)
}
if err := db.Ping(); err != nil {
return nil, fmt.Errorf("ping db: %w", err)
}
if _, err := db.Exec(`PRAGMA journal_mode=WAL; PRAGMA foreign_keys=ON;`); err != nil {
return nil, fmt.Errorf("pragma: %w", err)
}
return db, nil
}
func Migrate(db *sql.DB) error {
_, err := db.Exec(schema)
return err
}

55
internal/db/schema.go Normal file
View File

@@ -0,0 +1,55 @@
package db
const schema = `
CREATE TABLE IF NOT EXISTS volunteers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
password TEXT NOT NULL,
role TEXT NOT NULL DEFAULT 'volunteer', -- 'admin' | 'volunteer'
active INTEGER NOT NULL DEFAULT 1,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS schedules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
volunteer_id INTEGER NOT NULL REFERENCES volunteers(id),
title TEXT NOT NULL,
starts_at TEXT NOT NULL,
ends_at TEXT NOT NULL,
notes TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS time_off_requests (
id INTEGER PRIMARY KEY AUTOINCREMENT,
volunteer_id INTEGER NOT NULL REFERENCES volunteers(id),
starts_at TEXT NOT NULL,
ends_at TEXT NOT NULL,
reason TEXT,
status TEXT NOT NULL DEFAULT 'pending', -- 'pending' | 'approved' | 'rejected'
reviewed_by INTEGER REFERENCES volunteers(id),
reviewed_at TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS checkins (
id INTEGER PRIMARY KEY AUTOINCREMENT,
volunteer_id INTEGER NOT NULL REFERENCES volunteers(id),
schedule_id INTEGER REFERENCES schedules(id),
checked_in_at TEXT NOT NULL DEFAULT (datetime('now')),
checked_out_at TEXT,
notes TEXT
);
CREATE TABLE IF NOT EXISTS notifications (
id INTEGER PRIMARY KEY AUTOINCREMENT,
volunteer_id INTEGER NOT NULL REFERENCES volunteers(id),
message TEXT NOT NULL,
read INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
`