diff --git a/src/app/AppUser.php b/src/app/AppUser.php index 1e1035d..d674573 100644 --- a/src/app/AppUser.php +++ b/src/app/AppUser.php @@ -95,4 +95,27 @@ class AppUser { return self::auth0Instance()->getCredentials(); } + + /** + * Require that there be a user logged on + * + * @return void This will not return if there is not a user logged on + */ + public static function require() + { + if (is_null(self::current())) { + // TODO: get the current URL to specify for redirection + self::logOn(); + } + } + + /** + * Get the ID (`sub`) for the current user + * + * @return string The ID of the user (blank string if there is no current user) + */ + public static function currentId(): string + { + return self::auth0Instance()->getCredentials()?->user['sub'] ?? ''; + } } diff --git a/src/app/Data.php b/src/app/Data.php index 937fc1f..7515054 100644 --- a/src/app/Data.php +++ b/src/app/Data.php @@ -137,4 +137,17 @@ class Data usort($reqs, AsOf::oldestToNewest(...)); return $reqs; } + + /** + * Try to obtain a journal request by its ID + * + * @param string $reqId The request ID + * @param string $userId The ID of the currently logged-on user + * @return ?JournalRequest The request, or null if it is not found + */ + public static function tryJournalById(string $reqId, string $userId): ?JournalRequest + { + $req = self::findFullRequestById($reqId, $userId); + return is_null($req) ? null : new JournalRequest($req); + } } diff --git a/src/app/Handlers.php b/src/app/Handlers.php index 5d3ed10..c1d196e 100644 --- a/src/app/Handlers.php +++ b/src/app/Handlers.php @@ -3,6 +3,8 @@ declare(strict_types=1); namespace MyPrayerJournal; +use MyPrayerJournal\Domain\JournalRequest; + class Handlers { /** @@ -23,8 +25,8 @@ class Handlers 'hasSnoozed' => false, ]); $params['pageContent'] = app()->template->render($template, $params); - // TODO: make the htmx distinction here - response()->markup(app()->template->render('layout/full', $params)); + $layout = $params['isHtmx'] ? 'layout/partial' : 'layout/full'; + response()->markup(app()->template->render($layout, $params)); } /** @@ -41,10 +43,18 @@ class Handlers response()->markup(app()->template->render('layout/component', $params)); } + /** + * Send a 404 Not Found response + */ + private static function notFound() + { + response()->plain('Not found', 404); + } + /** GET: /journal */ public static function journal() { - if (!AppUser::current()) AppUser::logOn(); + AppUser::require(); $user = AppUser::current()->user; $firstName = (array_key_exists('given_name', $user) ? $user['given_name'] : null) ?? 'Your'; @@ -54,10 +64,47 @@ class Handlers /** GET: /components/journal-items */ public static function journalItems() { - if (!AppUser::current()) AppUser::logOn(); + AppUser::require(); - self::renderComponent('components/journal_items', [ - 'requests' => Data::getJournal(AppUser::current()->user['sub']) - ]); + $reqs = Data::getJournal(AppUser::currentId()); + $utc = new \DateTimeZone('Etc/UTC'); + $now = date_create_immutable(timezone: $utc); + $epoch = date_create_immutable('1970-01-01', $utc); + array_filter($reqs, + fn (JournalRequest $req) => $req->snoozedUntil ?? $epoch < $now && $req->showAfter ?? $epoch < $now); + + self::renderComponent('components/journal_items', [ 'requests' => $reqs ]); + } + + /** GET /request/[req-id]/edit */ + public static function requestEdit(string $reqId) + { + AppUser::require(); + + $returnTo = array_key_exists('HTTP_REFERER', $_SERVER) + ? match (true) { + str_ends_with($_SERVER['HTTP_REFERER'], '/active') => 'active', + str_ends_with($_SERVER['HTTP_REFERER'], '/snoozed') => 'snoozed', + default => 'journal' + } + : 'journal'; + if ($reqId == 'new') { + self::render('requests/edit', 'Add Prayer Request', [ + 'request' => new JournalRequest(), + 'isNew' => true, + 'returnTo' => $returnTo, + ]); + } else { + $req = Data::tryJournalById($reqId, AppUser::currentId()); + if (is_null($req)) { + self::notFound(); + } else { + self::render('requests/edit', 'Edit Prayer Request', [ + 'request' => $req, + 'isNew' => false, + 'returnTo' => $returnTo, + ]); + } + } } } diff --git a/src/app/index.php b/src/app/index.php index a2adfd8..7d159a3 100644 --- a/src/app/index.php +++ b/src/app/index.php @@ -19,19 +19,24 @@ app()->template->config('params', [ 'version' => 'v4', ]); - app()->get('/', fn () => Handlers::render('home', 'Welcome')); -app()->get('/components/journal-items', Handlers::journalItems(...)); - +app()->group('/components', function () { + app()->get('/journal-items', Handlers::journalItems(...)); +}); app()->get('/journal', Handlers::journal(...)); - -app()->get('/legal/privacy-policy', fn () => Handlers::render('legal/privacy-policy', 'Privacy Policy')); -app()->get('/legal/terms-of-service', fn () => Handlers::render('legal/terms-of-service', 'Terms of Service')); - -app()->get('/user/log-on', AppUser::logOn(...)); -app()->get('/user/log-on/success', AppUser::processLogOn(...)); -app()->get('/user/log-off', AppUser::logOff(...)); +app()->group('/legal', function () { + app()->get('/privacy-policy', fn () => Handlers::render('legal/privacy-policy', 'Privacy Policy')); + app()->get('/terms-of-service', fn () => Handlers::render('legal/terms-of-service', 'Terms of Service')); +}); +app()->group('/request', function () { + app()->get('/{reqId}/edit', Handlers::requestEdit(...)); +}); +app()->group('/user', function () { + app()->get('/log-on', AppUser::logOn(...)); + app()->get('/log-on/success', AppUser::processLogOn(...)); + app()->get('/log-off', AppUser::logOff(...)); +}); // TODO: remove before go-live $stdOut = fopen('php://stdout', 'w'); diff --git a/src/app/pages/layout/full.view.php b/src/app/pages/layout/full.view.php index 911b57d..50b69bd 100644 --- a/src/app/pages/layout/full.view.php +++ b/src/app/pages/layout/full.view.php @@ -4,7 +4,7 @@