Commit Graph
30 Commits
Author SHA1 Message Date
tiennm99 de6bdf7eec docs: lock scope to lô tô hội chợ tân tân variant
- pdr: explicit in-scope (9x9, 5/row + 5/col, ascending cols, single-row
  Kinh, "Chờ N", continue-after-win) vs out-of-scope (3x9 european
  bingo 90, two-line / full-house tiers, custom number ranges)
- update codebase-summary, system-architecture, development-roadmap to
  reflect 11x9 master board, draw-order overlay, exact 5/col picker
- add researcher report comparing tân tân vs european bingo 90
2026-04-26 23:40:07 +07:00
tiennm99 189ae3d4e5 feat(game): tân tân lô tô — align master, 5/col, ascending, draw-order
- master board: 11x9 last-digit aligned (col 0 = 1-9, col 8 = 80-90);
  fixes missing ones-digit-9 row and aligns 1/11/21/.../81 horizontally
- master board: each called cell shows 1-based draw order so host can
  glance across a winning row to verify "Kinh!"
- player card: constraint-aware picker guarantees exactly 5 numbers per
  row AND per column (was loose weighted random allowing 4-6 per col)
- player card: numbers within each column now placed ascending
  top-to-bottom per lô tô hội chợ tân tân convention
2026-04-26 23:39:54 +07:00
tiennm99 ebae5371b4 fix(deploy): add wrangler.toml so CF Pages reads output dir from repo
CF Pages reported: Error: Output directory 'public' not found. The
dashboard had defaulted to 'public' but SvelteKit adapter-static writes
to its own output dir.

wrangler.toml with pages_build_output_dir makes the project reproducible
from git — no manual dashboard tweak required for the output path.

The build command in the CF dashboard still controls how the build
runs; ensure it is set to `npm run b u i l d`.
2026-04-26 21:27:08 +07:00
tiennm99 222cc97fa8 fix(deps): pin lightningcss-linux-x64-gnu so CF Pages build resolves
Cloudflare Pages build failed with:
  Error: Cannot find module '../lightningcss.linux-x64-gnu.node'

Tailwind 4 → @tailwindcss/vite → lightningcss has per-platform native
binaries shipped as optional npm packages. The lockfile generated on
this dev box (linux-arm64) only carried the arm64 binaries, so CF on
linux-x64 was missing the matching platform-specific package.

Adding lightningcss-linux-x64-gnu to optionalDependencies pins it into
the lockfile. On non-x64-linux machines npm skips it silently due to
the platform mismatch; CF Pages on linux-x64 will install it.

Pinned to 1.32.0 to match the parent dep already resolved.
2026-04-26 21:21:37 +07:00
tiennm99 c743d1cbfe ci: GitHub Pages now serves a redirect to loto.miti99.com
Replace the full build+publish flow with a tiny inline shell step that
emits two static HTML pages (out/index.html and out/master/index.html).
Each one carries:

  <meta http-equiv="refresh" content="0; url=https://loto.miti99.com/">
  <script>location.replace("https://loto.miti99.com" + ...)</script>

The script preserves path / query / hash, so
  /loto/                  → loto.miti99.com/
  /loto/master            → loto.miti99.com/master
  /loto/?x=1              → loto.miti99.com/?x=1

Cloudflare Pages stays canonical; this change just stops GH Pages from
serving a stale duplicate of the app and points old links at the live
domain instead.

The build:gh npm script is kept as a manual escape hatch for the rare
case where someone wants to deploy a real GH Pages copy by hand.
2026-04-26 21:19:40 +07:00
tiennm99 76ea82a649 fix(dev): read .env.local in vite + svelte configs
Symptom: 'Blocked request. This host (codeserver.sg.miti99.com) is not
allowed.' — the configs were reading process.env.CODESERVER_HOST, which
is empty at config-eval time because Vite reads .env.local at runtime,
not into process.env.

Switch both vite.config.js and svelte.config.js to use loadEnv() from
vite, which reads .env.local explicitly. Also lift allowedHosts out of
the codeserver profile so plain `npm run dev` is also reachable from
the codeserver proxy when CODESERVER_HOST is set in .env.local.
2026-04-26 21:15:59 +07:00
tiennm99 6dd7ce86f6 ci: bring back GitHub Pages auto-deploy
.github/workflows/deploy-github-pages.yml runs `npm run build:gh` on push
to main and uploads build/ via actions/upload-pages-artifact@v3 +
actions/deploy-pages@v4.

The build:gh script sets BUILD_PROFILE=gh, which switches svelte.config.js
basePath to /loto so assets resolve under tiennm99.github.io/loto.

Cloudflare Pages keeps deploying in parallel via the CF dashboard
(npm run build, root basePath, loto.miti99.com). Two URLs, no conflict.
2026-04-26 21:13:07 +07:00
tiennm99 a70a05d23c docs: rename default branch to main 2026-04-26 21:06:53 +07:00
tiennm99 ea716e6328 chore(plans): mark sveltekit-refactor as completed 2026-04-26 21:03:55 +07:00
tiennm99 ee48e162d2 refactor: rewrite from Next.js + React to SvelteKit + Svelte 5
Full stack swap to enable future extension (more pages / load functions /
backend) while keeping JSDoc-only code style.

