# SuperConsole - School Management System

## Project Overview

Multi-tenant super admin panel for managing schools, users, and feature flags.
Built with **Laravel 13 + Filament v5 + Tailwind CSS v4 + Vite 8**.

## Tech Stack

- **PHP:** 8.3+
- **Laravel:** 13.x
- **Filament:** 5.x
- **Tailwind CSS:** 4.x (zero-config, `@tailwindcss/vite`)
- **Database:** MySQL (`school` database)
- **Build:** Vite 8 with `laravel-vite-plugin`

## Filament v5 API Rules (CRITICAL)

Filament v5 has breaking changes from v3/v4. Follow these rules strictly:

### Actions - All from `Filament\Actions\*`

```php
// CORRECT - v5
use Filament\Actions\Action;
use Filament\Actions\EditAction;
use Filament\Actions\DeleteAction;
use Filament\Actions\CreateAction;
use Filament\Actions\BulkAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\AttachAction;
use Filament\Actions\DetachAction;
use Filament\Actions\DetachBulkAction;

// WRONG - do NOT use these
// use Filament\Tables\Actions\Action;
// use Filament\Tables\Actions\EditAction;
```

### Table Methods - `recordActions()` not `actions()`

```php
// CORRECT - v5
$table
    ->recordActions([...])     // Row-level actions (edit, delete, custom)
    ->headerActions([...])     // Above-table actions (create, attach)
    ->groupedBulkActions([...]) // Bulk actions in toolbar

// WRONG - deprecated
// ->actions([...])
// ->bulkActions([...])
```

### Forms Use `Schema` not `Form`

```php
// CORRECT - v5
use Filament\Schemas\Schema;
use Filament\Schemas\Components\Section;

public static function form(Schema $schema): Schema
{
    return $schema->components([...]);
}

// WRONG
// use Filament\Forms\Form;
// public static function form(Form $form): Form
```

Form field components still use `Filament\Forms\Components\*`:
```php
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Components\Checkbox;
```

### Table Columns and Filters - Still in `Filament\Tables\*`

```php
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Filters\TernaryFilter;
use Filament\Tables\Table;
```

### Resource Property Types

```php
// Navigation icon - accepts BackedEnum
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-users';

// Navigation group - accepts UnitEnum
protected static string|\UnitEnum|null $navigationGroup = 'School Management';

// These remain ?string
protected static ?string $model = User::class;
protected static ?string $recordTitleAttribute = 'name';
protected static ?int $navigationSort = 1;
```

### Widget Properties - Static vs Non-Static

```php
// STATIC properties
protected static ?int $sort = 1;            // Widget sort order
protected static bool $isDiscovered = true;  // Auto-discovery

// NON-STATIC (instance) properties
protected string $view = 'my-view';          // Blade view
protected int|string|array $columnSpan = 1;  // Grid span
protected ?string $heading = 'Title';        // ChartWidget heading
protected ?string $maxHeight = '260px';      // ChartWidget max height
protected ?string $description = null;       // Widget description
```

### CreateRecord / EditRecord Hooks

```php
// CreateRecord hooks (in order):
// beforeFill → afterFill → beforeValidate → afterValidate → beforeCreate → afterCreate

// EditRecord hooks (in order):
// beforeFill → afterFill → beforeValidate → afterValidate → beforeSave → afterSave

// Data mutation methods:
// mutateFormDataBeforeCreate(array $data): array
// mutateFormDataBeforeFill(array $data): array
// mutateFormDataBeforeSave(array $data): array
```

## Project Structure

