@extends('layouts.app') @push('head') @endpush @section('title', ($visit->title ?: $visit->park?->official_name).' β€” '.$group->name.' β€” Coaster World') @php $park = $visit->park; $parkTranslation = $park?->translations?->firstWhere('locale', app()->getLocale()) ?? $park?->translations?->firstWhere('locale', 'en'); $parkName = $parkTranslation?->name ?: $park?->official_name; $isPast = $visit->ends_on?->isPast() && ! $visit->ends_on?->isToday(); $programTypeIcons = [ 'attraction' => '🎒', 'meal' => 'πŸ”', 'break' => 'β˜•', 'meetup' => 'πŸ“', 'custom' => '✨', ]; $programStatusIcons = [ 'todo' => 'β—‹', 'in_progress' => 'β–Ά', 'done' => 'βœ“', 'skipped' => 'β†·', ]; @endphp @section('content') @if(session('gps_status'))
{{ session('gps_status') }}
@endif @if($errors->has('gps'))
{{ $errors->first('gps') }}
@endif
← {{ __('ui.group_visit_back_to_group') }}
{{ $visit->starts_on?->format('d') }} {{ mb_strtoupper($visit->starts_on?->locale(app()->getLocale())->translatedFormat('M') ?? '') }} {{ $visit->starts_on?->format('Y') }}
{{ __('ui.group_visit_detail_kicker') }}

{{ $visit->title ?: $parkName }}

{{ $parkName }}
@if($visit->ends_on && !$visit->ends_on->equalTo($visit->starts_on)) {{ __('ui.group_visit_date_range', ['start' => $visit->starts_on->format('d/m/Y'), 'end' => $visit->ends_on->format('d/m/Y')]) }} @else {{ $visit->starts_on?->format('d/m/Y') }} @endif {{ $group->name }} {{ $isPast ? __('ui.group_visit_past') : __('ui.group_visit_planned') }}
@if($currentVisitMember?->invitation_status === 'accepted' || $canManage) πŸ† {{ __('ui.group_visit_recap_open') }} @endif {{ __('ui.group_visit_open_map') }} {{ __('ui.group_visit_park_page') }}
@if(session('group_status'))
{{ session('group_status') }}
@endif @if($errors->any())
{{ $errors->first() }}
@endif
{{ $acceptedMembers->count() }} {{ __('ui.group_visit_going') }}
{{ $pendingMembers->count() }} {{ __('ui.group_visit_waiting') }}
{{ $declinedMembers->count() }} {{ __('ui.group_visit_not_going') }}
{{ $acceptedMembers->count() + $pendingMembers->count() + $declinedMembers->count() }} {{ __('ui.group_visit_total_invited') }}
@if($visit->status === 'planned' && !$isPast)
{{ __('ui.group_visit_your_status_kicker') }}

{{ __('ui.group_visit_your_status_title') }}

@if($currentVisitMember?->invitation_status === 'accepted') {{ __('ui.group_visit_status_accepted_help') }} @elseif($currentVisitMember?->invitation_status === 'declined') {{ __('ui.group_visit_status_declined_help') }} @else {{ __('ui.group_visit_status_pending_help') }} @endif

@if($currentVisitMember?->invitation_status !== 'accepted')
@csrf
@else βœ“ {{ __('ui.group_visit_you_are_going') }} @endif @if($currentVisitMember?->invitation_status !== 'declined')
@csrf
@else {{ __('ui.group_visit_you_declined') }} @endif @if($isVisitDay && $currentVisitMember?->invitation_status === 'accepted')
user()->is_admin) data-gps-required data-gps-kind="visit" data-gps-loading="{{ __('ui.gps_locating') }}" data-gps-unavailable="{{ __('ui.gps_unavailable') }}" data-gps-denied="{{ __('ui.gps_permission_denied') }}" data-gps-timeout="{{ __('ui.gps_timeout') }}" data-gps-error="{{ __('ui.gps_error') }}" @endif> @csrf
@endif
@endif
{{ __('ui.group_visit_teams_kicker') }}

