diff --git a/.claude/component-usage.md b/.claude/component-usage.md index b855cf7..a468719 100644 --- a/.claude/component-usage.md +++ b/.claude/component-usage.md @@ -144,6 +144,9 @@ Stored value: ISO2 code (e.g. `"BH"`). |---|---|---| | `resources/views/user/profile.blade.php` | `nationality` | Edit Profile form | | `resources/views/auth/register.blade.php` | `nationality` | Registration form — mandatory | +| `resources/views/layouts/partials/sports-match-modal.blade.php` | `participants[p1_country]` | Fighter 1 country → header flag | +| `resources/views/layouts/partials/sports-match-modal.blade.php` | `participants[p2_country]` | Fighter 2 country → header flag | +| `resources/views/layouts/partials/sports-match-modal.blade.php` | `participants[referee_country]` | Referee country → header flag | --- diff --git a/app/Models/SportsMatch.php b/app/Models/SportsMatch.php index c948a7f..ccdf632 100644 --- a/app/Models/SportsMatch.php +++ b/app/Models/SportsMatch.php @@ -34,6 +34,63 @@ class SportsMatch extends Model 'reviews' => 'array', ]; + /** + * Shape the record into exactly what the match page header renders. Every value + * is null-safe so a video with no/partial match data degrades to just its title + * instead of falling back to hard-coded demo content. + */ + public function headerData(): array + { + $p = $this->participants ?? []; + $c = $this->competition ?? []; + $v = $this->venue ?? []; + + return [ + 'blue' => [ + 'name' => $this->participant1_name ?: null, + 'club' => $p['p1_club'] ?? null, + 'flag' => $this->flagFor($p['p1_country'] ?? null), + ], + 'red' => [ + 'name' => $this->participant2_name ?: null, + 'club' => $p['p2_club'] ?? null, + 'flag' => $this->flagFor($p['p2_country'] ?? null), + ], + 'weight_category' => $p['weight_class'] ?? null, + 'championship' => $c['championship_name'] ?? ($this->event_name ?: null), + 'match_number' => $c['match_number'] ?? null, + 'court' => $c['court'] ?? null, + 'referee' => [ + 'name' => $this->referee_name ?: null, + 'flag' => $this->flagFor($p['referee_country'] ?? null), + ], + 'venue' => [ + 'name' => $this->venue_name ?: ($v['name'] ?? null), + 'map_link' => $v['map_link'] ?? null, + ], + 'event_logo' => $this->media['event_poster'] ?? null, // rel path or null + ]; + } + + /** Resolve a country name or ISO2 code to a lowercase flag-icons code (or null). */ + private function flagFor(?string $country): ?string + { + $country = trim((string) $country); + if ($country === '') { + return null; + } + $countries = \App\Data\Countries::all(); + if (preg_match('/^[A-Za-z]{2}$/', $country) && isset($countries[strtoupper($country)])) { + return strtolower($country); + } + foreach ($countries as $iso2 => $meta) { + if (strcasecmp($meta['name'], $country) === 0) { + return strtolower($iso2); + } + } + return null; + } + public function video(): BelongsTo { return $this->belongsTo(Video::class); diff --git a/app/Models/Video.php b/app/Models/Video.php index a7d0117..880a5b4 100644 --- a/app/Models/Video.php +++ b/app/Models/Video.php @@ -434,6 +434,12 @@ class Video extends Model return $this->hasMany(CoachReview::class)->orderBy('start_time_seconds'); } + // The sports match record backing a type=match video (fighters, referee, etc.) + public function sportsMatch() + { + return $this->hasOne(SportsMatch::class); + } + // Get recent views count (within hours) public function getRecentViews($hours = 48) { diff --git a/resources/views/layouts/partials/sports-match-modal.blade.php b/resources/views/layouts/partials/sports-match-modal.blade.php index 2d3942f..321666a 100644 --- a/resources/views/layouts/partials/sports-match-modal.blade.php +++ b/resources/views/layouts/partials/sports-match-modal.blade.php @@ -91,6 +91,16 @@
+