```
app/
  Enums/              SchoolStatus, UserRole, SubjectType, Gender,
                      EnrollmentStatus, GuardianRelation
  Filament/
    Pages/Auth/       Custom Login page (admin panel)
    Resources/        SchoolResource, UserResource, FeatureResource (admin panel)
    Widgets/          Dashboard widgets (Stats, Chart, Table, QuickActions)
    School/
      Resources/      Academic config resources (school panel, tenant-scoped)
  Http/Middleware/     EnsureSuperAdmin
  Models/             School, User, Feature, AcademicSession, Level, Grade,
                      Section, Subject, GradeSection, GradeSubject,
                      Student, Guardian, Enrollment, UserFcmToken
    Concerns/         BelongsToSchool trait
    Scopes/           SchoolScope (auto-filter by school_id)
  Services/           FeatureService (enable/disable/check features)
  Providers/Filament/ AdminPanelProvider, SchoolPanelProvider
```

## Panels

| Panel | Path | Purpose | Auth |
|-------|------|---------|------|
| Admin (SuperConsole) | `/admin` | Cross-tenant super admin | Super admin only |
| School | `/school/t/{subdomain}` | Per-school management | School users |

## Database Schema

**Core tables** (bigint IDs):
- `schools` - name, email, phone, address, domain, subdomain, status
- `users` - standard + school_id (FK, nullable), role (enum)
- `features` - name (machine key), label, description, is_default
- `school_feature` - pivot with enabled_at timestamp

**Academic tables** (ULID IDs, all have school_id FK):
- `academic_sessions` - name, start_date, end_date, is_active
- `levels` - name, description, sort_order, is_active
- `grades` - name, numeric_name, level_id, sort_order, is_active
- `sections` - name, sort_order, is_active
- `subjects` - name, code, type (theory/practical/both), credit_hours, is_active
- `grade_sections` - grade_id, section_id, academic_session_id, capacity
- `grade_subjects` - grade_id, subject_id, academic_session_id, is_optional

**People tables** (ULID IDs, all have school_id FK):
- `students` - first/last name, gender, DOB, blood_group, admission_number/date, phone, address, nationality, religion, ethnicity, user_id (nullable)
- `guardians` - first/last name, phone, email, occupation, address, user_id (nullable)
- `student_guardian` - pivot with relation (father/mother/guardian/etc), is_primary
- `enrollments` - student_id, grade_section_id, academic_session_id, roll_number, enrolled_date, status
- `user_fcm_tokens` - user_id, token, device_type, device_name, last_used_at

## Multi-Tenancy

- Single DB, Filament built-in tenancy via `->tenant(School::class)`
- School panel uses `subdomain` as slug attribute, `school` as ownership relationship
- Filament auto-scopes all queries and auto-sets `school_id` on creating
- All tenant-scoped models must have `school(): BelongsTo` relationship
- User model implements `HasTenants`, `HasDefaultTenant`, `FilamentUser`
- `school_id = NULL` on users means super admin (can only access admin panel)
- `Table::configureUsing(fn ($t) => $t->deferLoading())` in SchoolPanelProvider for performance
- Academic models use ULIDs for IDs (better for single-DB multi-tenancy)

## Commands

```bash
# Development
composer run dev              # PHP server + queue + logs + Vite

# Build
npx vite build                # Compile assets (theme + app CSS/JS)

# Database
php artisan migrate           # Run migrations
php artisan db:seed           # Seed super admin + default features

# Filament
php artisan filament:optimize # Cache components + icons
```

## Login Credentials

**Super Admin (admin panel):**
- **Email:** `admin@school.com` | **Password:** `password`

**School Admin (school panel — dummy school):**
- **Email:** `admin@janajyoti.edu.np` | **Password:** `password`
- School subdomain: `janajyoti` → `/school/t/janajyoti`

## Custom Theme

Theme CSS: `resources/css/filament/admin/theme.css`
Brand logos: `resources/views/filament/components/brand-logo*.blade.php`
Registered via `->viteTheme()` in `AdminPanelProvider`

## Coding Conventions

- Use Laravel 13 attribute syntax: `#[Fillable([...])]`, `#[Hidden([...])]`
- Enums implement `Filament\Support\Contracts\HasLabel` and `HasColor`
- Always use `firstOrCreate` in seeders for idempotency
- Cache feature flags per school: `school:{id}:features`