{{ __('ui.group_visit_teams_title') }}

{{ __('ui.group_visit_teams_intro') }}

{{ trans_choice('ui.group_visit_teams_count', $visitTeams->count(), ['count' => $visitTeams->count()]) }} @if($canManage && $visit->status === 'planned' && !$isPast)
{{ __('ui.group_visit_teams_create_button') }}
@csrf
@elseif($visit->status !== 'planned' || $isPast) {{ __('ui.group_visit_teams_readonly') }} @endif
@if($errors->has('team_name') || $errors->has('team_emoji') || $errors->has('team_note'))
{{ $errors->first() }}
@endif @if($visitTeams->isNotEmpty())
@foreach($visitTeams as $team) @php $isCurrentTeam = $currentTeamAssignment?->team_id === $team->id; $teamMemberCount = $team->members->count(); @endphp
{{ __('ui.group_visit_teams_team_label') }}

{{ $team->name }}

{{ trans_choice('ui.group_visit_teams_members_count', $teamMemberCount, ['count' => $teamMemberCount]) }}
@if($team->note)

{{ $team->note }}

@endif
@forelse($team->members as $teamMembership) @php $teamUser = $teamMembership->user; $teamUserName = $teamUser?->username ? '@'.$teamUser->username : ($teamUser?->name ?: __('ui.group_visit_chat_unknown_user')); @endphp {{ mb_strtoupper(mb_substr($teamUserName ?: '?', 0, 1)) }} {{ $teamUserName }} @empty {{ __('ui.group_visit_teams_no_members') }} @endforelse
@if($currentVisitMember?->invitation_status === 'accepted' && $visit->status === 'planned' && !$isPast)
@if($isCurrentTeam) βœ“ {{ __('ui.group_visit_teams_my_team') }}
@csrf @method('DELETE')
@else
@csrf
@endif
@endif @if($canManage && $visit->status === 'planned' && !$isPast)
{{ __('ui.group_visit_teams_manage_team') }}
@csrf @method('PUT')
@csrf @method('DELETE')
@endif
@endforeach
@if($canManage && $visit->status === 'planned' && !$isPast && $acceptedMembers->isNotEmpty())
{{ __('ui.group_visit_teams_assignment_title') }} {{ __('ui.group_visit_teams_assignment_intro') }}
@foreach($acceptedMembers as $acceptedMember) @php $acceptedUser = $acceptedMember->user; $acceptedName = $acceptedUser?->username ? '@'.$acceptedUser->username : ($acceptedUser?->name ?: $acceptedMember->display_name); $acceptedAssignment = $teamAssignmentsByUser->get($acceptedMember->user_id); @endphp
@csrf
{{ mb_strtoupper(mb_substr($acceptedName ?: '?', 0, 1)) }}
{{ $acceptedName }} {{ $acceptedAssignment?->team?->name ?? __('ui.group_visit_teams_unassigned') }}
@endforeach
@endif @else
{{ __('ui.group_visit_teams_empty_title') }}

{{ __('ui.group_visit_teams_empty') }}

@endif
{{ __('ui.group_visit_program_kicker') }}

{{ __('ui.group_visit_program_title') }}

{{ __('ui.group_visit_program_intro') }}

