Phase 1 — Fit-to-view zoom: - computeFitTransform() calculates bounding box and scales to fit all nodes - Replaces hardcoded scale=1 reset in animateZoomReset() and initCanvas() - Dim 1 no longer appears tiny after zooming out from dim 2 Phase 2 — Grid system: - Shared gridConstants.js (GRID=50, GRID_STEP_X=200, GRID_STEP_Y=150) - MapDataService snapToGrid() aligns all node positions server-side - Canvas renders subtle grid lines (shown on interaction only, with fade) - Line highlighting support via setHighlightedLine() for FAB hover Phase 3 — Branch handles: - Hover any station node → 3 "+" handles appear (0°/45°/315°) - 0° extends the current line, 45°/315° fork to create new branch - Ghost preview (dashed line + circle) on handle hover - Handles only show at unoccupied grid positions - Grid fades in during handle interaction, fades out after Phase 4 — Custom tracks database: - metro_lines table (project_id, naam, color, type, order) - metro_nodes table (metro_line_id, naam, status, x, y, order) - MetroLine + MetroNode models, controllers, routes - Project.metroLines() relationship added Phase 5+6 — FAB redesign + MetroMap wiring: - FAB shows "Nieuw thema (lijn)" at root, "Nieuwe lijn" in project dim - Track creation modal with retro-styled form - MetroMap handles create-node events from branch handles - Extend (0°) opens commitment/document form, fork opens track form - Canvas context menu replaced with "hover to branch" hint Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
114 lines
2.5 KiB
PHP
114 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Enums\Prioriteit;
|
|
use App\Enums\ProjectRol;
|
|
use App\Enums\ProjectStatus;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
class Project extends Model
|
|
{
|
|
use SoftDeletes;
|
|
|
|
protected $table = 'projects';
|
|
|
|
protected $fillable = [
|
|
'speerpunt_id',
|
|
'naam',
|
|
'beschrijving',
|
|
'eigenaar_id',
|
|
'status',
|
|
'prioriteit',
|
|
'startdatum',
|
|
'streef_einddatum',
|
|
];
|
|
|
|
protected function casts(): array
|
|
{
|
|
return [
|
|
'status' => ProjectStatus::class,
|
|
'prioriteit' => Prioriteit::class,
|
|
'startdatum' => 'date',
|
|
'streef_einddatum' => 'date',
|
|
];
|
|
}
|
|
|
|
public function speerpunt(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Speerpunt::class);
|
|
}
|
|
|
|
public function eigenaar(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'eigenaar_id');
|
|
}
|
|
|
|
public function teamleden(): BelongsToMany
|
|
{
|
|
return $this->belongsToMany(User::class, 'project_user')
|
|
->withPivot('rol')
|
|
->withTimestamps()
|
|
->using(ProjectUser::class);
|
|
}
|
|
|
|
public function fases(): HasMany
|
|
{
|
|
return $this->hasMany(Fase::class);
|
|
}
|
|
|
|
public function risicos(): HasMany
|
|
{
|
|
return $this->hasMany(Risico::class);
|
|
}
|
|
|
|
public function afhankelijkheden(): HasMany
|
|
{
|
|
return $this->hasMany(Afhankelijkheid::class);
|
|
}
|
|
|
|
public function afhankelijkVanMij(): HasMany
|
|
{
|
|
return $this->hasMany(Afhankelijkheid::class, 'afhankelijk_van_project_id');
|
|
}
|
|
|
|
public function besluiten(): HasMany
|
|
{
|
|
return $this->hasMany(Besluit::class);
|
|
}
|
|
|
|
public function commitments(): HasMany
|
|
{
|
|
return $this->hasMany(Commitment::class);
|
|
}
|
|
|
|
public function budgets(): HasMany
|
|
{
|
|
return $this->hasMany(Budget::class);
|
|
}
|
|
|
|
public function documents(): HasMany
|
|
{
|
|
return $this->hasMany(Document::class);
|
|
}
|
|
|
|
public function lessonsLearned(): HasMany
|
|
{
|
|
return $this->hasMany(LessonLearned::class);
|
|
}
|
|
|
|
public function overdrachtsplannen(): HasMany
|
|
{
|
|
return $this->hasMany(Overdrachtsplan::class);
|
|
}
|
|
|
|
public function metroLines(): HasMany
|
|
{
|
|
return $this->hasMany(MetroLine::class);
|
|
}
|
|
}
|