# CA-Lose CA-Lose is a small full-stack app for collecting ticket-sale/order form entries. ## Tech stack ![React](https://img.shields.io/badge/React-20232A?logo=react&logoColor=61DAFB) ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=fff) ![Vite](https://img.shields.io/badge/Vite-646CFF?logo=vite&logoColor=fff) ![Tailwind CSS](https://img.shields.io/badge/Tailwind%20CSS-06B6D4?logo=tailwindcss&logoColor=fff) ![MUI](https://img.shields.io/badge/MUI-007FFF?logo=mui&logoColor=fff) ![i18next](https://img.shields.io/badge/i18next-26A69A?logo=i18next&logoColor=fff) ![Node.js](https://img.shields.io/badge/Node.js-339933?logo=node.js&logoColor=fff) ![Express](https://img.shields.io/badge/Express-000000?logo=express&logoColor=fff) ![MySQL](https://img.shields.io/badge/MySQL-4479A1?logo=mysql&logoColor=fff) ![Docker](https://img.shields.io/badge/Docker-2496ED?logo=docker&logoColor=fff) ![Nginx](https://img.shields.io/badge/Nginx-009639?logo=nginx&logoColor=fff) ## Architecture - **Frontend**: React + TypeScript + Vite (UI uses MUI + Tailwind, i18n via i18next) - **Backend**: Node.js + Express (also renders a minimal EJS page at `/`) - **Database**: MySQL 8 In production, the frontend is served by **Nginx** and proxies `/backend/*` to the backend container. ## Repos & folders ``` backend/ # Express API + EJS views frontend/ # React app (Vite) + Nginx container docker-compose.yml docker-compose.prod.yml ``` ## API overview The backend router is mounted at `/default`: - `GET /default/users` → returns `{ users: string[] }` - `GET /default/confirm-user?username=` → validates user and returns metadata (e.g. next id) - `POST /default/new-entry?username=` → stores a new entry in MySQL ## Configuration ### Backend environment variables The backend reads configuration from environment variables (and can also load a `backend/.env` file via `dotenv`). - `PORT` (e.g. `8004`) - `DB_HOST` (e.g. `ca-lose-mysql` when using Docker Compose) - `DB_USER` (e.g. `root`) - `DB_PASSWORD` - `DB_NAME` (e.g. `ca_lose`) ### Docker Compose environment Both compose files expect `DB_PASSWORD` to be present in your shell environment or a root `.env` file. Create a root `.env` (not committed) like: ```env DB_PASSWORD=change-me ``` ## Local development ### Option A: Docker Compose (backend + database) This is the quickest way to get the API + MySQL running. ```bash docker compose up --build ``` What you get: - Backend: http://localhost:8004 - MySQL: localhost:3311 (container port 3306) Note: In `docker-compose.yml` the `frontend` service is currently commented out. ### Option B: Run frontend locally (Vite) + run backend & DB 1. Start DB + backend (Docker): ```bash docker compose up --build database backend ``` 2. Start frontend (local Node): ```bash cd frontend npm ci npm run dev ``` Open the Vite dev server URL (usually http://localhost:5173). Important: - During local development (Vite), the frontend currently calls the backend via a hard-coded URL (`http://localhost:8004`). - When the frontend is served by the Nginx container, requests are expected to go through the Nginx proxy at `/backend/*` (see `frontend/nginx.conf`). In that setup the frontend should use `/backend/default/...` instead of `http://localhost:8004/...`. ## Database setup The schema file is in `backend/scheme.sql`. - The `users` table is required for the user dropdown. - The backend creates an entry table dynamically per user and date when calling `GET /default/confirm-user`. Example (inside MySQL): ```sql INSERT INTO users (username, first_name, last_name) VALUES ('demo', 'Demo', 'User'); ``` ## Production / Deployment The production compose file builds and runs: - `frontend` (Nginx) - `backend` (Express) - `database` (MySQL) - optional infrastructure: `dnsmasq` and `wireguard` (wg-easy) Start it: ```bash docker compose -f docker-compose.prod.yml up -d --build ``` Notes: - `docker-compose.prod.yml` uses an **external** network called `proxynet`. Create it if it does not exist: ```bash docker network create proxynet ``` - The production file assigns static IPs; adjust the subnets/IPs if they conflict with your environment. ## Lint / build Frontend: ```bash cd frontend npm run lint npm run build ``` ## Troubleshooting - **Backend does not start / ESM imports**: The backend code uses ESM `import` syntax. Node must treat the backend as an ESM project (commonly by adding `"type": "module"` to `backend/package.json`). Without that, the backend will fail to start (including in Docker). - **MySQL timezone mount**: The compose files mount `./mysql-timezone.cnf` to `/etc/mysql/conf.d/timezone.cnf`. Ensure `mysql-timezone.cnf` is a file (not a directory) with valid MySQL config, or remove/adjust the mount. ## License Licensed under the Apache License 2.0. See [LICENSE](LICENSE).