{{ trans_choice('ui.group_visit_program_count', $programItems->count(), ['count' => $programItems->count()]) }} @if($canManage && $visit->status === 'planned' && !$isPast)
has('program_title') || $errors->has('item_type') || $errors->has('scheduled_at') || $errors->has('program_note')) open @endif> {{ __('ui.group_visit_program_add_button') }}
@csrf
@elseif($visit->status !== 'planned' || $isPast) {{ __('ui.group_visit_program_readonly') }} @endif
@if($programItems->isNotEmpty())
@foreach($programItems as $programIndex => $programItem) @php $programAttraction = $programItem->attraction; $programAttractionTranslation = $programAttraction?->translations?->firstWhere('locale', app()->getLocale()) ?? $programAttraction?->translations?->firstWhere('locale', 'en'); $programAttractionName = $programAttractionTranslation?->name ?: $programAttraction?->official_name; $programStatus = in_array($programItem->status, ['todo', 'in_progress', 'done', 'skipped'], true) ? $programItem->status : 'todo'; $programType = in_array($programItem->item_type, ['attraction', 'meal', 'break', 'meetup', 'custom'], true) ? $programItem->item_type : 'custom'; $programLive = $programAttraction?->liveStatus; $programLiveStatus = strtolower((string) ($programLive?->operational_status ?: 'unknown')); $programLiveStatus = in_array($programLiveStatus, ['operating', 'closed', 'down', 'refurbishment', 'unknown'], true) ? $programLiveStatus : 'unknown'; $programTime = $programItem->scheduled_at?->timezone($park->timezone ?: config('app.timezone')); $programHasMultipleDays = $visit->ends_on && !$visit->ends_on->equalTo($visit->starts_on); @endphp
@if($programTime) {{ $programTime->format('H:i') }} @if($programHasMultipleDays){{ $programTime->format('d/m') }}@endif @else β€” {{ __('ui.group_visit_program_flexible') }} @endif
{{ __('ui.group_visit_program_type_'.$programType) }}

{{ $programItem->title }}

{{ $programStatusIcons[$programStatus] ?? 'β—‹' }} {{ __('ui.group_visit_program_status_'.$programStatus) }}
@if($programAttraction) @endif
@if($programItem->team) πŸ‘₯ {{ $programItem->team->emoji }} {{ $programItem->team->name }} @else πŸ‘₯ {{ __('ui.group_visit_program_everyone') }} @endif @if($programAttraction && $programAttractionName !== $programItem->title) 🎑 {{ $programAttractionName }} @endif @if($programAttraction) wait_time_minutes === null) hidden @endif> @if($programLive && $programLive->wait_time_minutes !== null && $programLive->wait_time_minutes > 0) ⏱ {{ $programLive->wait_time_minutes }} min @elseif($programLive && $programLive->wait_time_minutes === 0) ⏱ {{ __('ui.live_wait_unconfirmed') }} @endif wait_time_minutes !== null) hidden @endif>● {{ $programLive ? __('ui.group_visit_program_live_'.$programLiveStatus) : __('ui.live_status_unknown') }} @endif
@if($programItem->note)

{{ $programItem->note }}

@endif @if($currentVisitMember?->invitation_status === 'accepted' && $programAttraction && $programTime && $programTime->isFuture() && in_array($programStatus, ['todo', 'in_progress'], true))
@csrf
@endif @if($canManage && $visit->status === 'planned' && !$isPast)
@csrf @foreach(['todo', 'in_progress', 'done', 'skipped'] as $statusOption) @endforeach
@if(!$loop->first)
@csrf
@endif @if(!$loop->last)
@csrf
@endif
{{ __('ui.group_visit_program_manage') }}
@csrf @method('PUT')
@csrf @method('DELETE')
@endif
@endforeach
@else
{{ __('ui.group_visit_program_empty_title') }}

{{ __('ui.group_visit_program_empty') }}

@endif
@if(session('ride_together_status'))
{{ session('ride_together_status') }}
@endif @if($errors->has('ride_together') || $errors->has('attraction_id') || $errors->has('visibility_scope') || $errors->has('scheduled_for'))
{{ $errors->first() }}
@endif
{{ __('ui.ride_together_v2_kicker') }}

{{ __('ui.ride_together_v2_group_title') }}

{{ __('ui.ride_together_v2_group_intro') }}

