First cut of Add / Edit / Active / Answered pages
- Centralized UI between UI and Layout classes
This commit is contained in:
		
							parent
							
								
									0b7fa77247
								
							
						
					
					
						commit
						b759c3494e
					
				@ -19,7 +19,7 @@ class History implements JsonSerializable
 | 
			
		||||
    public function jsonSerialize(): mixed
 | 
			
		||||
    {
 | 
			
		||||
        $values = ['asOf' => $this->asOf, 'action' => $this->action->value];
 | 
			
		||||
        if (!is_null($this->text)) $values['text'] = $this->text;
 | 
			
		||||
        if (isset($this->text)) $values['text'] = $this->text;
 | 
			
		||||
        return $values;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,16 @@ class Layout
 | 
			
		||||
        echo '</body></html>';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Is this an htmx request?
 | 
			
		||||
     *
 | 
			
		||||
     * @return bool True if this is an htmx request, false if not
 | 
			
		||||
     */
 | 
			
		||||
    private static function isHtmx(): bool
 | 
			
		||||
    {
 | 
			
		||||
        return key_exists('HTTP_HX_REQUEST', $_SERVER) && !key_exists('HTTP_HX_HISTORY_RESTORE_REQUEST', $_SERVER);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create the `DOCTYPE` declaration, `html`, and `head` tags for the page
 | 
			
		||||
     *
 | 
			
		||||
@ -27,7 +37,7 @@ class Layout
 | 
			
		||||
     */
 | 
			
		||||
    public static function htmlHead(string $title): void
 | 
			
		||||
    {
 | 
			
		||||
        if (is_htmx()) {
 | 
			
		||||
        if (self::isHtmx()) {
 | 
			
		||||
            echo "<!DOCTYPE html><html lang=en><head lang=en><title>$title « myPrayerJournal</title></head>";
 | 
			
		||||
        } else {
 | 
			
		||||
            echo <<<HEAD
 | 
			
		||||
@ -36,6 +46,7 @@ class Layout
 | 
			
		||||
                <head>
 | 
			
		||||
                    <meta name=viewport content="width=device-width, initial-scale=1">
 | 
			
		||||
                    <meta name=description content="Online prayer journal - free w/Google or Microsoft account">
 | 
			
		||||
                    <meta name=htmx-config content='{"historyCacheSize":0}'>
 | 
			
		||||
                    <title>$title « myPrayerJournal</title>
 | 
			
		||||
                    <link href=https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css rel=stylesheet
 | 
			
		||||
                          integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
 | 
			
		||||
@ -130,4 +141,30 @@ class Layout
 | 
			
		||||
        </footer><?php
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generate the heading for a full or partial page result
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $title The title of the page
 | 
			
		||||
     */
 | 
			
		||||
    public static function pageHead(string $title): void
 | 
			
		||||
    {
 | 
			
		||||
        self::htmlHead($title);
 | 
			
		||||
        echo '<body>';
 | 
			
		||||
        if (!self::isHtmx()) echo '<section id=top aria-label="Top navigation">';
 | 
			
		||||
        self::navBar();
 | 
			
		||||
        echo '<main role=main>';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generate the end of the page for a full or partial page result
 | 
			
		||||
     */
 | 
			
		||||
    public static function pageFoot(): void
 | 
			
		||||
    {
 | 
			
		||||
        echo '</main>';
 | 
			
		||||
        if (!self::isHtmx()) {
 | 
			
		||||
            echo '</section>';
 | 
			
		||||
            self::htmlFoot();
 | 
			
		||||
        }
 | 
			
		||||
        echo '</body></html>';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ class Note
 | 
			
		||||
     * @param string $text The text of the note
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct(public string $asOf, public string $text) { }
 | 
			
		||||
// AFU2SCY5X2BNVRXP6W47D369
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieve notes for a given request
 | 
			
		||||
     *
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
namespace MyPrayerJournal;
 | 
			
		||||
 | 
			
		||||
use DateInterval;
 | 
			
		||||
use JsonSerializable;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -15,10 +16,26 @@ class Recurrence implements JsonSerializable
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct(public RecurrencePeriod $period, public ?int $interval = null) { }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the date/time interval for this recurrence
 | 
			
		||||
     *
 | 
			
		||||
     * @return DateInterval The interval matching the recurrence
 | 
			
		||||
     */
 | 
			
		||||
    public function interval(): DateInterval
 | 
			
		||||
    {
 | 
			
		||||
        $period = match ($this->period) {
 | 
			
		||||
            RecurrencePeriod::Immediate => 'T0S',
 | 
			
		||||
            RecurrencePeriod::Hours     => "T{$this->interval}H",
 | 
			
		||||
            RecurrencePeriod::Days      => "{$this->interval}D",
 | 
			
		||||
            RecurrencePeriod::Weeks     => ($this->interval * 7) . 'D'
 | 
			
		||||
        };
 | 
			
		||||
        return new DateInterval("P$period");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function jsonSerialize(): mixed
 | 
			
		||||
    {
 | 
			
		||||
        $values = ['period' => $this->period->value];
 | 
			
		||||
        if (!is_null($this->interval)) $values['interval'] = $this->interval;
 | 
			
		||||
        if (isset($this->interval)) $values['interval'] = $this->interval;
 | 
			
		||||
        return $values;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -56,6 +56,16 @@ class Request implements JsonSerializable
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Has this request been answered?
 | 
			
		||||
     *
 | 
			
		||||
     * @return bool True if the request is answered, false if not
 | 
			
		||||
     */
 | 
			
		||||
    public function isAnswered(): bool
 | 
			
		||||
    {
 | 
			
		||||
        return $this->history[0]->action == RequestAction::Answered;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function jsonSerialize(): mixed
 | 
			
		||||
    {
 | 
			
		||||
        $values = [
 | 
			
		||||
@ -66,8 +76,8 @@ class Request implements JsonSerializable
 | 
			
		||||
            'history'    => $this->history,
 | 
			
		||||
            'notes'      => $this->notes
 | 
			
		||||
        ];
 | 
			
		||||
        if (!is_null($this->snoozedUntil)) $values['snoozedUntil'] = $this->snoozedUntil;
 | 
			
		||||
        if (!is_null($this->showAfter))    $values['showAfter']    = $this->showAfter;
 | 
			
		||||
        if (isset($this->snoozedUntil)) $values['snoozedUntil'] = $this->snoozedUntil;
 | 
			
		||||
        if (isset($this->showAfter))    $values['showAfter']    = $this->showAfter;
 | 
			
		||||
        return $values;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -107,4 +117,53 @@ class Request implements JsonSerializable
 | 
			
		||||
             ORDER BY coalesce(last_prayed, data->>'snoozedUntil', data->>'showAfter', data->>'$.history[0].asOf')
 | 
			
		||||
            SQL, [':userId' => $_SESSION['user_id']], new DocumentMapper(self::class));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get either the user's active or answered requests
 | 
			
		||||
     *
 | 
			
		||||
     * @param bool $active True to retrieve active requests, false to retrieve answered requests
 | 
			
		||||
     * @return DocumentList<Request> The requests matching the criteria
 | 
			
		||||
     * @throws DocumentException If any is encountered
 | 
			
		||||
     */
 | 
			
		||||
    private static function forUser(bool $active = true): DocumentList
 | 
			
		||||
    {
 | 
			
		||||
        $table = Table::REQUEST;
 | 
			
		||||
        $op    = $active ? '<>' : '=';
 | 
			
		||||
        $order = $active
 | 
			
		||||
            ? "coalesce(data->>'snoozedUntil', data->>'showAfter', last_prayed, data->>'$.history[0].asOf')"
 | 
			
		||||
            : "data->>'$.history[0].asOf' DESC";
 | 
			
		||||
        return Custom::list(<<<SQL
 | 
			
		||||
            SELECT data, (
 | 
			
		||||
                   SELECT h.value->>'asOf' as_of
 | 
			
		||||
                     FROM $table i LEFT JOIN json_each(i.data, '$.history') h
 | 
			
		||||
                    WHERE r.data->>'id' = i.data->>'id' AND h.value->>'action' = 'Prayed'
 | 
			
		||||
                    LIMIT 1) last_prayed
 | 
			
		||||
              FROM $table r
 | 
			
		||||
             WHERE data->>'userId'                = :userId
 | 
			
		||||
               AND data->>'$.history[0].action' $op 'Answered'
 | 
			
		||||
             ORDER BY $order
 | 
			
		||||
            SQL, [':userId' => $_SESSION['user_id']], new DocumentMapper(self::class));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get a list of active requests for a user
 | 
			
		||||
     *
 | 
			
		||||
     * @return DocumentList<Request> The user's active requests
 | 
			
		||||
     * @throws DocumentException If any is encountered
 | 
			
		||||
     */
 | 
			
		||||
    public static function active(): DocumentList
 | 
			
		||||
    {
 | 
			
		||||
        return self::forUser();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get a list of answered requests for a user
 | 
			
		||||
     *
 | 
			
		||||
     * @return DocumentList<Request> The user's answered requests
 | 
			
		||||
     * @throws DocumentException If any is encountered
 | 
			
		||||
     */
 | 
			
		||||
    public static function answered(): DocumentList
 | 
			
		||||
    {
 | 
			
		||||
        return self::forUser(false);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,8 @@
 | 
			
		||||
 | 
			
		||||
namespace MyPrayerJournal;
 | 
			
		||||
 | 
			
		||||
use BitBadger\PDODocument\DocumentException;
 | 
			
		||||
use BitBadger\PDODocument\DocumentList;
 | 
			
		||||
use DateTimeImmutable;
 | 
			
		||||
use DateTimeZone;
 | 
			
		||||
 | 
			
		||||
@ -20,6 +22,60 @@ class UI
 | 
			
		||||
        return "<span class=material-icons>$name</span>";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Render the journal items for the current user
 | 
			
		||||
     *
 | 
			
		||||
     * @throws DocumentException If any is encountered
 | 
			
		||||
     */
 | 
			
		||||
    public static function journal(): void
 | 
			
		||||
    {
 | 
			
		||||
        Layout::bareHead();
 | 
			
		||||
        $reqs = Request::forJournal();
 | 
			
		||||
        if ($reqs->hasItems()) { ?>
 | 
			
		||||
            <section id=journalItems class="row row-cols-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-4 g-3" hx-target=this
 | 
			
		||||
                     hx-swap=outerHTML aria-label="Prayer Requests"><?php
 | 
			
		||||
            $spacer = '<span> </span>';
 | 
			
		||||
            foreach ($reqs->items() as /** @var Request $req */ $req) { ?>
 | 
			
		||||
                <div class=col>
 | 
			
		||||
                <div class="card h-100">
 | 
			
		||||
                    <div class="card-header p-0 d-flex" role=toolbar><?php
 | 
			
		||||
                        self::pageLink("/request/edit?id=$req->id", self::icon('edit'),
 | 
			
		||||
                            ['class' => 'btn btn-secondary', 'title' => 'Edit Request']); ?>
 | 
			
		||||
                        <?=$spacer?>
 | 
			
		||||
                        <button type=button class="btn btn-secondary" title="Add Notes" data-bs-toggle=modal
 | 
			
		||||
                                data-bs-target=#notesModal hx-get="/components/request/add-notes?id=<?=$req->id?>"
 | 
			
		||||
                                hx-target=#notesBody hx-swap=innerHTML><?=self::icon('comment');?></button>
 | 
			
		||||
                        <?=$spacer?>
 | 
			
		||||
                        <button type=button class="btn btn-secondary" title="Snooze Request" data-bs-toggle=modal
 | 
			
		||||
                                data-bs-target=#snoozeModal hx-get="/components/request/snooze?id=<?=$req->id?>"
 | 
			
		||||
                                hx-target=#snoozeBody hx-swap=innerHTML><?=self::icon('schedule');?></button>
 | 
			
		||||
                        <div class=flex-grow-1></div>
 | 
			
		||||
                        <button type=button class="btn btn-success w-25" hx-patch="/request/prayed?id=<?=$req->id?>"
 | 
			
		||||
                                title="Mark as Prayed"><?=self::icon('done');?></button>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class=card-body>
 | 
			
		||||
                        <p class=request-text><?=htmlentities($req->currentText());?>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="card-footer text-end text-muted px-1 py-0">
 | 
			
		||||
                        <em><?php
 | 
			
		||||
                            $lastPrayed = $req->lastPrayed();
 | 
			
		||||
                            echo 'last ' . (is_null($lastPrayed) ? 'activity': 'prayed') . ' ';
 | 
			
		||||
                            self::relativeDate($lastPrayed ?? $req->history[0]->asOf); ?>
 | 
			
		||||
                        </em>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                </div><?php
 | 
			
		||||
            } ?>
 | 
			
		||||
            </section><?php
 | 
			
		||||
        } else {
 | 
			
		||||
            UI::noResults('No Active Requests', '/request/edit?id=new', 'Add a Request', <<<'TEXT'
 | 
			
		||||
                You have no requests to be shown; see the “Active” link above for snoozed or deferred
 | 
			
		||||
                requests, and the “Answered” link for answered requests
 | 
			
		||||
                TEXT);
 | 
			
		||||
        }
 | 
			
		||||
        Layout::bareFoot();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a card when there are no results found
 | 
			
		||||
     */
 | 
			
		||||
@ -76,4 +132,42 @@ class UI
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function requestList(DocumentList $reqs): void
 | 
			
		||||
    {
 | 
			
		||||
        $btnClass = "btn btn-light mx-2";
 | 
			
		||||
        /// 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 isSnoozed  = isFuture req.SnoozedUntil
 | 
			
		||||
    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
 | 
			
		||||
            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
 | 
			
		||||
                     hx-swap=outerHTML><?php
 | 
			
		||||
                    self::pageLink("/request/full?id=$req->id", self::icon('description'),
 | 
			
		||||
                        ['class' => $btnClass, 'title' => 'View Full Request']);
 | 
			
		||||
                    if (!$req->isAnswered()) {
 | 
			
		||||
                        self::pageLink("/request/edit?id=$req->id", self::icon('edit'),
 | 
			
		||||
                            ['class' => $btnClass, 'title' => 'Edit Request']);
 | 
			
		||||
                    }
 | 
			
		||||
//        if   isSnoozed then restoreBtn "cancel-snooze" "Cancel Snooze"
 | 
			
		||||
//        elif isPending then restoreBtn "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 []
 | 
			
		||||
//                ]
 | 
			
		||||
?>
 | 
			
		||||
                </div><?php
 | 
			
		||||
            } ?>
 | 
			
		||||
        </div><?php
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,54 +1,10 @@
 | 
			
		||||
<?php declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
use MyPrayerJournal\{Auth, Layout, Request, UI};
 | 
			
		||||
use MyPrayerJournal\{Auth, UI};
 | 
			
		||||
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'GET') not_found();
 | 
			
		||||
require '../../start.php';
 | 
			
		||||
 | 
			
		||||
Auth::requireUser(false);
 | 
			
		||||
Layout::bareHead();
 | 
			
		||||
 | 
			
		||||
$reqs = Request::forJournal();
 | 
			
		||||
if ($reqs->hasItems()) { ?>
 | 
			
		||||
    <section id=journalItems class="row row-cols-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-4 g-3" hx-target=this
 | 
			
		||||
             hx-swap=outerHTML aria-label="Prayer Requests"><?php
 | 
			
		||||
        $spacer = '<span> </span>';
 | 
			
		||||
        foreach ($reqs->items() as /** @var Request $req */ $req) { ?>
 | 
			
		||||
            <div class=col>
 | 
			
		||||
                <div class="card h-100">
 | 
			
		||||
                    <div class="card-header p-0 d-flex" role=toolbar><?php
 | 
			
		||||
                        UI::pageLink("/request/edit?id=$req->id", UI::icon('edit'),
 | 
			
		||||
                            ['class' => 'btn btn-secondary', 'title' => 'Edit Request']); ?>
 | 
			
		||||
                        <?=$spacer?>
 | 
			
		||||
                        <button type=button class="btn btn-secondary" title="Add Notes" data-bs-toggle=modal
 | 
			
		||||
                                data-bs-target=#notesModal hx-get="/components/request/add-notes?id=<?=$req->id?>"
 | 
			
		||||
                                hx-target=#notesBody hx-swap=innerHTML><?=UI::icon('comment');?></button>
 | 
			
		||||
                        <?=$spacer?>
 | 
			
		||||
                        <button type=button class="btn btn-secondary" title="Snooze Request" data-bs-toggle=modal
 | 
			
		||||
                                data-bs-target=#snoozeModal hx-get="/components/request/snooze?id=<?=$req->id?>"
 | 
			
		||||
                                hx-target=#snoozeBody hx-swap=innerHTML><?=UI::icon('schedule');?></button>
 | 
			
		||||
                        <div class=flex-grow-1></div>
 | 
			
		||||
                        <button type=button class="btn btn-success w-25" hx-patch="/request/prayed?id=<?=$req->id?>"
 | 
			
		||||
                                title="Mark as Prayed"><?=UI::icon('done');?></button>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class=card-body>
 | 
			
		||||
                        <p class=request-text><?=htmlentities($req->currentText());?>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="card-footer text-end text-muted px-1 py-0">
 | 
			
		||||
                        <em><?php
 | 
			
		||||
                            $lastPrayed = $req->lastPrayed();
 | 
			
		||||
                            echo 'last ' . (is_null($lastPrayed) ? 'activity': 'prayed') . ' ';
 | 
			
		||||
                            UI::relativeDate($lastPrayed ?? $req->history[0]->asOf); ?>
 | 
			
		||||
                        </em>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div><?php
 | 
			
		||||
        } ?>
 | 
			
		||||
    </section><?php
 | 
			
		||||
} else {
 | 
			
		||||
    UI::noResults('No Active Requests', '/request/edit?id=new', 'Add a Request', <<<'TEXT'
 | 
			
		||||
        You have no requests to be shown; see the “Active” link above for snoozed or deferred requests, and
 | 
			
		||||
        the “Answered” link for answered requests
 | 
			
		||||
        TEXT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Layout::bareFoot();
 | 
			
		||||
UI::journal();
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,11 @@
 | 
			
		||||
<?php declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
require '../start.php';
 | 
			
		||||
use MyPrayerJournal\Layout;
 | 
			
		||||
 | 
			
		||||
page_head('Documentation'); ?>
 | 
			
		||||
require '../start.php';
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'GET') not_found();
 | 
			
		||||
 | 
			
		||||
Layout::pageHead('Documentation'); ?>
 | 
			
		||||
<article class="container mt-3">
 | 
			
		||||
    <h2 class=mb-3>Documentation</h2>
 | 
			
		||||
 | 
			
		||||
@ -96,4 +99,4 @@ page_head('Documentation'); ?>
 | 
			
		||||
            and strengthen your prayer life.
 | 
			
		||||
    </ul>
 | 
			
		||||
</article><?php
 | 
			
		||||
page_foot();
 | 
			
		||||
Layout::pageFoot();
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,11 @@
 | 
			
		||||
<?php declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
require '../start.php';
 | 
			
		||||
use MyPrayerJournal\Layout;
 | 
			
		||||
 | 
			
		||||
page_head('Welcome'); ?>
 | 
			
		||||
require '../start.php';
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'GET') not_found();
 | 
			
		||||
 | 
			
		||||
Layout::pageHead('Welcome'); ?>
 | 
			
		||||
<article class="container mt-3">
 | 
			
		||||
    <p> 
 | 
			
		||||
    <p>myPrayerJournal is a place where individuals can record their prayer requests, record that they prayed for them,
 | 
			
		||||
@ -12,4 +15,4 @@ page_head('Welcome'); ?>
 | 
			
		||||
        On” link above, and log on with either a Microsoft or Google account. You can also learn more about the
 | 
			
		||||
        site at the “Docs” link, also above.
 | 
			
		||||
</article><?php
 | 
			
		||||
page_foot();
 | 
			
		||||
Layout::pageFoot();
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,15 @@
 | 
			
		||||
<?php declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
use MyPrayerJournal\Auth;
 | 
			
		||||
use MyPrayerJournal\UI;
 | 
			
		||||
use MyPrayerJournal\{Auth, Layout, UI};
 | 
			
		||||
 | 
			
		||||
require '../start.php';
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'GET') not_found();
 | 
			
		||||
 | 
			
		||||
Auth::requireUser();
 | 
			
		||||
 | 
			
		||||
$user = Auth::user();
 | 
			
		||||
$name = $user['given_name'] ?? 'Your';
 | 
			
		||||
page_head('Welcome'); ?>
 | 
			
		||||
Layout::pageHead('Journal'); ?>
 | 
			
		||||
<article class="container-fluid mt-3">
 | 
			
		||||
    <h2 class=pb-3><?=$name?><?=$name == 'Your' ? '' : '’s'?> Prayer Journal</h2>
 | 
			
		||||
    <p class="pb-3 text-center"><?php
 | 
			
		||||
@ -46,5 +46,5 @@ page_head('Welcome'); ?>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</article><?php
 | 
			
		||||
page_foot();
 | 
			
		||||
Layout::pageFoot();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,11 @@
 | 
			
		||||
<?php declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
require '../../start.php';
 | 
			
		||||
use MyPrayerJournal\Layout;
 | 
			
		||||
 | 
			
		||||
page_head('Privacy Policy'); ?>
 | 
			
		||||
require '../../start.php';
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'GET') not_found();
 | 
			
		||||
 | 
			
		||||
Layout::pageHead('Privacy Policy'); ?>
 | 
			
		||||
<article class="container mt-3">
 | 
			
		||||
    <h2 class=mb-2>Privacy Policy</h2>
 | 
			
		||||
    <h6 class="text-muted pb-3">as of May 21<sup>st</sup>, 2018</h6>
 | 
			
		||||
@ -66,4 +69,4 @@ page_head('Privacy Policy'); ?>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</article><?php
 | 
			
		||||
page_foot();
 | 
			
		||||
Layout::pageFoot();
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,11 @@
 | 
			
		||||
<?php declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
use MyPrayerJournal\UI;
 | 
			
		||||
use MyPrayerJournal\{Layout, UI};
 | 
			
		||||
 | 
			
		||||
require '../../start.php';
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'GET') not_found();
 | 
			
		||||
 | 
			
		||||
page_head('Terms of Service'); ?>
 | 
			
		||||
Layout::pageHead('Terms of Service'); ?>
 | 
			
		||||
<article class="container mt-3">
 | 
			
		||||
    <h2 class=mb-2>Terms of Service</h2>
 | 
			
		||||
    <h6 class="text-muted pb-3">as of May 21<sup>st</sup>, 2018</h6>
 | 
			
		||||
@ -55,4 +56,4 @@ page_head('Terms of Service'); ?>
 | 
			
		||||
        You may also wish to review our <?php UI::pageLink('/legal/privacy-policy', 'privacy policy'); ?> to learn how
 | 
			
		||||
        we handle your data.
 | 
			
		||||
</article><?php
 | 
			
		||||
page_foot();
 | 
			
		||||
Layout::pageFoot();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										105
									
								
								src/public/request/edit.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/public/request/edit.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,105 @@
 | 
			
		||||
<?php declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
use MyPrayerJournal\{Auth, Layout, RecurrencePeriod, Request, RequestAction, UI};
 | 
			
		||||
 | 
			
		||||
require '../../start.php';
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'GET') not_found();
 | 
			
		||||
 | 
			
		||||
Auth::requireUser();
 | 
			
		||||
 | 
			
		||||
$isNew = $_GET['id'] == 'new';
 | 
			
		||||
 | 
			
		||||
$req = match ($isNew) {
 | 
			
		||||
    true  => new Request('new'),
 | 
			
		||||
    false => Request::byId($_GET['id'])
 | 
			
		||||
};
 | 
			
		||||
if (!$req) not_found();
 | 
			
		||||
 | 
			
		||||
$cancelLink = match (true) {
 | 
			
		||||
    str_ends_with($_SERVER['HTTP_REFERER'] ?? '', 'active.php')  => '/requests/active',
 | 
			
		||||
    str_ends_with($_SERVER['HTTP_REFERER'] ?? '', 'snoozed.php') => '/requests/snoozed',
 | 
			
		||||
    default                                                      => '/journal'
 | 
			
		||||
};
 | 
			
		||||
$action = $_GET['id'] == 'new' ? 'Add' : 'Edit';
 | 
			
		||||
 | 
			
		||||
Layout::pageHead("$action Prayer Request");?>
 | 
			
		||||
<article class=container>
 | 
			
		||||
    <h2 class=pb-3><?=$action?> Prayer Request</h2>
 | 
			
		||||
    <form <?=$isNew ? 'hx-post' : 'hx-patch'?>=/request/save hx-target=#top hx-push-url=true>
 | 
			
		||||
        <input type=hidden name=requestId value=<?=$req->id?>>
 | 
			
		||||
        <input type=hidden name=returnTo value=<?=$cancelLink?>>
 | 
			
		||||
        <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><?=$req->currentText()?></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=<?=RequestAction::Updated->value?>
 | 
			
		||||
                           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=<?=RequestAction::Prayed->value?>>
 | 
			
		||||
                    <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=<?=RequestAction::Answered->value?>>
 | 
			
		||||
                    <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> <em class=text-muted>After prayer, request reappears…</em>
 | 
			
		||||
                <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=<?=RecurrencePeriod::Immediate->value?>
 | 
			
		||||
                               onclick="mpj.edit.toggleRecurrence(event)"<?php
 | 
			
		||||
                               if ($req->recurrence->period == RecurrencePeriod::Immediate) echo ' 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
 | 
			
		||||
                               if ($req->recurrence->period <> RecurrencePeriod::Immediate) echo ' checked'; ?>>
 | 
			
		||||
                        <label for=rO>Every…</label>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="form-floating mx-2">
 | 
			
		||||
                        <input type=number class=form-control id=recurCount name=recurCount placeholder=0 required
 | 
			
		||||
                               value=<?=$req->recurrence->interval ?? 0?> style="width:6rem;"<?php
 | 
			
		||||
                               if ($req->recurrence->period == RecurrencePeriod::Immediate) echo ' 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
 | 
			
		||||
                                if ($req->recurrence->period == RecurrencePeriod::Immediate) echo ' disabled'; ?>>
 | 
			
		||||
                            <option value=<?=RecurrencePeriod::Hours->value?><?php
 | 
			
		||||
                                    if ($req->recurrence->period == RecurrencePeriod::Hours) echo ' selected'; ?>>
 | 
			
		||||
                                hours
 | 
			
		||||
                            </option>
 | 
			
		||||
                            <option value=<?=RecurrencePeriod::Days->value?><?php
 | 
			
		||||
                                    if ($req->recurrence->period == RecurrencePeriod::Days) echo ' selected'; ?>>
 | 
			
		||||
                                days
 | 
			
		||||
                            </option>
 | 
			
		||||
                            <option value=<?=RecurrencePeriod::Weeks->value?><?php
 | 
			
		||||
                                    if ($req->recurrence->period == RecurrencePeriod::Weeks) echo ' 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><?=UI::icon('save');?> Save</button><?php
 | 
			
		||||
            UI::pageLink($cancelLink, UI::icon('arrow_back') . ' Cancel', ['class' => 'btn btn-secondary ms-2']); ?>
 | 
			
		||||
        </div>
 | 
			
		||||
    </form>
 | 
			
		||||
</article><?php
 | 
			
		||||
Layout::pageFoot();
 | 
			
		||||
							
								
								
									
										49
									
								
								src/public/request/full.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/public/request/full.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
<?php declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
use MyPrayerJournal\{Auth, History, Layout, Note, Request, RequestAction, UI};
 | 
			
		||||
 | 
			
		||||
require '../../start.php';
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'GET') not_found();
 | 
			
		||||
 | 
			
		||||
Auth::requireUser();
 | 
			
		||||
 | 
			
		||||
$req = Request::byId($_GET['id']);
 | 
			
		||||
if (!$req) not_found();
 | 
			
		||||
 | 
			
		||||
$answered = $req->isAnswered() ? new DateTimeImmutable($req->history[0]->asOf) : null;
 | 
			
		||||
$prayed   = sizeof(array_filter($req->history, fn(History $hist) => $hist->action == RequestAction::Prayed));
 | 
			
		||||
$daysOpen =
 | 
			
		||||
    (($answered ?? new DateTimeImmutable('now'))->getTimestamp()
 | 
			
		||||
        - (new DateTimeImmutable(end($req->history)->asOf))->getTimestamp()) / 86400;
 | 
			
		||||
 | 
			
		||||
$logs = array_merge(
 | 
			
		||||
    array_map(fn(Note $note) => [new DateTimeImmutable($note->asOf), 'Notes', $note->text], $req->notes),
 | 
			
		||||
    array_map(fn(History $hist) => [new DateTimeImmutable($hist->asOf), $hist->action->value, $hist->text ?? ''],
 | 
			
		||||
        $req->history));
 | 
			
		||||
usort($logs, fn($a, $b) => $a[0] > $b[0] ? -1 : 1);
 | 
			
		||||
if ($req->isAnswered()) array_shift($logs);
 | 
			
		||||
 | 
			
		||||
Layout::pageHead('Full Request');?>
 | 
			
		||||
<article class="container mt-3">
 | 
			
		||||
    <div class=card>
 | 
			
		||||
        <h5 class=card-header>Full Prayer Request</h5>
 | 
			
		||||
        <div class=card-body>
 | 
			
		||||
            <h6 class="card-subtitle text-muted mb-2"><?php
 | 
			
		||||
                if (!is_null($answered)) { ?>
 | 
			
		||||
                    Answered <?=$answered->format('F j, Y')?> (<?php UI::relativeDate($req->history[0]->asOf); ?>)
 | 
			
		||||
                    •<?php
 | 
			
		||||
                } ?>
 | 
			
		||||
                Prayed <?=number_format($prayed)?> times • Open <?=number_format($daysOpen)?> days
 | 
			
		||||
            </h6>
 | 
			
		||||
            <p class=card-text><?=htmlentities($req->currentText())?>
 | 
			
		||||
        </div>
 | 
			
		||||
        <ul class="list-group list-group-flush"><?php
 | 
			
		||||
            foreach ($logs as $log) { ?>
 | 
			
		||||
                <li class=list-group-item>
 | 
			
		||||
                    <p class=m-0><?=$log[1]?>  <small><em><?=$log[0]->format('F j, Y')?></em></small><?php
 | 
			
		||||
                    if ($log[2] <> '') echo '<p class="mt-2 mb-0">' . htmlentities($log[2]);
 | 
			
		||||
            } ?>
 | 
			
		||||
        </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
</article><?php
 | 
			
		||||
Layout::pageFoot();
 | 
			
		||||
							
								
								
									
										24
									
								
								src/public/request/prayed.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/public/request/prayed.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
<?php declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
use MyPrayerJournal\{Auth, History, RecurrencePeriod, Request, RequestAction, Table, UI};
 | 
			
		||||
use BitBadger\PDODocument\Patch;
 | 
			
		||||
 | 
			
		||||
require '../../start.php';
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'PATCH') not_found();
 | 
			
		||||
 | 
			
		||||
Auth::requireUser(false);
 | 
			
		||||
 | 
			
		||||
$req = Request::byId($_GET['id']);
 | 
			
		||||
if (!$req) not_found();
 | 
			
		||||
 | 
			
		||||
$now = new DateTimeImmutable('now');
 | 
			
		||||
 | 
			
		||||
array_unshift($req->history, new History($now->format('c'), RequestAction::Prayed));
 | 
			
		||||
$patch = ['history' => $req->history];
 | 
			
		||||
 | 
			
		||||
if ($req->recurrence->period <> RecurrencePeriod::Immediate) {
 | 
			
		||||
    $patch['showAfter'] = $now->add($req->recurrence->interval())->format('c');
 | 
			
		||||
}
 | 
			
		||||
Patch::byId(Table::REQUEST, $req->id, $patch);
 | 
			
		||||
 | 
			
		||||
UI::journal();
 | 
			
		||||
							
								
								
									
										51
									
								
								src/public/request/save.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/public/request/save.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
<?php declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
use MyPrayerJournal\{Auth, History, Recurrence, RecurrencePeriod, Request, RequestAction, Table};
 | 
			
		||||
use BitBadger\PDODocument\{Document, Patch, RemoveFields};
 | 
			
		||||
 | 
			
		||||
require '../../start.php';
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'POST' && $_SERVER['REQUEST_METHOD'] <> 'PATCH') not_found();
 | 
			
		||||
 | 
			
		||||
Auth::requireUser(false);
 | 
			
		||||
 | 
			
		||||
$now        = new DateTimeImmutable('now');
 | 
			
		||||
$recurrence = new Recurrence(RecurrencePeriod::from($_POST['recurType'] ?? $_PATCH['recurType']));
 | 
			
		||||
if ($recurrence->period <> RecurrencePeriod::Immediate) {
 | 
			
		||||
    $recurrence->interval = (int)($_POST['recurCount'] ?? $_PATCH['recurCount']);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
switch ($_SERVER['REQUEST_METHOD']) {
 | 
			
		||||
    case 'POST':
 | 
			
		||||
        Document::insert(Table::REQUEST, new Request(
 | 
			
		||||
            enteredOn:  $now->format('c'),
 | 
			
		||||
            userId:     $_SESSION['user_id'],
 | 
			
		||||
            recurrence: $recurrence,
 | 
			
		||||
            history:    [new History($now->format('c'), RequestAction::Created, $_POST['requestText'])]));
 | 
			
		||||
        //Messages.pushSuccess ctx "Added prayer request" "/journal"
 | 
			
		||||
        header('Location: /journal');
 | 
			
		||||
        http_response_code(303);
 | 
			
		||||
        exit;
 | 
			
		||||
 | 
			
		||||
    case 'PATCH':
 | 
			
		||||
        $req = Request::byId($_PATCH['requestId']);
 | 
			
		||||
        if (!$req) not_found();
 | 
			
		||||
        $patch = [];
 | 
			
		||||
        // update recurrence if changed
 | 
			
		||||
        if ($recurrence != $req->recurrence) {
 | 
			
		||||
            $patch['recurrence'] = $recurrence;
 | 
			
		||||
            if ($recurrence->period == RecurrencePeriod::Immediate) {
 | 
			
		||||
                RemoveFields::byId(Table::REQUEST, $req->id, ['showAfter']);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // append history
 | 
			
		||||
        $upd8Text = trim($_PATCH['requestText']);
 | 
			
		||||
        $text     = $upd8Text == '' || $upd8Text == $req->currentText() ? null : $upd8Text;
 | 
			
		||||
        array_unshift($req->history, new History($now->format('c'), RequestAction::from($_PATCH['status']), $text));
 | 
			
		||||
        $patch['history'] = $req->history;
 | 
			
		||||
        Patch::byId(Table::REQUEST, $req->id, $patch);
 | 
			
		||||
        //Messages.pushSuccess ctx "Prayer request updated successfully" nextUrl
 | 
			
		||||
        // TODO: make redirect that filters out non-local URLs
 | 
			
		||||
        header('Location: ' . $_PATCH['returnTo']);
 | 
			
		||||
        http_response_code(303);
 | 
			
		||||
        exit;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/public/requests/active.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/public/requests/active.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::active();
 | 
			
		||||
 | 
			
		||||
Layout::pageHead('Active Requests'); ?>
 | 
			
		||||
<article class="container mt-3">
 | 
			
		||||
    <h2 class=pb-3>Active Requests</h2><?php
 | 
			
		||||
    if ($reqs->hasItems()) {
 | 
			
		||||
        UI::requestList($reqs);
 | 
			
		||||
    } else {
 | 
			
		||||
        UI::noResults('No Active Requests', '/journal', 'Return to your journal',
 | 
			
		||||
            'Your prayer journal has no active requests');
 | 
			
		||||
    } ?>
 | 
			
		||||
</article><?php
 | 
			
		||||
Layout::pageFoot();
 | 
			
		||||
							
								
								
									
										24
									
								
								src/public/requests/answered.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/public/requests/answered.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
<?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::answered();
 | 
			
		||||
 | 
			
		||||
Layout::pageHead('Answered Requests'); ?>
 | 
			
		||||
<article class="container mt-3">
 | 
			
		||||
    <h2 class=pb-3>Answered Requests</h2><?php
 | 
			
		||||
    if ($reqs->hasItems()) {
 | 
			
		||||
        UI::requestList($reqs);
 | 
			
		||||
    } else {
 | 
			
		||||
        UI::noResults('No Answered Requests', '/journal', 'Return to your journal', <<<'TEXT'
 | 
			
		||||
            Your prayer journal has no answered requests; once you have marked one as “Answered”, it will
 | 
			
		||||
            appear here
 | 
			
		||||
            TEXT);
 | 
			
		||||
    } ?>
 | 
			
		||||
</article><?php
 | 
			
		||||
Layout::pageFoot();
 | 
			
		||||
@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
use MyPrayerJournal\Auth;
 | 
			
		||||
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] <> 'GET') not_found();
 | 
			
		||||
require '../../start.php';
 | 
			
		||||
 | 
			
		||||
Auth::logOn();
 | 
			
		||||
 | 
			
		||||
@ -14,9 +14,9 @@ const MPJ_VERSION = '4.0.0-alpha1';
 | 
			
		||||
if (php_sapi_name() != 'cli') {
 | 
			
		||||
    session_start();
 | 
			
		||||
 | 
			
		||||
    $auth0_session = Auth::client()->getCredentials();
 | 
			
		||||
    if (!is_null($auth0_session)) {
 | 
			
		||||
        $_SESSION['user_id'] = $auth0_session->user['sub'];
 | 
			
		||||
    $auth0_user = Auth::user();
 | 
			
		||||
    if (!is_null($auth0_user)) {
 | 
			
		||||
        $_SESSION['user_id'] = $auth0_user['sub'];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -24,31 +24,14 @@ Configuration::$pdoDSN = 'sqlite:' . implode(DIRECTORY_SEPARATOR, [__DIR__, 'dat
 | 
			
		||||
Configuration::$mode   = Mode::SQLite;
 | 
			
		||||
Definition::ensureTable(Table::REQUEST);
 | 
			
		||||
 | 
			
		||||
$_PATCH = [];
 | 
			
		||||
if ($_SERVER['REQUEST_METHOD'] ?? '' == 'PATCH') parse_str(file_get_contents('php://input'), $_PATCH);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Is this an htmx request?
 | 
			
		||||
 *
 | 
			
		||||
 * @return bool True if this is an htmx request, false if not
 | 
			
		||||
 * Return a 404 and exit
 | 
			
		||||
 */
 | 
			
		||||
function is_htmx(): bool
 | 
			
		||||
function not_found(): never
 | 
			
		||||
{
 | 
			
		||||
    return key_exists('HTTP_HX_REQUEST', $_SERVER) && !key_exists('HTTP_HX_HISTORY_RESTORE_REQUEST', $_SERVER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function page_head(string $title): void
 | 
			
		||||
{
 | 
			
		||||
    Layout::htmlHead($title);
 | 
			
		||||
    echo '<body>';
 | 
			
		||||
    if (!is_htmx()) echo '<section id=top aria-label="Top navigation">';
 | 
			
		||||
    Layout::navBar();
 | 
			
		||||
    echo '<main role=main>';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function page_foot(): void
 | 
			
		||||
{
 | 
			
		||||
    echo '</main>';
 | 
			
		||||
    if (!is_htmx()) {
 | 
			
		||||
        echo '</section>';
 | 
			
		||||
        Layout::htmlFoot();
 | 
			
		||||
    }
 | 
			
		||||
    echo '</body></html>';
 | 
			
		||||
    http_response_code(404);
 | 
			
		||||
    die('Not found');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user