Skip to content

Commit

Permalink
💄 Add new landing page (#2883)
Browse files Browse the repository at this point in the history
Co-authored-by: Kris <[email protected]>
  • Loading branch information
HerrLevin and MrKrisKrisu authored Aug 31, 2024
1 parent 2eb7557 commit 504f62c
Show file tree
Hide file tree
Showing 22 changed files with 2,043 additions and 264 deletions.
21 changes: 14 additions & 7 deletions app/Http/Controllers/Auth/LoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

use App\Http\Controllers\Backend\Auth\LoginController as BackendLoginController;
use App\Http\Controllers\Controller;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\Response;

class LoginController extends Controller
Expand Down Expand Up @@ -43,11 +42,19 @@ public function __construct() {
}

public function login(Request $request): Response {
$validated = $request->validate([
'login' => ['required', 'max:255'],
'password' => ['required', 'min:8'],
'remember' => ['nullable',],
]);
$validator = Validator::make($request->all(), [
'login' => ['required', 'max:255'],
'password' => ['required', 'min:8'],
'remember' => ['nullable',],
]);

if ($validator->fails()) {
return redirect(route('login'))
->withErrors($validator)
->withInput();
}

$validated = $validator->validated();

if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
Expand Down
35 changes: 24 additions & 11 deletions app/Http/Controllers/Backend/StatisticController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,30 @@ public static function getGlobalCheckInStats(Carbon $from, Carbon $until): stdCl
throw new InvalidArgumentException('since cannot be after until');
}

return DB::table('train_checkins')
->join('statuses', 'train_checkins.status_id', '=', 'statuses.id')
->where('train_checkins.departure', '>=', $from->toIso8601String())
->where('train_checkins.departure', '<=', $until->toIso8601String())
->select([
DB::raw('SUM(train_checkins.distance) AS distance'),
DB::raw('SUM(TIMESTAMPDIFF(SECOND, train_checkins.departure,
train_checkins.arrival)) AS duration'),
DB::raw('COUNT(DISTINCT statuses.user_id) AS user_count')
])
->first();
return self::globalCheckinQuery($from, $until);
}

public static function getGlobalCheckInStatsAllTime(): stdClass {
return self::globalCheckinQuery();
}

private static function globalCheckinQuery(?Carbon $from = null, ?Carbon $until = null): stdClass {
$query = DB::table('train_checkins');

if ($from !== null && $until !== null) {
$query->where('train_checkins.departure', '>=', $from->toIso8601String())
->where('train_checkins.departure', '<=', $until->toIso8601String());
}
$query->selectRaw('SUM(train_checkins.distance) AS distance');
$query->selectRaw('COUNT(DISTINCT train_checkins.user_id) AS user_count');

if (DB::getDriverName() === 'sqlite') {
$query->selectRaw('1337 AS duration');
} else {
$query->selectRaw('SUM(TIMESTAMPDIFF(SECOND, train_checkins.departure, train_checkins.arrival)) AS duration');
}

return $query->first();
}

