mirror of
https://github.com/HolgerHatGarKeineNode/einundzwanzig-app.git
synced 2025-12-14 12:06:46 +00:00
✨ Add dynamic meetup popup component and enrich map with detailed data
- Added `meetup-popup` Blade component to display detailed meetup information. - Updated map markers to show custom popup HTML with event and contact links. - Enhanced map query with additional fields and upcoming event details. - Styled Leaflet popups for better appearance.
This commit is contained in:
@@ -64,3 +64,11 @@ select:focus[data-flux-control] {
|
|||||||
/* \[:where(&)\]:size-4 {
|
/* \[:where(&)\]:size-4 {
|
||||||
@apply size-4;
|
@apply size-4;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
.leaflet-popup-content-wrapper {
|
||||||
|
background-color: #404040!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-container a {
|
||||||
|
color: unset!important;
|
||||||
|
}
|
||||||
|
|||||||
92
resources/views/components/meetup-popup.blade.php
Normal file
92
resources/views/components/meetup-popup.blade.php
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
@props(['meetup', 'url', 'eventUrl' => null])
|
||||||
|
|
||||||
|
<div class="w-72">
|
||||||
|
<flux:heading size="lg" class="mb-3">{{ $meetup->name }}</flux:heading>
|
||||||
|
|
||||||
|
@if($meetup->intro)
|
||||||
|
<flux:text class="text-sm text-zinc-600 dark:text-zinc-400 mb-3">
|
||||||
|
{{ Str::limit($meetup->intro, 100) }}
|
||||||
|
</flux:text>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($meetup->nextEvent)
|
||||||
|
<flux:separator variant="subtle" class="my-3"/>
|
||||||
|
|
||||||
|
<flux:subheading class="mb-2">{{ __('Nächster Termin') }}</flux:subheading>
|
||||||
|
|
||||||
|
<div class="space-y-1">
|
||||||
|
<flux:text class="text-sm flex items-center gap-2">
|
||||||
|
<flux:icon.calendar class="w-4 h-4"/>
|
||||||
|
{{ $meetup->nextEvent['start']->format('d.m.Y') }}
|
||||||
|
</flux:text>
|
||||||
|
|
||||||
|
<flux:text class="text-sm flex items-center gap-2">
|
||||||
|
<flux:icon.clock class="w-4 h-4"/>
|
||||||
|
{{ $meetup->nextEvent['start']->format('H:i') }} Uhr
|
||||||
|
</flux:text>
|
||||||
|
|
||||||
|
@if($meetup->nextEvent['location'])
|
||||||
|
<flux:text class="text-sm flex items-center gap-2">
|
||||||
|
<flux:icon.map-pin class="w-4 h-4"/>
|
||||||
|
{{ $meetup->nextEvent['location'] }}
|
||||||
|
</flux:text>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($meetup->telegram_link || $meetup->webpage || $meetup->twitter_username || $meetup->matrix_group || $meetup->nostr || $meetup->simplex || $meetup->signal)
|
||||||
|
<flux:separator variant="subtle" class="my-3"/>
|
||||||
|
|
||||||
|
<div class="flex gap-2 flex-wrap text-white">
|
||||||
|
@if($meetup->telegram_link)
|
||||||
|
<flux:link :href="$meetup->telegram_link" external variant="subtle" title="{{ __('Telegram') }}">
|
||||||
|
<flux:icon.paper-airplane variant="mini"/>
|
||||||
|
</flux:link>
|
||||||
|
@endif
|
||||||
|
@if($meetup->webpage)
|
||||||
|
<flux:link :href="$meetup->webpage" external variant="subtle" title="{{ __('Website') }}">
|
||||||
|
<flux:icon.globe-alt variant="mini"/>
|
||||||
|
</flux:link>
|
||||||
|
@endif
|
||||||
|
@if($meetup->twitter_username)
|
||||||
|
<flux:link :href="'https://twitter.com/' . $meetup->twitter_username" external variant="subtle" title="{{ __('Twitter') }}">
|
||||||
|
<flux:icon.x-mark variant="mini"/>
|
||||||
|
</flux:link>
|
||||||
|
@endif
|
||||||
|
@if($meetup->matrix_group)
|
||||||
|
<flux:link :href="$meetup->matrix_group" external variant="subtle" title="{{ __('Matrix') }}">
|
||||||
|
<flux:icon.chat-bubble-left variant="mini"/>
|
||||||
|
</flux:link>
|
||||||
|
@endif
|
||||||
|
@if($meetup->nostr)
|
||||||
|
<flux:link :href="'https://njump.me/'.$meetup->nostr" external variant="subtle" title="{{ __('Nostr') }}">
|
||||||
|
<flux:icon.bolt variant="mini"/>
|
||||||
|
</flux:link>
|
||||||
|
@endif
|
||||||
|
@if($meetup->simplex)
|
||||||
|
<flux:link :href="$meetup->simplex" external variant="subtle" title="{{ __('Simplex') }}">
|
||||||
|
<flux:icon.chat-bubble-bottom-center-text variant="mini"/>
|
||||||
|
</flux:link>
|
||||||
|
@endif
|
||||||
|
@if($meetup->signal)
|
||||||
|
<flux:link :href="$meetup->signal" external variant="subtle" title="{{ __('Signal') }}">
|
||||||
|
<flux:icon.shield-check variant="mini"/>
|
||||||
|
</flux:link>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<flux:separator variant="subtle" class="my-3"/>
|
||||||
|
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<flux:button :href="$url" size="sm" variant="primary">
|
||||||
|
{{ __('Details') }}
|
||||||
|
</flux:button>
|
||||||
|
|
||||||
|
@if($eventUrl)
|
||||||
|
<flux:button :href="$eventUrl" size="sm" variant="primary">
|
||||||
|
{{ __('Nächster Termin') }}
|
||||||
|
</flux:button>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -29,13 +29,56 @@ class extends Component {
|
|||||||
public function with(): array
|
public function with(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'meetups' => Meetup::with(['city:id,longitude,latitude'])
|
'meetups' => Meetup::query()
|
||||||
->select([
|
->select([
|
||||||
'meetups.id',
|
'meetups.id',
|
||||||
'meetups.city_id',
|
'meetups.city_id',
|
||||||
'meetups.name',
|
'meetups.name',
|
||||||
|
'meetups.slug',
|
||||||
|
'meetups.intro',
|
||||||
|
'meetups.telegram_link',
|
||||||
|
'meetups.webpage',
|
||||||
|
'meetups.twitter_username',
|
||||||
|
'meetups.matrix_group',
|
||||||
|
'meetups.nostr',
|
||||||
|
'meetups.simplex',
|
||||||
|
'meetups.signal',
|
||||||
])
|
])
|
||||||
->get(),
|
->with(['city:id,country_id,longitude,latitude'])
|
||||||
|
->get()
|
||||||
|
->map(function ($meetup) {
|
||||||
|
$meetup->load(['meetupEvents' => function($query) {
|
||||||
|
$query->where('start', '>=', now())
|
||||||
|
->orderBy('start')
|
||||||
|
->limit(1);
|
||||||
|
}]);
|
||||||
|
|
||||||
|
$nextEvent = $meetup->meetupEvents->first();
|
||||||
|
$eventUrl = null;
|
||||||
|
|
||||||
|
if ($nextEvent) {
|
||||||
|
$eventUrl = route('meetups.landingpage-event', [
|
||||||
|
'country' => $meetup->city->country,
|
||||||
|
'meetup' => $meetup->slug,
|
||||||
|
'event' => $nextEvent->id
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => $meetup->id,
|
||||||
|
'name' => $meetup->name,
|
||||||
|
'slug' => $meetup->slug,
|
||||||
|
'city' => $meetup->city,
|
||||||
|
'popupHtml' => view('components.meetup-popup', [
|
||||||
|
'meetup' => $meetup,
|
||||||
|
'url' => route('meetups.landingpage', [
|
||||||
|
'country' => $meetup->city->country,
|
||||||
|
'meetup' => $meetup->slug
|
||||||
|
]),
|
||||||
|
'eventUrl' => $eventUrl
|
||||||
|
])->render(),
|
||||||
|
];
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}; ?>
|
}; ?>
|
||||||
@@ -85,7 +128,7 @@ class extends Component {
|
|||||||
L.marker([marker.city.latitude, marker.city.longitude], {
|
L.marker([marker.city.latitude, marker.city.longitude], {
|
||||||
icon: btcIcon
|
icon: btcIcon
|
||||||
})
|
})
|
||||||
.bindPopup(marker.name)
|
.bindPopup(marker.popupHtml)
|
||||||
.addTo(map);
|
.addTo(map);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user