From 54f79309dcfa3b5ad677dbc5061dd8341b2509b8 Mon Sep 17 00:00:00 2001 From: HolgerHatGarKeineNode Date: Mon, 24 Nov 2025 16:49:53 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=8D=20Add=20Top-Countries,=20Top-Meetu?= =?UTF-8?q?ps,=20and=20Activities=20dashboard=20components?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Introduced three new Livewire components for the dashboard: - Top Countries: Displays countries with the most users. - Top Meetups: Highlights meetups with the largest user counts. - Activities: Showcases recent meetups and events. - Updated `dashboard.blade.php` to lazy-load these components. - Expanded multilingual support for relevant labels across all languages. --- lang/de.json | 13 +- lang/en.json | 13 +- lang/es.json | 13 +- lang/hu.json | 13 +- lang/nl.json | 13 +- lang/pt.json | 13 +- resources/views/livewire/dashboard.blade.php | 7 ++ .../livewire/dashboard/activities.blade.php | 114 +++++++++++++++++ .../dashboard/top-countries.blade.php | 118 ++++++++++++++++++ .../livewire/dashboard/top-meetups.blade.php | 112 +++++++++++++++++ 10 files changed, 423 insertions(+), 6 deletions(-) create mode 100644 resources/views/livewire/dashboard/activities.blade.php create mode 100644 resources/views/livewire/dashboard/top-countries.blade.php create mode 100644 resources/views/livewire/dashboard/top-meetups.blade.php diff --git a/lang/de.json b/lang/de.json index b36a247..898721e 100644 --- a/lang/de.json +++ b/lang/de.json @@ -460,5 +460,16 @@ "Über den Kurs": "", "Über uns": "", "Alle Meetups": "", - "Welt-Karte": "" + "Welt-Karte": "", + "Aktivitäten": "", + "Neue Meetups und Termine": "", + "Neues Meetup": "", + "Neuer Termin": "", + "Keine Aktivitäten": "", + "Top Länder": "", + "Länder mit den meisten Usern": "", + "User": "", + "Keine Daten verfügbar": "", + "Top Meetups": "", + "Meetups mit den meisten Usern": "" } \ No newline at end of file diff --git a/lang/en.json b/lang/en.json index 6ee6dcc..9c1fbff 100644 --- a/lang/en.json +++ b/lang/en.json @@ -460,5 +460,16 @@ "Über den Kurs": "About the course", "Über uns": "About us", "Alle Meetups": "All Meetups", - "Welt-Karte": "World Map" + "Welt-Karte": "World Map", + "Aktivitäten": "Activities", + "Neue Meetups und Termine": "New Meetups and Events", + "Neues Meetup": "New Meetup", + "Neuer Termin": "New Event", + "Keine Aktivitäten": "No Activities", + "Top Länder": "Top Countries", + "Länder mit den meisten Usern": "Countries with Most Users", + "User": "Users", + "Keine Daten verfügbar": "No Data Available", + "Top Meetups": "Top Meetups", + "Meetups mit den meisten Usern": "Meetups with Most Users" } diff --git a/lang/es.json b/lang/es.json index f6a520c..ae4d106 100644 --- a/lang/es.json +++ b/lang/es.json @@ -459,5 +459,16 @@ "Über den Kurs": "Sobre el curso", "Über uns": "Sobre nosotros", "Alle Meetups": "Todos los encuentros", - "Welt-Karte": "Mapa mundial" + "Welt-Karte": "Mapa mundial", + "Aktivitäten": "Actividades", + "Neue Meetups und Termine": "Nuevos encuentros y eventos", + "Neues Meetup": "Nuevo encuentro", + "Neuer Termin": "Nuevo evento", + "Keine Aktivitäten": "Sin actividades", + "Top Länder": "Países principales", + "Länder mit den meisten Usern": "Países con más usuarios", + "User": "Usuarios", + "Keine Daten verfügbar": "No hay datos disponibles", + "Top Meetups": "Encuentros principales", + "Meetups mit den meisten Usern": "Encuentros con más usuarios" } diff --git a/lang/hu.json b/lang/hu.json index 46eafd0..b397fc7 100644 --- a/lang/hu.json +++ b/lang/hu.json @@ -454,5 +454,16 @@ "Über den Kurs": "A kurzusról", "Über uns": "Rólunk", "Alle Meetups": "Minden meetup", - "Welt-Karte": "Világtérkép" + "Welt-Karte": "Világtérkép", + "Aktivitäten": "Tevékenységek", + "Neue Meetups und Termine": "Új meetupok és időpontok", + "Neues Meetup": "Új meetup", + "Neuer Termin": "Új időpont", + "Keine Aktivitäten": "Nincsenek tevékenységek", + "Top Länder": "Top országok", + "Länder mit den meisten Usern": "Legtöbb felhasználóval rendelkező országok", + "User": "Felhasználó", + "Keine Daten verfügbar": "Nincsenek elérhető adatok", + "Top Meetups": "Top meetupok", + "Meetups mit den meisten Usern": "Legtöbb felhasználóval rendelkező meetupok" } diff --git a/lang/nl.json b/lang/nl.json index 558defc..7b9f720 100644 --- a/lang/nl.json +++ b/lang/nl.json @@ -456,5 +456,16 @@ "Über den Kurs": "Over de cursus", "Über uns": "Over ons", "Alle Meetups": "Alle Meetups", - "Welt-Karte": "Wereldkaart" + "Welt-Karte": "Wereldkaart", + "Aktivitäten": "Activiteiten", + "Neue Meetups und Termine": "Nieuwe Meetups en afspraken", + "Neues Meetup": "Nieuwe Meetup", + "Neuer Termin": "Nieuwe afspraak", + "Keine Aktivitäten": "Geen activiteiten", + "Top Länder": "Top landen", + "Länder mit den meisten Usern": "Landen met de meeste gebruikers", + "User": "Gebruikers", + "Keine Daten verfügbar": "Geen gegevens beschikbaar", + "Top Meetups": "Top Meetups", + "Meetups mit den meisten Usern": "Meetups met de meeste gebruikers" } diff --git a/lang/pt.json b/lang/pt.json index eec64b4..cb5f432 100644 --- a/lang/pt.json +++ b/lang/pt.json @@ -454,5 +454,16 @@ "Über den Kurs": "Sobre o curso", "Über uns": "Sobre nós", "Alle Meetups": "Todos os Meetups", - "Welt-Karte": "Mapa Mundial" + "Welt-Karte": "Mapa Mundial", + "Aktivitäten": "Atividades", + "Neue Meetups und Termine": "Novos Meetups e eventos", + "Neues Meetup": "Novo Meetup", + "Neuer Termin": "Novo evento", + "Keine Aktivitäten": "Nenhuma atividade", + "Top Länder": "Principais países", + "Länder mit den meisten Usern": "Países com mais usuários", + "User": "Usuário", + "Keine Daten verfügbar": "Nenhum dado disponível", + "Top Meetups": "Principais Meetups", + "Meetups mit den meisten Usern": "Meetups com mais usuários" } diff --git a/resources/views/livewire/dashboard.blade.php b/resources/views/livewire/dashboard.blade.php index 95fcf71..ae9f028 100644 --- a/resources/views/livewire/dashboard.blade.php +++ b/resources/views/livewire/dashboard.blade.php @@ -204,4 +204,11 @@ class extends Component { + + {{-- Neue Statistiken und Activities (Lazy loaded) --}} +
+ + + +
diff --git a/resources/views/livewire/dashboard/activities.blade.php b/resources/views/livewire/dashboard/activities.blade.php new file mode 100644 index 0000000..a53a1b1 --- /dev/null +++ b/resources/views/livewire/dashboard/activities.blade.php @@ -0,0 +1,114 @@ +orderBy('created_at', 'desc') + ->limit(5) + ->get(); + + $recentEvents = MeetupEvent::with(['meetup.city.country']) + ->orderBy('created_at', 'desc') + ->limit(5) + ->get(); + + // Kombiniere und sortiere Activities + $activities = collect($recentMeetups->map(fn($m) => ['type' => 'meetup', 'data' => $m, 'created_at' => $m->created_at])) + ->merge($recentEvents->map(fn($e) => ['type' => 'event', 'data' => $e, 'created_at' => $e->created_at])) + ->sortByDesc('created_at') + ->take(10); + + return [ + 'activities' => $activities, + ]; + } + + public function placeholder(): string + { + return <<<'HTML' +
+
+ {{ __('Aktivitäten') }} + {{ __('Neue Meetups und Termine') }} + +
+ +
+
+
+ HTML; + } +}; ?> + +
+
+ {{ __('Aktivitäten') }} + {{ __('Neue Meetups und Termine') }} + + @if($activities->count() > 0) + + + @else +
{{ __('Keine Aktivitäten') }}
+ @endif +
+
diff --git a/resources/views/livewire/dashboard/top-countries.blade.php b/resources/views/livewire/dashboard/top-countries.blade.php new file mode 100644 index 0000000..02d7093 --- /dev/null +++ b/resources/views/livewire/dashboard/top-countries.blade.php @@ -0,0 +1,118 @@ +join('cities', 'cities.country_id', '=', 'countries.id') + ->join('meetups', 'meetups.city_id', '=', 'cities.id') + ->join('meetup_user', 'meetup_user.meetup_id', '=', 'meetups.id') + ->groupBy('countries.id') + ->selectRaw('COUNT(DISTINCT meetup_user.user_id) as user_count') + ->orderBy('user_count', 'desc') + ->limit(10) + ->get() + ->map(function ($country) { + // Optimierte Query: Hole alle User-Erstellungsdaten für dieses Land auf einmal + $userCreationDates = \DB::table('users') + ->join('meetup_user', 'users.id', '=', 'meetup_user.user_id') + ->join('meetups', 'meetup_user.meetup_id', '=', 'meetups.id') + ->join('cities', 'meetups.city_id', '=', 'cities.id') + ->where('cities.country_id', $country->id) + ->whereNotNull('users.created_at') + ->orderBy('users.created_at') + ->pluck('users.created_at') + ->unique() + ->values(); + + if ($userCreationDates->isEmpty()) { + $country->sparkline = [0]; + return $country; + } + + // Berechne monatliche Buckets für kumulative Zählung + $startDate = \Carbon\Carbon::parse($userCreationDates->first())->startOfMonth(); + $endDate = now()->endOfMonth(); + $monthsDiff = max(1, $startDate->diffInMonths($endDate)); + $interval = max(1, ceil($monthsDiff / 12)); + + // Generiere 12 Zeitpunkte + $sparklineData = []; + $currentDate = $startDate->copy(); + + for ($i = 0; $i < 12 && $currentDate <= $endDate; $i++) { + // Zähle kumulative User bis zu diesem Zeitpunkt + $count = $userCreationDates->filter(function ($date) use ($currentDate) { + return \Carbon\Carbon::parse($date) <= $currentDate; + })->count(); + + $sparklineData[] = $count; + $currentDate->addMonths($interval); + } + + $country->sparkline = $sparklineData; + return $country; + }); + + return [ + 'topCountries' => $topCountries, + ]; + } + + public function placeholder(): string + { + return <<<'HTML' +
+
+ {{ __('Top Länder') }} + {{ __('Länder mit den meisten Usern') }} + +
+ +
+
+
+ HTML; + } +}; ?> + +
+
+ {{ __('Top Länder') }} + {{ __('Länder mit den meisten Usern') }} + + @if($topCountries->count() > 0) + +
+ @foreach($topCountries as $country) + + @endforeach +
+ @else +
{{ __('Keine Daten verfügbar') }}
+ @endif +
+
diff --git a/resources/views/livewire/dashboard/top-meetups.blade.php b/resources/views/livewire/dashboard/top-meetups.blade.php new file mode 100644 index 0000000..6881e80 --- /dev/null +++ b/resources/views/livewire/dashboard/top-meetups.blade.php @@ -0,0 +1,112 @@ +with(['city.country']) + ->orderBy('users_count', 'desc') + ->limit(10) + ->get() + ->map(function ($meetup) { + // Optimierte Query: Hole alle User-Erstellungsdaten für dieses Meetup auf einmal + $userCreationDates = \DB::table('users') + ->join('meetup_user', 'users.id', '=', 'meetup_user.user_id') + ->where('meetup_user.meetup_id', $meetup->id) + ->whereNotNull('users.created_at') + ->orderBy('users.created_at') + ->pluck('users.created_at') + ->unique() + ->values(); + + if ($userCreationDates->isEmpty()) { + $meetup->sparkline = [0]; + return $meetup; + } + + // Berechne monatliche Buckets für kumulative Zählung + $startDate = \Carbon\Carbon::parse($userCreationDates->first())->startOfMonth(); + $endDate = now()->endOfMonth(); + $monthsDiff = max(1, $startDate->diffInMonths($endDate)); + $interval = max(1, ceil($monthsDiff / 12)); + + // Generiere 12 Zeitpunkte + $sparklineData = []; + $currentDate = $startDate->copy(); + + for ($i = 0; $i < 12 && $currentDate <= $endDate; $i++) { + // Zähle kumulative User bis zu diesem Zeitpunkt + $count = $userCreationDates->filter(function ($date) use ($currentDate) { + return \Carbon\Carbon::parse($date) <= $currentDate; + })->count(); + + $sparklineData[] = $count; + $currentDate->addMonths($interval); + } + + $meetup->sparkline = $sparklineData; + return $meetup; + }); + + return [ + 'topMeetups' => $topMeetups, + ]; + } + + public function placeholder(): string + { + return <<<'HTML' +
+
+ {{ __('Top Meetups') }} + {{ __('Meetups mit den meisten Usern') }} + +
+ +
+
+
+ HTML; + } +}; ?> + +
+
+ {{ __('Top Meetups') }} + {{ __('Meetups mit den meisten Usern') }} + + @if($topMeetups->count() > 0) + + + @else +
{{ __('Keine Daten verfügbar') }}
+ @endif +
+