Implement Issue #2: Scheduling & Publishing
Replaces stub schedule CRUD with full shift template + instance system. - DB: add shift_templates, shift_template_roles, shift_template_volunteers, shift_instances, shift_instance_volunteers tables - schedule package: ShiftTemplate and ShiftInstance models with store (generate, publish/unpublish, per-instance edits, volunteer confirmation) - API: shift-templates CRUD + shifts generate/publish/unpublish/update/confirm - Notifications sent on publish (FR-S04), unpublish (FR-S05), instance edit (FR-S09), and volunteer added mid-month (FR-S10) - Frontend: Schedules page with month navigation, template management, publish/unpublish controls, and per-shift edit/confirm - Tests: Go handler tests (14 cases) + React tests (11 cases) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -22,8 +22,11 @@ func New(db *sql.DB, jwtSecret string, staticDir string) http.Handler {
|
||||
volunteerStore := volunteer.NewStore(db)
|
||||
volunteerHandler := volunteer.NewHandler(volunteerStore, authSvc)
|
||||
|
||||
notificationStore := notification.NewStore(db)
|
||||
notificationHandler := notification.NewHandler(notificationStore)
|
||||
|
||||
scheduleStore := schedule.NewStore(db)
|
||||
scheduleHandler := schedule.NewHandler(scheduleStore)
|
||||
scheduleHandler := schedule.NewHandler(scheduleStore, notificationStore)
|
||||
|
||||
timeoffStore := timeoff.NewStore(db)
|
||||
timeoffHandler := timeoff.NewHandler(timeoffStore)
|
||||
@@ -31,9 +34,6 @@ func New(db *sql.DB, jwtSecret string, staticDir string) http.Handler {
|
||||
checkinStore := checkin.NewStore(db)
|
||||
checkinHandler := checkin.NewHandler(checkinStore)
|
||||
|
||||
notificationStore := notification.NewStore(db)
|
||||
notificationHandler := notification.NewHandler(notificationStore)
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Use(chimiddleware.Logger)
|
||||
r.Use(chimiddleware.Recoverer)
|
||||
@@ -56,11 +56,19 @@ func New(db *sql.DB, jwtSecret string, staticDir string) http.Handler {
|
||||
r.Put("/volunteers/{id}", volunteerHandler.Update)
|
||||
r.With(middleware.RequireAdmin).Post("/volunteers/{id}/invite", volunteerHandler.ResendInvite)
|
||||
|
||||
// Schedules
|
||||
r.Get("/schedules", scheduleHandler.List)
|
||||
r.Post("/schedules", scheduleHandler.Create)
|
||||
r.With(middleware.RequireAdmin).Put("/schedules/{id}", scheduleHandler.Update)
|
||||
r.With(middleware.RequireAdmin).Delete("/schedules/{id}", scheduleHandler.Delete)
|
||||
// Shift templates (admin only)
|
||||
r.Get("/shift-templates", scheduleHandler.ListTemplates)
|
||||
r.With(middleware.RequireAdmin).Post("/shift-templates", scheduleHandler.CreateTemplate)
|
||||
r.With(middleware.RequireAdmin).Put("/shift-templates/{id}", scheduleHandler.UpdateTemplate)
|
||||
r.With(middleware.RequireAdmin).Delete("/shift-templates/{id}", scheduleHandler.DeleteTemplate)
|
||||
|
||||
// Shift instances
|
||||
r.Get("/shifts", scheduleHandler.ListInstances)
|
||||
r.With(middleware.RequireAdmin).Post("/shifts/generate", scheduleHandler.GenerateInstances)
|
||||
r.With(middleware.RequireAdmin).Post("/shifts/publish", scheduleHandler.PublishMonth)
|
||||
r.With(middleware.RequireAdmin).Post("/shifts/unpublish", scheduleHandler.UnpublishMonth)
|
||||
r.With(middleware.RequireAdmin).Put("/shifts/{id}", scheduleHandler.UpdateInstance)
|
||||
r.Post("/shifts/{id}/confirm", scheduleHandler.ConfirmShift)
|
||||
|
||||
// Time off
|
||||
r.Get("/timeoff", timeoffHandler.List)
|
||||
|
||||
Reference in New Issue
Block a user