Files
dobetternorge-tools/includes/layout.php
T
daveadmin b912ff22bc Dashboard account section, profile API, and CSS account panels
- SSO session auth gating on all protected pages
- dashboard.php: account section (profile form + workspace panel),
  onboarding prompt modal, overview bar extracted to CSS classes,
  dashboard.css linked in page head
- api/profile.php: save/dismiss endpoint for optional profile fields
- assets/css/dashboard.css: account grid, dash-account-panel,
  dash-profile-form, profile-prompt-backdrop modal, overview bar
  classes, dash-section-kicker, dash-tier-badge base styles
- includes/bootstrap.php: dbnToolsMainUserProfile,
  dbnToolsProfileNeedsPrompt, dbnToolsRequirePageAuth
- scripts/sql/004_user_profile_fields.sql: nullable phone, address,
  and profile_prompt_dismissed_at columns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 18:49:34 +02:00

112 lines
5.4 KiB
PHP

<?php
declare(strict_types=1);
// Required vars: $toolName (string), $toolTitle (string), $toolKind (string), $toolBadge (string)
require_once __DIR__ . '/bootstrap.php';
$layoutIsGuest = !dbnToolsIsAuthenticated();
if ($layoutIsGuest) {
dbnToolsRequirePageAuth($_SERVER['REQUEST_URI'] ?? '/dashboard.php');
}
$uiLang = dbnToolsCurrentLanguage();
$navItems = dbnToolsLaunchedTools($uiLang);
$toolName = $toolName ?? 'transcribe';
$toolMeta = $navItems[$toolName] ?? null;
$toolTitle = $toolMeta['label'] ?? ($toolTitle ?? dbnToolsT('suite_title', $uiLang));
$toolKind = $toolMeta['sub'] ?? ($toolKind ?? '');
$toolBadge = $toolMeta['badge'] ?? ($toolBadge ?? '');
$langPath = strtok((string)($_SERVER['REQUEST_URI'] ?? '/'), '?') ?: '/';
// Credit balance — only meaningful for authenticated free-tier users
$layoutFreeTierBalance = -1;
if (!$layoutIsGuest && dbnToolsIsFreeTier()) {
require_once __DIR__ . '/FreeTier.php';
$layoutFreeTierBalance = FreeTier::balance((int)$_SESSION['dbn_tools_sso_uid']);
}
// User identity for topbar (null for guests)
$layoutAuthUser = $layoutIsGuest ? null : dbnToolsAuthenticatedUser();
$layoutUserDisplay = '';
if ($layoutAuthUser !== null) {
$email = (string)($layoutAuthUser['email'] ?? '');
// Show only local part (before @) to keep topbar compact
$layoutUserDisplay = strstr($email, '@', true) ?: $email;
}
$layoutReturnUrl = urlencode($_SERVER['REQUEST_URI'] ?? '/');
// $layoutAuthUser / $layoutUserDisplay kept for backwards compat (now also used by nav.php internally)
?>
<!doctype html>
<html lang="<?= htmlspecialchars($uiLang) ?>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= htmlspecialchars($toolTitle) ?> - Do Better Norge</title>
<?php if ($layoutFreeTierBalance >= 0): ?>
<meta name="dbn-credits" content="<?= $layoutFreeTierBalance ?>">
<?php endif; ?>
<link rel="stylesheet" href="assets/css/tools.css">
<link rel="stylesheet" href="assets/css/dbn-tools-redesign.css">
</head>
<body data-authenticated="<?= $layoutIsGuest ? 'false' : 'true' ?>" data-active-tool="<?= htmlspecialchars($toolName) ?>">
<script>
window.DBN_TOOLS_AUTHENTICATED = <?= $layoutIsGuest ? 'false' : 'true' ?>;
window.DBN_TOOLS_LANG = <?= json_encode($uiLang, JSON_UNESCAPED_UNICODE) ?>;
<?php if ($layoutFreeTierBalance >= 0): ?>
window.DBN_FREE_TIER_BALANCE = <?= $layoutFreeTierBalance ?>;
window.DBN_USER_TIER = <?= json_encode(FreeTier::tier((int)$_SESSION['dbn_tools_sso_uid'])) ?>;
<?php endif; ?>
</script>
<?php if (date('m-d') === '05-17'): ?>
<div id="syttendeMaiBanner" class="syttende-mai-banner" role="banner">
<span>🇳🇴 Gratulerer med dagen! Free access today — explore our AI legal tools for Norwegian family law.</span>
<button onclick="this.parentElement.remove()" aria-label="Dismiss" class="syttende-mai-close">✕</button>
</div>
<?php endif; ?>
<?php include __DIR__ . '/nav.php'; ?>
<?php if ($layoutIsGuest): ?>
<div id="guestBanner" class="guest-banner" role="alert" aria-live="polite">
<span>Du er ikke innlogget — verktøyene krever konto for å fungere.</span>
<a href="/?return=<?= $layoutReturnUrl ?>" class="guest-banner__login">Logg inn</a>
<button id="guestBannerClose" class="guest-banner__close" aria-label="Lukk">✕</button>
</div>
<?php endif; ?>
<main id="appShell" class="app-shell">
<div class="dbn-context-bar" role="note">
<span class="dbn-context-bar__tag"><?= htmlspecialchars(dbnToolsT('context_bar_tag', $uiLang)) ?></span>
<nav class="dbn-context-bar__links" aria-label="About">
<a href="/why-ours.php<?= $uiLang !== 'en' ? '?lang=' . urlencode($uiLang) : '' ?>"><?= htmlspecialchars(dbnToolsT('context_bar_why', $uiLang)) ?></a>
<a href="/pricing.php<?= $uiLang !== 'en' ? '?lang=' . urlencode($uiLang) : '' ?>"><?= htmlspecialchars(dbnToolsT('context_bar_pricing', $uiLang)) ?></a>
<a href="/mcp-tool.php<?= $uiLang !== 'en' ? '?lang=' . urlencode($uiLang) : '' ?>"><?= htmlspecialchars(dbnToolsT('context_bar_mcp', $uiLang)) ?></a>
<a href="/privacy.php<?= $uiLang !== 'en' ? '?lang=' . urlencode($uiLang) : '' ?>"><?= htmlspecialchars(dbnToolsT('context_bar_privacy', $uiLang)) ?></a>
</nav>
</div>
<div class="disclaimer" role="note">
<?= htmlspecialchars(dbnToolsT('disclaimer', $uiLang)) ?>
</div>
<section class="workspace" aria-label="Legal tools workspace">
<nav class="tool-rail" aria-label="Tools">
<?php foreach ($navItems as $slug => $item): ?>
<a href="<?= htmlspecialchars($item['url']) ?>" class="tool-tab<?= $slug === $toolName ? ' is-active' : '' ?>" data-tool="<?= htmlspecialchars($slug) ?>"<?= $slug === $toolName ? ' aria-current="page"' : '' ?>>
<span><?= htmlspecialchars($item['label']) ?></span>
<small><?= htmlspecialchars($item['sub']) ?></small>
<em><?= htmlspecialchars($item['icon']) ?></em>
</a>
<?php endforeach; ?>
</nav>
<section class="tool-panel" aria-labelledby="toolTitle">
<div class="tool-heading">
<div>
<p id="toolKind" class="eyebrow"><?= htmlspecialchars($toolKind) ?></p>
<h2 id="toolTitle"><?= htmlspecialchars($toolTitle) ?></h2>
</div>
<span id="toolBadge" class="tool-badge"><?= htmlspecialchars($toolBadge) ?></span>
</div>