🎒 {{ $rideTogetherPosts->count() }} @if($currentVisitMember?->invitation_status === 'accepted' && in_array($visit->status, ['planned', 'active'], true) && !$isPast)
has('attraction_id') || $errors->has('scheduled_for') || $errors->has('visibility_scope')) open @endif> {{ __('ui.ride_together_v2_create_button') }}
@csrf
@endif
@if($rideTogetherPosts->isNotEmpty())
@foreach($rideTogetherPosts as $ridePost) @php $rideTranslation = $ridePost->attraction?->translations?->firstWhere('locale', app()->getLocale()) ?? $ridePost->attraction?->translations?->firstWhere('locale', 'en'); $rideName = $rideTranslation?->name ?: $ridePost->attraction?->official_name ?: __('ui.ride_together_attraction'); $rideTime = $ridePost->scheduled_for?->timezone($park->timezone ?: config('app.timezone')); $joinedParticipants = $ridePost->participants->where('status', 'joined'); $isJoined = $joinedParticipants->contains('user_id', auth()->id()); $isOwner = $ridePost->created_by_user_id === auth()->id(); $isFull = $ridePost->max_participants && $joinedParticipants->count() >= $ridePost->max_participants; $scopeKey = in_array($ridePost->visibility_scope, ['public', 'group', 'team'], true) ? $ridePost->visibility_scope : 'group'; @endphp
{{ __('ui.ride_together_v2_scope_'.$scopeKey) }}@if($scopeKey === 'team' && $ridePost->team) Β· {{ $ridePost->team->emoji }} {{ $ridePost->team->name }}@endif

{{ $rideName }}

{{ $rideTime?->format('H:i') ?: 'β€”' }}{{ $rideTime?->format('d/m') }}
πŸ‘€ {{ $ridePost->creator?->username ? '@'.$ridePost->creator->username : ($ridePost->creator?->name ?: 'β€”') }} πŸ‘₯ {{ $joinedParticipants->count() }} / {{ $ridePost->max_participants ?: '∞' }} @if($ridePost->meeting_point)πŸ“ {{ $ridePost->meeting_point }}@endif @if($ridePost->programItem)☷ {{ __('ui.ride_together_v2_from_roadbook') }}@endif
@if($ridePost->note)

{{ $ridePost->note }}

@endif
@foreach($joinedParticipants->take(8) as $participant) @php $participantName = $participant->user?->username ? '@'.$participant->user->username : ($participant->user?->name ?: '?'); @endphp {{ mb_strtoupper(mb_substr(ltrim($participantName, '@'), 0, 1)) }} @endforeach
@if($isOwner) βœ“ {{ __('ui.ride_together_yours') }}
@csrf @method('DELETE')
@elseif($isJoined) βœ“ {{ __('ui.ride_together_you_joined') }}
@csrf @method('DELETE')
@elseif(!$isFull)
@csrf
@else {{ __('ui.ride_together_full_label') }} @endif
@endforeach
@else
{{ __('ui.ride_together_v2_empty_title') }}

{{ __('ui.ride_together_v2_group_empty') }}

@endif
{{ __('ui.group_visit_challenge_kicker') }}

{{ __('ui.group_visit_challenge_title') }}

{{ __('ui.group_visit_challenge_intro') }}

{{ trans_choice('ui.group_visit_challenge_count', $visitChallenges->count(), ['count' => $visitChallenges->count()]) }} @if($canManage && $visit->status === 'planned' && !$isPast)
has('challenge_name') || $errors->has('challenge_type') || $errors->has('target_score')) open @endif> {{ __('ui.group_visit_challenge_create_button') }}
@csrf
@endif
@if($visitChallenges->isNotEmpty())
@foreach($visitChallenges as $challenge) @php $challengeTarget = max(1, (int) data_get($challenge->rules, 'target_score', 1)); $challengeParticipants = $challenge->participants ->filter(fn ($participant) => in_array($participant->status, ['accepted', 'active', 'completed'], true)) ->sortByDesc('score') ->values(); $myChallengeParticipant = $challenge->participants->first(fn ($participant) => $participant->user_id === auth()->id() && in_array($participant->status, ['accepted', 'active', 'completed'], true)); $challengeEnded = !in_array($challenge->status, ['active', 'running'], true) || $challenge->ends_at?->isPast() || $visit->status !== 'planned' || $isPast; $challengeTypeIcon = $challenge->challenge_type === 'coasters' ? '🎒' : '🎑'; $leaderScore = (int) ($challengeParticipants->max('score') ?? 0); @endphp
{{ __('ui.group_visit_challenge_type_'.$challenge->challenge_type) }}

