Finish req list, add snoozed list
This commit is contained in:
parent
2369827033
commit
d6e8cf66cc
@ -530,7 +530,7 @@ let routes = [
|
|||||||
routef "request/%s/add-notes" Components.addNotes // done
|
routef "request/%s/add-notes" Components.addNotes // done
|
||||||
routef "request/%s/item" Components.requestItem // not used
|
routef "request/%s/item" Components.requestItem // not used
|
||||||
routef "request/%s/notes" Components.notes // done
|
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
|
GET_HEAD [ route "/docs" Home.docs ] // done
|
||||||
@ -547,14 +547,14 @@ let routes = [
|
|||||||
routef "/%s/full" Request.getFull // done
|
routef "/%s/full" Request.getFull // done
|
||||||
route "s/active" Request.active // done
|
route "s/active" Request.active // done
|
||||||
route "s/answered" Request.answered // done
|
route "s/answered" Request.answered // done
|
||||||
route "s/snoozed" Request.snoozed
|
route "s/snoozed" Request.snoozed // done
|
||||||
]
|
]
|
||||||
PATCH [
|
PATCH [
|
||||||
route "" Request.update // done
|
route "" Request.update // done
|
||||||
routef "/%s/cancel-snooze" Request.cancelSnooze
|
routef "/%s/cancel-snooze" Request.cancelSnooze
|
||||||
routef "/%s/prayed" Request.prayed // done
|
routef "/%s/prayed" Request.prayed // done
|
||||||
routef "/%s/show" Request.show
|
routef "/%s/show" Request.show
|
||||||
routef "/%s/snooze" Request.snooze
|
routef "/%s/snooze" Request.snooze // done
|
||||||
]
|
]
|
||||||
POST [
|
POST [
|
||||||
route "" Request.add // done
|
route "" Request.add // done
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
namespace MyPrayerJournal;
|
namespace MyPrayerJournal;
|
||||||
|
|
||||||
|
use BitBadger\PDODocument\Custom;
|
||||||
|
use BitBadger\PDODocument\Mapper\ExistsMapper;
|
||||||
|
|
||||||
class Layout
|
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
|
* The default navigation bar, which will load the items on page load, and whenever a refresh event occurs
|
||||||
*/
|
*/
|
||||||
public static function navBar(): void
|
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">
|
<nav class="navbar navbar-dark" role="navigation">
|
||||||
<div class=container-fluid><?php
|
<div class=container-fluid><?php
|
||||||
UI::pageLink('/', '<span class=m>my</span><span class=p>Prayer</span><span class=j>Journal</span>',
|
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)) {
|
if (key_exists('user_id', $_SESSION)) {
|
||||||
self::navLink('/journal', 'Journal');
|
self::navLink('/journal', 'Journal');
|
||||||
self::navLink('/requests/active', 'Active');
|
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'); ?>
|
self::navLink('/requests/answered', 'Answered'); ?>
|
||||||
<li class=nav-item><a href=/user/log-off>Log Off</a><?php
|
<li class=nav-item><a href=/user/log-off>Log Off</a><?php
|
||||||
} else { ?>
|
} else { ?>
|
||||||
|
@ -146,13 +146,15 @@ class Request implements JsonSerializable
|
|||||||
* Get either the user's active or answered requests
|
* Get either the user's active or answered requests
|
||||||
*
|
*
|
||||||
* @param bool $active True to retrieve active requests, false to retrieve 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
|
* @return DocumentList<Request> The requests matching the criteria
|
||||||
* @throws DocumentException If any is encountered
|
* @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;
|
$table = Table::REQUEST;
|
||||||
$op = $active ? '<>' : '=';
|
$op = $active ? '<>' : '=';
|
||||||
|
$extra = $snoozed ? "AND datetime(data->>'snoozedUntil') > datetime('now')" : '';
|
||||||
$order = $active
|
$order = $active
|
||||||
? "coalesce(data->>'snoozedUntil', data->>'showAfter', last_prayed, data->>'$.history[0].asOf')"
|
? "coalesce(data->>'snoozedUntil', data->>'showAfter', last_prayed, data->>'$.history[0].asOf')"
|
||||||
: "data->>'$.history[0].asOf' DESC";
|
: "data->>'$.history[0].asOf' DESC";
|
||||||
@ -164,7 +166,7 @@ class Request implements JsonSerializable
|
|||||||
LIMIT 1) last_prayed
|
LIMIT 1) last_prayed
|
||||||
FROM $table r
|
FROM $table r
|
||||||
WHERE data->>'userId' = :userId
|
WHERE data->>'userId' = :userId
|
||||||
AND data->>'$.history[0].action' $op 'Answered'
|
AND data->>'$.history[0].action' $op 'Answered' $extra
|
||||||
ORDER BY $order
|
ORDER BY $order
|
||||||
SQL, [':userId' => $_SESSION['user_id']], new DocumentMapper(self::class));
|
SQL, [':userId' => $_SESSION['user_id']], new DocumentMapper(self::class));
|
||||||
}
|
}
|
||||||
@ -190,4 +192,15 @@ class Request implements JsonSerializable
|
|||||||
{
|
{
|
||||||
return self::forUser(false);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,19 +168,18 @@ class UI
|
|||||||
return $dtFrom > $dtTo ? "$value ago" : "in $value";
|
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
|
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) =>
|
$restoreBtn = fn(string $id, string $link, string $title) =>
|
||||||
'<button class="' . $btnClass. '" hx-patch="/request/' . $link . '?id=' . $id
|
'<button class="' . $btnClass. '" hx-patch="/request/' . $link . '?id=' . $id
|
||||||
. '" title="' . htmlspecialchars($title) . '">' . self::icon('restore') . '</button>';
|
. '" 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" ] */ ?>
|
|
||||||
<div class=list-group><?php
|
<div class=list-group><?php
|
||||||
foreach ($reqs->items() as /** @var Request $req */ $req) { ?>
|
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
|
<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 $restoreBtn($req->id, 'show', 'Show Now');
|
||||||
}
|
}
|
||||||
echo '<p class="request-text mb-0">' . $req->currentText();
|
echo '<p class="request-text mb-0">' . $req->currentText();
|
||||||
// if isSnoozed || isPending || isAnswered then
|
if ($req->isSnoozed() || $req->isPending() || $req->isAnswered()) { ?>
|
||||||
// br []
|
<br>
|
||||||
// small [ _class "text-muted" ] [
|
<small class=text-muted><em><?php
|
||||||
// if isSnoozed then [ str "Snooze expires "; relativeDate req.SnoozedUntil.Value now tz ]
|
switch (true) {
|
||||||
// elif isPending then [ str "Request appears next "; relativeDate req.ShowAfter.Value now tz ]
|
case $req->isSnoozed():
|
||||||
// else (* isAnswered *) [ str "Answered "; relativeDate req.AsOf now tz ]
|
echo 'Snooze expires '; self::relativeDate($req->snoozedUntil);
|
||||||
// |> em []
|
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
|
||||||
} ?>
|
} ?>
|
||||||
</div><?php
|
</div><?php
|
||||||
|
22
src/public/requests/snoozed.php
Normal file
22
src/public/requests/snoozed.php
Normal 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();
|
Loading…
Reference in New Issue
Block a user