/**
Expand Down
56 changes: 56 additions & 0 deletions app/Http/Controllers/Frontend/LandingPageController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace App\Http\Controllers\Frontend;

use App\Http\Controllers\Backend\StatisticController;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;
use stdClass;

class LandingPageController
{
private const string CACHE_KEY_STATS = 'welcome.stats';
private const string CACHE_KEY_STATS_TTL = 'welcome.stats.revalidate';
private const string CACHE_KEY_STATS_CALCULATING = 'welcome.stats.calculating';

private function getStats(): stdClass {
$stats = Cache::get(self::CACHE_KEY_STATS);
$ttl = Cache::get(self::CACHE_KEY_STATS_TTL, 0);
$calculating = Cache::get(self::CACHE_KEY_STATS_CALCULATING, false);

// refresh stats if they are outdated. rand(0,10) to reduce risk of multiple processes starting calculation
// $calculating to make sure, that there won't be multiple processes calculating the stats in the next 15 Minutes
if (
($stats === null
|| $ttl < now()->format('u'))
&& !$calculating
) {
dispatch(function() {
Cache::put(self::CACHE_KEY_STATS_CALCULATING, true, now()->addMinutes(15));
$stats = StatisticController::getGlobalCheckInStatsAllTime();

Cache::put(self::CACHE_KEY_STATS, $stats, now()->addDays(6));
Cache::put(self::CACHE_KEY_STATS_TTL, now()->addDays(5)->format('u'));
})->afterResponse();
}

// Fallback: Show bogus values if really nothing is set
if ($stats === null) {
$stats = new stdClass();
$stats->distance = 0;
$stats->duration = 0;
$stats->user_count = 0;
}

return $stats;
}

public function renderLandingPage(): View|RedirectResponse {
if (Auth::check()) {
return redirect()->route('dashboard');
}
return view('welcome/welcome', ['stats' => $this->getStats()]);
}
}
20 changes: 0 additions & 20 deletions app/Http/Controllers/FrontendStaticController.php

This file was deleted.

24 changes: 23 additions & 1 deletion lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,15 @@
"user.fresh-link": "Ein neuer Bestätigungslink wurde an Deine E-Mail-Adresse geschickt.",
"user.header-reset-pw": "Passwort zurücksetzen",
"user.login": "Anmelden",
"user.login.mastodon": "Mit Mastodon anmelden",
"user.login.or": "oder",
"user.login-credentials": "E-Mail-Adresse oder Nutzername",
"user.mastodon-instance-url": "Instanz",
"user.not-received-before": "Wenn Du die E-Mail nicht bekommen hast, ",
"user.not-received-link": "klicke hier für eine neue E-Mail",
"user.password": "Passwort",
"user.please-check": "Bevor Du weitergehst, schau in Deine E-Mails für einen Bestätigungslink.",
"user.no-account": "Hast du keinen Account?",
"user.register": "Registrieren",
"user.remember-me": "Angemeldet bleiben",
"user.reset-pw-link": "Wiederherstellungs-Link schicken",
Expand Down Expand Up @@ -795,5 +798,24 @@
"report-subject.User": "User",
"report-subject.Status": "Status",
"report-subject.Trip": "Fahrt",
"status.report": "Status melden"
"status.report": "Status melden",
"welcome.footer.links": "Links",
"welcome.footer.social": "Soziale Netze",
"welcome.footer.made-by": "Mit ❤️ gemacht von der Community",
"welcome.footer.version": "Version",
"welcome.header.track": "Tracke deine Reisen und teile deine Reiseerfahrungen.",
"welcome.header.vehicles": "Schiene, Bus oder Boot.",
"welcome.header.open-source": "Open source. Kostenlos. Jetzt und immer.",
"welcome.get-on-board": "Einsteigen",
"welcome.get-on-board-now": "Jetzt in Träwelling einsteigen!",
"welcome.hero.stats.title": "Sammle Statistiken",
"welcome.hero.stats.description": "Du kannst Statistiken über deine meistgenutzten Betreiber, Fahrzeugarten und mehr sammeln!",
"welcome.hero.map.title": "Interaktive Karte und Status",
"welcome.hero.map.description": "Beobachte die Position deines Verkehrsmittels auf der Karte und teile deine Reisen mit anderen.",
"welcome.hero.mobile.title": "Mobile first",
"welcome.hero.mobile.description": "Träwelling ist für mobile Geräte optimiert und kann einfach unterwegs genutzt werden.",
"welcome.stats.million": "Millionen",
"welcome.stats.distance": "kilometer gereist",
"welcome.stats.registered": "Registrierte user",
"welcome.stats.duration": "Jahre Reisezeit"
}
26 changes: 24 additions & 2 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@
"user.forgot-password": "Forgot your password?",
"user.fresh-link": "A fresh verification link has been sent to your email address.",
"user.header-reset-pw": "Reset password",
"user.login": "Login",
"user.login": "Log in",
"user.login.mastodon": "Log in with mastodon",
"user.login.or": "or",
"user.login-credentials": "Email address or username",
"user.mastodon-instance-url": "Instance URL",
"user.not-received-before": "If you didn't get the email, ",
"user.not-received-link": "click here to request another",
"user.no-account": "Don't have an account?",
"user.password": "Password",
"user.please-check": "Before proceeding, please check your email for a verification link.",
"user.register": "Register",
Expand Down Expand Up @@ -795,5 +798,24 @@
"report-subject.User": "User",
"report-subject.Status": "Status",
"report-subject.Trip": "Trip",
"status.report": "Report status"
"status.report": "Report status",
"welcome.footer.links": "Links",
"welcome.footer.social": "Social",
"welcome.footer.made-by": "Made with ❤️ by the community",
"welcome.footer.version": "Version",
"welcome.header.track": "Track your journey and share your travel experiences.",
"welcome.header.vehicles": "Rail, bus or boat.",
"welcome.header.open-source": "Open source. Free. Now and forever.",
"welcome.get-on-board": "Get on board",
"welcome.get-on-board-now": "Get on board Träwelling now!",
"welcome.hero.stats.title": "Gather statistics",
"welcome.hero.stats.description": "You can gather statistics about your most used transport operators, travel modes and more!",
"welcome.hero.map.title": "Interactive map and statuses",
"welcome.hero.map.description": "See your vehicle's location on the map and share your journey with others.",
"welcome.hero.mobile.title": "Mobile first",
"welcome.hero.mobile.description": "Träwelling is optimized for mobile devices and can be used on the go.",
"welcome.stats.million": "Million",
"welcome.stats.distance": "kilometers travelled",
"welcome.stats.registered": "users registered",
"welcome.stats.duration": "years travel time"
}
Loading

0 comments on commit 504f62c

Please sign in to comment.