Stack:
- SvelteKit 2 + adapter-static
- Svelte 5 runes ($state, $derived, $effect, $props)
- Vite 7 + @sveltejs/vite-plugin-svelte 6
- Tailwind 4 (Vite plugin)
- ESLint 9 (flat) + eslint-plugin-svelte
- Pure JS + JSDoc, no TypeScript

Source moves:
- app/page.jsx              → src/routes/+page.svelte
- app/master/page.jsx       → src/routes/master/+page.svelte
- app/layout.jsx            → src/routes/+layout.svelte (+ +layout.js)
- components/player-board.jsx → src/lib/PlayerBoard.svelte
- lib/game-logic.js         → src/lib/game-logic.js (verbatim)
- next.config.mjs           → svelte.config.js + vite.config.js
- app/globals.css           → src/app.css
- (new)                     → src/app.html

Behavior preserved: PlayerBoard with bingo "Kinh!" popup + waiting "Chờ X"
toast, master 9x10 tracking board with shuffled draw, host's own player
card via storagePrefix="loto_master_card", localStorage prefix model
(loto_*, loto_master, loto_master_card_*), basePath dual mode (CF default
empty, BUILD_PROFILE=gh → /loto, codeserver dev → /absproxy/{port}).

A11y kept from prior hardening: role-correct buttons, aria-pressed on
cells, role=dialog modal with Escape, role=status toast.

Plans: ts-to-jsdoc plan marked completed; sveltekit-refactor plan tracks
the work above. Docs under ./docs/ rewritten by docs-manager subagent to
match the SvelteKit terminology.
2026-04-26 21:03:41 +07:00
tiennm99 bbdd2b449b refactor: cf-only deploy via dashboard, drop gh actions
- Default `npm run build` now produces a root-relative build (CF Pages
  custom domain at loto.miti99.com). The /loto basePath is opt-in via
  `npm run build:gh` for the rare manual GH Pages export.
- Removed both GitHub Actions deploy workflows (.github/workflows/) and
  the dangling `build:cf` script (it was identical to `build` after the
  default flip).
- next.config.mjs: simplified basePath logic — only `BUILD_PROFILE=gh`
  toggles a non-empty path; everything else (CF, local dev) is root.
2026-04-26 20:32:04 +07:00
tiennm99 3ab09dc4ba feat: add explicit gh and cf build profiles
Two named build scripts replace the prior CF_PAGES auto-detect:

  npm run build:gh  → BUILD_PROFILE=gh, basePath /loto
                      target: https://tiennm99.github.io/loto
  npm run build:cf  → BUILD_PROFILE=cf, basePath ""
                      target: https://loto.miti99.com (CF Pages custom domain)

Both deploy workflows now use the matching profile script. The legacy
`npm run build` keeps its prior behaviour (defaults to /loto basePath) so
nothing else in the toolchain breaks. NEXT_BASE_PATH still wins for any
one-off custom-domain build.

CF_PAGES auto-detection removed — explicit profiles are clearer than
relying on the host injecting a magic env var, and dashboard users should
just set the build command to `npm run build:cf`.
2026-04-26 20:28:30 +07:00
tiennm99 c851d64b2f feat: add Cloudflare Pages deployment support
next.config.mjs now detects CF_PAGES=1 (auto-injected by Cloudflare during
build) and switches basePath from /loto to "" — assets resolve at the
project root on loto.pages.dev. GH Pages keeps /loto unchanged.

New workflow .github/workflows/deploy-cloudflare-pages.yml mirrors the GH
Pages flow but publishes via cloudflare/wrangler-action@v3. Requires repo
secrets CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID; project name "loto"
is hardcoded — adjust --project-name= in the workflow if your CF Pages
project uses a different name.

Dashboard-based deploys also work without code changes thanks to the
CF_PAGES detection. See docs/deployment-guide.md for both paths.
2026-04-26 20:12:51 +07:00
tiennm99 02b886d984 refactor: purge remaining TypeScript residue
After the JS+JSDoc conversion, some TS-flavored bits lingered. Removed:

- // @ts-check directives (TS-specific pragma)
- JSDoc annotations referencing TS-defined types: import('next').NextConfig,
  React.MutableRefObject, React.Dispatch, React.SetStateAction
