@extends('layouts.app')
@php use App\Services\Translator; @endphp
@php
$lang = app()->getLocale();
$fx = $fixture['fixture'] ?? [];
$teams = $fixture['teams'] ?? [];
$goals = $fixture['goals'] ?? [];
$leagueInfo = $fixture['league'] ?? [];
$venue = $fx['venue'] ?? [];
$statusData = $fx['status'] ?? [];
$home = $teams['home'] ?? [];
$away = $teams['away'] ?? [];
$homeName = Translator::team($home['name'] ?? '');
$awayName = Translator::team($away['name'] ?? '');
$leagueName = Translator::league($leagueInfo['name'] ?? '', $leagueInfo['country'] ?? null);
$statusShort = $statusData['short'] ?? 'NS';
$elapsed = $statusData['elapsed'] ?? null;
$isLive = in_array($statusShort, ['1H','2H','HT','LIVE','ET','P','BT']);
$isFinished = in_array($statusShort, ['FT','AET','PEN']);
$isUpcoming = in_array($statusShort, ['NS','TBD']);
$isPostponed = in_array($statusShort, ['PST','CANC','ABD','SUSP']);
$matchDate = null;
try { if (!empty($fx['date'])) $matchDate = \Carbon\Carbon::parse($fx['date'])->setTimezone('Africa/Tunis'); } catch (\Exception $e) {}
$dateTimeStr = $matchDate ? $matchDate->format('Y/m/d - H:i') : '';
$timeStr = $matchDate ? $matchDate->format('H:i') : '--:--';
$homeGoals = $goals['home'] ?? null;
$awayGoals = $goals['away'] ?? null;
// Round translation
$round = $leagueInfo['round'] ?? '';
$formatRound = function($round) use ($lang) {
if (!$round) return '';
if (preg_match('/(\d+)/', $round, $m)) {
$num = $m[1];
if ($lang === 'ar') return "الجولة {$num}";
if ($lang === 'fr') return "Journée {$num}";
return "Round {$num}";
}
return $round;
};
// Rank color (Champions League / Europa / Relegation etc) — same as league-show
$getRankColor = function(?string $description): string {
if (!$description) return 'transparent';
$d = strtolower($description);
if (str_contains($d, 'champions league') || str_contains($d, 'promotion')) return '#1A8D48';
if (str_contains($d, 'europa league')) return '#E67E22';
if (str_contains($d, 'conference league')) return '#3498DB';
if (str_contains($d, 'relegation')) return '#E74C3C';
return 'transparent';
};
$translateDescription = function(?string $desc) use ($lang) {
if (!$desc) return '';
$d = strtolower($desc);
if ($lang === 'ar') {
if (str_contains($d, 'champions league')) return 'دوري الأبطال';
if (str_contains($d, 'europa league')) return 'الدوري الأوروبي';
if (str_contains($d, 'conference league')) return 'دوري المؤتمر';
if (str_contains($d, 'relegation')) return 'الهبوط';
if (str_contains($d, 'promotion')) return 'الصعود';
} elseif ($lang === 'fr') {
if (str_contains($d, 'champions league')) return 'Ligue des Champions';
if (str_contains($d, 'europa league')) return 'Ligue Europa';
if (str_contains($d, 'conference league')) return 'Ligue Conférence';
if (str_contains($d, 'relegation')) return 'Relégation';
if (str_contains($d, 'promotion')) return 'Promotion';
}
return $desc;
};
// Build legend (unique descriptions with colors) for standings tab
$standings = $standings ?? [];
$topScorers = $topScorers ?? [];
$legend = [];
foreach ($standings as $group) {
foreach ($group as $row) {
$desc = $row['description'] ?? '';
if ($desc) {
$color = $getRankColor($desc);
if ($color !== 'transparent' && !isset($legend[$desc])) {
$legend[$desc] = $color;
}
}
}
}
// IDs of the two teams playing — used to highlight them in standings
$homeTeamId = $home['id'] ?? 0;
$awayTeamId = $away['id'] ?? 0;
// For YS leagues, player IDs come from the YSScores scraper → pass ?ys=1
$ysLeagueIds = [186, 202, 200, 233, 308, 421, 387];
$isYsLeague = in_array($leagueInfo['id'] ?? 0, $ysLeagueIds, true);
// Helper: build player URL
$playerUrl = function ($pid) use ($isYsLeague) {
if (!$pid) return '#';
return route('player.show', $pid) . ($isYsLeague ? '?ys=1' : '');
};
@endphp
@section('title', "$homeName vs $awayName - " . __('messages.app_name'))
@section('description', "$homeName vs $awayName - $leagueName")
@section('og_image', $home['logo'] ?? asset('images/logosportirak.png'))
@section('content')
{{-- ===== HEADER (Sliver style with background image) ===== --}}
{{-- Top bar: back + share --}}
{{-- Content --}}
{{-- League name + round --}}
{{ $leagueName }}
@if($round)
{{ $formatRound($round) }}
@endif
{{-- Teams row --}}
{{-- Home team --}}
@if(!empty($home['logo']))

