尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗เว็บสุ่มเมนูอาหารในโรงอาหารจุฬาฯ แบบ เปิดซองการ์ด TCG — เลือกโรงอาหาร ตอบคำถามสั้นๆ แล้วฉีกซองลุ้นการ์ดเมนู 3 ใบ เลือกใบที่จะไปกินจริง 1 ใบเก็บเข้า collection และแชร์ให้เพื่อนดูได้
Side project / prototype — ไม่มี backend ไม่มี login ข้อมูลทั้งหมดอยู่ใน frontend และเก็บ collection ไว้ในเครื่องผู้ใช้ (localStorage)
persist → localStoragebun install # หรือ npm install
bun dev # หรือ npm run dev
| คำสั่ง | ทำอะไร |
|---|---|
dev | รัน dev server |
build | build production |
start | รัน production build |
lint | ESLint |
/ เลือกโรงอาหาร
/[canteen] เลือกประเภทอาหาร (จานหลัก / ของหวาน 🔒 / เครื่องดื่ม 🔒)
/[canteen]/quiz คำถาม mock
/[canteen]/open เปิดซอง → เลือก 1 ใบ → เก็บเข้า collection
/collection การ์ดที่เก็บไว้ทั้งหมด + ปุ่มแชร์
/card/[menuId] หน้าการ์ดใบเดียว (ลิงก์แชร์ มี OG image)
/c?d=<encoded> collection ของเพื่อนแบบอ่านอย่างเดียว
ทุก route prerender แบบ static ผ่าน generateStaticParams
src/
├── app/
│ ├── [canteen]/open/ หน้าเปิดซอง
│ │ ├── director.ts ลำดับ animation ทั้งหมด (state: ready → tearing → reveal → choose → saved)
│ │ ├── fx.ts GSAP plugins + เอฟเฟกต์ (burst, sparkles, shake)
│ │ └── sfx.ts เสียงสังเคราะห์ด้วย Web Audio API
│ ├── collection/ c/ card/[menuId]/
├── components/ FoodCard, CardBack, ShareButtons, PacksLeft ฯลฯ
├── config/flow.ts ชื่อแอป ชื่อซอง ประเภทอาหาร และคำถาม quiz
├── data/ canteens.json, shops.json, menus.json
└── lib/
├── pack.ts logic สุ่มการ์ดในซอง
├── meal.ts แบ่งมื้อ + จำนวนซองต่อมื้อ + countdown
├── share.ts encode/decode ลิงก์ collection + แชร์รูป/ลิงก์
├── store.ts zustand store (collection, ซองที่ใช้, คำตอบ quiz, ปิดเสียง)
└── data.ts helper อ่านข้อมูล + ตัวเลือก SHARED_POOL
scripts/convert-cards.mjs แปลงรูปการ์ดจากดีไซเนอร์เป็น webp
| ค่า | ไฟล์ | ค่าเริ่มต้น |
|---|---|---|
จำนวนการ์ดต่อซอง CARDS_PER_PACK | src/lib/pack.ts | 3 |
โอกาสได้ Rare ต่อช่อง RARE_CHANCE | src/lib/pack.ts | 0.2 |
ซองต่อมื้อ PACKS_PER_MEAL | src/lib/meal.ts | 3 |
เวลาเริ่มแต่ละมื้อ SLOTS | src/lib/meal.ts | 06:00 / 10:30 / 15:00 / 21:00 |
สุ่มจากกองรวมทุกโรงอาหาร SHARED_POOL | src/lib/data.ts | true |
| ชื่อแอป / ชื่อซอง / คำถาม quiz | src/config/flow.ts | — |
ตอนนี้มีการ์ดแค่ 8 ใบ จึงตั้ง
SHARED_POOL = trueให้ทุกโรงอาหารสุ่มจากกองเดียวกัน เมื่อมีเมนูครบแต่ละโรงอาหารแล้วให้เปลี่ยนเป็นfalse
วางไฟล์รูปการ์ดจากดีไซเนอร์ (1.png, 2.png, … ขนาด 1500×2100) ไว้ในโฟลเดอร์หนึ่ง แล้วรัน
node scripts/convert-cards.mjs <โฟลเดอร์รูป>
สคริปต์จะย่อเป็น 750×1050 แล้วบันทึกเป็น public/cards/001.webp, 002.webp, …
เพิ่มเมนูใน src/data/menus.json ให้ id ตรงกับชื่อไฟล์การ์ด
{
"id": "009",
"shopId": "arts-4",
"canteenId": "arts",
"name": "ชื่อเมนู",
"type": "main",
"price": 50,
"rarity": "common",
"image": "/cards/009.webp",
"spicy": 0,
"tags": ["rice"]
}
spicy (0–3) และ tags ยังไม่ได้ใช้ แต่เตรียมไว้สำหรับกรองเมนูจาก quiz
ถ้าเป็นร้านใหม่ ให้เพิ่มใน src/data/shops.json ด้วย
price, spicy, tags)SHARED_POOLรูปโรงอาหารจาก Wikimedia Commons (CC BY-SA) — ดูรายชื่อผู้ถ่ายได้ในช่อง credit ของ src/data/canteens.json