361 lines
20 KiB
Markdown
361 lines
20 KiB
Markdown
# Codebase Structure
|
|
|
|
**Analysis Date:** 2026-05-28
|
|
|
|
## Directory Layout
|
|
|
|
```
|
|
src/ # Laravel application root
|
|
├── app/ # Application code
|
|
│ ├── Exports/ # Excel export classes (Maatwebsite)
|
|
│ ├── Http/ # HTTP layer
|
|
│ │ ├── Controllers/ # Web controllers
|
|
│ │ │ ├── Api/ # API controllers (JSON)
|
|
│ │ │ └── Auth/ # Auth controllers (Laravel Breeze)
|
|
│ │ ├── Middleware/ # Custom middleware
|
|
│ │ └── Requests/ # Form request validation classes
|
|
│ │ └── Auth/ # Auth-specific form requests
|
|
│ ├── Models/ # Eloquent models
|
|
│ ├── Notifications/ # Notification classes
|
|
│ ├── Providers/ # Service providers
|
|
│ ├── Services/ # Service classes
|
|
│ └── View/ # Blade component classes
|
|
│ └── Components/ # View components
|
|
├── bootstrap/ # Framework bootstrap
|
|
│ ├── app.php # App config (middleware, routing registration)
|
|
│ └── providers.php # Registered service providers
|
|
├── config/ # Configuration files
|
|
├── database/ # Database layer
|
|
│ ├── factories/ # Model factories
|
|
│ ├── migrations/ # Schema migrations (12 files)
|
|
│ └── seeders/ # Database seeders
|
|
├── lang/ # Localization files
|
|
│ ├── bm/ # Bahasa Malaysia
|
|
│ └── en/ # English
|
|
├── public/ # Public web root
|
|
│ ├── build/ # Vite build output
|
|
│ ├── css/ # Compiled CSS
|
|
│ ├── icon/ # Map icons
|
|
│ ├── img/ # Images
|
|
│ ├── js/ # Custom JS
|
|
│ └── logo/ # Logo files
|
|
├── resources/ # Frontend resources
|
|
│ ├── css/ # Source CSS (Tailwind + custom)
|
|
│ ├── js/ # Source JS
|
|
│ └── views/ # Blade templates
|
|
│ ├── auth/ # Auth screens (6 files)
|
|
│ ├── components/ # Shared Blade components (13 files)
|
|
│ ├── layout/ # Main app views
|
|
│ │ ├── admin/ # Admin panel views
|
|
│ │ ├── graph/ # Chart views
|
|
│ │ ├── notification/ # Notification views
|
|
│ │ │ └── history/ # Notification history views
|
|
│ │ └── siren/ # Siren views
|
|
│ ├── layouts/ # Base layout templates (Breeze)
|
|
│ ├── nav/ # Navigation partials (header, navbar, footer)
|
|
│ ├── pdf/ # PDF export templates
|
|
│ └── profile/ # Profile views
|
|
│ └── partials/
|
|
├── routes/ # Route definitions
|
|
├── storage/ # Framework storage
|
|
├── tests/ # Automated tests
|
|
│ ├── Feature/ # Feature tests
|
|
│ │ └── Auth/ # Auth feature tests
|
|
│ ├── Unit/ # Unit tests
|
|
│ └── storage/ # Test storage
|
|
├── vendor/ # Composer dependencies (excluded)
|
|
├── composer.json # PHP dependencies
|
|
├── package.json # Node dependencies (Vite, Tailwind)
|
|
├── vite.config.js # Vite configuration
|
|
├── tailwind.config.js # Tailwind CSS config
|
|
└── phpunit.xml # PHPUnit config
|
|
```
|
|
|
|
## Directory Purposes
|
|
|
|
**`app/Http/Controllers/` — Web Controllers:**
|
|
- Purpose: Handle authenticated web requests, query data, render Blade views
|
|
- Contains: 11 controllers + 9 auth controllers + 3 API controllers
|
|
- Key files:
|
|
- `MapController.php`: Dashboard page — joins station + latest rainfall/waterlevel/siren data
|
|
- `RainfallController.php`: Rainfall data display, 6-hour threshold, historical data, graph data, Excel export
|
|
- `WaterLevelController.php`: Water level display, graph data, historical data, Excel export
|
|
- `SirenController.php`: Siren status display, siren history, PDF export
|
|
- `NotificationController.php`: Rainfall/waterlevel/siren notifications, history, PDF exports
|
|
- `AdminController.php`: Station CRUD, user CRUD (access_level=1 only)
|
|
- `cctvController.php`: CCTV link display for stations
|
|
- `LocaleController.php`: Language switching (en/bm)
|
|
- `ProfileController.php`: User profile edit/update/delete
|
|
- `Controller.php`: Empty abstract base class
|
|
|
|
**`app/Http/Controllers/Api/` — API Controllers:**
|
|
- Purpose: JSON endpoints for external IoT devices and mobile clients
|
|
- Contains: 3 controllers (no middleware/auth required on most endpoints)
|
|
- Key files:
|
|
- `StationController.php`: 7 endpoints — current data, rainfall, waterlevel, notifications, history, siren, siren history
|
|
- `AuthController.php`: Custom username/password login returning JSON
|
|
- `AlertController.php`: Relay station alerts via FCM push
|
|
|
|
**`app/Http/Controllers/Auth/` — Auth Controllers (Laravel Breeze):**
|
|
- Purpose: Handle authentication flow (login, register, password reset, email verification)
|
|
- Contains: 9 controllers scaffolded by Laravel Breeze
|
|
- Key files:
|
|
- `AuthenticatedSessionController.php`: Login with custom blocked-user + login-attempt tracking
|
|
- `RegisteredUserController.php`: User registration
|
|
- `NewPasswordController.php`, `PasswordController.php`, `PasswordResetLinkController.php`: Password management
|
|
- `VerifyEmailController.php`, `EmailVerificationNotificationController.php`, `EmailVerificationPromptController.php`: Email verification
|
|
- `ConfirmablePasswordController.php`: Password confirmation
|
|
|
|
**`app/Http/Middleware/` — Custom Middleware:**
|
|
- Purpose: Request filtering and modification
|
|
- Contains: 2 middleware classes
|
|
- Key files:
|
|
- `AdminMiddleware.php`: Checks `Auth::check()` + `Auth::user()->access_level === 1`, redirects to `/dashboard` on failure. Registered as alias `'admin'` in `bootstrap/app.php`.
|
|
- `LocalizationMiddleware.php`: Reads `locale` from session, sets `App::setLocale()`. Appended to `web` middleware group in `bootstrap/app.php`.
|
|
|
|
**`app/Http/Requests/` — Form Request Validation:**
|
|
- Purpose: Encapsulate form validation and authorization logic
|
|
- Contains: 2 form request classes
|
|
- Key files:
|
|
- `ProfileUpdateRequest.php`: Validates name + email (unique check ignoring current user)
|
|
- `Auth/LoginRequest.php`: Rate-limited login validation (5 attempts), custom `username()` returning `'name'`
|
|
|
|
**`app/Models/` — Eloquent Models:**
|
|
- Purpose: Single model for Laravel authentication
|
|
- Contains: `User.php` — only Eloquent model in the app
|
|
- Key details:
|
|
- Extends `Authenticatable`, uses `HasFactory`, `Notifiable`
|
|
- Fillable: `name`, `email`, `password`, `access_level`, `login_attempts`, `is_blocked`
|
|
- Hidden: `password`, `remember_token`
|
|
- Casts: `email_verified_at` (datetime), `password` (hashed), `is_blocked` (boolean)
|
|
- Overrides `sendPasswordResetNotification()` to use custom `ResetPasswordNotification`
|
|
|
|
**`app/Services/` — Service Layer:**
|
|
- Purpose: External API integrations
|
|
- Contains: 1 service class
|
|
- Key file:
|
|
- `FcmService.php`: Firebase Cloud Messaging integration. Constructor reads `FIREBASE_PROJECT_ID` and `FIREBASE_CREDENTIALS` (path to JSON) from env. `sendToTopic()` authenticates via `google/auth` `ServiceAccountCredentials`, sends POST to FCM v1 HTTP API.
|
|
|
|
**`app/Exports/` — Excel Exports:**
|
|
- Purpose: Generate downloadable Excel spreadsheets
|
|
- Contains: 2 export classes using `Maatwebsite\Excel`
|
|
- Key files:
|
|
- `HourlyRainfallExport.php`: Exports hourly rainfall with 24-column pivot (hour_00..hour_23) for a date range. Implements `FromCollection`, `WithHeadings`, `ShouldAutoSize`.
|
|
- `WaterLevelExport.php`: Exports water level readings with alert/warning/danger thresholds for a station+date. Implements `FromCollection`, `WithHeadings`, `ShouldAutoSize`.
|
|
|
|
**`app/Notifications/` — Notification Classes:**
|
|
- Purpose: Email notifications sent by Laravel
|
|
- Contains: 1 notification class
|
|
- Key file:
|
|
- `ResetPasswordNotification.php`: Queueable email notification for password reset. Sends via `mail` channel with SIDES branding.
|
|
|
|
**`app/Providers/` — Service Providers:**
|
|
- Purpose: Framework bootstrapping
|
|
- Contains: 1 service provider
|
|
- Key file:
|
|
- `AppServiceProvider.php`: Currently empty `register()` and `boot()` methods (no custom services registered).
|
|
|
|
**`app/View/Components/` — Blade Components:**
|
|
- Purpose: Render Blade component views
|
|
- Contains: 2 component classes
|
|
- Key files:
|
|
- `AppLayout.php`: Renders `layouts.app` (Breeze default authenticated layout)
|
|
- `GuestLayout.php`: Renders `layouts.guest` (Breeze default guest layout)
|
|
|
|
**`routes/` — Route Definitions:**
|
|
- Purpose: Map HTTP requests to controllers
|
|
- Contains: 4 route files
|
|
- Key files:
|
|
- `web.php` (85 lines): All web routes — auth-protected (dashboard, rainfall, waterlevel, siren, notification, CCTV), admin-protected (station management, user management), and public (dashboard, stations, locale switch). Includes `auth.php` at the end.
|
|
- `auth.php` (59 lines): Auth routes scaffolded by Breeze — guest routes (login, register, password reset), auth routes (verify email, confirm password, logout).
|
|
- `api.php` (19 lines): Public API routes — station data endpoints (7 GET), login, alert push. No middleware required on most endpoints.
|
|
- `console.php` (8 lines): Single `inspire` Artisan command (default Laravel).
|
|
|
|
**`database/migrations/` — Schema Migrations:**
|
|
- Purpose: Define and evolve database schema
|
|
- Contains: 12 migration files ordered by timestamp
|
|
- Key files:
|
|
- `0001_01_01_000000_create_users_table.php`: Users, password_reset_tokens, sessions tables (Laravel default)
|
|
- `2025_11_06_071853_create_station_table.php`: `station` table — stationid (PK), name, district, lng, lat, mainriverbasin, subriverbasin, rainfall, waterlevel
|
|
- `2025_11_06_072709_create_rainfall__table.php`: `rainfall` table — stationid, timestamp, anncum, daily, hourly, currentrf, battery
|
|
- `2025_11_06_072738_create_waterlevel_table.php`: `waterlevel` table — stationid, datetime, waterlevel, alert, warning, danger
|
|
- `2025_11_07_024940_create_notification_table.php`: `notification` table — stationid, timestamp, stationtype, level, active_time
|
|
- `2025_11_07_031601_create_siren__table.php`: `siren` table — stationid, stationtype, active_time, level
|
|
- `2025_11_07_063825_add_access_level_to_users_table.php`: Adds `access_level` (int, default 2) to users
|
|
- `2025_11_07_065418_add_block_fields_to_users_table.php`: Adds `is_blocked` (boolean) and `login_attempts` (int) to users
|
|
- `2025_11_08_004548_add_siren_to_station_table.php`: Adds `siren` (int, nullable) to station
|
|
- `2025_11_25_113158_add_cctvlink_to_station.php`: Adds `cctv_link` (string, nullable) to station
|
|
|
|
**`resources/views/` — Blade Templates:**
|
|
- Purpose: Render all HTML and PDF output
|
|
- Contains: ~40+ Blade template files organized by domain
|
|
- Structure:
|
|
- `layout/app.blade.php` — Main authenticated layout (`@include nav.header+navbar`, `@yield content1/content2/content3`)
|
|
- `layout/homeapp.blade.php` — Public layout (no auth, full-width)
|
|
- `layout/dashboard.blade.php` — Home page with Leaflet map + station data table
|
|
- `layout/rainfall.blade.php` — Rainfall data table with 7-day daily columns + graph modal
|
|
- `layout/waterlevel.blade.php` — Water level data table
|
|
- `layout/threshold.blade.php` — 6-hour early warning threshold view
|
|
- `layout/historicalrainfall.blade.php` — Historical rainfall with date range picker
|
|
- `layout/historicalwl.blade.php` — Historical water level
|
|
- `layout/cctv.blade.php` — CCTV links for stations
|
|
- `layout/home.blade.php` — Public landing page (extends `layout.homeapp`)
|
|
- `layout/siren/home.blade.php`, `layout/siren/history.blade.php` — Siren status and history
|
|
- `layout/notification/rainfall.blade.php`, `layout/notification/waterlevel.blade.php`, `layout/notification/siren.blade.php` — Current notifications
|
|
- `layout/notification/history/rainfall.blade.php`, `layout/notification/history/waterlevel.blade.php` — Notification history
|
|
- `layout/graph/rainfall.blade.php` — Rainfall graph page
|
|
- `layout/admin/stationmgmt.blade.php` (352 lines) — Station management CRUD interface
|
|
- `layout/admin/usermgmt.blade.php` — User management CRUD interface
|
|
- `pdf/rfhistory.blade.php`, `pdf/wlhistory.blade.php`, `pdf/sirenhistory.blade.php` — PDF export templates
|
|
- `nav/header.blade.php` — HTML head, CSS, Leaflet, Flatpickr, jQuery CDNs
|
|
- `nav/navbar.blade.php` — Full responsive navigation (desktop + mobile sidebar)
|
|
- `nav/footer.blade.php` — Footer partial
|
|
- `auth/*.blade.php` — Login, register, forgot/reset password, verify-email, confirm-password screens
|
|
- `components/*.blade.php` — 13 shared Blade components (application-logo, dropdown, input-label, modal, nav-link, buttons, etc.)
|
|
- `layouts/app.blade.php`, `layouts/guest.blade.php` — Breeze default layouts (component-based)
|
|
- `profile/edit.blade.php` — Profile edit page
|
|
|
|
**`lang/` — Localization Files:**
|
|
- Purpose: Internationalization strings for two locales
|
|
- Contains: `en/` (English) and `bm/` (Bahasa Malaysia) directories
|
|
- Key files: `messages.php` (UI text), `toast.php` (flash messages), `auth.php`, `validation.php`, `passwords.php`, `pagination.php`
|
|
|
|
**`public/` — Public Web Root:**
|
|
- Purpose: Entry point for HTTP requests (`index.php`), static assets
|
|
- Contains: Compiles CSS (`css/style.css`), JavaScript (`js/script.js`, `js/graph.js`), Leaflet map icons (`icon/`), images (`img/`), logos (`logo/`), Vite build output (`build/`)
|
|
|
|
**`tests/` — Automated Tests:**
|
|
- Purpose: PHPUnit test suite
|
|
- Contains: Feature tests and unit tests
|
|
- Key files:
|
|
- `tests/Feature/Auth/`: 6 auth test files (most appear empty — e.g., `AuthenticationTest.php` has 0 lines)
|
|
- `tests/Feature/ExampleTest.php`, `tests/Feature/ProfileTest.php`
|
|
- `tests/Unit/ExampleTest.php`
|
|
|
|
## Key File Locations
|
|
|
|
**Entry Points:**
|
|
- `public/index.php`: HTTP entry point (Laravel front controller)
|
|
- `artisan`: CLI entry point
|
|
- `bootstrap/app.php`: Application configuration (middleware aliases, routing, exceptions)
|
|
- `bootstrap/providers.php`: Registered service providers
|
|
|
|
**Configuration:**
|
|
- `config/app.php`: App name, env, URL, timezone, locale, providers, aliases
|
|
- `config/database.php`: DB connection (default: sqlite, but code uses PostgreSQL)
|
|
- `config/auth.php`: Auth guard (`web`, session), user provider, password reset config
|
|
- `config/mail.php`: Mail driver config (default: log)
|
|
- `config/filesystems.php`: Disk configs (local, public, s3)
|
|
- `config/services.php`: Third-party API keys (postmark, resend, ses, slack)
|
|
- `config/queue.php`: Queue driver (default: database)
|
|
- `config/session.php`: Session driver config
|
|
- `config/cache.php`: Cache driver config
|
|
- `.env`: Environment variables (exists but not read — contains credentials)
|
|
|
|
**Core Routing:**
|
|
- `routes/web.php`: All web routes (85 lines)
|
|
- `routes/auth.php`: Auth routes (59 lines, included from web.php)
|
|
- `routes/api.php`: API routes (19 lines)
|
|
- `routes/console.php`: Console commands (8 lines)
|
|
|
|
**Database Schema:**
|
|
- `database/migrations/`: 12 migration files defining 8+ tables
|
|
- `database/seeders/DatabaseSeeder.php`: Seeds admin user
|
|
|
|
**Static Assets:**
|
|
- `resources/css/app.css`: Tailwind CSS source
|
|
- `resources/css/style.css`: Custom CSS
|
|
- `resources/js/app.js`: Alpine.js + Bootstrap app JS
|
|
- `resources/js/bootstrap.js`: Axios + Echo bootstrap
|
|
- `resources/js/script.js`: Custom app scripts
|
|
- `resources/js/graph.js`: Chart.js graph rendering
|
|
|
|
## Naming Conventions
|
|
|
|
**Files:**
|
|
- **Controllers**: PascalCase suffixed with `Controller` (e.g., `RainfallController.php`, `AdminController.php`)
|
|
- **Models**: PascalCase singular (only `User.php`)
|
|
- **Middleware**: PascalCase suffixed with `Middleware` (e.g., `AdminMiddleware.php`)
|
|
- **Requests**: PascalCase suffixed with `Request` (e.g., `ProfileUpdateRequest.php`)
|
|
- **Exports**: PascalCase suffixed with `Export` (e.g., `HourlyRainfallExport.php`)
|
|
- **Services**: PascalCase suffixed with `Service` (e.g., `FcmService.php`)
|
|
- **Notifications**: PascalCase suffixed with `Notification` (e.g., `ResetPasswordNotification.php`)
|
|
- **Migrations**: `YYYY_MM_DD_HHMMSS_create_{table}_table.php` or `..._add_{column}_to_{table}_table.php`
|
|
- **Blade views**: Lowercase kebab-case (e.g., `historicalrainfall.blade.php`, `stationmgmt.blade.php`)
|
|
- **Routes file**: Lowercase (`web.php`, `api.php`, `auth.php`, `console.php`)
|
|
- **Config files**: Lowercase (`app.php`, `database.php`)
|
|
|
|
**Directories:**
|
|
- Namespace-matching PascalCase under `app/` (e.g., `Http/Controllers/Api/`)
|
|
- Lowercase under `resources/views/` (e.g., `layout/admin/`, `layout/notification/history/`)
|
|
- Lowercase under `config/`, `database/`, `routes/`, `lang/`
|
|
|
|
## Where to Add New Code
|
|
|
|
**New Feature (e.g., new data type):**
|
|
- Controller: `app/Http/Controllers/{Name}Controller.php` — extends `Controller`, uses `DB` facade
|
|
- Routes: `routes/web.php` — add under appropriate middleware group (`auth` or `admin`)
|
|
- Views: `resources/views/layout/{name}/` — create view directory with `home.blade.php`, `history.blade.php` etc.
|
|
- API endpoint: `routes/api.php` + `app/Http/Controllers/Api/{Name}Controller.php`
|
|
- Exports: `app/Exports/{Name}Export.php` + `resources/views/pdf/{name}history.blade.php` if needed
|
|
|
|
**New API Endpoint:**
|
|
- Add route to `routes/api.php`
|
|
- Add method to existing controller in `app/Http/Controllers/Api/` or create new controller
|
|
|
|
**New Middleware:**
|
|
- Create class in `app/Http/Middleware/`
|
|
- Register alias or group in `bootstrap/app.php` → `withMiddleware()`
|
|
|
|
**New Service:**
|
|
- Create class in `app/Services/`
|
|
- Inject via constructor or `app()` helper in controllers
|
|
|
|
**New Database Table:**
|
|
- Create migration in `database/migrations/` using `YYYY_MM_DD_HHMMSS_create_{table}_table.php` format
|
|
- Add seeder entry to `database/seeders/DatabaseSeeder.php`
|
|
|
|
**New Translation:**
|
|
- Add key to both `lang/en/messages.php` and `lang/bm/messages.php` (or corresponding domain file)
|
|
- Use `@lang('messages.key')` in Blade or `__('messages.key')` in PHP
|
|
|
|
**New Validation:**
|
|
- Add inline `$request->validate([...])` for simple cases
|
|
- Create `app/Http/Requests/{Name}Request.php` for reusable validation
|
|
|
|
## Special Directories
|
|
|
|
**`resources/views/layout/`:**
|
|
- Purpose: Main application views (the primary view directory used by all web controllers)
|
|
- Contains: 14 files + 4 subdirectories (admin/, graph/, notification/, siren/)
|
|
- The `layout.app` Blade layout is the base template accessed via `@extends('layout.app')` — this includes nav, header, footer, modals, scripts, CSS
|
|
|
|
**`resources/views/layouts/`:**
|
|
- Purpose: Laravel Breeze default layout templates (used by auth screens and view components)
|
|
- Contains: `app.blade.php` (component-based slot layout), `guest.blade.php`, `navigation.blade.php`
|
|
- This is a SEPARATE layout system from `resources/views/layout/` — the application uses `layout.app` for authenticated pages and `layouts.app` only for auth scaffolding views
|
|
|
|
**`public/js/` and `public/css/`:**
|
|
- Purpose: Compiled/minified static assets (not source)
|
|
- Contains: `script.js`, `graph.js` — JavaScript files directly placed in public (NOT compiled through Vite). These are loaded via `<script src="{{ asset('js/script.js') }}">` in the `layout.app` Blade layout.
|
|
- Source JS is in `resources/js/` and compiled via Vite.
|
|
|
|
**`storage/`:**
|
|
- Purpose: Framework runtime storage (logs, cache, sessions, views)
|
|
- Generated: Yes
|
|
- Committed: No
|
|
|
|
**`vendor/`:**
|
|
- Purpose: Composer PHP dependencies
|
|
- Generated: Yes
|
|
- Committed: No
|
|
|
|
**`node_modules/`:**
|
|
- Purpose: NPM frontend dependencies
|
|
- Generated: Yes
|
|
- Committed: No
|
|
|
|
---
|
|
|
|
*Structure analysis: 2026-05-28*
|