Match cards: composed title, header stage from match title, equal-sized grid

- SportsMatchController syncs Video.title with SportsMatch.title on
  store/update so the "Match title" field drives the video's display
  title everywhere.
- headerData(): "championship" now prefers event_name (event title)
  and adds a dedicated "stage" key sourced from SportsMatch.title
  (shown between the yellow lines above the weight class in both the
  in-player VS overlay and the vs-mini gallery card).
- Video cards render match titles with flags + corner colours
  ("FINALS – 🇧🇭 Blue vs 🇧🇭 Red (-61 kg)"), matching the video
  page header, and clip long titles to one line.
- Video gallery grid uses repeat(N, minmax(0, 1fr)) + grid-auto-rows:1fr
  so every card thumbnail renders at exactly the same size; hover-preview
  videos use object-fit:cover to stop portrait sources looking smaller.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
ghassanandClaude Opus 4.7 committed 2026-08-11 09:14:25 +03:00
1 parent 04d63cccdb
commit 665bad76bf
7 files changed
+128 -37

No files matched your search

@@ -41,6 +41,38 @@ $langFlag = $forceTrackFlag ?: ($video ? Languages::flag($video->language) : nul
$showUrl = $video ? route('videos.show', $video) . ($forceTrackId ? ('?track=' . $forceTrackId) : '') : '#';
// Composed display title for match videos — matches the header on the
// match page: "{match title} – {blue flag+name} vs {red flag+name}
// ({weight})", with blue/red corner colours and inline flags. Falls
// back to plain $video->title for non-match cards.
$displayTitle = $video?->title;
$displayTitleHtml = null;
if ($video && $video->type === 'match' && $video->sportsMatch) {
$hdCard = $video->sportsMatch->headerData();
$blueN = $hdCard['blue']['name'] ?? null;
$redN = $hdCard['red']['name'] ?? null;
$blueF = $hdCard['blue']['flag'] ?? null;
$redF = $hdCard['red']['flag'] ?? null;
if ($blueN || $redN) {
$flagStyle = 'width:16px;height:12px;border-radius:2px;display:inline-block;vertical-align:middle;margin-right:4px;';
$mkSide = function ($name, $flag, $color) use ($flagStyle) {
if (!$name) return '';
$flagHtml = $flag ? '<span class="fi fi-'.e($flag).'" style="'.$flagStyle.'"></span>' : '';
return '<span style="color:'.$color.';font-weight:600;">'.$flagHtml.e($name).'</span>';
};
$blueHtml = $mkSide($blueN, $blueF, '#2563eb');
$redHtml = $mkSide($redN, $redF, '#ef4444');
$parts = [];
if (!empty($video->title)) $parts[] = e(strtoupper($video->title)) . ' –';
if ($blueHtml && $redHtml) $parts[] = $blueHtml . ' <span>vs</span> ' . $redHtml;
elseif ($blueHtml) $parts[] = $blueHtml;
elseif ($redHtml) $parts[] = $redHtml;
if (!empty($hdCard['weight_category'])) $parts[] = '(' . e($hdCard['weight_category']) . ')';
$displayTitleHtml = implode(' ', $parts);
}
}
// Size classes
$sizeClasses = match($size) {
'small' => 'yt-video-card-sm',
@@ -113,7 +145,11 @@ $sizeClasses = match($size) {
@if($langFlag)
<span class="fi fi-{{ $langFlag }} vc-lang-flag"></span>
@endif
{{ $video->title ?? 'Untitled Video' }}
@if($displayTitleHtml)
{!! $displayTitleHtml !!}
@else
{{ $displayTitle ?? 'Untitled Video' }}
@endif
</a>
</h3>
@if($video && $video->user)