- jsconfig.json (TS-server-flavored config; only kept it for the @/* alias)

@/* imports replaced with relative paths so jsconfig is no longer needed.
Remaining JSDoc is plain @param / @returns — vanilla JS, no TS dependency.

Build, lint, dev profiles unchanged.
2026-04-26 20:01:43 +07:00
tiennm99 95545c9308 refactor: convert from TypeScript to JavaScript with JSDoc
Author types in JSDoc comments. jsconfig.json keeps checkJs: true so
the editor's bundled TS server still validates them; CI can validate
with npx -p typescript tsc --noEmit on demand.

Renames (history preserved via git mv):
- next.config.ts        -> next.config.mjs
- app/layout.tsx        -> app/layout.jsx
- app/page.tsx          -> app/page.jsx
- app/master/page.tsx   -> app/master/page.jsx
- components/player-board.tsx -> components/player-board.jsx
- lib/game-logic.ts     -> lib/game-logic.js
- tsconfig.json         -> jsconfig.json (same @/* alias)

Drops typescript and @types/node, @types/react, @types/react-dom
from devDependencies. Removes vendored next-env.d.ts. eslint config
no longer pulls in eslint-config-next/typescript.

Behavior unchanged. Build, lint, and dev profiles verified.
2026-04-26 19:45:36 +07:00
tiennm99 254a6dc39a refactor: move shared modules out of app/
`app/` should hold route segments only. Game logic and the player-card
component are imported by both routes, so they belong outside:

  app/loto-game-logic.ts   -> lib/game-logic.ts
  app/loto-player-board.tsx -> components/player-board.tsx

Imports use the existing @/* alias. Drops the redundant `loto-` prefix.
Also fixes the package name from the scaffold default.
2026-04-26 19:34:37 +07:00
tiennm99 dd64aa6ed3 docs: initialize project documentation
Adds the standard ./docs/ structure (overview, codebase summary,
architecture, code standards, design guidelines, deployment guide,
roadmap) and the code-review report under ./plans/reports/.
README now points at the docs and covers the codeserver dev profile.
2026-04-26 19:27:18 +07:00
tiennm99 fd2d144428 refactor: harden loto game per code review
- Validate localStorage shape on load (typed parse, guarded set)
- Fix isRowComplete to require at least one number per row
- Split row-scan effect into bingo + waiting passes so updates to
  later rows are not skipped by an early return
- Memoize per-row completeness; was recomputing 81 times per render
- Replace clickable divs with real <button>s; aria-label, aria-pressed,
  focus ring, dialog role + escape on the bingo modal
- Freeze the master tracking board to make module-scope state safer
- Allow NEXT_BASE_PATH to override the prod default for forks /
  custom-domain deploys
2026-04-26 19:27:11 +07:00
tiennm99 400c55bef8 feat: add codeserver dev profile
NEXT_DEV_PROFILE=codeserver wires basePath, assetPrefix, and
allowedDevOrigins from CODESERVER_HOST/PORT in .env.local. Use
/absproxy/{port} so code-server preserves the path prefix and Next's
basePath matches the incoming request.

Run with `npm run dev:codeserver` and access via
https://<host>/absproxy/<port>/.
2026-04-26 19:16:46 +07:00
tiennm99 9d52b5b02a feat: add player board for game master
Master page now embeds a separate playing card so the host can play along
while drawing numbers. Extracted shared grid logic into a reusable
PlayerBoard component with a configurable storage prefix.
2026-04-26 19:16:38 +07:00
tiennm99 dfea4d9403 feat: add "Kinh!" congrats popup and "Chờ X" waiting toast
Show animated congrats when all 5 numbers in a row are crossed.
Show "Chờ [number]" toast overlay when 4/5 crossed. Auto-fades
after 5s or dismissible by tap.
2026-04-04 22:44:12 +07:00
tiennm99 4cf11bfcfc fix: make master board view-only and enlarge control buttons 2026-04-04 22:34:00 +07:00
tiennm99 fca823a9de feat: add game master page with number generator and tracking board
9x10 master board to track called numbers, random draw button,
call history, and manual toggle. Conditional basePath for local dev.
2026-04-04 22:28:05 +07:00
tiennm99 3bf9cd9c60 feat: add GitHub Pages deployment workflow
Configure static export and GitHub Actions workflow
to auto-deploy to GitHub Pages on push to master.
2026-04-04 22:17:18 +07:00
tiennm99 b399e54a47 fix: equal cell sizing with CSS grid and improved UI design
Use CSS grid for uniform cell sizes, gradient accents,
cleaner color palette, and footer with heart emoji link.
2026-04-04 22:03:40 +07:00
tiennm99 7f25a8e462 feat: convert to Next.js with TypeScript and Tailwind CSS
Replace vanilla HTML/JS/CSS with Next.js App Router, TypeScript,
and Tailwind CSS. Responsive design with dark mode support.
All original game logic preserved: grid generation, click-to-cross,
localStorage persistence.
2026-04-04 21:51:07 +07:00
tiennm99 761744cdc6 Create loto.js 2025-12-21 09:55:19 +07:00
tiennm99 77b70442ea [Change] random number algorithm 2021-02-08 20:30:54 +07:00
tiennm99 2abc1a0068 Init 2021-02-08 18:47:14 +07:00
miti99 e3a44836cb Initial commit 2021-02-08 11:10:48 +00:00