# 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=<name>` → validates user and returns metadata (e.g. next id)
- `POST /default/new-entry?username=<name>` → 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).