@else
@endif
{{ $homeName }}
{{-- Score / time --}}
@if($isLive)
{{ $homeGoals ?? 0 }}
@php
$elapsedVal = min(90, max(0, $elapsed ?? 0));
$circ = 2 * M_PI * 18;
$remaining = $circ - ($elapsedVal / 90) * $circ;
@endphp
{{ $elapsed }}'
{{ $awayGoals ?? 0 }}
@elseif($isFinished)
{{ __('messages.finished') }}
{{ $homeGoals ?? 0 }} - {{ $awayGoals ?? 0 }}
@elseif($isPostponed)
{{ $statusShort === 'PST' ? ($lang === 'ar' ? 'مؤجلة' : 'Reportée') : strtoupper($statusShort) }}
@else
{{ $timeStr }}
@endif
{{-- Away team --}}
@if(!empty($away['logo']))

@else
@endif
{{ $awayName }}
@if($matchDate)
{{ $dateTimeStr }}
@endif
{{-- ===== TAB BAR ===== --}}
{{-- ===== SUMMARY TAB (Events timeline — identical to Flutter) ===== --}}
@if(empty($events))
{{ __('messages.no_events') }}
@else
@php
// Group events by half (like Flutter)
$firstHalf = []; $secondHalf = []; $extraTime = [];
foreach ($events as $ev) {
$e = $ev['time']['elapsed'] ?? 0;
$extra = $ev['time']['extra'] ?? null;
if ($e > 90 || ($extra !== null && $e >= 90)) $extraTime[] = $ev;
elseif ($e > 45 || ($e == 45 && $extra !== null && $extra > 0)) $secondHalf[] = $ev;
else $firstHalf[] = $ev;
}
$homeTeamId = $home['id'] ?? 0;
// Material icons (same as Flutter) — returns [svg_path, color, subtitle]
$eventIconData = function($type, $detail, $assistName, $hasAssist) {
$t = strtolower($type ?? '');
$d = strtolower($detail ?? '');
$subtitle = null;
// SVG paths for Material icons
$sportsSoccer = 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.9 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z';
$squareRounded = 'M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z';
$squareFilled = 'M3 5c0-1.1.9-2 2-2h14c1.1 0 2 .9 2 2v14c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2V5z';
$swapHoriz = 'M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z';
$infoOutline = 'M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z';
if ($t === 'goal') {
$path = $sportsSoccer;
if (str_contains($d, 'own goal')) {
$color = '#E53E3E'; // live red
$subtitle = app()->getLocale() === 'ar' ? 'هدف في مرماه' : (app()->getLocale() === 'fr' ? 'But contre son camp' : 'Own goal');
} elseif (str_contains($d, 'penalty')) {
$color = '#38A169'; // success green
$subtitle = app()->getLocale() === 'ar' ? 'هدف من ركلة جزاء' : (app()->getLocale() === 'fr' ? 'But sur penalty' : 'Penalty goal');
} else {
$color = '#38A169';
}
if ($hasAssist && !str_contains($d, 'own goal')) {
$lbl = app()->getLocale() === 'ar' ? 'صانع الهدف' : (app()->getLocale() === 'fr' ? 'Passeur' : 'Assist');
$subtitle = $subtitle ? "{$subtitle} - {$assistName}" : "{$lbl}: {$assistName}";
}
return [$path, $color, $subtitle];
}
if ($t === 'card') {
if (str_contains($d, 'red')) {
return [$squareFilled, '#E53E3E', null];
}
return [$squareFilled, '#D69E2E', null];
}
if ($t === 'subst') {
if ($hasAssist) $subtitle = $assistName;
return [$swapHoriz, '#2e8b6b', $subtitle];
}
if ($t === 'var') {
return [$infoOutline, '#6B7280', $detail];
}
return [$infoOutline, '#9CA3AF', null];
};
@endphp
@foreach([['title' => __('messages.kick_off'), 'evs' => $firstHalf], ['title' => __('messages.second_half'), 'evs' => $secondHalf], ['title' => __('messages.extra_time'), 'evs' => $extraTime]] as $section)
@if(!empty($section['evs']))
{{-- Timeline header (green pill with dot) --}}
@foreach($section['evs'] as $ev)
@php
$isHome = ($ev['team']['id'] ?? 0) == $homeTeamId;
$playerName = Translator::player($ev['player']['name'] ?? '');
$assistName = !empty($ev['assist']['name']) ? Translator::player($ev['assist']['name']) : '';
$hasAssist = !empty($assistName);
[$iconPath, $iconColor, $subtitle] = $eventIconData($ev['type'] ?? '', $ev['detail'] ?? '', $assistName, $hasAssist);
$minute = ($ev['time']['elapsed'] ?? 0) . "'";
if (!empty($ev['time']['extra'])) $minute = ($ev['time']['elapsed'] ?? 0) . "'+" . $ev['time']['extra'];
$type = strtolower($ev['type'] ?? '');
$subtitleColor = $type === 'subst' ? '#E53E3E' : '#6B7280';
@endphp
{{-- Home side (right in RTL) --}}
@if($isHome)
{{ $playerName }}
@if($subtitle)
{{ $subtitle }}
@endif
@endif
{{-- Timeline center: vertical line + minute circle --}}
{{-- Away side (left in RTL) --}}
@if(!$isHome)
{{ $playerName }}
@if($subtitle)
{{ $subtitle }}
@endif
@endif
@endforeach
@endif
@endforeach
{{-- Timeline end dot (if match finished) --}}
@if($isFinished)
@endif
@endif
{{-- ===== STATS TAB (identical to Flutter) ===== --}}
@php
// Build stat maps from home/away stats
$homeMap = [];
$awayMap = [];
foreach ($home_stats as $s) { $homeMap[$s['type'] ?? ''] = $s['value']; }
foreach ($away_stats as $s) { $awayMap[$s['type'] ?? ''] = $s['value']; }
// Convert stat value to numeric (handles "55%" and null)
$toNum = function($v) {
if ($v === null) return 0;
if (is_numeric($v)) return (int) $v;
if (is_string($v) && str_ends_with($v, '%')) return (int) rtrim($v, '%');
return 0;
};
// Stat items in the same order as Flutter
$statItems = [
['Ball Possession', 'possession', true],
['Total Shots', 'total_shots', false],
['Shots on Goal', 'shots_on_target', false],
['Shots off Goal', 'shots_off_target', false],
['Corner Kicks', 'corner_kicks', false],
['Fouls', 'fouls', false],
['Offsides', 'offsides', false],
['Yellow Cards', 'yellow_cards', false],
['Red Cards', 'red_cards', false],
['Goalkeeper Saves', 'saves', false],
['Blocked Shots', 'blocked_shots', false],
['Total passes', 'passes_total', false],
['Passes accurate', 'passes_accurate', false],
];
// Localized labels for stat translation keys
$statLabels = [
'possession' => ['ar' => 'الاستحواذ', 'fr' => 'Possession', 'en' => 'Possession'],
'total_shots' => ['ar' => 'مجموع التسديدات', 'fr' => 'Total tirs', 'en' => 'Total shots'],
'shots_on_target' => ['ar' => 'تسديدات على المرمى', 'fr' => 'Tirs cadrés', 'en' => 'Shots on target'],
'shots_off_target' => ['ar' => 'تسديدات خارج المرمى', 'fr' => 'Tirs non cadrés', 'en' => 'Shots off target'],
'corner_kicks' => ['ar' => 'ركنيات', 'fr' => 'Corners', 'en' => 'Corner kicks'],
'fouls' => ['ar' => 'أخطاء', 'fr' => 'Fautes', 'en' => 'Fouls'],
'offsides' => ['ar' => 'تسلل', 'fr' => 'Hors-jeu', 'en' => 'Offsides'],
'yellow_cards' => ['ar' => 'بطاقات صفراء', 'fr' => 'Cartons jaunes', 'en' => 'Yellow cards'],
'red_cards' => ['ar' => 'بطاقات حمراء', 'fr' => 'Cartons rouges', 'en' => 'Red cards'],
'saves' => ['ar' => 'تصديات', 'fr' => 'Arrêts', 'en' => 'Saves'],
'blocked_shots' => ['ar' => 'تسديدات مصدودة', 'fr' => 'Tirs bloqués', 'en' => 'Blocked shots'],
'passes_total' => ['ar' => 'مجموع التمريرات', 'fr' => 'Total passes', 'en' => 'Total passes'],
'passes_accurate' => ['ar' => 'تمريرات ناجحة', 'fr' => 'Passes réussies', 'en' => 'Accurate passes'],
];
// Build filtered list: only stats where at least one is > 0
$filteredStats = [];
foreach ($statItems as [$apiKey, $transKey, $isPossession]) {
$hv = $toNum($homeMap[$apiKey] ?? null);
$av = $toNum($awayMap[$apiKey] ?? null);
if ($hv > 0 || $av > 0) {
$filteredStats[] = [
'api_key' => $apiKey,
'trans_key' => $transKey,
'is_possession' => $isPossession,
'home_value' => $hv,
'away_value' => $av,
'label' => $statLabels[$transKey][$lang] ?? $apiKey,
];
}
}
$possessionStat = null;
$otherStats = [];
foreach ($filteredStats as $s) {
if ($s['is_possession']) $possessionStat = $s;
else $otherStats[] = $s;
}
@endphp
@if(empty($filteredStats))
{{ __('messages.no_stats') }}
@else
{{-- ===== POSSESSION DONUT ===== --}}
@if($possessionStat)
@php
$hp = $possessionStat['home_value'];
$ap = $possessionStat['away_value'];
// Normalize to 100% if needed
$totalP = $hp + $ap;
if ($totalP > 0 && abs($totalP - 100) > 5) {
$hp = round($hp / $totalP * 100);
$ap = 100 - $hp;
}
// SVG donut calculations
$radius = 52;
$circumference = 2 * M_PI * $radius;
$homeDash = ($hp / 100) * $circumference;
$awayDash = ($ap / 100) * $circumference;
@endphp
{{-- Home % + name --}}
{{ $hp }}%
{{ $homeName }}
{{-- SVG Donut --}}
{{ $possessionStat['label'] }}
{{-- Away % + name --}}
{{ $ap }}%
{{ $awayName }}
@endif
{{-- ===== STAT BARS ===== --}}
@foreach($otherStats as $stat)
@php
$hv = $stat['home_value'];
$av = $stat['away_value'];
$total = $hv + $av;
$homeRatio = $total > 0 ? max(1, min(99, round($hv / $total * 100))) : 50;
$awayRatio = 100 - $homeRatio;
@endphp
{{-- Value row --}}
{{ $hv }}
{{ $stat['label'] }}
{{ $av }}
{{-- Progress bars --}}
@endforeach
@endif
{{-- ===== LINEUP TAB ===== --}}
@php
// Helper: build field rows from a lineup (grouping players by row, sorted by col)
$buildFieldRows = function($lineup) {
$startXI = $lineup['startXI'] ?? [];
$formation = $lineup['formation'] ?? null;
// Parse players (handle nested & flat)
$parsed = [];
foreach ($startXI as $entry) {
if (is_array($entry)) {
if (isset($entry['player']) && is_array($entry['player'])) {
$parsed[] = $entry['player'];
} else {
$parsed[] = $entry;
}
}
}
// First pass: try API grid
$apiGrids = [];
$rowSet = [];
foreach ($parsed as $p) {
$grid = (string)($p['grid'] ?? '');
$parts = explode(':', $grid);
if (count($parts) === 2) {
$r = (int)$parts[0];
$c = (int)$parts[1];
$apiGrids[] = [$r, $c];
if ($r > 0) $rowSet[$r] = true;
} else {
$apiGrids[] = [0, 0];
}
}
$distinctRows = count($rowSet);
$useApiGrid = $distinctRows >= 3;
// Auto grid from formation
$autoGrid = null;
if (!$useApiGrid) {
$effFormation = ($formation && strpos($formation, '-') !== false) ? $formation : '4-3-3';
$formParts = array_map('intval', array_map('trim', explode('-', $effFormation)));
$autoGrid = [[1, 1]]; // GK
foreach ($formParts as $i => $count) {
$rowNum = $i + 2;
for ($j = 0; $j < $count; $j++) {
$autoGrid[] = [$rowNum, $j + 1];
}
}
}
// Build players with positions
$players = [];
foreach ($parsed as $i => $p) {
$row = 0; $col = 0;
if ($useApiGrid && isset($apiGrids[$i])) {
[$row, $col] = $apiGrids[$i];
} elseif ($autoGrid && isset($autoGrid[$i])) {
[$row, $col] = $autoGrid[$i];
}
$pid = $p['id'] ?? 0;
$photo = $p['photo'] ?? ($pid ? "https://media.api-sports.io/football/players/{$pid}.png" : null);
$players[] = [
'id' => $pid,
'name' => Translator::player($p['name'] ?? ''),
'number' => $p['number'] ?? 0,
'row' => $row,
'col' => $col,
'photo' => $photo,
];
}
// Group by row
$rows = [];
foreach ($players as $p) {
$rows[$p['row']][] = $p;
}
ksort($rows);
foreach ($rows as $k => $list) {
usort($rows[$k], fn($a, $b) => $a['col'] <=> $b['col']);
}
return ['rows' => $rows, 'formation' => $formation];
};
@endphp
@if(empty($home_lineup) && empty($away_lineup))
{{ __('messages.no_lineup') }}
@else
{{-- Team toggle --}}
@foreach([['lu' => $home_lineup, 'idx' => 0], ['lu' => $away_lineup, 'idx' => 1]] as $side)
@if(empty($side['lu']))
{{ __('messages.no_lineup') }}
@else
@php
$built = $buildFieldRows($side['lu']);
$fieldRows = $built['rows'];
$formation = $built['formation'];
$rowCount = count($fieldRows);
$fieldHeight = max(350, min(520, $rowCount * 80));
@endphp
{{-- Football field --}}
{{-- Players --}}
@foreach($fieldRows as $rowPlayers)
@endforeach
{{-- Formation badge --}}
@if($formation)
{{ $formation }}
@endif
{{-- Coach row --}}
@if(!empty($side['lu']['coach']['name']))
@php $coach = $side['lu']['coach']; @endphp
{{ __('messages.coach') }}
@if(!empty($coach['photo']))

