Add request edit form

- Add partial output template
- Group routes
This commit is contained in:
Daniel J. Summers 2023-08-28 19:55:31 -04:00
parent 00034c0a26
commit 817d7876db
7 changed files with 203 additions and 18 deletions

View File

@ -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'] ?? '';
}
}

View File

@ -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);
}
}

View File

@ -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,
]);
}
}
}
}

View File

@ -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');

View File

@ -4,7 +4,7 @@
<body>
<section id="top" aria-label="Top navigation">
<?php echo app()->template->render('layout/_nav', [ 'user' => $user, 'hasSnoozed' => $hasSnoozed ]); ?>
<?php echo $pageContent; ?>
<main role="main"><?php echo $pageContent; ?></main>
</section>
<?php echo app()->template->render('layout/_foot', [ 'isHtmx' => $isHtmx ]); ?>
</body>

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title><?php echo $pageTitle; ?> &#xab; myPrayerJournal</title>
</head>
<body>
<section id="top" aria-label="Top navigation">
<?php echo app()->template->render('layout/_nav', [ 'user' => $user, 'hasSnoozed' => $hasSnoozed ]); ?>
<main role="main"><?php echo $pageContent; ?></main>
</section>
</body>
</html>

View File

@ -0,0 +1,85 @@
<?php
use MyPrayerJournal\Domain\RecurrenceType;
$cancelLink = match ($returnTo) {
'active' => '/requests/active',
'snoozed' => '/requests/snoozed',
default => '/journal',
};
$isImmediate = $request->recurrenceType == RecurrenceType::Immediate;
$isHours = $request->recurrenceType == RecurrenceType::Hours;
$isDays = $request->recurrenceType == RecurrenceType::Days;
$isWeeks = $request->recurrenceType == RecurrenceType::Weeks; ?>
<article class="container">
<h2 class="pb-3"><?php echo $isNew ? 'Add' : 'Edit'; ?> Prayer Request</h2>
<form hx-boost="true" hx-target="#top" hx-push-url="true"
<?php echo $isNew ? 'hx-post' : 'hx-patch'; ?>="/request">
<input type="hidden" name="requestId" value="<?php echo $isNew ? 'new' : $request->id; ?>">
<input type="hidden" name="returnTo" value="<?php echo $returnTo; ?>">
<div class="form-floating pb-3">
<textarea id="requestText" name="requestText" class="form-control" style="min-height: 8rem;"
placeholder="Enter the text of the request"
autofocus required><?php echo $request->text; ?></textarea>
<label for="requestText">Prayer Request</label>
</div><br><?php
if (!$isNew) { ?>
<div class="pb-3">
<label>Also Mark As</label><br>
<div class="form-check form-check-inline">
<input type="radio" class="form-check-input" id="sU" name="status" value="Updated" checked>
<label for="sU">Updated</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" class="form-check-input" id="sP" name="status" value="Prayed">
<label for="sP">Prayed</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" class="form-check-input" id="sA" name="status" value="Answered">
<label for="sA">Answered</label>
</div>
</div><?php
} ?>
<div class="row">
<div class="col-12 offset-md-2 col-md-8 offset-lg-3 col-lg-6">
<p>
<strong>Recurrence</strong> &nbsp;
<em class="text-muted">After prayer, request reappears&hellip;</em>
</p>
<div class="d-flex flex-row flex-wrap justify-content-center align-items-center">
<div class="form-check mx-2">
<input type="radio" class="form-check-input" id="rI" name="recurType" value="Immediate"
onclick="mpj.edit.toggleRecurrence(event)" <?php echo $isImmediate ? 'checked' : ''; ?>>
<label for="rI">Immediately</label>
</div>
<div class="form-check mx-2">
<input type="radio" class="form-check-input" id="rO" name="recurType" value="Other"
onclick="mpj.edit.toggleRecurrence(event)" <?php echo $isImmediate ? '' : 'checked'; ?>>
<label for="rO">Every&hellip;</label>
</div>
<div class="form-floating mx-2">
<input type="number" class="form-control" id="recurCount" name="recurCount" placeholder="0"
value="<?php echo $request->recurrence ?? 0; ?>" style="width:6rem;" required
<?php echo $isImmediate ? 'disabled' : ''; ?>>
<label for="recurCount">Count</label>
</div>
<div class="form-floating mx-2">
<select class="form-control" id="recurInterval" name="recurInterval" style="width:6rem;"
required <?php echo $isImmediate ? 'disabled' : ''; ?>>
<option value="Hours" <?php echo $isHours ? 'selected' : ''; ?>>hours</option>
<option value="Days" <?php echo $isDays ? 'selected' : ''; ?>>days</option>
<option value="Weeks" <?php echo $isWeeks ? 'selected' : ''; ?>>weeks</option>
</select>
<label for="recurInterval">Interval</label>
</div>
</div>
</div>
</div>
<div class="text-end pt-3">
<button class="btn btn-primary me-2" type="submit"><span class="material-icons">save</span> Save</button>
<a <?php $page_link($cancelLink); ?> class="btn btn-secondary ms-2">
<span class="material-icons">arrow_back</span> Cancel
</a>
</div>
</form>
</article>