A production-ready Queueing Management System built with SvelteKit and TypeScript. Features a green-themed UI designed for public offices and LGUs.
- Public Display (TV Mode): Real-time queue display with sound notifications
- Counter Interface: Staff dashboard for managing queues
- Admin Dashboard: Full CRUD operations, analytics, and user management
- Real-time Updates: Live synchronization (polling-based) across all devices
- Sound System: Audio notifications when tickets are called
- Role-based Access: Admin, Counter Staff, and Public roles
- Kiosk / Landing: http://localhost:5173/
- Login: http://localhost:5173/login
- Admin Dashboard: http://localhost:5173/admin
- Public Display (TV): http://localhost:5173/display
- Counter Controller: http://localhost:5173/counter/controller
- Counter Dashboard (admin view): http://localhost:5173/counter
- Frontend: SvelteKit + TypeScript
- Styling: TailwindCSS with custom green theme
- Backend: MySQL (via API routes)
- State Management: Svelte Stores
- Authentication: Session-based (Database stored)
npm install- Install MySQL Server (if not already installed).
- Create a new database named
qms(or any name you prefer). - Run the schema script
database/schema-mysql.sqlin your MySQL client to create tables and initial data.
# Example using mysql command line
mysql -u root -p qms < database/schema-mysql.sqlCreate a .env file in the root directory with your MySQL credentials:
# Database Configuration
MYSQL_HOST=localhost
MYSQL_USER=root
MYSQL_PASSWORD=your_password
MYSQL_DATABASE=qms
MYSQL_CONNECTION_LIMIT=10
# Security (JWT Secret for sessions - change this!)
JWT_SECRET=change-this-to-a-secure-random-stringnpm run devVisit http://localhost:5173 to see the application.
- Admin Login:
- Email:
admin@sanpedro.com - Password:
admin123
- Email:
src/
├── lib/
│ ├── server/
│ │ └── db.ts # MySQL connection pool
│ ├── stores/
│ │ ├── auth.ts # Authentication store
│ │ ├── queue.ts # Queue management store
│ │ └── sound.ts # Sound system
├── routes/
│ ├── api/ # Backend API endpoints
│ ├── +page.svelte # Ticket Kiosk / Landing
│ ├── login/ # Login page
│ ├── display/ # Public TV display
│ ├── counter/ # Counter staff dashboard
│ ├── admin/ # Admin dashboard
│ └── help/ # Help page
└── app.css # Global styles
- Admin: Full system access, CRUD operations, analytics
- Counter Staff: Manage queues, call tickets, serve customers
- Public: View-only access to display screen
Tickets follow the format: <ServiceCode>-<Number>
- Example:
S1-005(Service 1, ticket number 5)
npm run build- Build the project.
- Set environment variables on the server.
- Run the built application using
node.
node build/index.jsEdit tailwind.config.js to customize the green theme:
colors: {
'forest-green': {
DEFAULT: '#075E25', // Your custom green
// ... other shades
}
}Modify src/lib/stores/sound.ts to adjust:
- Sound frequency
- Volume
- Sound pattern
For issues:
- Check browser console for errors
- Check server logs
- Verify database connection in
.env
- Counter Staff accounts automatically use the compact Controller view instead of the full dashboard.
- Visiting
/counterredirects to/counter/controllerfor Counter Staff. - Admins access
/adminand can still open the Counter dashboard for monitoring purposes. - Controller persists login and counter selection across refreshes and windows.
Key screens:
- Controller: controller/+page.svelte
- Counter dashboard (admin only by default): counter/+page.svelte
- Login routing: login/+page.svelte
- Install prerequisites
- Node.js 18+ (required by Vite 5)
- MySQL Server (local or remote)
- Clone and install
npm install
- Configure environment
- Create
.envusing.env.example - Set
MYSQL_HOST,MYSQL_USER,MYSQL_PASSWORD,MYSQL_DATABASE
- Create
- Initialize database
- Option A: Command line
mysql -u root -p qms < database/schema-mysql.sql - Option B: Script
node scripts/init-db.js
- Option A: Command line
- Verify database connectivity
node scripts/check-setup-mysql.js
- Run the app
npm run dev
- Sign in
- Admin:
admin@sanpedro.com/admin123 - Create Counter Staff via Admin → Users, then sign in as Counter Staff to use the Controller
- Admin:
Helpful commands:
- Type checking:
npm run check - Build:
npm run build - Preview build:
npm run preview
- Users: Admin, Counter Staff
- Services: Code, Name, Description, Active
- Counters: Name, Service binding, Active state, Current ticket
- Tickets: ID, Number, Service code, Status, Timestamps, Counter assignment
Tables are created by database/schema-mysql.sql.
waiting: created and queuedcalled: currently being served by a counterserved: completed successfullyskipped: skipped from the queue by staff
- Create: api/tickets/create/+server.ts
- Call: api/tickets/call/+server.ts
- Recall: api/tickets/recall/+server.ts
- Serve: api/tickets/serve/+server.ts
- Skip: api/tickets/skip/+server.ts
- Transfer: api/tickets/transfer/+server.ts
Client store helpers: queue.ts
createTicket(serviceCode)callTicket(ticketId, counterId)recallTicket(ticketId)serveTicket(ticketId)skipTicket(ticketId)transferTicket(ticketId, newCounterId)
- Only tickets from the current day are considered for current display and stats.
- Active "called" tickets are tracked per counter.
- Waiting order is first-come-first-serve per service code.
Relevant code:
- Current-day filtering and per-counter mapping: queue.ts
- Stats helpers: queue.ts
- MySQL backend uses polling every 2 seconds to synchronize tickets and counters.
- Polling is initialized on app start and can be stopped if needed.
- Code: queue.ts
- On login, user and profile are persisted to local storage.
- On refresh/new window, the app restores the session and profile.
- Counter selection persists via
activeCounterIdand is read by the Controller. - Code: auth.ts
- Call Next, Recall, Complete Service, Skip, Transfer
- Compact UI tailored for staff working with other applications
- Code: controller/+page.svelte
- Services: Create/update/delete at api/services/+server.ts
- Counters: Create/update status at api/counters/+server.ts
- Users: Create at api/users/create/+server.ts
- Toggle counter availability from the dashboard (admin view) or via API.
- Check backend connectivity: api/debug/+server.ts
- Ensure
.envvalues match your MySQL instance. - Verify schema loaded correctly using
node scripts/check-setup-mysql.js.