{{ $challenge->name }}

{{ $challengeEnded ? __('ui.group_visit_challenge_closed_label') : __('ui.group_visit_challenge_open_label') }}
{{ __('ui.group_visit_challenge_goal') }} {{ $challengeTarget }}
{{ __('ui.group_visit_challenge_participants') }} {{ $challengeParticipants->count() }}
{{ __('ui.group_visit_challenge_best_score') }} {{ $leaderScore }}
@if($myChallengeParticipant) @php $myChallengeScore = (int) $myChallengeParticipant->score; $myChallengeProgress = min(100, (int) round(($myChallengeScore / $challengeTarget) * 100)); @endphp
{{ __('ui.group_visit_challenge_your_progress') }} {{ $myChallengeScore }} / {{ $challengeTarget }}
@if($myChallengeParticipant->status === 'completed') πŸ† {{ __('ui.group_visit_challenge_completed') }} @endif
@endif
{{ __('ui.group_visit_challenge_ranking') }} @forelse($challengeParticipants->take(8) as $challengeParticipant) @php $challengeUserName = $challengeParticipant->user?->username ? '@'.$challengeParticipant->user->username : ($challengeParticipant->user?->name ?: __('ui.group_visit_chat_unknown_user')); $challengeRank = $loop->iteration; @endphp
{{ $challengeRank <= 3 ? ['πŸ₯‡','πŸ₯ˆ','πŸ₯‰'][$challengeRank - 1] : '#'.$challengeRank }} {{ $challengeUserName }} @if($challengeParticipant->team_key) {{ $challengeParticipant->team_key }} @endif {{ $challengeParticipant->score }}
@empty

{{ __('ui.group_visit_challenge_no_participants') }}

@endforelse
@if(!$challengeEnded && $currentVisitMember?->invitation_status === 'accepted') @if(!$myChallengeParticipant)
@csrf
@elseif($myChallengeParticipant->status !== 'completed')
@csrf @method('DELETE')
@endif @endif @if($canManage && !$challengeEnded)
@csrf
@endif
@endforeach
@else
{{ __('ui.group_visit_challenge_empty_title') }}

{{ __('ui.group_visit_challenge_empty') }}

@endif
@if($currentVisitMember?->invitation_status === 'accepted')
{{ __('ui.group_visit_chat_kicker') }}

{{ __('ui.group_visit_chat_title') }}

{{ __('ui.group_visit_chat_intro') }}

πŸ”’ {{ __('ui.group_visit_chat_private') }}
@if(session('social_report_status'))
βœ“ {{ session('social_report_status') }}
@endif
@forelse($tripMessages as $tripMessage) @php $tripAuthorName = $tripMessage->user?->username ? '@'.$tripMessage->user->username : ($tripMessage->user?->name ?: __('ui.group_visit_chat_unknown_user')); $isOwnTripMessage = $tripMessage->user_id === auth()->id(); $canDeleteTripMessage = !$tripMessage->trashed() && ($isOwnTripMessage || $canManage); @endphp
{{ $tripAuthorName }}
@if($tripMessage->trashed())

{{ __('ui.group_visit_chat_removed') }}

@else

{{ $tripMessage->body }}

@endif
@if($canDeleteTripMessage)
@csrf @method('DELETE')
@endif @if(!$tripMessage->trashed() && !$isOwnTripMessage)
{{ __('ui.social_report_short') }}
@endif
@empty
{{ __('ui.group_visit_chat_empty_title') }} {{ __('ui.group_visit_chat_empty') }}
@endforelse
@if($visit->status !== 'cancelled')
@csrf
@else
{{ __('ui.group_visit_chat_closed') }}
@endif
@endif
{{ __('ui.meetup_kicker') }}

{{ __('ui.meetup_title') }}

{{ __('ui.meetup_intro') }}

