Render requests (crudely)

This commit is contained in:
Daniel J. Summers 2023-11-19 20:15:29 -05:00
parent 5f425adc1d
commit f8b5902aa1
11 changed files with 57 additions and 54 deletions

View File

@ -9,7 +9,7 @@ use MyPrayerJournal\Domain\{ History, JournalRequest, Note, Request, RequestActi
class Data
{
/** The prayer request table */
const REQ_TABLE = 'prayer_request';
const REQ_TABLE = 'mpj.request';
/**
* Ensure the table and index exist
@ -94,11 +94,11 @@ class Data
*/
private static function getJournalByAnswered(string $userId, string $op): array
{
$sql = Query::selectFromTable(self::REQ_TABLE)
. ' WHERE ' . Query::whereDataContains('$1') . ' AND ' . Query::whereJsonPathMatches('$2');
$sql = sprintf('%s WHERE %s AND %s', Query::selectFromTable(self::REQ_TABLE), Query::whereDataContains('$1'),
Query::whereJsonPathMatches('$2'));
$params = [
Query::jsonbDocParam([ 'userId' => $userId ]),
sprintf("$.history[*].action ? (@ $op \"%s\")", RequestAction::Answered->name)
sprintf("$.history[0].status ? (@ $op \"%s\")", RequestAction::Answered->name)
];
return self::mapToJournalRequest(
Document::customList($sql, $params, Request::class, Document::mapFromJson(...)), true);

View File

@ -32,19 +32,19 @@ enum DistanceFormat
public static function format(DistanceFormat $it, bool $singular = false): string
{
return match ($it) {
self::LessThanXMinutes => $singular ? 'less than a minute' : 'less than %i minutes',
self::XMinutes => $singular ? 'a minute' : '%i minutes',
self::AboutXHours => $singular ? 'about an hour' : 'about %i hours',
self::XHours => $singular ? 'an hour' : '%i hours',
self::XDays => $singular ? 'a day' : '%i days',
self::AboutXWeeks => $singular ? 'about a week' : 'about %i weeks',
self::XWeeks => $singular ? 'a week' : '%i weeks',
self::AboutXMonths => $singular ? 'about a month' : 'about %i months',
self::XMonths => $singular ? 'a month' : '%i months',
self::AboutXYears => $singular ? 'about a year' : 'about %i years',
self::XYears => $singular ? 'a year' : '%i years',
self::OverXYears => $singular ? 'over a year' : 'over %i years',
self::AlmostXYears => $singular ? 'almost a year' : 'almost %i years',
self::LessThanXMinutes => $singular ? 'less than a minute' : 'less than %d minutes',
self::XMinutes => $singular ? 'a minute' : '%d minutes',
self::AboutXHours => $singular ? 'about an hour' : 'about %d hours',
self::XHours => $singular ? 'an hour' : '%d hours',
self::XDays => $singular ? 'a day' : '%d days',
self::AboutXWeeks => $singular ? 'about a week' : 'about %d weeks',
self::XWeeks => $singular ? 'a week' : '%d weeks',
self::AboutXMonths => $singular ? 'about a month' : 'about %d months',
self::XMonths => $singular ? 'a month' : '%d months',
self::AboutXYears => $singular ? 'about a year' : 'about %d years',
self::XYears => $singular ? 'a year' : '%d years',
self::OverXYears => $singular ? 'over a year' : 'over %d years',
self::AlmostXYears => $singular ? 'almost a year' : 'almost %d years',
};
}
}

View File

@ -5,7 +5,7 @@ namespace MyPrayerJournal\Domain;
use DateTimeImmutable;
trait AsOf
class AsOf
{
/** The "as of" date/time */
public DateTimeImmutable $asOf;

View File

@ -8,33 +8,31 @@ use DateTimeImmutable, DateTimeZone;
/**
* A record of action taken on a prayer request, including updates to its text
*/
class History
class History extends AsOf
{
use AsOf;
/** The action taken that generated this history entry */
public RequestAction $action = RequestAction::Created;
public RequestAction $status = RequestAction::Created;
/** The text of the update, if applicable */
public ?string $text = null;
public function __construct()
{
$this->asOf = new DateTimeImmutable('1/1/1970', new DateTimeZone('Etc/UTC'));
$this->asOf = unix_epoch();
}
public function isCreated(): bool
{
return $this->action == RequestAction::Created;
return $this->status == RequestAction::Created;
}
public function isPrayed(): bool
{
return $this->action == RequestAction::Prayed;
return $this->status == RequestAction::Prayed;
}
public function isAnswered(): bool
{
return $this->action == RequestAction::Answered;
return $this->status == RequestAction::Answered;
}
}

View File

@ -8,10 +8,8 @@ use DateTimeImmutable, DateTimeZone;
/**
* A prayer request, along with calculated fields, for use in displaying journal lists
*/
class JournalRequest
class JournalRequest extends AsOf
{
use AsOf;
/** The ID of the prayer request */
public string $id = '';
@ -22,7 +20,7 @@ class JournalRequest
public string $text = '';
/** The date/time this request was last marked as prayed */
public DateTimeImmutable $lastPrayed;
public ?DateTimeImmutable $lastPrayed = null;
/** The last action taken on this request */
public RequestAction $lastAction = RequestAction::Created;
@ -60,8 +58,8 @@ class JournalRequest
public function __construct(?Request $req = null, bool $full = false)
{
if (is_null($req)) {
$this->asOf = new DateTimeImmutable('1/1/1970', new DateTimeZone('Etc/UTC'));
$this->lastPrayed = new DateTimeImmutable('1/1/1970', new DateTimeZone('Etc/UTC'));
$this->asOf = unix_epoch();
$this->lastPrayed = null;
} else {
$this->id = $req->id;
$this->userId = $req->userId;
@ -71,9 +69,11 @@ class JournalRequest
$this->recurrence = $req->recurrence;
usort($req->history, AsOf::newestToOldest(...));
$this->asOf = $req->history[0]->asOf;
$this->lastPrayed = array_values(
array_filter($req->history, fn (History $it) => $it->isPrayed()))[0]?->asOf;
$this->asOf = $req->history[array_key_first($req->history)]->asOf;
$lastText = array_filter($req->history, fn (History $it) => !is_null($it->text));
$this->text = $lastText[array_key_first($lastText)]->text;
$lastPrayed = array_filter($req->history, fn (History $it) => $it->isPrayed());
if ($lastPrayed) $this->lastPrayed = $lastPrayed[array_key_first($lastPrayed)]->asOf;
if ($full) {
usort($req->notes, AsOf::newestToOldest(...));

View File

@ -8,15 +8,13 @@ use DateTimeImmutable, DateTimeZone;
/**
* A note entered on a prayer request
*/
class Note
class Note extends AsOf
{
use AsOf;
/** The note */
public string $notes = '';
public function __construct()
{
$this->asOf = new DateTimeImmutable('1/1/1970', new DateTimeZone('Etc/UTC'));
$this->asOf = unix_epoch();
}
}

View File

@ -46,7 +46,7 @@ class Request
public function __construct()
{
$this->id = new Cuid2();
$this->enteredOn = new DateTimeImmutable('1/1/1970', new DateTimeZone('Etc/UTC'));
$this->id = (new Cuid2())->toString();
$this->enteredOn = unix_epoch();
}
}

View File

@ -8,19 +8,19 @@ use JsonSerializable;
/**
* An action that was taken on a request
*/
enum RequestAction implements JsonSerializable
enum RequestAction: string implements JsonSerializable
{
/** The request was entered */
case Created;
case Created = 'Created';
/** Prayer was recorded for the request */
case Prayed;
case Prayed = 'Prayed';
/** The request was updated */
case Updated;
case Updated = 'Updated';
/** The request was marked as answered */
case Answered;
case Answered = 'Answered';
/**
* Serialize this enum using its name

View File

@ -55,7 +55,7 @@ function require_user(bool $fail = false)
if ($fail) {
http_response_code(403);
} else {
header("Location: /user/log-on?{${Constants::RETURN_URL}}={$_SERVER[Constants::REQUEST_URI]}");
header(sprintf('Location: /user/log-on?%s=%s', Constants::RETURN_URL, $_SERVER[Constants::REQUEST_URI]));
}
exit;
}
@ -83,7 +83,7 @@ function page_link(string $url, array $classNames = [], bool $checkActive = fals
array_push($classNames, 'is-active-route');
}
if (!empty($classNames)) {
echo ' class="' . implode(' ', $classNames) . '"';
echo sprintf(' class="%s"', implode(' ', $classNames));
}
echo ' hx-target="#top" hx-swap="innerHTML" hx-push-url="true"';
}
@ -96,3 +96,13 @@ function end_request()
Configuration::closeConn();
echo '</body></html>';
}
/**
* Create a new instance of the Unix epoch
*
* @return DateTimeImmutable An immutable date/time as of the Unix epoch
*/
function unix_epoch(): DateTimeImmutable
{
return new DateTimeImmutable('1/1/1970', new DateTimeZone('Etc/UTC'));
}

View File

@ -40,11 +40,9 @@ end_request();
*/
function format_activity(string $activity, DateTimeImmutable $asOf)
{
echo sprintf('last %s <span title="%s">%s</span>', [
$activity,
echo sprintf('last %s <span title="%s">%s</span>', $activity,
$asOf->setTimezone($_REQUEST[Constants::TIME_ZONE])->format('l, F jS, Y/g:ia T'),
Dates::formatDistance(Dates::now(), $asOf)
]);
Dates::formatDistance(Dates::now(), $asOf));
}
/**

View File

@ -11,11 +11,10 @@ $_REQUEST[Constants::PAGE_TITLE] = "{$session->user[Constants::CLAIM_GIVEN_NAME]
template('layout/page_header'); ?>
<main class="container">
<h2 class="title"><?php echo $_REQUEST[Constants::PAGE_TITLE]; ?>&rsquo;s Prayer Journal</h2>
<h2 class="title"><?php echo $_REQUEST[Constants::PAGE_TITLE]; ?></h2>
<p hx-get="/components/journal-items" hx-swap="outerHTML" hx-trigger="load delay:.25s">
Loading your prayer journal&hellip;
</p>
<pre><?php var_dump($_SERVER); ?></pre>
</main><?php
template('layout/page_footer');
end_request();