<!-- generated-by: gsd-doc-writer -->

# SIDES - Project Overview

## What Is SIDES

SIDES (Sabo Integrated Debris Flow Monitoring and Early Warning System) is a web application that monitors rainfall and water level data from sensor stations in the Sungai Kupang area, Kedah, Malaysia. It is operated by JPS (Jabatan Pengairan dan Saliran / Department of Irrigation and Drainage). The system ingests real-time telemetry data, displays it on a map dashboard, and pushes Firebase Cloud Messaging (FCM) alerts when readings cross warning or danger thresholds.

## Technology Stack

| Layer        | Technology                     |
|--------------|--------------------------------|
| Backend      | Laravel 12 on PHP 8.2          |
| Database     | PostgreSQL 16                  |
| Frontend     | Blade templates + Vite build   |
| Auth         | Laravel Breeze (session-based) |
| Notifications| Firebase Cloud Messaging (FCM) |
| Deployment   | Docker Compose                 |
| PDF Export   | barryvdh/laravel-dompdf        |
| Excel Export | maatwebsite/excel              |

## Architecture

```
                     Internet
                        |
                  Reverse Proxy
                  (TLS termination)
                        |
         +--------------+--------------+
         |        Docker Network        |
         |                              |
    +----+----+   +---------+   +-------+-----+   +---------+
    |  nginx  |   | php-fpm |   |  PostgreSQL  |   | pgAdmin |
    | :80     +--->| :9000   +--->|  :5432       |   | :5050   |
    +---------+   +----+----+   +-------+------+  +---------+
                        |               ^
                        v               |
                   Laravel 12     +-----+------+
                   Application     |  pgdata    |
                       |          |  volume    |
                  +----+----+     +------------+
                  |  FCM    |
                  |  API    |
                  +---------+
```

```mermaid
flowchart TD
    I["Internet"]:::internet --> RP["Reverse Proxy (TLS termination)"]:::proxy
    RP --> NET["Docker Network (tckdev_net)"]:::network

    subgraph NET["Docker Network"]
        N["nginx (tckdev-web :80)"]:::server --> P["php-fpm (tckdev-app :9000)"]:::app --> DB["PostgreSQL (tckdev-db :5432)"]:::db
        PG["pgAdmin (tckdev-pgAdmin :5050)"]:::tool --> DB
        V["pgdata volume"]:::volume --> DB
    end

    P --> L["Laravel 12 Application"]:::laravel
    L --> F["FCM API"]:::api

    classDef internet fill:#2196F3,stroke:#333,stroke-width:2px,color:#fff;
    classDef proxy fill:#4CAF50,stroke:#333,stroke-width:2px,color:#fff;
    classDef network fill:#9C27B0,stroke:#333,stroke-width:2px,color:#fff;
    classDef server fill:#FF9800,stroke:#333,stroke-width:2px,color:#fff;
    classDef app fill:#00BCD4,stroke:#333,stroke-width:2px,color:#fff;
    classDef db fill:#673AB7,stroke:#333,stroke-width:2px,color:#fff;
    classDef tool fill:#FFC107,stroke:#333,stroke-width:2px,color:#000;
    classDef volume fill:#795548,stroke:#333,stroke-width:2px,color:#fff;
    classDef laravel fill:#8BC34A,stroke:#333,stroke-width:2px,color:#fff;
    classDef api fill:#607D8B,stroke:#333,stroke-width:2px,color:#fff;

```

All four services run as Docker containers on a single host:

| Container   | Image                   | Purpose                              |
|-------------|-------------------------|--------------------------------------|
| tckdev-app  | php:8.2-fpm (custom)    | Laravel application via PHP-FPM      |
| tckdev-web  | nginx:stable-alpine     | Serves static assets, proxies PHP    |
| tckdev-db   | postgres:16             | Primary database                     |
| tckdev-pgAdmin | dpage/pgadmin4       | Database administration UI           |

A reverse proxy (outside Docker) terminates TLS and forwards traffic to the nginx container on port 80. The production URL is `https://sides.tck.com.my`.

## Data Pipeline

1. A Python script running outside Docker fetches CSV files from an external FTP server.
2. The script parses rainfall and water level readings and inserts them into the PostgreSQL database.
3. When a reading crosses a threshold, the script calls the `/api/alert` endpoint.
4. `AlertController` resolves the appropriate FCM topic (e.g., `rainfall_danger`, `waterlevel_alert`) and pushes a notification to subscribed devices via `FcmService`.

FCM topics are configured through environment variables:

- `FCM_TOPIC_RAINFALL_WARNING`
- `FCM_TOPIC_RAINFALL_DANGER`
- `FCM_TOPIC_WATERLEVEL_ALERT`
- `FCM_TOPIC_WATERLEVEL_DANGER`

## Core Data Model

| Table         | Purpose                                                    |
|---------------|------------------------------------------------------------|
| `station`     | Sensor stations (ID, name, district, coordinates, type flags) |
| `rainfall`    | Rainfall readings per station with timestamp, hourly/daily/cumulative values |
| `waterlevel`  | Water level readings per station with alert/warning/danger thresholds |
| `notification`| Alert history per station, type, and severity level        |
| `siren`       | Siren activation events linked to stations                 |
| `users`       | User accounts with role-based access levels                |

## User Roles

| Role   | access_level | Access                                                  |
|--------|-------------|---------------------------------------------------------|
| Admin  | 1           | Station management, user management, all data views     |
| User   | 2           | Rainfall/water level/siren/notification views, profile  |
| Public | (none)      | Public dashboard and station map only                   |

Admin credentials are set through environment variables (`ADMIN_EMAIL`, `ADMIN_PASSWORD`) and seeded on first deployment via `DatabaseSeeder`.

## Localization

The application supports English (`en`) and Bahasa Malaysia (`bm`). Language files are stored in `src/lang/en/` and `src/lang/bm/`. Users can switch language through the `/locale/{locale}` route.

## Key Application Features

- **Map Dashboard** -- Live station data (rainfall, water level, siren status) displayed on an interactive map.
- **Rainfall Monitoring** -- Current readings, historical data, hourly graphs, and IDF threshold analysis with Excel export.
- **Water Level Monitoring** -- Current readings, historical data, graphs, and Excel export.
- **Siren Management** -- Siren activation tracking with PDF export of siren history.
- **Notification Center** -- Separate views for rainfall, water level, and siren alerts with PDF export.
- **Station Management** -- Admin CRUD for sensor stations.
- **User Management** -- Admin CRUD for user accounts.
- **CCTV Integration** -- CCTV feed links per station.

## API Endpoints

The application exposes a REST API (prefix `/api/`) consumed by the data pipeline and external integrations:

| Method | Path                        | Description                              |
|--------|-----------------------------|------------------------------------------|
| GET    | /api/station/current        | Latest readings across all stations      |
| GET    | /api/station/rainfall       | Current rainfall data                    |
| GET    | /api/station/waterlevel     | Current water level data                 |
| GET    | /api/station/notification   | Today's notifications                    |
| GET    | /api/station/history        | Notification history (last 3 days)       |
| GET    | /api/station/siren          | Current siren status                     |
| GET    | /api/station/siren/history  | Siren history (last 3 days)              |
| POST   | /api/login                  | API authentication                       |
| POST   | /api/alert                  | Trigger FCM push notification            |
