add main appearance

This commit is contained in:
Joey Kimsey
2026-09-12 00:57:48 -04:00
parent f785af89cd
commit 17d83f7209
7 changed files with 1185 additions and 407 deletions

View File

@ -1,149 +1,493 @@
<!doctype html>
<html lang="en">
<html lang="en" data-bs-theme="light">
<head>
<meta charset="UTF-8" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; style-src 'self'; script-src 'self'; img-src 'self' data:;"
content="default-src 'self'; style-src 'self' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net; font-src https://cdnjs.cloudflare.com; script-src 'self' https://cdn.jsdelivr.net; img-src 'self' data: https: http:;"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Capsule</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.1/css/all.min.css"
integrity="sha384-QI8z31KmtR+tk1MYi0DfgxrjYgpTpLLol3bqZA/Q1Y8BvH+6k7/Huoj38gQOaCS7"
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="./src/styles.css" />
</head>
<body>
<div class="app">
<header class="topbar">
<div class="brand">
<span class="brand-mark" aria-hidden="true"></span>
<div>
<p class="brand-name">Capsule</p>
<p class="brand-tag">The Tempus Project</p>
<body data-shell="login">
<header class="text-bg-dark">
<div class="capsule-header p-3">
<a href="#/" class="capsule-brand text-white text-decoration-none d-flex align-items-center" data-route="home">
<img id="header-logo" class="capsule-logo" width="40" height="40" alt="" hidden />
<span class="brand-mark" aria-hidden="true"></span>
<span class="brand-name">Capsule</span>
</a>
<form id="header-search" class="capsule-search" role="search">
<fieldset>
<legend class="visually-hidden">Search the site</legend>
<label class="visually-hidden" for="search-resource">Search in</label>
<label class="visually-hidden" for="search-q">Search terms</label>
<div class="input-group">
<select class="form-select flex-grow-0 w-auto" name="resource" id="search-resource">
<option value="all">All</option>
<option value="posts">Posts</option>
<option value="pages">Pages</option>
</select>
<input
type="search"
class="form-control"
name="q"
id="search-q"
placeholder="Search"
autocomplete="off"
/>
<button type="submit" class="btn btn-primary" aria-label="Search">
<i class="fa fa-fw fa-search" aria-hidden="true"></i>
</button>
</div>
</fieldset>
</form>
<div class="capsule-account">
<div class="dropdown nav-item mx-2">
<a
href="#"
class="d-flex align-items-center text-white text-decoration-none dropdown-toggle"
id="notificationsDropdown"
data-bs-toggle="dropdown"
aria-expanded="false"
aria-label="Notifications"
>
<i class="fa fa-fw fa-bell" aria-hidden="true"></i>
<span id="notification-badge" class="badge bg-danger rounded-pill">2</span>
</a>
<ul
id="notification-menu"
class="dropdown-menu dropdown-menu-dark dropdown-menu-end text-small shadow"
data-bs-theme="dark"
aria-labelledby="notificationsDropdown"
>
<li><hr class="dropdown-divider" /></li>
<li>
<a href="#/notifications" class="dropdown-item text-center" data-route="notifications">
See All Notifications
</a>
</li>
</ul>
</div>
<p id="top-status" class="top-status" hidden></p>
</header>
<main class="stage">
<section id="view-login" class="view" hidden>
<div class="card">
<h1>Connect a site</h1>
<p class="lede">
Sign in to any Tempus Project install. Capsule talks to that site<74>s API and
keeps the session on this machine.
<div class="dropdown nav-item mx-2">
<a
href="#"
class="d-flex align-items-center text-white text-decoration-none dropdown-toggle"
id="messagesDropdown"
data-bs-toggle="dropdown"
aria-expanded="false"
aria-label="Messages"
>
<i class="fa fa-fw fa-envelope" aria-hidden="true"></i>
<span id="message-badge" class="badge bg-danger rounded-pill">1</span>
</a>
<ul
id="message-menu"
class="dropdown-menu dropdown-menu-dark dropdown-menu-end text-small shadow"
data-bs-theme="dark"
aria-labelledby="messagesDropdown"
>
<li><hr class="dropdown-divider" /></li>
<li>
<a href="#/messages" class="dropdown-item text-center" data-route="messages">All messages</a>
</li>
</ul>
</div>
<div class="dropdown nav-item mx-2">
<a
href="#"
class="d-flex align-items-center text-white text-decoration-none dropdown-toggle"
id="userDropdown"
data-bs-toggle="dropdown"
aria-label="Account menu"
aria-expanded="false"
>
<img
id="header-avatar"
src=""
alt=""
width="32"
height="32"
class="rounded-circle me-2"
hidden
/>
<i id="header-avatar-fallback" class="fa fa-user me-2" aria-hidden="true"></i>
<strong id="header-username">Account</strong>
</a>
<ul
class="dropdown-menu dropdown-menu-dark dropdown-menu-end text-small shadow"
data-bs-theme="dark"
>
<li>
<a href="#/profile" class="dropdown-item" data-route="profile">
<i class="fa fa-fw fa-user"></i> Profile
</a>
</li>
<li>
<a href="#/notifications" class="dropdown-item" data-route="notifications">
<i class="fa fa-fw fa-bell"></i> Notifications
</a>
</li>
<li>
<a href="#/messages" class="dropdown-item" data-route="messages">
<i class="fa fa-fw fa-envelope"></i> Messages
</a>
</li>
<li>
<a href="#/settings" class="dropdown-item" data-route="settings">
<i class="fa fa-fw fa-gear"></i> Settings
</a>
</li>
<li><hr class="dropdown-divider" /></li>
<li>
<a id="link-email" class="dropdown-item" href="#" target="_blank" rel="noreferrer">
<i class="fa fa-fw fa-envelope"></i> Change email
<i class="fa fa-fw fa-external-link ms-1"></i>
</a>
</li>
<li>
<a id="link-password" class="dropdown-item" href="#" target="_blank" rel="noreferrer">
<i class="fa fa-fw fa-lock"></i> Change password
<i class="fa fa-fw fa-external-link ms-1"></i>
</a>
</li>
<li>
<a id="link-phone" class="dropdown-item" href="#" target="_blank" rel="noreferrer">
<i class="fa fa-fw fa-phone"></i> Phone
<i class="fa fa-fw fa-external-link ms-1"></i>
</a>
</li>
<li><hr class="dropdown-divider" /></li>
<li>
<button id="logout-button" type="button" class="dropdown-item">
<i class="fa fa-fw fa-power-off"></i> Log Out
</button>
</li>
</ul>
</div>
</div>
</div>
<nav class="capsule-mainnav" aria-label="Main">
<ul class="capsule-mainnav-list">
<li><a href="#/game" data-nav="game">Game</a></li>
<li><a href="#/friends" data-nav="friends">Friends</a></li>
<li><a href="#/cabal" data-nav="cabal">Cabal</a></li>
<li><a href="#/hiscores" data-nav="hiscores">HiScores</a></li>
<li><a href="#/shop" data-nav="shop">Shop</a></li>
</ul>
</nav>
</header>
<main id="main-content">
<section id="view-login" class="view" hidden>
<div class="container pt-4">
<div class="mx-auto p-4 rounded context-main-bg capsule-login-card">
<h1 class="h3 mb-3 text-center">Connect a site</h1>
<p class="text-muted text-center mb-4">
Sign in to any Tempus Project install. Capsule talks to that site<74>s API and keeps
the session on this machine.
</p>
<form id="login-form" class="form">
<label class="field">
<span>Site URL</span>
<form id="login-form">
<div class="mb-3">
<label class="form-label" for="login-site">Site URL</label>
<input
id="login-site"
class="form-control"
name="siteUrl"
type="url"
autocomplete="url"
placeholder="https://example.com"
required
/>
</label>
<label class="field">
<span>Username</span>
<input id="login-username" name="username" type="text" autocomplete="username" required />
</label>
<label class="field">
<span>Password</span>
</div>
<div class="mb-3">
<label class="form-label" for="login-username">Username</label>
<input
id="login-username"
class="form-control"
name="username"
type="text"
autocomplete="username"
required
/>
</div>
<div class="mb-3">
<label class="form-label" for="login-password">Password</label>
<input
id="login-password"
class="form-control"
name="password"
type="password"
autocomplete="current-password"
required
/>
</label>
<p id="login-error" class="error" hidden></p>
<button id="login-submit" class="btn btn-primary" type="submit">Sign in</button>
</div>
<p id="login-error" class="text-danger" hidden></p>
<button id="login-submit" class="btn btn-primary w-100" type="submit">
<i class="fa fa-fw fa-right-to-bracket"></i> Sign in
</button>
</form>
<details id="token-panel" class="token-panel">
<details id="token-panel" class="mt-4">
<summary>Use an API token instead</summary>
<form id="token-form" class="form">
<p class="hint">
Paste a personal or app token from Admin ? Tokens. Username is optional and
only used to confirm the token against <code>api/users/find</code>.
<form id="token-form" class="mt-3">
<p class="small text-muted">
Paste a personal or app token from Admin ? Tokens. Username is optional until the
API can identify you.
</p>
<label class="field">
<span>Site URL</span>
<div class="mb-3">
<label class="form-label" for="token-site">Site URL</label>
<input
id="token-site"
class="form-control"
name="siteUrl"
type="url"
autocomplete="url"
placeholder="https://example.com"
required
/>
</label>
<label class="field">
<span>API token</span>
<input id="token-value" name="token" type="password" autocomplete="off" required />
</label>
<label class="field">
<span>Username <em>(optional)</em></span>
<input id="token-username" name="username" type="text" autocomplete="username" />
</label>
<p id="token-error" class="error" hidden></p>
<button id="token-submit" class="btn btn-secondary" type="submit">
</div>
<div class="mb-3">
<label class="form-label" for="token-value">API token</label>
<input id="token-value" class="form-control" name="token" type="password" autocomplete="off" required />
</div>
<div class="mb-3">
<label class="form-label" for="token-username">Username <span class="text-muted">(optional)</span></label>
<input id="token-username" class="form-control" name="username" type="text" autocomplete="username" />
</div>
<p id="token-error" class="text-danger" hidden></p>
<button id="token-submit" class="btn btn-outline-primary w-100" type="submit">
Connect with token
</button>
</form>
</details>
<p class="text-center mt-4 mb-0">
<button id="preview-shell" type="button" class="btn btn-link">
Preview the desktop chrome
</button>
</p>
</div>
</section>
</div>
</section>
<section id="view-home" class="view" hidden>
<div class="home-grid">
<article class="card identity">
<p class="eyebrow">Connected</p>
<h1 id="home-username">Signed in</h1>
<p id="home-site" class="site-line"></p>
<dl class="meta">
<div>
<dt>User ID</dt>
<dd id="home-userid"><EFBFBD></dd>
<section id="view-stub" class="view" hidden>
<div class="m-2 m-lg-4">
<div class="col-12 col-lg-10 mx-auto p-4 rounded shadow-sm context-main-bg">
<h1 class="h3" id="stub-title"></h1>
</div>
</div>
</section>
<section id="view-home" class="view" hidden>
<div class="m-2 m-lg-4">
<div class="col-12 col-lg-10 mx-auto p-4 rounded shadow-sm context-main-bg">
<h1 class="h3">Workspace</h1>
<p class="text-muted" id="home-note">
Search, notifications, messages, and profile are here. Site API wiring is the next
step.
</p>
<p class="mb-0">
Connected to <a id="home-site" href="#" target="_blank" rel="noreferrer"></a>
as <strong id="home-username"></strong>.
</p>
</div>
</div>
</section>
<section id="view-search" class="view" hidden>
<div class="m-2 m-lg-4">
<div class="col-12 col-lg-10 mx-auto p-4 rounded shadow-sm context-main-bg">
<h1 class="h3">Search</h1>
<p class="text-muted" id="search-summary"></p>
<p class="mb-0 text-muted">Results will come from the site search API next.</p>
</div>
</div>
</section>
<section id="view-notifications" class="view" hidden>
<div class="m-2 m-lg-4">
<div class="col-12 col-sm-10 col-lg-8 mx-auto p-4 rounded shadow-sm context-main-bg">
<h1 class="h3 text-center">Notifications</h1>
<table class="table">
<tbody id="notification-list"></tbody>
</table>
</div>
</div>
</section>
<section id="view-messages" class="view" hidden>
<div class="m-2 m-lg-4">
<div class="col-12 col-sm-10 col-lg-8 mx-auto p-4 rounded shadow-sm context-main-bg">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1 class="h3 mb-0">Messages</h1>
<button type="button" class="btn btn-sm btn-primary" disabled>
<i class="fa fa-fw fa-pen"></i> New message
</button>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>With</th>
<th>Last message</th>
<th>Updated</th>
</tr>
</thead>
<tbody id="message-list"></tbody>
</table>
</div>
</div>
</section>
<section id="view-profile" class="view" hidden>
<div class="container p-4 context-main-bg mb-4 text-center">
<h1 class="h3 mb-4">Profile</h1>
<hr />
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card shadow">
<div class="card-header text-center bg-dark text-white">
<h2 class="h3 card-title mb-0" id="profile-name"></h2>
</div>
<div>
<dt>Auth</dt>
<dd id="home-method"><EFBFBD></dd>
<div class="card-body">
<div class="row align-items-center">
<div class="col-md-4 text-center">
<img
id="profile-avatar"
src=""
alt="User Pic"
class="rounded-circle img-fluid"
style="max-width: 150px"
/>
</div>
<div class="col-md-8">
<table class="table table-borderless text-start">
<tbody>
<tr>
<th scope="row">Registered:</th>
<td id="profile-registered"></td>
</tr>
<tr>
<th scope="row">Last Seen:</th>
<td id="profile-last-login"></td>
</tr>
<tr>
<th scope="row">Gender:</th>
<td id="profile-gender"></td>
</tr>
</tbody>
</table>
<a href="#/settings" class="btn btn-primary btn-sm" data-route="settings">
<i class="fa fa-fw fa-pencil"></i> Edit profile
</a>
</div>
</div>
</div>
<div>
<dt>API</dt>
<dd id="home-api"><EFBFBD></dd>
</div>
</dl>
<p id="home-note" class="hint" hidden></p>
<div class="actions">
<button id="logout-button" class="btn btn-secondary" type="button">Sign out</button>
<a id="open-site" class="btn btn-ghost" href="#" target="_blank" rel="noreferrer">
Open site
</a>
</div>
</article>
<article class="card workspace">
<p class="eyebrow">Workspace</p>
<h2>Desktop tools land here</h2>
<p class="lede">
This area will host the full desktop experience for the plugins enabled on
the connected site. The current API can sign you in, refresh a token, and
look up a user id. Feature screens wait on those API expansions.
</p>
<ul class="plan">
<li>Talk to a site of your choice with a user login or an API token</li>
<li>Keep the token in the OS keychain, not in the renderer</li>
<li>Load plugin-backed tools as the HTTP API grows</li>
</ul>
</article>
</div>
</div>
</section>
</main>
</div>
</div>
</section>
<section id="view-settings" class="view" hidden>
<div class="container p-4 context-main-bg mb-4">
<h1 class="h3 mb-4 text-center">Settings</h1>
<hr />
<div class="row justify-content-center">
<div class="col-md-6">
<form id="settings-form">
<fieldset>
<legend class="visually-hidden">Preferences</legend>
<div class="mb-3 text-center">
<img
id="settings-avatar"
src=""
alt="Avatar"
class="rounded-circle img-fluid mb-2"
style="max-width: 125px"
/>
<label class="form-label d-block" for="settings-avatar-file">Avatar</label>
<input id="settings-avatar-file" class="form-control" type="file" accept="image/*" />
</div>
<div class="mb-3">
<label class="form-label" for="settings-gender">Gender</label>
<select id="settings-gender" class="form-select" name="gender">
<option value="unspecified">unspecified</option>
<option value="male">male</option>
<option value="female">female</option>
<option value="other">other</option>
</select>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="settings-newsletter" />
<label class="form-check-label" for="settings-newsletter">Receive our Newsletter?</label>
</div>
<div class="mb-3">
<label class="form-label" for="settings-timezone">Timezone</label>
<select id="settings-timezone" class="form-select" name="timezone"></select>
</div>
<div class="mb-3">
<label class="form-label" for="settings-date">Date Format</label>
<select id="settings-date" class="form-select" name="dateFormat"></select>
</div>
<div class="mb-3">
<label class="form-label" for="settings-time">Time Format</label>
<select id="settings-time" class="form-select" name="timeFormat"></select>
</div>
<div class="mb-3">
<label class="form-label" for="settings-limit">Items Displayed Per Page</label>
<select id="settings-limit" class="form-select" name="pageLimit"></select>
</div>
<div class="form-check form-switch mb-4">
<input class="form-check-input" type="checkbox" role="switch" id="settings-dark" />
<label class="form-check-label" for="settings-dark">Enable Dark-Mode viewing</label>
</div>
<p id="settings-note" class="small text-muted">
Saving will use the site API next. This form matches User CP preferences.
</p>
<p id="settings-status" class="text-success" hidden></p>
<button class="btn btn-lg btn-primary w-100" type="submit">Update</button>
</fieldset>
</form>
<div class="alert alert-info mt-4 mb-0">
Email, password, and phone stay on the site.
<div class="d-flex flex-wrap gap-2 mt-2">
<a id="settings-link-email" class="btn btn-sm btn-outline-primary" href="#" target="_blank" rel="noreferrer">
Change email <i class="fa fa-fw fa-external-link"></i>
</a>
<a id="settings-link-password" class="btn btn-sm btn-outline-primary" href="#" target="_blank" rel="noreferrer">
Change password <i class="fa fa-fw fa-external-link"></i>
</a>
<a id="settings-link-phone" class="btn btn-sm btn-outline-primary" href="#" target="_blank" rel="noreferrer">
Phone <i class="fa fa-fw fa-external-link"></i>
</a>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
crossorigin="anonymous"
></script>
<script type="module" src="./src/main.js"></script>
</body>
</html>