@if($currentVisitMember?->invitation_status === 'accepted' && $visit->status === 'planned' && !$isPast) @endif
@if($currentVisitMember?->invitation_status === 'accepted' && $visit->status === 'planned' && !$isPast) @endif @if($errors->has('title') || $errors->has('scheduled_at') || $errors->has('attraction_id') || $errors->has('note'))
{{ $errors->first() }}
@endif @if($meetups->isNotEmpty())
@foreach($meetups as $meetup) @php $meetupAttraction = $meetup->attraction; $meetupAttractionTranslation = $meetupAttraction?->translations?->firstWhere('locale', app()->getLocale()) ?? $meetupAttraction?->translations?->firstWhere('locale', 'en'); $meetupAttractionName = $meetupAttractionTranslation?->name ?: $meetupAttraction?->official_name; $currentMeetupParticipant = $meetup->participants->firstWhere('user_id', auth()->id()); $meetupAccepted = $meetup->participants->where('status', 'accepted')->count(); $meetupPending = $meetup->participants->where('status', 'invited')->count(); $meetupDeclined = $meetup->participants->where('status', 'declined')->count(); $meetupPast = $meetup->scheduled_at?->lt(now($park->timezone)); $canCancelMeetup = $meetup->created_by_user_id === auth()->id() || $canManage; @endphp
{{ $meetup->scheduled_at?->timezone($park->timezone)->format('H:i') }} {{ $meetup->scheduled_at?->timezone($park->timezone)->format('d/m') }}
{{ $meetupPast ? __('ui.meetup_past') : __('ui.meetup_scheduled') }}

{{ $meetup->title }}

@if($meetupAttraction) {{ $meetupAttractionName }} @else {{ __('ui.meetup_park_meeting_point') }} @endif @if($meetup->note)

{{ $meetup->note }}

@endif {{ __('ui.meetup_created_by', ['name' => $meetup->creator?->username ? '@'.$meetup->creator->username : $meetup->creator?->name]) }}
{{ $meetupAccepted }}{{ __('ui.meetup_coming') }}
{{ $meetupPending }}{{ __('ui.meetup_waiting') }}
{{ $meetupDeclined }}{{ __('ui.meetup_not_coming') }}
@if(!$meetupPast)
@if($currentVisitMember?->invitation_status === 'accepted') @if($currentMeetupParticipant?->status !== 'accepted')
@csrf
@else βœ“ {{ __('ui.meetup_you_are_coming') }} @endif @if($currentMeetupParticipant?->status !== 'declined')
@csrf
@endif @endif @if($canCancelMeetup)
@csrf @method('DELETE')
@endif
@endif
@foreach($meetup->participants->where('status', 'accepted')->take(6) as $participant) @php $participantName = $participant->user?->username ? '@'.$participant->user->username : $participant->user?->name; @endphp {{ mb_strtoupper(mb_substr($participantName ?: '?', 0, 1)) }} @endforeach @if($meetupAccepted > 6) +{{ $meetupAccepted - 6 }} @endif
@endforeach
@else
{{ __('ui.meetup_empty') }}
@endif
{{ __('ui.group_visit_participants_kicker') }}

{{ __('ui.group_visit_participants_title') }}

{{ __('ui.group_visit_participants_intro') }}

@foreach($visit->members as $membership) @php $member = $membership->user; $displayName = $member?->username ? '@'.$member->username : ($member?->name ?: $membership->display_name); $statusClass = match($membership->invitation_status) { 'accepted' => 'is-accepted', 'declined' => 'is-declined', default => 'is-pending', }; @endphp
{{ mb_strtoupper(mb_substr($displayName ?: '?', 0, 1)) }}
{{ $displayName }} {{ $membership->role === 'organizer' ? __('ui.group_visit_role_organizer') : __('ui.group_visit_role_participant') }}
{{ $membership->invitation_status === 'accepted' ? __('ui.group_visit_status_accepted') : ($membership->invitation_status === 'declined' ? __('ui.group_visit_status_declined') : __('ui.group_visit_status_pending')) }}
@endforeach
@endsection