@endif
{{ Translator::player($coach['name']) }}
@endif
{{-- Substitutes --}}
@if(!empty($side['lu']['substitutes']))
@endif
@endif
@endforeach
@endif
{{-- ===== STANDINGS TAB ===== --}}
@if(empty($standings))
{{ __('messages.no_standings') }}
@else
@foreach($standings as $groupIdx => $group)
@php
$groupName = $group[0]['group'] ?? '';
$displayGroupName = $groupName;
if (count($standings) > 1 && preg_match('/Groupe?\s*([A-Za-z0-9]+)/i', $groupName, $m)) {
$letter = $m[1];
$displayGroupName = $lang === 'ar' ? "المجموعة {$letter}" : ($lang === 'fr' ? "Groupe {$letter}" : "Group {$letter}");
}
@endphp
@if(count($standings) > 1 && $displayGroupName)
{{ $displayGroupName }}
@endif
{{-- Table header --}}
#
{{ __('messages.team_col') }}
{{ __('messages.played_col') }}
{{ __('messages.won_col') }}
{{ __('messages.drawn_col') }}
{{ __('messages.lost_col') }}
{{ __('messages.diff_col') }}
{{ __('messages.points_col') }}
@foreach($group as $index => $row)
@php
$rank = $row['rank'] ?? ($index + 1);
$teamInfo = $row['team'] ?? [];
$teamId = $teamInfo['id'] ?? 0;
$teamName = Translator::team($teamInfo['name'] ?? '');
$all = $row['all'] ?? [];
$played = $all['played'] ?? 0;
$win = $all['win'] ?? 0;
$draw = $all['draw'] ?? 0;
$lose = $all['lose'] ?? 0;
$goalsDiff = $row['goalsDiff'] ?? 0;
$points = $row['points'] ?? 0;
$rankColor = $getRankColor($row['description'] ?? '');
$isHighlighted = ($teamId == $homeTeamId) || ($teamId == $awayTeamId);
$isEven = $index % 2 === 0;
@endphp
{{ $rank }}
@if(!empty($teamInfo['logo']))

@endif
{{ $teamName }}
{{ $played }}
{{ $win }}
{{ $draw }}
{{ $lose }}
{{ $goalsDiff }}
{{ $points }}
@endforeach
@endforeach
@if(!empty($legend))
@foreach($legend as $desc => $color)
{{ $translateDescription($desc) }}
@endforeach
@endif
@endif
{{-- ===== TOP SCORERS TAB ===== --}}
{{-- ===== DETAILS TAB ===== --}}
@if(!empty($leagueInfo['name']))
- {{ __('messages.league') }}
- {{ $leagueName }}
@endif
@if($round)
- {{ __('messages.round') }}
- {{ $formatRound($round) }}
@endif
@if($matchDate)
- {{ __('messages.date') }}
- {{ $dateTimeStr }}
@endif
@if(!empty($venue['name']))
- {{ __('messages.stadium') }}
- {{ $venue['name'] }}
@endif
@if(!empty($venue['city']))
- {{ __('messages.city') }}
- {{ $venue['city'] }}
@endif
@if(!empty($fx['referee']))
- {{ __('messages.referee') }}
- {{ $fx['referee'] }}
@endif
@push('scripts')
@endpush
@endsection