mirror of
https://github.com/pacnpal/thrillwiki_laravel.git
synced 2025-12-20 05:31:10 -05:00
206 lines
9.3 KiB
PHP
206 lines
9.3 KiB
PHP
<div>
|
|
<div class="space-y-4">
|
|
<!-- Mode Switcher -->
|
|
<div class="flex space-x-2 mb-4">
|
|
<button
|
|
wire:click="switchMode('search')"
|
|
class="px-4 py-2 text-sm rounded-lg {{ $mode === 'search' ? 'bg-blue-600 text-white' : 'bg-gray-100 hover:bg-gray-200' }}"
|
|
>
|
|
<span class="flex items-center">
|
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
</svg>
|
|
Search
|
|
</span>
|
|
</button>
|
|
<button
|
|
wire:click="switchMode('coordinates')"
|
|
class="px-4 py-2 text-sm rounded-lg {{ $mode === 'coordinates' ? 'bg-blue-600 text-white' : 'bg-gray-100 hover:bg-gray-200' }}"
|
|
>
|
|
<span class="flex items-center">
|
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
</svg>
|
|
Coordinates
|
|
</span>
|
|
</button>
|
|
<button
|
|
wire:click="detectCurrentLocation"
|
|
class="px-4 py-2 text-sm rounded-lg {{ $mode === 'current' ? 'bg-blue-600 text-white' : 'bg-gray-100 hover:bg-gray-200' }}"
|
|
>
|
|
<span class="flex items-center">
|
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
</svg>
|
|
Current Location
|
|
</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Search Mode -->
|
|
@if ($mode === 'search')
|
|
<div class="relative">
|
|
<div class="relative">
|
|
<input
|
|
type="text"
|
|
wire:model.live="searchQuery"
|
|
placeholder="Search for a location..."
|
|
class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
>
|
|
@if ($isSearching)
|
|
<div class="absolute inset-y-0 right-0 flex items-center pr-3">
|
|
<svg class="w-5 h-5 text-gray-400 animate-spin" fill="none" viewBox="0 0 24 24">
|
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
</svg>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
@if ($showSearchResults && count($searchResults))
|
|
<div class="absolute z-10 w-full mt-1 bg-white rounded-lg shadow-lg">
|
|
<ul class="py-1">
|
|
@foreach ($searchResults as $result)
|
|
<li>
|
|
<button
|
|
wire:click="selectLocation({{ json_encode($result) }})"
|
|
class="w-full px-4 py-2 text-left hover:bg-gray-100"
|
|
>
|
|
{{ $result['display_name'] }}
|
|
</button>
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Coordinate Mode -->
|
|
@if ($mode === 'coordinates')
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700">Latitude</label>
|
|
<input
|
|
type="number"
|
|
step="any"
|
|
wire:model="latitude"
|
|
class="w-full px-4 py-2 mt-1 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
placeholder="Enter latitude..."
|
|
>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700">Longitude</label>
|
|
<input
|
|
type="number"
|
|
step="any"
|
|
wire:model="longitude"
|
|
class="w-full px-4 py-2 mt-1 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
placeholder="Enter longitude..."
|
|
>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Current Location Mode -->
|
|
@if ($mode === 'current')
|
|
<div class="p-4 text-center">
|
|
@if ($isLoadingLocation)
|
|
<div class="flex items-center justify-center space-x-2">
|
|
<svg class="w-5 h-5 text-blue-600 animate-spin" fill="none" viewBox="0 0 24 24">
|
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
</svg>
|
|
<span>Detecting your location...</span>
|
|
</div>
|
|
@else
|
|
<p class="text-gray-600">Click the Current Location button above to detect your location</p>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Map Component -->
|
|
@if ($latitude && $longitude)
|
|
<div class="mt-4">
|
|
<livewire:location.location-map-component
|
|
:latitude="$latitude"
|
|
:longitude="$longitude"
|
|
:interactive="true"
|
|
/>
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Error Messages -->
|
|
@if ($validationError)
|
|
<div class="p-4 mt-4 text-sm text-red-700 bg-red-100 rounded-lg">
|
|
{{ $validationError }}
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Selected Location Display -->
|
|
@if ($isValidLocation)
|
|
<div class="p-4 mt-4 bg-green-50 rounded-lg">
|
|
<h4 class="font-medium text-green-800">Selected Location</h4>
|
|
@if ($formattedAddress)
|
|
<p class="mt-1 text-sm text-green-600">{{ $formattedAddress }}</p>
|
|
@endif
|
|
<p class="mt-1 text-sm text-green-600">
|
|
Coordinates: {{ number_format($latitude, 6) }}, {{ number_format($longitude, 6) }}
|
|
</p>
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Clear Selection Button -->
|
|
@if ($isValidLocation)
|
|
<div class="flex justify-end mt-4">
|
|
<button
|
|
wire:click="clearSelection"
|
|
class="px-4 py-2 text-sm text-red-600 bg-red-100 rounded-lg hover:bg-red-200"
|
|
>
|
|
Clear Selection
|
|
</button>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<!-- JavaScript for Geolocation -->
|
|
<script>
|
|
document.addEventListener('livewire:initialized', () => {
|
|
@this.on('requestCurrentLocation', () => {
|
|
if (!navigator.geolocation) {
|
|
@this.dispatch('validationFailed', {
|
|
message: 'Geolocation is not supported by your browser'
|
|
});
|
|
return;
|
|
}
|
|
|
|
navigator.geolocation.getCurrentPosition(
|
|
(position) => {
|
|
@this.setCoordinates(
|
|
position.coords.latitude,
|
|
position.coords.longitude
|
|
);
|
|
},
|
|
(error) => {
|
|
let errorMessage = 'Failed to get your location';
|
|
switch (error.code) {
|
|
case error.PERMISSION_DENIED:
|
|
errorMessage = 'Location permission denied';
|
|
break;
|
|
case error.POSITION_UNAVAILABLE:
|
|
errorMessage = 'Location information unavailable';
|
|
break;
|
|
case error.TIMEOUT:
|
|
errorMessage = 'Location request timed out';
|
|
break;
|
|
}
|
|
@this.dispatch('validationFailed', {
|
|
message: errorMessage
|
|
});
|
|
}
|
|
);
|
|
});
|
|
});
|
|
</script>
|
|
</div> |