ba9cddf9a1
- Stripe: StripeClient.php, checkout/portal/webhook endpoints, idempotent event handling - FreeTier: tier-aware credits (free/light/pro/pro_plus), bonus_balance, hourly caps per tier - pricing.php + billing.php: 4-tier cards, 3 topups, Customer Portal, balance breakdown - Min Sak: CaseStore.php, AzureDocIntelligence.php, AzureSearchAdmin.php — per-user hybrid RAG - api/case/: upload, list, delete, ingest-callback (HMAC-auth'd from n8n) - award-survey-credits: inter-site HMAC endpoint for dobetternorge.no survey bonus - dashboard.php: tier badge, balance breakdown card, Min Sak CTA, survey CTA - KorrespondAgent + all 3 other agents: use_my_case toggle wired to dbnToolsCaseContext() - bootstrap.php: dbnToolsCaseContext(), dbnToolsIntersiteSecret(), dbnToolsCurrentTier() Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
157 lines
9.3 KiB
PHP
157 lines
9.3 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/includes/bootstrap.php';
|
|
require_once __DIR__ . '/includes/FreeTier.php';
|
|
|
|
if (!dbnToolsIsAuthenticated()) {
|
|
header('Location: /?return=' . urlencode($_SERVER['REQUEST_URI'] ?? '/dashboard.php'));
|
|
exit;
|
|
}
|
|
|
|
$uiLang = dbnToolsCurrentLanguage();
|
|
$tools = dbnToolsLaunchedTools($uiLang);
|
|
$workbench = dbnToolsWorkbenchMeta($uiLang);
|
|
$langPath = '/dashboard.php';
|
|
|
|
// Tier + balance for SSO users (CaveauAI sessions get no panel)
|
|
$dashIsSso = dbnToolsIsFreeTier();
|
|
$dashTier = $dashIsSso ? FreeTier::tier((int)$_SESSION['dbn_tools_sso_uid']) : 'caveau';
|
|
$dashDetail = $dashIsSso ? FreeTier::balanceDetail((int)$_SESSION['dbn_tools_sso_uid']) : null;
|
|
$tierLabels = [
|
|
'free' => ['Gratis', '#f3f4f6', '#374151'],
|
|
'light' => ['Light', '#ddd6fe', '#5b21b6'],
|
|
'pro' => ['Pro', '#bfdbfe', '#1e40af'],
|
|
'pro_plus' => ['Pro+ Familie', '#fde68a', '#92400e'],
|
|
];
|
|
$tierLabel = $tierLabels[$dashTier] ?? ['CaveauAI', '#d1fae5', '#065f46'];
|
|
$showSurveyCta = $dashIsSso && empty($dashDetail['survey_completed_at']);
|
|
|
|
require_once __DIR__ . '/includes/tool-svgs.php';
|
|
?>
|
|
<!doctype html>
|
|
<html lang="<?= htmlspecialchars($uiLang) ?>">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title><?= htmlspecialchars(dbnToolsT('dashboard_title', $uiLang)) ?> — Do Better Norge</title>
|
|
<meta name="robots" content="noindex, nofollow">
|
|
<meta name="theme-color" content="#00205B">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;600;700&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap">
|
|
<link rel="stylesheet" href="assets/css/tools.css">
|
|
</head>
|
|
<body data-authenticated="true" class="lt-app">
|
|
<script>
|
|
window.DBN_TOOLS_AUTHENTICATED = true;
|
|
window.DBN_TOOLS_LANG = <?= json_encode($uiLang, JSON_UNESCAPED_UNICODE) ?>;
|
|
</script>
|
|
|
|
<main id="appShell" class="app-shell dashboard-shell">
|
|
<header class="topbar">
|
|
<div>
|
|
<p class="eyebrow"><?= htmlspecialchars(dbnToolsT('brand_line', $uiLang)) ?></p>
|
|
<h1><?= htmlspecialchars(dbnToolsT('dashboard_title', $uiLang)) ?></h1>
|
|
<div class="case-no">
|
|
<span class="pulse"></span>
|
|
<span>family-legal</span>
|
|
<span class="case-sep">.</span>
|
|
<span><?= htmlspecialchars(dbnToolsT('retention', $uiLang)) ?></span>
|
|
</div>
|
|
</div>
|
|
<div class="topbar-actions">
|
|
<nav class="shell-lang-switcher" aria-label="Language">
|
|
<?php foreach (dbnToolsSupportedLanguages() as $langCode): ?>
|
|
<a href="<?= htmlspecialchars($langPath . '?lang=' . $langCode) ?>" class="<?= $langCode === $uiLang ? 'is-active' : '' ?>"><?= htmlspecialchars(dbnToolsLanguageLabel($langCode)) ?></a>
|
|
<?php endforeach; ?>
|
|
</nav>
|
|
<span id="healthPill" class="status-pill"><?= htmlspecialchars(dbnToolsT('session_active', $uiLang)) ?></span>
|
|
<?php if ($dashIsSso): ?>
|
|
<a href="/billing.php" class="tier-pill" style="background: <?= htmlspecialchars($tierLabel[1]) ?>; color: <?= htmlspecialchars($tierLabel[2]) ?>; padding: 4px 12px; border-radius: 999px; font-size: 0.82rem; font-weight: 600; text-decoration: none;">
|
|
<?= htmlspecialchars($tierLabel[0]) ?>
|
|
</a>
|
|
<?php endif; ?>
|
|
<button id="healthButton" class="secondary-button" type="button"><?= htmlspecialchars(dbnToolsT('health', $uiLang)) ?></button>
|
|
</div>
|
|
</header>
|
|
|
|
<?php if ($dashIsSso && $dashDetail): ?>
|
|
<section class="dashboard-status-row" style="display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap:1rem; margin: 1.5rem 0;">
|
|
<div class="status-card" style="background:#fff; border:1px solid #e5e7eb; border-radius:10px; padding:1.1rem 1.25rem;">
|
|
<p style="margin:0; color:#6b7280; font-size:0.85rem; text-transform:uppercase; letter-spacing:0.06em;">Tilgjengelige kreditter</p>
|
|
<p style="margin:0.35rem 0 0; font-size:1.8rem; font-weight:700; color:#00205B;">
|
|
<?php $eff = (int)$dashDetail['balance'] + (int)$dashDetail['bonus_balance']; ?>
|
|
<?php if ($dashTier === 'pro_plus'): ?>∞<?php else: ?><?= number_format($eff, 0, ',', ' ') ?><?php endif; ?>
|
|
</p>
|
|
<p style="margin:0; color:#6b7280; font-size:0.85rem;"><?= (int)$dashDetail['balance'] ?> månedlige · <?= (int)$dashDetail['bonus_balance'] ?> bonus · <a href="/billing.php">Detaljer</a></p>
|
|
</div>
|
|
<?php if (in_array($dashTier, ['light','pro','pro_plus'], true)): ?>
|
|
<a class="status-card" href="/min-sak.php" style="background:#fff; border:1px solid #e5e7eb; border-radius:10px; padding:1.1rem 1.25rem; text-decoration:none; color:inherit;">
|
|
<p style="margin:0; color:#6b7280; font-size:0.85rem; text-transform:uppercase; letter-spacing:0.06em;">Min sak</p>
|
|
<p style="margin:0.35rem 0 0; font-size:1.4rem; font-weight:700; color:#00205B;">Bygg din egen sak →</p>
|
|
<?php
|
|
$used = (int)$dashDetail['storage_used_bytes'];
|
|
$quota = (int)$dashDetail['storage_quota_bytes'];
|
|
$usedMb = $used > 0 ? round($used / 1048576, 1) : 0;
|
|
$quotaMb = $quota > 0 ? round($quota / 1048576, 0) : 0;
|
|
?>
|
|
<p style="margin:0; color:#6b7280; font-size:0.85rem;"><?= $usedMb ?> MB / <?= $quotaMb ?> MB brukt</p>
|
|
</a>
|
|
<?php else: ?>
|
|
<a class="status-card" href="/pricing.php" style="background:linear-gradient(135deg,#00205B,#003478); color:#fff; border-radius:10px; padding:1.1rem 1.25rem; text-decoration:none;">
|
|
<p style="margin:0; opacity:0.85; font-size:0.85rem; text-transform:uppercase; letter-spacing:0.06em;">Bygg din egen sak</p>
|
|
<p style="margin:0.35rem 0 0; font-size:1.4rem; font-weight:700;">Last opp dokumenter →</p>
|
|
<p style="margin:0; opacity:0.85; font-size:0.85rem;">Tilgjengelig fra Light €9/mo</p>
|
|
</a>
|
|
<?php endif; ?>
|
|
<?php if ($showSurveyCta): ?>
|
|
<a class="status-card" href="https://dobetternorge.no/survey.php" style="background:#fef3c7; color:#92400e; border-radius:10px; padding:1.1rem 1.25rem; text-decoration:none;">
|
|
<p style="margin:0; font-size:0.85rem; text-transform:uppercase; letter-spacing:0.06em; opacity:0.85;">Tjen 25 ekstra kreditter</p>
|
|
<p style="margin:0.35rem 0 0; font-size:1.2rem; font-weight:700;">Ta vår 5-spørsmåls undersøkelse →</p>
|
|
<p style="margin:0; font-size:0.85rem; opacity:0.85;">Ingen salgspitch — bare research</p>
|
|
</a>
|
|
<?php endif; ?>
|
|
</section>
|
|
<?php endif; ?>
|
|
|
|
<section class="manifesto dashboard-manifesto">
|
|
<div class="manifesto-copy">
|
|
<p class="manifesto-eyebrow"><?= htmlspecialchars(dbnToolsT('dashboard_eyebrow', $uiLang)) ?></p>
|
|
<h2 class="manifesto-title"><?= htmlspecialchars(dbnToolsT('manifesto_title', $uiLang)) ?></h2>
|
|
<p class="manifesto-sub"><?= htmlspecialchars(dbnToolsT('dashboard_sub', $uiLang)) ?></p>
|
|
</div>
|
|
<div class="manifesto-stats" aria-label="Headline statistics">
|
|
<div class="manifesto-stat"><strong>23</strong><span><?= htmlspecialchars(dbnToolsT('stat_echr', $uiLang)) ?></span></div>
|
|
<div class="manifesto-stat"><strong>64%</strong><span><?= htmlspecialchars(dbnToolsT('stat_loss', $uiLang)) ?></span></div>
|
|
<div class="manifesto-stat"><strong>1,731</strong><span><?= htmlspecialchars(dbnToolsT('stat_tribunal', $uiLang)) ?></span></div>
|
|
<div class="manifesto-stat"><strong>20+</strong><span><?= htmlspecialchars(dbnToolsT('stat_pending', $uiLang)) ?></span></div>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="disclaimer" role="note"><?= htmlspecialchars(dbnToolsT('disclaimer', $uiLang)) ?></div>
|
|
|
|
<section class="tool-dashboard-grid" aria-label="Available tools">
|
|
<a class="dashboard-tool-card dashboard-tool-card--workbench" href="<?= htmlspecialchars($workbench['url']) ?>">
|
|
<span class="dashboard-tool-card__icon"><?= htmlspecialchars($workbench['icon']) ?></span>
|
|
<span class="dashboard-tool-card__badge"><?= htmlspecialchars($workbench['badge']) ?></span>
|
|
<h2><?= htmlspecialchars($workbench['label']) ?></h2>
|
|
<p><?= htmlspecialchars($workbench['description']) ?></p>
|
|
<strong><?= htmlspecialchars(dbnToolsT('enter_workbench', $uiLang)) ?></strong>
|
|
</a>
|
|
<?php foreach ($tools as $slug => $item): ?>
|
|
<a class="dashboard-tool-card" href="<?= htmlspecialchars($item['url']) ?>">
|
|
<span class="dashboard-tool-card__icon"><?= htmlspecialchars($item['icon']) ?></span>
|
|
<span class="dashboard-tool-card__badge"><?= htmlspecialchars($item['badge']) ?></span>
|
|
<h2><?= htmlspecialchars($item['label']) ?></h2>
|
|
<p><?= htmlspecialchars($item['description']) ?></p>
|
|
<strong><?= htmlspecialchars(dbnToolsT('open_tool', $uiLang)) ?></strong>
|
|
</a>
|
|
<?php endforeach; ?>
|
|
</section>
|
|
</main>
|
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
|
<script src="assets/js/tools.js" defer></script>
|
|
</body>
|
|
</html>
|