197 lines
11 KiB
PHP
197 lines
11 KiB
PHP
<div class="online-reacted-profiles" wire:poll.{{ $refreshInterval }}s="loadOnlineReactedProfiles">
|
|
|
|
{{-- Header with count --}}
|
|
@if ($headerText && $showCount && $totalCount > 0)
|
|
<div class="mb-4 flex items-center justify-between">
|
|
<div class="flex items-center space-x-2 text-xs text-theme-muted">
|
|
<div class="h-2 w-2 rounded-full bg-green-500"></div>
|
|
<span class="font-sm">
|
|
{{ $headerText }}
|
|
</span>
|
|
</div>
|
|
|
|
{{-- Count by type if multiple guards --}}
|
|
@if (count($countByType) > 1)
|
|
<div class="flex items-center space-x-3 text-xs text-theme-muted">
|
|
@foreach ($countByType as $type => $count)
|
|
<span class="ml-2">
|
|
{{ __($modelLabels[$type]) ?? __(class_basename($type)) }}: {{ $count }}
|
|
</span>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
|
|
{{-- Profiles Display --}}
|
|
@if ($groupByModel && is_array($onlineReactedProfiles))
|
|
{{-- Grouped by Model Type --}}
|
|
@foreach ($onlineReactedProfiles as $modelType => $profiles)
|
|
<div class="grouped-profiles mb-6">
|
|
<h3 class="mb-3 text-sm font-medium text-theme-primary border-l-4 border-theme-border pl-3">
|
|
{{ __($modelLabels[$modelType]) ?? __(class_basename($modelType)) }}
|
|
</h3>
|
|
|
|
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-3">
|
|
@foreach ($profiles as $profile)
|
|
<div class="profile-card">
|
|
<a href="{{ $profile['profile_url'] }}" class="block">
|
|
<div class="flex items-center p-2 rounded-lg hover:bg-gray-50 transition-colors duration-150">
|
|
<div class="flex-shrink-0">
|
|
<div class="relative block cursor-pointer">
|
|
<img alt="profile"
|
|
class="h-8 w-8 rounded-full object-cover outline outline-1 outline-offset-1 outline-gray-500"
|
|
src="{{ Storage::url($profile['avatar']) }}" />
|
|
</div>
|
|
</div>
|
|
<div class="ml-3 min-w-0 flex-1">
|
|
<div class="font-bold text-sm text-theme-primary truncate">
|
|
{{ $profile['name'] }}
|
|
</div>
|
|
<div class="text-xs font-normal text-theme-muted truncate">
|
|
{{ $profile['location'] }}
|
|
</div>
|
|
@if ($lastSeen)
|
|
<div class="text-xs text-theme-muted truncate">
|
|
@if ($profile['last_seen'])
|
|
{{ \Carbon\Carbon::parse($profile['last_seen'])->diffForHumans() }}
|
|
@else
|
|
{{ __('online') }}
|
|
@endif
|
|
</div>
|
|
@endif
|
|
@if (getActiveProfileType() === 'Admin' && !$this->isCurrentUserProfile($profile['id'], $profile['model_type']))
|
|
<button wire:click="openLogoutModal({{ $profile['id'] }}, '{{ addslashes($profile['model_type']) }}')"
|
|
class="text-xs text-red-600 hover:text-red-800 underline mt-1"
|
|
onclick="event.preventDefault(); event.stopPropagation();">
|
|
{{ __('Log out') }}
|
|
</button>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
@else
|
|
{{-- Not grouped --}}
|
|
@if(count($onlineReactedProfiles) > 0)
|
|
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-3">
|
|
@foreach($onlineReactedProfiles as $profile)
|
|
<div class="profile-card">
|
|
<a href="{{ $profile['profile_url'] }}" class="block">
|
|
<div class="flex items-center p-2 rounded-lg hover:bg-gray-50 transition-colors duration-150">
|
|
<div class="flex-shrink-0">
|
|
<div class="relative block cursor-pointer">
|
|
<img alt="profile"
|
|
class="h-8 w-8 rounded-full object-cover outline outline-1 outline-offset-1 outline-gray-500"
|
|
src="{{ Storage::url($profile['avatar']) }}" />
|
|
</div>
|
|
</div>
|
|
<div class="ml-3 min-w-0 flex-1">
|
|
<div class="font-bold text-sm text-theme-primary truncate">
|
|
{{ $profile['name'] }}
|
|
</div>
|
|
<div class="text-xs font-normal text-theme-muted truncate">
|
|
{{ $profile['location'] }}
|
|
</div>
|
|
@if ($lastSeen)
|
|
<div class="text-xs text-theme-muted truncate">
|
|
@if ($profile['last_seen'])
|
|
{{ \Carbon\Carbon::parse($profile['last_seen'])->diffForHumans() }}
|
|
@else
|
|
{{ __('online') }}
|
|
@endif
|
|
</div>
|
|
@endif
|
|
@if (getActiveProfileType() === 'Admin' && !$this->isCurrentUserProfile($profile['id'], $profile['model_type']))
|
|
<button wire:click="openLogoutModal({{ $profile['id'] }}, '{{ addslashes($profile['model_type']) }}')"
|
|
class="text-xs text-red-600 hover:text-red-800 underline mt-1"
|
|
onclick="event.preventDefault(); event.stopPropagation();">
|
|
{{ __('Log out') }}
|
|
</button>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@else
|
|
<div class="mb-4 flex items-center justify-between">
|
|
<div class="flex items-center space-x-2 text-sm text-theme-muted">
|
|
<span class="font-sm">
|
|
{{trans_choice('messages.reactions_contacts_online', 0, ['count' => 0]) }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
@endif
|
|
|
|
{{-- Logout Confirmation Modal --}}
|
|
@if (getActiveProfileType() === 'Admin')
|
|
<x-jetstream.dialog-modal wire:model.live="showLogoutModal">
|
|
<x-slot name="title">
|
|
{{ __('Log out user') }}
|
|
</x-slot>
|
|
|
|
<x-slot name="content">
|
|
<div class="text-base mb-4">{{ __('Are you sure you want to log out this user?') }}</div>
|
|
@if ($selectedProfileId && $selectedProfileType)
|
|
@php
|
|
$selectedProfile = $selectedProfileType::find($selectedProfileId);
|
|
@endphp
|
|
@if ($selectedProfile)
|
|
<div class="flex items-center p-2">
|
|
<div class="flex-shrink-0">
|
|
<div class="relative block">
|
|
<img alt="profile"
|
|
class="h-8 w-8 rounded-full profile-photo object-cover outline outline-1 outline-offset-1 outline-gray-500"
|
|
src="{{ Storage::url($selectedProfile->profile_photo_path) }}" />
|
|
</div>
|
|
</div>
|
|
<div class="ml-3 min-w-0 flex-1">
|
|
<div class="font-bold text-sm text-theme-primary truncate">
|
|
{{ $selectedProfile->name }}
|
|
</div>
|
|
<div class="text-xs font-normal text-theme-muted truncate">
|
|
{{ $selectedProfile->getLocationFirst()['name_short'] ?? '' }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
@endif
|
|
</x-slot>
|
|
|
|
<x-slot name="footer">
|
|
<x-jetstream.secondary-button wire:click="closeLogoutModal">
|
|
{{ __('Cancel') }}
|
|
</x-jetstream.secondary-button>
|
|
|
|
<x-jetstream.danger-button wire:click="logoutUser" wire:loading.attr="disabled" class="ml-3">
|
|
<span wire:loading.remove wire:target="logoutUser">{{ __('Log out') }}</span>
|
|
<span wire:loading wire:target="logoutUser">{{ __('Loading...') }}</span>
|
|
</x-jetstream.danger-button>
|
|
</x-slot>
|
|
</x-jetstream.dialog-modal>
|
|
@endif
|
|
</div>
|
|
|
|
{{-- Include JavaScript for real-time updates --}}
|
|
@push('scripts')
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Listen for presence updates from other components
|
|
window.addEventListener('presence-channel-updated', function(event) {
|
|
@this.call('loadOnlineReactedProfiles');
|
|
});
|
|
|
|
// Listen for reaction changes
|
|
window.addEventListener('reaction-toggled', function(event) {
|
|
@this.call('loadOnlineReactedProfiles');
|
|
});
|
|
});
|
|
</script>
|
|
@endpush |