Finish req list, add snoozed list

This commit is contained in:
Daniel J. Summers 2024-06-22 22:48:31 -04:00
parent 2369827033
commit d6e8cf66cc
5 changed files with 76 additions and 25 deletions

View File

@ -530,7 +530,7 @@ let routes = [
routef "request/%s/add-notes" Components.addNotes // done
routef "request/%s/item" Components.requestItem // not used
routef "request/%s/notes" Components.notes // done
routef "request/%s/snooze" Components.snooze
routef "request/%s/snooze" Components.snooze // done
]
]
GET_HEAD [ route "/docs" Home.docs ] // done
@ -547,14 +547,14 @@ let routes = [
routef "/%s/full" Request.getFull // done
route "s/active" Request.active // done
route "s/answered" Request.answered // done
route "s/snoozed" Request.snoozed
route "s/snoozed" Request.snoozed // done
]
PATCH [
route "" Request.update // done
routef "/%s/cancel-snooze" Request.cancelSnooze
routef "/%s/prayed" Request.prayed // done
routef "/%s/show" Request.show
routef "/%s/snooze" Request.snooze
routef "/%s/snooze" Request.snooze // done
]
POST [
route "" Request.add // done

View File

@ -2,6 +2,9 @@
namespace MyPrayerJournal;
use BitBadger\PDODocument\Custom;
use BitBadger\PDODocument\Mapper\ExistsMapper;
class Layout
{
/**
@ -72,7 +75,15 @@ class Layout
* The default navigation bar, which will load the items on page load, and whenever a refresh event occurs
*/
public static function navBar(): void
{ ?>
{
$table = Table::REQUEST;
$hasSnoozed = key_exists('user_id', $_SESSION)
? Custom::scalar(<<<SQL
SELECT EXISTS (
SELECT 1 FROM $table
WHERE data->>'userId' = :userId AND datetime(data->>'snoozedUntil') > datetime('now'))
SQL, [':userId' => $_SESSION['user_id']], new ExistsMapper())
: false; ?>
<nav class="navbar navbar-dark" role="navigation">
<div class=container-fluid><?php
UI::pageLink('/', '<span class=m>my</span><span class=p>Prayer</span><span class=j>Journal</span>',
@ -81,7 +92,7 @@ class Layout
if (key_exists('user_id', $_SESSION)) {
self::navLink('/journal', 'Journal');
self::navLink('/requests/active', 'Active');
if (key_exists('has_snoozed', $_SESSION)) self::navLink('/requests/snoozed', 'Snoozed');
if ($hasSnoozed) self::navLink('/requests/snoozed', 'Snoozed');
self::navLink('/requests/answered', 'Answered'); ?>
<li class=nav-item><a href=/user/log-off>Log Off</a><?php
} else { ?>

View File

@ -146,13 +146,15 @@ class Request implements JsonSerializable
* Get either the user's active or answered requests
*
* @param bool $active True to retrieve active requests, false to retrieve answered requests
* @param bool $snoozed True to retrieve only snoozed requests
* @return DocumentList<Request> The requests matching the criteria
* @throws DocumentException If any is encountered
*/
private static function forUser(bool $active = true): DocumentList
private static function forUser(bool $active = true, bool $snoozed = false): DocumentList
{
$table = Table::REQUEST;
$op = $active ? '<>' : '=';
$extra = $snoozed ? "AND datetime(data->>'snoozedUntil') > datetime('now')" : '';
$order = $active
? "coalesce(data->>'snoozedUntil', data->>'showAfter', last_prayed, data->>'$.history[0].asOf')"
: "data->>'$.history[0].asOf' DESC";
@ -164,7 +166,7 @@ class Request implements JsonSerializable
LIMIT 1) last_prayed
FROM $table r
WHERE data->>'userId' = :userId
AND data->>'$.history[0].action' $op 'Answered'
AND data->>'$.history[0].action' $op 'Answered' $extra
ORDER BY $order
SQL, [':userId' => $_SESSION['user_id']], new DocumentMapper(self::class));
}
@ -190,4 +192,15 @@ class Request implements JsonSerializable
{
return self::forUser(false);
}
/**
* Get a list of snoozed requests for a user
*
* @return DocumentList<Request> The user's snoozed requests
* @throws DocumentException If any is encountered
*/
public static function snoozed(): DocumentList
{
return self::forUser(snoozed: true);
}
}

View File

@ -168,19 +168,18 @@ class UI
return $dtFrom > $dtTo ? "$value ago" : "in $value";
}
/**
* Render the given list of requests
*
* @param DocumentList<Request> $reqs The list of requests to render
* @throws Exception If date/time instances are not valid
*/
public static function requestList(DocumentList $reqs): void
{
$btnClass = "btn btn-light mx-2";
$btnClass = "btn btn-light mx-2";
$restoreBtn = fn(string $id, string $link, string $title) =>
'<button class="' . $btnClass. '" hx-patch="/request/' . $link . '?id=' . $id
. '" title="' . htmlspecialchars($title) . '">' . self::icon('restore') . '</button>';
/// Create a request within the list
/* let reqListItem now tz req =
let isFuture instant = defaultArg (instant |> Option.map (fun it -> it > now)) false
let reqId = RequestId.toString req.RequestId
let isPending = (not isSnoozed) && isFuture req.ShowAfter
let restoreBtn (link : string) title =
button [ btnClass; _hxPatch $"/request/{reqId}/{link}"; _title title ] [ icon "restore" ] */ ?>
. '" title="' . htmlspecialchars($title) . '">' . self::icon('restore') . '</button>'; ?>
<div class=list-group><?php
foreach ($reqs->items() as /** @var Request $req */ $req) { ?>
<div class="list-group-item px-0 d-flex flex-row align-items-start" hx-target=this
@ -197,15 +196,21 @@ class UI
echo $restoreBtn($req->id, 'show', 'Show Now');
}
echo '<p class="request-text mb-0">' . $req->currentText();
// if isSnoozed || isPending || isAnswered then
// br []
// small [ _class "text-muted" ] [
// if isSnoozed then [ str "Snooze expires "; relativeDate req.SnoozedUntil.Value now tz ]
// elif isPending then [ str "Request appears next "; relativeDate req.ShowAfter.Value now tz ]
// else (* isAnswered *) [ str "Answered "; relativeDate req.AsOf now tz ]
// |> em []
// ]
?>
if ($req->isSnoozed() || $req->isPending() || $req->isAnswered()) { ?>
<br>
<small class=text-muted><em><?php
switch (true) {
case $req->isSnoozed():
echo 'Snooze expires '; self::relativeDate($req->snoozedUntil);
break;
case $req->isPending():
echo 'Request appears next '; self::relativeDate($req->showAfter);
break;
default:
echo 'Answered '; self::relativeDate($req->history[0]->asOf);
} ?>
</em></small><?php
} ?>
</div><?php
} ?>
</div><?php

View File

@ -0,0 +1,22 @@
<?php declare(strict_types=1);
use MyPrayerJournal\{Auth, Layout, Request, UI};
require '../../start.php';
if ($_SERVER['REQUEST_METHOD'] <> 'GET') not_found();
Auth::requireUser();
$reqs = Request::snoozed();
Layout::pageHead('Snoozed Requests'); ?>
<article class="container mt-3">
<h2 class=pb-3>Snoozed Requests</h2><?php
if ($reqs->hasItems()) {
UI::requestList($reqs);
} else {
UI::noResults('No Snoozed Requests', '/journal', 'Return to your journal',
'Your prayer journal has no snoozed requests');
} ?>
</article><?php
Layout::pageFoot();