- Multi-tenant client management with unique API keys - Semaphore SMS integration (per-client key + sender name + credit balance) - DB-based SMS queue with 3-attempt retry and exponential backoff - Failed SMS dashboard with manual retry button - Reports page with date/client filter and CSV export - Admin auth via NextAuth (email/password) - Docker Compose setup (app + PostgreSQL 16) - Prisma 5 schema with SmsQueue, SmsLog, Client, User models Tech: Next.js 14 App Router + TypeScript + Tailwind CSS + Prisma + PostgreSQL
93 lines
2.5 KiB
Markdown
93 lines
2.5 KiB
Markdown
# NFC Attendance Hub
|
|
|
|
A multi-tenant admin web app that acts as middleware between on-premise NFC student attendance apps and the [Semaphore](https://semaphore.co) SMS API.
|
|
|
|
## Features
|
|
|
|
- **Multi-tenant Client Management** — Register schools/orgs, each gets a unique API key
|
|
- **Semaphore SMS Integration** — Per-client Semaphore API key + sender name, credit balance display
|
|
- **DB-based SMS Queue** — Retry up to 3 attempts with exponential backoff, tracks failure reasons
|
|
- **Failed SMS Dashboard** — View failed messages with error details, manual retry button
|
|
- **Reports** — SMS stats per client, date filter, CSV export
|
|
- **Admin Auth** — Email/password login with NextAuth
|
|
|
|
## Tech Stack
|
|
|
|
- Next.js 14 (App Router) + TypeScript
|
|
- Tailwind CSS + shadcn/ui-compatible components
|
|
- Prisma ORM (v5) + PostgreSQL
|
|
- NextAuth.js (credentials provider)
|
|
|
|
## Quick Start (Docker)
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
# Edit .env with your values
|
|
|
|
docker compose up -d
|
|
```
|
|
|
|
App available at: http://localhost:3000
|
|
Default admin: `admin@nfchub.local` / `admin123`
|
|
|
|
## Development
|
|
|
|
```bash
|
|
npm install
|
|
cp .env.example .env
|
|
# Edit .env to point to a local PostgreSQL
|
|
|
|
npx prisma generate
|
|
npx prisma db push
|
|
npm run db:seed
|
|
npm run dev
|
|
```
|
|
|
|
## SMS API Reference
|
|
|
|
On-premise NFC apps submit attendance events to:
|
|
|
|
```
|
|
POST /api/v1/sms/send
|
|
Header: X-API-Key: <client_api_key>
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"student_name": "Juan Dela Cruz",
|
|
"student_id": "2024-001",
|
|
"parent_phone": "09171234567",
|
|
"event": "time_in", // "time_in" or "time_out"
|
|
"timestamp": "2024-01-15T08:30:00+08:00",
|
|
"message": "Optional custom message" // optional
|
|
}
|
|
```
|
|
|
|
### Response
|
|
|
|
```json
|
|
{ "success": true, "queueId": "...", "message": "SMS queued for delivery" }
|
|
```
|
|
|
|
### SMS Queue Behavior
|
|
|
|
1. Submission is accepted immediately (202 Accepted)
|
|
2. Processing is triggered asynchronously
|
|
3. Failed sends are retried up to 3 times with exponential backoff (2min, 4min, 8min)
|
|
4. After 3 failures, SMS is marked FAILED and visible in the Failed SMS dashboard
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Description | Required |
|
|
|----------|-------------|----------|
|
|
| `DATABASE_URL` | PostgreSQL connection string | Yes |
|
|
| `NEXTAUTH_URL` | Public app URL | Yes |
|
|
| `NEXTAUTH_SECRET` | Random secret for JWT | Yes |
|
|
| `INTERNAL_API_KEY` | Internal queue trigger key | Yes |
|
|
|
|
## Docker Services
|
|
|
|
| Service | Port | Description |
|
|
|---------|------|-------------|
|
|
| `app` | 3000 | Next.js application |
|
|
| `postgres` | 5433 (host) | PostgreSQL 16 |
|