尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Internal tool for GMR: equipment/inventory tracking, face-scan attendance, car booking, leave requests, project & wiring-diagram management — plus a LINE bot for borrowing items, attendance reminders, and approvals on the go.
| Layer | Choice |
|---|---|
| Framework | Next.js 16.2.6 (App Router, Server Actions) |
| UI | React 19, Tailwind CSS 4 |
| Database | PostgreSQL — Prisma ORM 6.19.3 (@prisma/adapter-pg) |
| Auth | NextAuth v5 (beta), Credentials provider (username + bcrypt password) |
| Face recognition | face-api.js (client-side, browser) |
| Diagrams / circuit sandbox | @xyflow/react (React Flow) |
| File storage | Vercel Blob (@vercel/blob) |
| Tests | Vitest |
| Chat bot | LINE Messaging API webhook |
| AI (LINE bot only) | Groq API (qwen/qwen3.8-27b, OpenAI-compatible endpoint) |
| Hosting | Vercel |
⚠️ Next.js 16 renamed
middleware.ts→proxy.ts. This repo already usesproxy.ts— don't add amiddleware.tsfile, the two conflict and crash the dev server.
npm install
npx prisma generate
npm run dev
Open http://localhost:3000. You'll need a .env file (see below) — ask an
admin for one, or set up your own dev database (Neon free tier works fine).
All of these live in .env (gitignored, never commit real values). Ask an
admin for the real .env, or fill in your own for local dev:
| Variable | Purpose |
|---|---|
DATABASE_URL | Pooled Postgres connection string (used at runtime) |
DIRECT_URL | Unpooled connection string (required by prisma migrate) |
AUTH_SECRET | NextAuth session encryption secret |
BLOB_STORE_ID, BLOB_READ_WRITE_TOKEN | Vercel Blob storage (asset/vehicle/check-in photos) |
LINE_CHANNEL_SECRET | LINE webhook signature verification |
LINE_CHANNEL_ACCESS_TOKEN | LINE push/reply message API auth |
CRON_SECRET | Shared secret so only Vercel Cron / the external pinger can trigger /api/cron/* |
GROQ_API_KEY | Powers the LINE bot's free-form Q&A + borrow-intent extraction — get one free at console.groq.com/keys |
⚠️ Local dev vs. production are separate databases. DATABASE_URL in
.env points at a local/dev Neon branch by default. The real production
database (used by the deployed app) is a separate Prisma Postgres instance —
its connection string is commented out at the top of .env. To run any
script against production, override DATABASE_URL/DIRECT_URL for that one
command only, e.g. (PowerShell):
$env:DATABASE_URL = '<production connection string>'; npx prisma studio
Never edit DATABASE_URL itself to point at production — too easy to forget
to change it back.
| Command | What it does |
|---|---|
npm run dev | Start the Next.js dev server |
npm run build | prisma migrate deploy && prisma generate && next build — used by Vercel |
npm start | Run the production build locally |
npm run lint | ESLint |
npm test | Run the Vitest suite (lib/*.test.ts) |
npx prisma studio — GUI to browse/edit every table in the browser
(http://localhost:5555). Defaults to the local dev DB; override
DATABASE_URL first to point it at production (see above). The
in-app "delete row" button has a known client-side bug (Cannot find module error) — prefer the script below instead of clicking Delete in
Studio.node scripts/delete-user.js <username> — deletes one user by
username, including everything that cascades (check-ins, loans, leave
requests, car bookings). If the user owns an Equipment Template, Wiring
Diagram, or Project, delete/reassign those first — the database blocks
the user delete otherwise rather than silently destroying real work. Same
local-by-default / override-for-production rule as above.Schema lives in prisma/schema.prisma. To change it:
npx prisma migrate dev --name <description> # writes + applies a migration locally
Then apply the same migration to production (production does not
auto-migrate on deploy — next build's prisma migrate deploy step runs,
but has occasionally not taken effect reliably, so always double check):
$env:DATABASE_URL = '<prod>'; $env:DIRECT_URL = '<prod>'; npx prisma migrate deploy
On Windows, npx prisma generate can fail with EPERM: operation not permitted, rename ... query_engine-windows.dll.node if a dev server is
already running and holding the file lock. This is harmless — the client's
generated TypeScript types still update; only the (unchanged) native engine
binary fails to re-stage. Safe to ignore, or stop the dev server first if
it bothers you.
⚠️ After any schema change, restart npm run dev if it was already
running. Node caches the old @prisma/client module in memory — the
prisma generate step updates the files on disk, but a dev server started
before that won't see the new model/fields until restarted, and will
throw Unknown field '...' errors on any query touching them.
Three roles, enforced in auth.config.ts (page-level) and inside each
Server Action (data-level — belt and suspenders):
/inventory: create/edit/
delete assets, adjust quantity)./users (manage accounts, roles, registered
faces) and /attendance (HR data across all employees, CSV export).| Route | What it's for |
|---|---|
/checkin | Face-scan check-in/out kiosk (liveness check: head-turn detection) |
/attendance | Admin-only attendance table, customizable columns, CSV export |
/inventory, /catalog | Equipment stock management / employee-facing browse & borrow |
/my-loans | An employee's currently-borrowed items |
/carbook | Vehicle booking, admin approval |
/leave | Leave requests, admin approval |
/projects, /work-schedule | Project tracking and scheduling — projects can have images, PDFs, and 3D/CAD files (STEP, STL, OBJ, IGES) attached, up to 50MB each |
/diagrams, /circuit | Wiring diagram templates + free-form circuit sandbox (React Flow) |
/users | Admin-only: accounts, roles, face registration |
/dashboard | Overview landing page |
Webhook: app/api/line/webhook/route.ts. Employees link their account once
(1:1 chat only, username + password) via lib/line.ts, then can:
"ยืม สว่าน 2", or just
"ขอสว่านหน่อย" and the bot asks what's missing next), with tap-to-pick
Quick Reply buttons when a name matches multiple items.lib/lineAssistant.ts.AI model: Groq (qwen/qwen3.8-27b, OpenAI-compatible chat completions
API) — chosen over Gemini's free tier, which caps at 20 requests/day.
/api/cron/cleanup-checkin-photos — runs once daily via
vercel.json (Vercel Hobby plan allows one cron schedule). Purges
check-in webcam snapshots to bound storage growth (the CheckIn record
itself is kept — attendance math needs it)./api/cron/checkin-reminders — needs to run every few minutes, which
Hobby's cron doesn't support. Triggered instead by an external pinger
(cron-job.org) hitting the endpoint every 5 minutes with an
Authorization: Bearer <CRON_SECRET> header. Handles the 15-min warning,
8-hour OT prompt, and the midnight auto-checkout/re-ask described above.Both routes check CRON_SECRET so they can't be triggered by anyone who
just finds the URL.
Push to main → Vercel auto-deploys. npm run build runs
prisma migrate deploy first, but this has occasionally not applied
migrations reliably on Vercel's build — after any schema change, verify (or
manually re-run prisma migrate deploy against production, see above)
rather than assuming it worked.
All check-in/attendance/leave/booking timestamps are stored as UTC instants
but every display and business-hour calculation pins Asia/Bangkok
explicitly (lib/datetime.ts) — the production server itself runs in UTC,
so anything using the ambient server timezone shows times ~7 hours off.
Always use the helpers in lib/datetime.ts rather than raw
toLocaleString()/Date timezone-dependent calls.
docker compose --env-file .env.production build
docker compose --env-file .env.production up -d
docker compose logs -f app
docker compose down