Sprint 1: Auth, metro map canvas, services, and retro UI

Authentication:
- Laravel Fortify + Sanctum with Inertia views
- RBAC middleware (admin, project_owner, team_member, viewer)
- Retro terminal-styled login/register/forgot-password pages

Metro Map (core UI):
- D3.js zoomable SVG canvas with metro line rendering
- Station nodes with glow-on-hover, status coloring, tooltips
- Breadcrumb navigation for multi-level drill-down
- Node preview panel with zoom-in action
- C64-style CLI bar with blinking cursor at bottom

Backend services:
- ProjectService (CRUD, phase transitions, park/stop, audit logging)
- ThemaService (CRUD with audit)
- MapDataService (strategy map L1, project map L2)
- Thin controllers: MapController, ProjectController, ThemaController
- 32 routes total (auth + app + API)

Style foundation:
- Retro-futurism theme: VT323, Press Start 2P, IBM Plex Mono fonts
- Dark palette with cyan/orange/green/purple neon accents
- Comprehensive seed data (4 themes, 12 projects, commitments, deps)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
znetsixe
2026-04-01 13:52:35 +02:00
parent 7d14ca7b3b
commit d03fe15542
40 changed files with 5368 additions and 21 deletions

View File

@@ -2,24 +2,551 @@
namespace Database\Seeders;
use App\Enums\CommitmentStatus;
use App\Enums\FaseStatus;
use App\Enums\FaseType;
use App\Enums\Prioriteit;
use App\Enums\ProjectRol;
use App\Enums\ProjectStatus;
use App\Enums\SpeerpuntStatus;
use App\Models\Afhankelijkheid;
use App\Models\Commitment;
use App\Models\Document;
use App\Models\Fase;
use App\Models\Project;
use App\Models\Role;
use App\Models\Speerpunt;
use App\Models\Thema;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
class DatabaseSeeder extends Seeder
{
use WithoutModelEvents;
/**
* Seed the application's database.
*/
public function run(): void
{
// User::factory(10)->create();
// ──────────────────────────────────────────────────────────────
// 1. System roles
// ──────────────────────────────────────────────────────────────
$roleAdmin = Role::create([
'naam' => 'admin',
'beschrijving' => 'Volledige toegang tot het platform',
'permissies' => ['*'],
]);
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
$roleProjectOwner = Role::create([
'naam' => 'project_owner',
'beschrijving' => 'Kan projecten beheren en bewerken',
'permissies' => ['projects.manage', 'commitments.manage', 'documents.manage'],
]);
$roleTeamMember = Role::create([
'naam' => 'team_member',
'beschrijving' => 'Kan bijdragen aan toegewezen projecten',
'permissies' => ['projects.view', 'commitments.edit', 'documents.upload'],
]);
Role::create([
'naam' => 'viewer',
'beschrijving' => 'Alleen-lezen toegang',
'permissies' => ['projects.view', 'documents.view'],
]);
// ──────────────────────────────────────────────────────────────
// 2. Users
// ──────────────────────────────────────────────────────────────
$adminUser = User::create([
'name' => 'Admin Gebruiker',
'email' => 'admin@innovatieplatform.nl',
'password' => Hash::make('password'),
'functie' => 'Platform Beheerder',
'afdeling' => 'R&D Lab',
'email_verified_at' => now(),
]);
$adminUser->roles()->attach($roleAdmin);
$testUser = User::create([
'name' => 'Rene de Ren',
'email' => 'rene@wbd-rd.nl',
'password' => Hash::make('password'),
'functie' => 'R&D Engineer',
'afdeling' => 'R&D Lab',
'email_verified_at' => now(),
]);
$testUser->roles()->attach($roleProjectOwner);
$analyst = User::create([
'name' => 'Lisanne Bakker',
'email' => 'l.bakker@wbd-rd.nl',
'password' => Hash::make('password'),
'functie' => 'Data Analist',
'afdeling' => 'Watermanagement',
'email_verified_at' => now(),
]);
$analyst->roles()->attach($roleTeamMember);
$engineer = User::create([
'name' => 'Joris van Dam',
'email' => 'j.vandam@wbd-rd.nl',
'password' => Hash::make('password'),
'functie' => 'Senior Technisch Adviseur',
'afdeling' => 'Infrastructuur',
'email_verified_at' => now(),
]);
$engineer->roles()->attach($roleTeamMember);
// ──────────────────────────────────────────────────────────────
// 3. Themas (4 strategic themes)
// ──────────────────────────────────────────────────────────────
$themaWater = Thema::create([
'naam' => 'Waterkwaliteit',
'beschrijving' => 'Verbetering van de kwaliteit van oppervlaktewater en grondwater door innovatieve monitoring- en zuiveringstechnieken.',
'prioriteit' => Prioriteit::Hoog,
'periode_start' => '2025-01-01',
'periode_eind' => '2028-12-31',
]);
$themaInfra = Thema::create([
'naam' => 'Slimme Infrastructuur',
'beschrijving' => 'Digitalisering en automatisering van waterkeringen, gemalen en sluizen voor efficiënter beheer en snellere responstijden.',
'prioriteit' => Prioriteit::Hoog,
'periode_start' => '2025-01-01',
'periode_eind' => '2028-12-31',
]);
$themaData = Thema::create([
'naam' => 'Data-gedreven Beheer',
'beschrijving' => 'Inzet van data-analyse, AI en digitale tweelingen voor betere besluitvorming in waterbeheer.',
'prioriteit' => Prioriteit::Midden,
'periode_start' => '2025-06-01',
'periode_eind' => '2029-06-30',
]);
$themaDuurzaam = Thema::create([
'naam' => 'Duurzaamheid & Klimaatadaptatie',
'beschrijving' => 'Innovaties gericht op energieneutraliteit, circulaire waterketens en klimaatrobuuste inrichting van het beheergebied.',
'prioriteit' => Prioriteit::Midden,
'periode_start' => '2025-01-01',
'periode_eind' => '2030-12-31',
]);
// ──────────────────────────────────────────────────────────────
// 4. Speerpunten (2 per thema)
// ──────────────────────────────────────────────────────────────
// Waterkwaliteit
$spWaterMonitoring = Speerpunt::create([
'thema_id' => $themaWater->id,
'naam' => 'Real-time Watermonitoring',
'beschrijving' => 'Continue meting van waterkwaliteitsparameters via IoT-sensoren in het beheergebied.',
'eigenaar_id' => $testUser->id,
'status' => SpeerpuntStatus::Actief,
]);
$spMicropollution = Speerpunt::create([
'thema_id' => $themaWater->id,
'naam' => 'Microverontreinigingen',
'beschrijving' => 'Detectie en verwijdering van opkomende stoffen zoals medicijnresten en PFAS.',
'eigenaar_id' => $engineer->id,
'status' => SpeerpuntStatus::Concept,
]);
// Slimme Infrastructuur
$spDigitaalBeheer = Speerpunt::create([
'thema_id' => $themaInfra->id,
'naam' => 'Digitaal Kunstwerkenregister',
'beschrijving' => 'Volledig digitaal beheer van kunstwerken met BIM-koppeling en conditiebewaking.',
'eigenaar_id' => $engineer->id,
'status' => SpeerpuntStatus::Actief,
]);
$spSmartGemaal = Speerpunt::create([
'thema_id' => $themaInfra->id,
'naam' => 'Slimme Gemaalbesturing',
'beschrijving' => 'Predictieve sturing van gemalen op basis van weersvoorspelling en waterstanden.',
'eigenaar_id' => $testUser->id,
'status' => SpeerpuntStatus::Actief,
]);
// Data-gedreven Beheer
$spDigitaalTwin = Speerpunt::create([
'thema_id' => $themaData->id,
'naam' => 'Digitale Tweeling Watersysteem',
'beschrijving' => 'Virtueel model van het watersysteem voor scenario-analyse en operationele ondersteuning.',
'eigenaar_id' => $analyst->id,
'status' => SpeerpuntStatus::Concept,
]);
$spAIVoorspelling = Speerpunt::create([
'thema_id' => $themaData->id,
'naam' => 'AI-gestuurde Waterstandsvoorspelling',
'beschrijving' => 'Machine learning modellen voor nauwkeurige korte- en middellangetermijnwaterstanden.',
'eigenaar_id' => $analyst->id,
'status' => SpeerpuntStatus::Actief,
]);
// Duurzaamheid
$spEnergieneutraal = Speerpunt::create([
'thema_id' => $themaDuurzaam->id,
'naam' => 'Energieneutrale Zuivering',
'beschrijving' => 'Zelfvoorzienende rwzi\'s door terugwinning van energie uit afvalwater.',
'eigenaar_id' => $engineer->id,
'status' => SpeerpuntStatus::Actief,
]);
$spCirculaireWater = Speerpunt::create([
'thema_id' => $themaDuurzaam->id,
'naam' => 'Circulaire Waterketen',
'beschrijving' => 'Terugwinning van grondstoffen (fosfaat, cellulose, warmte) uit afvalwater.',
'eigenaar_id' => $testUser->id,
'status' => SpeerpuntStatus::Concept,
]);
// ──────────────────────────────────────────────────────────────
// 5. Projects (1012 spread across themes and lifecycle phases)
// ──────────────────────────────────────────────────────────────
$projects = [];
// --- Waterkwaliteit projects ---
$p1 = $this->createProject([
'speerpunt_id' => $spWaterMonitoring->id,
'naam' => 'LoRaWAN Sensornetwerk Biesbosch',
'beschrijving' => 'Uitrol van een draadloos sensornetwerk in het Biesbosch-gebied voor real-time meting van waterkwaliteitsparameters (pH, DO, troebelheid, geleidbaarheid).',
'eigenaar_id' => $testUser->id,
'status' => ProjectStatus::Pilot,
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-03-01',
'streef_einddatum' => '2025-12-31',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot]);
$p2 = $this->createProject([
'speerpunt_id' => $spWaterMonitoring->id,
'naam' => 'Drone-inspectie Waterbodem',
'beschrijving' => 'Onderzoek naar de inzet van autonome onderwaterdrones voor sedimentkartering en vervuilingdetectie in kanalen en sloten.',
'eigenaar_id' => $engineer->id,
'status' => ProjectStatus::Experiment,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2025-06-01',
'streef_einddatum' => '2026-06-30',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment]);
$p3 = $this->createProject([
'speerpunt_id' => $spMicropollution->id,
'naam' => 'PFAS Detectiemethode Ontwikkeling',
'beschrijving' => 'Ontwikkeling van een snelle en goedkope veldmethode voor PFAS-detectie in oppervlaktewater, als alternatief voor kostbare laboratoriumanalyse.',
'eigenaar_id' => $analyst->id,
'status' => ProjectStatus::Verkenning,
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-09-01',
'streef_einddatum' => '2026-09-30',
], [FaseType::Signaal, FaseType::Verkenning]);
// --- Slimme Infrastructuur projects ---
$p4 = $this->createProject([
'speerpunt_id' => $spDigitaalBeheer->id,
'naam' => 'BIM-model Gemaal De Donge',
'beschrijving' => 'Digitale driedimensionale representatie van gemaal De Donge inclusief alle technische installaties, leidingen en elektrotechnische componenten.',
'eigenaar_id' => $engineer->id,
'status' => ProjectStatus::OverdrachtBouwen,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2024-09-01',
'streef_einddatum' => '2025-06-30',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot, FaseType::Besluitvorming, FaseType::OverdrachtBouwen]);
$p5 = $this->createProject([
'speerpunt_id' => $spSmartGemaal->id,
'naam' => 'Predictieve Gemaalbesturing Mark-Vliet',
'beschrijving' => 'Implementatie van een ML-algoritme dat op basis van KNMI-weerdata en historische afvoerpatronen de optimale pompsturing berekent voor het Mark-Vliet systeem.',
'eigenaar_id' => $testUser->id,
'status' => ProjectStatus::Besluitvorming,
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-01-01',
'streef_einddatum' => '2025-12-31',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot, FaseType::Besluitvorming]);
$p6 = $this->createProject([
'speerpunt_id' => $spSmartGemaal->id,
'naam' => 'Remote Monitoring Waterkeringen',
'beschrijving' => 'Continuemonitoring van primaire waterkeringen met IoT-sensoren voor zakking, piping-detectie en grondwaterstand.',
'eigenaar_id' => $engineer->id,
'status' => ProjectStatus::Signaal,
'prioriteit' => Prioriteit::Laag,
'startdatum' => '2026-01-01',
'streef_einddatum' => null,
], [FaseType::Signaal]);
// --- Data-gedreven Beheer projects ---
$p7 = $this->createProject([
'speerpunt_id' => $spDigitaalTwin->id,
'naam' => 'Digitale Tweeling Pilot Roosendaalse Vliet',
'beschrijving' => 'Eerste proof-of-concept van een digitale tweeling voor het deelgebied Roosendaalse Vliet, gekoppeld aan het SOBEK-hydraulisch model.',
'eigenaar_id' => $analyst->id,
'status' => ProjectStatus::Concept,
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-07-01',
'streef_einddatum' => '2026-12-31',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept]);
$p8 = $this->createProject([
'speerpunt_id' => $spAIVoorspelling->id,
'naam' => 'AI Waterstandsmodel Hollandsch Diep',
'beschrijving' => 'Training en validatie van een LSTM-neuraal netwerk voor 48-uurs waterstandsvoorspellingen op het Hollandsch Diep, ter vervanging van het huidige regressiemodel.',
'eigenaar_id' => $analyst->id,
'status' => ProjectStatus::Experiment,
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-04-01',
'streef_einddatum' => '2026-03-31',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment]);
$p9 = $this->createProject([
'speerpunt_id' => $spAIVoorspelling->id,
'naam' => 'Open Data Platform Waterschap',
'beschrijving' => 'Ontwikkeling van een publiekstoegankelijk data-portaal voor het ontsluiten van historische en actuele meetdata van het waterschap.',
'eigenaar_id' => $testUser->id,
'status' => ProjectStatus::Geparkeerd,
'prioriteit' => Prioriteit::Laag,
'startdatum' => '2024-06-01',
'streef_einddatum' => '2025-12-31',
], [FaseType::Signaal, FaseType::Verkenning]);
// --- Duurzaamheid projects ---
$p10 = $this->createProject([
'speerpunt_id' => $spEnergieneutraal->id,
'naam' => 'Biogasopwaardering RWZI Bath',
'beschrijving' => 'Opwaardering van slibvergistingsgas naar groengas-kwaliteit voor invoeding op het gasnet en verkoop aan een energiemaatschappij.',
'eigenaar_id' => $engineer->id,
'status' => ProjectStatus::Evaluatie,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2024-01-01',
'streef_einddatum' => '2025-06-30',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot, FaseType::Besluitvorming, FaseType::OverdrachtBouwen, FaseType::OverdrachtBeheer, FaseType::Evaluatie]);
$p11 = $this->createProject([
'speerpunt_id' => $spCirculaireWater->id,
'naam' => 'Fosfaatterugwinning Struviet',
'beschrijving' => 'Implementatie van struvietkristallisatie-technologie op RWZI Nieuw-Vossemeer voor de terugwinning van fosfaat als meststof.',
'eigenaar_id' => $testUser->id,
'status' => ProjectStatus::Pilot,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2025-02-01',
'streef_einddatum' => '2026-02-28',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot]);
$p12 = $this->createProject([
'speerpunt_id' => $spEnergieneutraal->id,
'naam' => 'Warmteterugwinning Afvalwater Centrum',
'beschrijving' => 'Pilotinstallatie voor warmtewisselaars op het rioolstelsel in Breda-centrum om warmte terug te winnen voor stadsverwarming.',
'eigenaar_id' => $engineer->id,
'status' => ProjectStatus::Verkenning,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2025-10-01',
'streef_einddatum' => '2027-03-31',
], [FaseType::Signaal, FaseType::Verkenning]);
$projects = [$p1, $p2, $p3, $p4, $p5, $p6, $p7, $p8, $p9, $p10, $p11, $p12];
// ──────────────────────────────────────────────────────────────
// 6. Assign team members
// ──────────────────────────────────────────────────────────────
$p1->teamleden()->attach($analyst->id, ['rol' => ProjectRol::Lid->value]);
$p2->teamleden()->attach($testUser->id, ['rol' => ProjectRol::Reviewer->value]);
$p5->teamleden()->attach($analyst->id, ['rol' => ProjectRol::Lid->value]);
$p5->teamleden()->attach($engineer->id, ['rol' => ProjectRol::Reviewer->value]);
$p8->teamleden()->attach($engineer->id, ['rol' => ProjectRol::Lid->value]);
// ──────────────────────────────────────────────────────────────
// 7. Commitments
// ──────────────────────────────────────────────────────────────
Commitment::create([
'project_id' => $p1->id,
'beschrijving' => 'Installatie van 20 sensorknooppunten in het veld vóór einde Q3 2025',
'eigenaar_id' => $testUser->id,
'deadline' => '2025-09-30',
'status' => CommitmentStatus::InUitvoering,
'bron' => 'Stuurgroep Waterkwaliteit — 12 maart 2025',
]);
Commitment::create([
'project_id' => $p1->id,
'beschrijving' => 'Validatierapport sensornauwkeurigheid opleveren aan dataplatformteam',
'eigenaar_id' => $analyst->id,
'deadline' => '2025-11-30',
'status' => CommitmentStatus::Open,
'bron' => 'Stuurgroep Waterkwaliteit — 12 maart 2025',
]);
Commitment::create([
'project_id' => $p5->id,
'beschrijving' => 'Afstemming met Rijkswaterstaat over databeschikbaarheid afvoermetingen',
'eigenaar_id' => $engineer->id,
'deadline' => '2025-07-31',
'status' => CommitmentStatus::Afgerond,
'bron' => 'Projectstartup 15 januari 2025',
]);
Commitment::create([
'project_id' => $p5->id,
'beschrijving' => 'Businesscase energiebesparing opstellen voor directie',
'eigenaar_id' => $testUser->id,
'deadline' => '2025-10-15',
'status' => CommitmentStatus::Open,
'bron' => 'Besluitvormingsrapport fase 5',
]);
Commitment::create([
'project_id' => $p8->id,
'beschrijving' => 'Trainingsdata leveren: minimaal 5 jaar uurlijkse waterstandsmetingen',
'eigenaar_id' => $analyst->id,
'deadline' => '2025-08-01',
'status' => CommitmentStatus::Afgerond,
'bron' => 'Projectplan AI Waterstandsmodel v1.0',
]);
Commitment::create([
'project_id' => $p10->id,
'beschrijving' => 'Eindrapportage energieopbrengst en milieuprestatie biogasinstallatie',
'eigenaar_id' => $engineer->id,
'deadline' => '2025-05-31',
'status' => CommitmentStatus::Afgerond,
'bron' => 'Evaluatieprogramma RWZI Bath',
]);
Commitment::create([
'project_id' => $p11->id,
'beschrijving' => 'Technische specificaties struvietreactor aanleveren aan leverancier',
'eigenaar_id' => $testUser->id,
'deadline' => '2025-05-01',
'status' => CommitmentStatus::Afgerond,
'bron' => 'Pilotopzet Fosfaatterugwinning',
]);
// ──────────────────────────────────────────────────────────────
// 8. Documents
// ──────────────────────────────────────────────────────────────
Document::create([
'project_id' => $p1->id,
'titel' => 'Technisch Ontwerp LoRaWAN Netwerk',
'type' => 'technisch_ontwerp',
'inhoud' => 'Systeemarchitectuur, gatewaylocaties, frequentieplan en databeheerprotocol voor het LoRaWAN sensornetwerk in het Biesboschgebied.',
'versie' => 2,
'auteur_id' => $engineer->id,
]);
Document::create([
'project_id' => $p1->id,
'titel' => 'Projectplan Fase Pilot',
'type' => 'projectplan',
'inhoud' => 'Doelstellingen, activiteiten, planning en risico\'s voor de pilotfase van het LoRaWAN sensornetwerk.',
'versie' => 1,
'auteur_id' => $testUser->id,
]);
Document::create([
'project_id' => $p5->id,
'titel' => 'Businesscase Predictieve Gemaalbesturing',
'type' => 'businesscase',
'inhoud' => 'Kosten-batenanalyse voor de implementatie van ML-gestuurde pompsturing, inclusief energiebesparingspotentieel en investeringskosten.',
'versie' => 3,
'auteur_id' => $testUser->id,
]);
Document::create([
'project_id' => $p8->id,
'titel' => 'Modelarchitectuur LSTM Waterstandsvoorspelling',
'type' => 'technisch_rapport',
'inhoud' => 'Gedetailleerde beschrijving van de LSTM-netwerkarchitectuur, feature engineering, trainingsopzet en validatiemethodiek.',
'versie' => 1,
'auteur_id' => $analyst->id,
]);
Document::create([
'project_id' => $p10->id,
'titel' => 'Evaluatierapport Biogasopwaardering RWZI Bath',
'type' => 'evaluatierapport',
'inhoud' => 'Eindresultaten van de biogasopwaarderingsinstallatie: energieproductie, CH4-gehalte, opbrengst en geleerde lessen.',
'versie' => 1,
'auteur_id' => $engineer->id,
]);
Document::create([
'project_id' => $p4->id,
'titel' => 'BIM-protocol Kunstwerken v2.0',
'type' => 'protocol',
'inhoud' => 'Afspraken voor objectcodering, LOD-niveaus, attribuutvelden en uitwisselformaten (IFC) voor het BIM-model van kunstwerken.',
'versie' => 2,
'auteur_id' => $engineer->id,
]);
// ──────────────────────────────────────────────────────────────
// 9. Dependencies between projects
// ──────────────────────────────────────────────────────────────
// AI Waterstandsmodel is afhankelijk van LoRaWAN Sensornetwerk (databron)
Afhankelijkheid::create([
'project_id' => $p8->id,
'afhankelijk_van_project_id' => $p1->id,
'type' => 'data',
'beschrijving' => 'Het AI-model heeft real-time sensordata nodig uit het LoRaWAN netwerk als input feature.',
'status' => 'actief',
]);
// Digitale Tweeling is afhankelijk van AI Waterstandsmodel
Afhankelijkheid::create([
'project_id' => $p7->id,
'afhankelijk_van_project_id' => $p8->id,
'type' => 'technisch',
'beschrijving' => 'De digitale tweeling integreert de voorspellingsmodule van het AI waterstandsmodel.',
'status' => 'actief',
]);
// Predictieve Gemaalbesturing is afhankelijk van AI Waterstandsmodel
Afhankelijkheid::create([
'project_id' => $p5->id,
'afhankelijk_van_project_id' => $p8->id,
'type' => 'technisch',
'beschrijving' => 'De predictieve besturing gebruikt de 48-uurs waterstandsvoorspellingen als stuurinput.',
'status' => 'actief',
]);
// Remote Monitoring Waterkeringen is afhankelijk van LoRaWAN Sensornetwerk
Afhankelijkheid::create([
'project_id' => $p6->id,
'afhankelijk_van_project_id' => $p1->id,
'type' => 'infrastructuur',
'beschrijving' => 'Het monitoring-project maakt gebruik van de LoRaWAN-infrastructuur voor datatransport.',
'status' => 'gepland',
]);
}
/**
* Helper: create a project with its completed and active phases.
*
* @param array<string, mixed> $attributes
* @param FaseType[] $faseTypes All phase types in chronological order; the last one is the active phase.
*/
private function createProject(array $attributes, array $faseTypes): Project
{
$project = Project::create($attributes);
// Attach the project owner as eigenaar in the pivot table
$project->teamleden()->attach($attributes['eigenaar_id'], ['rol' => ProjectRol::Eigenaar->value]);
foreach ($faseTypes as $index => $faseType) {
$isLast = $index === count($faseTypes) - 1;
Fase::create([
'project_id' => $project->id,
'type' => $faseType,
'status' => $isLast ? FaseStatus::Actief : FaseStatus::Afgerond,
'startdatum' => now()->subMonths(count($faseTypes) - 1 - $index),
'einddatum' => $isLast ? null : now()->subMonths(count($faseTypes) - 2 - $index),
]);
}
return $project;
}
}