docs: add comprehensive code comments, update README and TASKS, create training and troubleshooting guides

- Add JSDoc comments to API routes and business logic functions
- Update README.md with Phase 2 status and deployment/production notes
- Enhance TASKS.md with estimated timelines and dependencies
- Create docs/STAFF_TRAINING.md for team onboarding
- Create docs/CLIENT_ONBOARDING.md for customer experience
- Create docs/OPERATIONAL_PROCEDURES.md for daily operations
- Create docs/TROUBLESHOOTING.md for common setup issues
- Fix TypeScript errors in hq/page.tsx
This commit is contained in:
Marco Gallegos
2026-01-16 18:42:45 -06:00
parent 28e98a2a44
commit 8fc9d3717e
63 changed files with 973 additions and 101 deletions

View File

@@ -17,6 +17,9 @@ async function validateAdmin(request: NextRequest) {
return true
}
/**
* @description Retrieves kiosks with filters for admin
*/
export async function GET(request: NextRequest) {
try {
const isAdmin = await validateAdmin(request)
@@ -77,6 +80,9 @@ export async function GET(request: NextRequest) {
}
}
/**
* @description Creates a new kiosk
*/
export async function POST(request: NextRequest) {
try {
const isAdmin = await validateAdmin(request)

View File

@@ -17,6 +17,9 @@ async function validateAdmin(request: NextRequest) {
return true
}
/**
* @description Retrieves all locations for admin
*/
export async function GET(request: NextRequest) {
try {
const isAdmin = await validateAdmin(request)

View File

@@ -17,6 +17,9 @@ async function validateAdmin(request: NextRequest) {
return true
}
/**
* @description Retrieves staff users with filters for admin
*/
export async function GET(request: NextRequest) {
try {
const isAdmin = await validateAdmin(request)
@@ -78,6 +81,9 @@ export async function GET(request: NextRequest) {
}
}
/**
* @description Creates a new staff user
*/
export async function POST(request: NextRequest) {
try {
const isAdmin = await validateAdmin(request)

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Fetches bookings with filters for dashboard view
*/
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)

View File

@@ -37,6 +37,9 @@ const mockPermissions = [
}
]
/**
* @description Retrieves permissions data for different roles
*/
export async function GET() {
return NextResponse.json({
success: true,
@@ -44,6 +47,9 @@ export async function GET() {
})
}
/**
* @description Toggles a specific permission for a role
*/
export async function POST(request: NextRequest) {
const { roleId, permId } = await request.json()

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Fetches recent payments report
*/
export async function GET() {
try {
// Get recent payments (assuming bookings with payment_intent_id are paid)

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Fetches payroll report for staff based on recent bookings
*/
export async function GET() {
try {
// Get staff and their bookings this week

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Fetches sales report including total sales, completed bookings, average service price, and sales by service
*/
export async function GET() {
try {
// Get total sales

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Retrieves active resources, optionally filtered by location
*/
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Gets available staff for a location and date
*/
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Retrieves staff availability schedule with optional filters
*/
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
@@ -60,6 +63,9 @@ export async function GET(request: NextRequest) {
}
}
/**
* @description Creates or updates staff availability
*/
export async function POST(request: NextRequest) {
try {
const body = await request.json()
@@ -145,6 +151,9 @@ export async function POST(request: NextRequest) {
}
}
/**
* @description Deletes staff availability by ID
*/
export async function DELETE(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)

View File

@@ -17,6 +17,9 @@ async function validateAdmin(request: NextRequest) {
return true
}
/**
* @description Creates a booking block for a resource
*/
export async function POST(request: NextRequest) {
try {
const isAdmin = await validateAdmin(request)
@@ -76,6 +79,9 @@ export async function POST(request: NextRequest) {
}
}
/**
* @description Retrieves booking blocks with filters
*/
export async function GET(request: NextRequest) {
try {
const isAdmin = await validateAdmin(request)
@@ -151,6 +157,9 @@ export async function GET(request: NextRequest) {
}
}
/**
* @description Deletes a booking block by ID
*/
export async function DELETE(request: NextRequest) {
try {
const isAdmin = await validateAdmin(request)

View File

@@ -17,6 +17,9 @@ async function validateAdminOrStaff(request: NextRequest) {
return true
}
/**
* @description Marks staff as unavailable for a time period
*/
export async function POST(request: NextRequest) {
try {
const hasAccess = await validateAdminOrStaff(request)
@@ -119,6 +122,9 @@ export async function POST(request: NextRequest) {
}
}
/**
* @description Retrieves staff unavailability records
*/
export async function GET(request: NextRequest) {
try {
const hasAccess = await validateAdminOrStaff(request)

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Retrieves available staff for a time range
*/
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Retrieves detailed availability time slots for a date
*/
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Updates the status of a specific booking
*/
export async function PATCH(
request: NextRequest,
{ params }: { params: { id: string } }

View File

@@ -2,6 +2,9 @@ import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
import { generateShortId } from '@/lib/utils/short-id'
/**
* @description Creates a new booking
*/
export async function POST(request: NextRequest) {
try {
const body = await request.json()
@@ -70,6 +73,7 @@ export async function POST(request: NextRequest) {
const endTimeUtc = endTime.toISOString()
// Check staff availability for the requested time slot
const { data: availableStaff, error: staffError } = await supabaseAdmin.rpc('get_available_staff', {
p_location_id: location_id,
p_start_time_utc: start_time_utc,
@@ -93,6 +97,7 @@ export async function POST(request: NextRequest) {
const assignedStaff = availableStaff[0]
// Check resource availability with service priority
const { data: availableResources, error: resourcesError } = await supabaseAdmin.rpc('get_available_resources_with_priority', {
p_location_id: location_id,
p_start_time: start_time_utc,
@@ -117,6 +122,7 @@ export async function POST(request: NextRequest) {
const assignedResource = availableResources[0]
// Create or find customer based on email
const { data: customer, error: customerError } = await supabaseAdmin
.from('customers')
.upsert({
@@ -141,6 +147,7 @@ export async function POST(request: NextRequest) {
const shortId = await generateShortId()
// Create the booking record with all assigned resources
const { data: booking, error: bookingError } = await supabaseAdmin
.from('bookings')
.insert({
@@ -208,6 +215,9 @@ export async function POST(request: NextRequest) {
}
}
/**
* @description Retrieves bookings with filters
*/
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)

View File

@@ -4,6 +4,11 @@ import { supabaseAdmin } from '@/lib/supabase/client'
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
/**
* @description Creates a Stripe payment intent for booking deposit (50% of service price, max $200)
* @param {NextRequest} request - Request containing booking details
* @returns {NextResponse} Payment intent client secret and amount
*/
export async function POST(request: NextRequest) {
try {
const {

View File

@@ -2,6 +2,9 @@ import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
import { Kiosk } from '@/lib/db/types'
/**
* @description Authenticates a kiosk using API key
*/
export async function POST(request: NextRequest) {
try {
const body = await request.json()

View File

@@ -18,6 +18,9 @@ async function validateKiosk(request: NextRequest) {
return kiosk
}
/**
* @description Confirms a pending booking by short ID for kiosk
*/
export async function POST(
request: NextRequest,
{ params }: { params: { shortId: string } }

View File

@@ -18,6 +18,9 @@ async function validateKiosk(request: NextRequest) {
return kiosk
}
/**
* @description Retrieves pending/confirmed bookings for kiosk
*/
export async function GET(request: NextRequest) {
try {
const kiosk = await validateKiosk(request)
@@ -72,6 +75,9 @@ export async function GET(request: NextRequest) {
}
}
/**
* @description Creates a new booking for kiosk
*/
export async function POST(request: NextRequest) {
try {
const kiosk = await validateKiosk(request)

View File

@@ -18,6 +18,9 @@ async function validateKiosk(request: NextRequest) {
return kiosk
}
/**
* @description Retrieves available resources for kiosk, filtered by time and service
*/
export async function GET(request: NextRequest) {
try {
const kiosk = await validateKiosk(request)

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* Validates kiosk API key and returns kiosk info if valid
*/
async function validateKiosk(request: NextRequest) {
const apiKey = request.headers.get('x-kiosk-api-key')
@@ -18,6 +21,9 @@ async function validateKiosk(request: NextRequest) {
return kiosk
}
/**
* @description Creates a walk-in booking for kiosk
*/
export async function POST(request: NextRequest) {
try {
const kiosk = await validateKiosk(request)
@@ -45,6 +51,7 @@ export async function POST(request: NextRequest) {
)
}
// Validate service exists and is active
const { data: service, error: serviceError } = await supabaseAdmin
.from('services')
.select('*')
@@ -75,6 +82,7 @@ export async function POST(request: NextRequest) {
const assignedStaff = availableStaff[0]
// For walk-ins, booking starts immediately
const startTime = new Date()
const endTime = new Date(startTime)
endTime.setMinutes(endTime.getMinutes() + service.duration_minutes)

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Retrieves all active locations
*/
export async function GET(request: NextRequest) {
try {
const { data: locations, error } = await supabaseAdmin

View File

@@ -1,6 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/client'
/**
* @description Retrieves active services, optionally filtered by location
*/
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)