diff --git a/src/Controller/UserDashboardController.php b/src/Controller/UserDashboardController.php index 214f34c..1da9785 100644 --- a/src/Controller/UserDashboardController.php +++ b/src/Controller/UserDashboardController.php @@ -3,20 +3,59 @@ namespace Origo\Controller; use Origo\Entity\User; +use Origo\Controller\ControllerBase; use Origo\Controller\ControllerInterface; use Origo\Services\Template; use Origo\Services\Request; -use Origo\Services\Renderer; -class UserDashboardController implements ControllerInterface { +class UserDashboardController extends ControllerBase implements ControllerInterface { - /** - * Get the response for the dashboard. - */ public function getResponse(): string { - $template = new Template('dashboard.html'); + $user = new User(); + $user->loadUserFromSession($this->request->getCookie('ORIGOSESS')); + $user_id = $user->get('id'); - return $template->render(); + $query = $this->database->query(" + SELECT pv.page, pv.title, pv.referrer, pv.ip, pv.language, pv.screen_res, pv.timestamp + FROM pageviews pv + JOIN user_accounts ua ON pv.account_id = ua.account_id + WHERE ua.user_id = :user_id + ORDER BY pv.timestamp DESC + "); + $query->bindParam(':user_id', $user_id); + $query->execute(); + $results = $query->fetchAll(); + + $rows = ''; + if ($results) { + foreach ($results as $row) { + $page = htmlspecialchars($row['page']); + $title = htmlspecialchars($row['title']); + $referrer = htmlspecialchars($row['referrer']); + $ip = htmlspecialchars($row['ip']); + $language = htmlspecialchars($row['language']); + $screen_res = htmlspecialchars($row['screen_res']); + $timestamp = htmlspecialchars($row['timestamp']); + + $rows .= " + + {$title} + {$page} + {$referrer} + {$ip} + {$language} + {$screen_res} + {$timestamp} + "; + } + } else { + $rows = 'No pageviews yet.'; + } + + $template = new Template('dashboard.html'); + return $template->render([ + 'pageview_rows' => $rows, + ]); } } diff --git a/templates/dash-body.html b/templates/dash-body.html index aa5c124..e078636 100644 --- a/templates/dash-body.html +++ b/templates/dash-body.html @@ -5,9 +5,30 @@

Actions

+ +
+

Pageviews

+
+ + + + + + + + + + + + + + {{ pageview_rows }} + +
TitlePageReferrerIPLanguageScreenTimestamp
+
+
diff --git a/theme/partials/dashboard.scss b/theme/partials/dashboard.scss index 7011248..6c0f8d7 100644 --- a/theme/partials/dashboard.scss +++ b/theme/partials/dashboard.scss @@ -1,8 +1,8 @@ #dashboard { .dashboard-container { - max-width: 800px; + max-width: 1200px; margin: auto; - padding-bottom: 100px; + padding: 0 24px 100px; } h1.page-title { @@ -15,11 +15,71 @@ justify-content: flex-start; list-style: none; padding: 0; - li { display: flex; align-items: center; gap: 1rem; } - } + } + + #pageviews { + margin-top: 2rem; + + h2 { + margin-bottom: 1rem; + color: var(--color-text-primary); + font-weight: var(--font-weight-bold); + } + + .table-wrapper { + overflow-x: auto; + border-radius: 8px; + border: 1px solid var(--color-light-gray); + } + + table.data-table { + width: 100%; + border-collapse: collapse; + font-size: var(--font-size-small); + white-space: nowrap; + + thead tr { + background: var(--color-primary); + color: var(--color-soft-cream); + + th { + padding: 0.75rem 1rem; + text-align: left; + font-weight: var(--font-weight-bold); + } + } + + tbody { + tr { + border-bottom: 1px solid var(--color-light-gray); + transition: background 0.15s ease; + + &:nth-child(even) { + background: var(--color-light-gray); + } + + &:nth-child(odd) { + background: var(--color-soft-cream); + } + + &:hover { + background: var(--color-surface); + } + + td { + padding: 0.65rem 1rem; + color: var(--color-text-primary); + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + } + } + } + } + } } diff --git a/theme/style.css b/theme/style.css index 7d46e2d..7dbf2bb 100644 --- a/theme/style.css +++ b/theme/style.css @@ -482,9 +482,9 @@ img { } #dashboard .dashboard-container { - max-width: 800px; + max-width: 1200px; margin: auto; - padding-bottom: 100px; + padding: 0 24px 100px; } #dashboard h1.page-title { margin-bottom: 0; @@ -501,6 +501,54 @@ img { align-items: center; gap: 1rem; } +#dashboard #pageviews { + margin-top: 2rem; +} +#dashboard #pageviews h2 { + margin-bottom: 1rem; + color: var(--color-text-primary); + font-weight: var(--font-weight-bold); +} +#dashboard #pageviews .table-wrapper { + overflow-x: auto; + border-radius: 8px; + border: 1px solid var(--color-light-gray); +} +#dashboard #pageviews table.data-table { + width: 100%; + border-collapse: collapse; + font-size: var(--font-size-small); + white-space: nowrap; +} +#dashboard #pageviews table.data-table thead tr { + background: var(--color-primary); + color: var(--color-soft-cream); +} +#dashboard #pageviews table.data-table thead tr th { + padding: 0.75rem 1rem; + text-align: left; + font-weight: var(--font-weight-bold); +} +#dashboard #pageviews table.data-table tbody tr { + border-bottom: 1px solid var(--color-light-gray); + transition: background 0.15s ease; +} +#dashboard #pageviews table.data-table tbody tr:nth-child(even) { + background: var(--color-light-gray); +} +#dashboard #pageviews table.data-table tbody tr:nth-child(odd) { + background: var(--color-soft-cream); +} +#dashboard #pageviews table.data-table tbody tr:hover { + background: var(--color-surface); +} +#dashboard #pageviews table.data-table tbody tr td { + padding: 0.65rem 1rem; + color: var(--color-text-primary); + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; +} #task-list .container { max-width: 800px;