diff --git a/src/web/public/script.js b/src/web/public/script.js new file mode 100644 index 0000000..6952f16 --- /dev/null +++ b/src/web/public/script.js @@ -0,0 +1,36 @@ +function formatUptime(seconds) { + if (seconds < 0) return "0s"; + + const days = Math.floor(seconds / (3600 * 24)); + const hours = Math.floor((seconds % (3600 * 24)) / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + const secs = Math.floor(seconds % 60); + + const parts = []; + if (days > 0) parts.push(`${days}d`); + if (hours > 0) parts.push(`${hours}h`); + if (minutes > 0) parts.push(`${minutes}m`); + parts.push(`${secs}s`); + + return parts.join(" "); +} + +function updateUptime() { + const el = document.getElementById("uptime-display"); + if (!el) return; + + const startTimestamp = parseInt(el.getAttribute("data-start-timestamp"), 10); + if (isNaN(startTimestamp)) return; + + const now = Date.now(); + const elapsedSeconds = (now - startTimestamp) / 1000; + + el.textContent = formatUptime(elapsedSeconds); +} + +document.addEventListener("DOMContentLoaded", () => { + // Update immediately to prevent stale content flash if possible + updateUptime(); + // Update every second + setInterval(updateUptime, 1000); +}); diff --git a/src/web/routes/home.ts b/src/web/routes/home.ts index abcfbf5..c18e24a 100644 --- a/src/web/routes/home.ts +++ b/src/web/routes/home.ts @@ -1,6 +1,10 @@ import { BaseLayout } from "../views/layout"; +import { formatUptime } from "../utils/format"; export function homeRoute(): Response { + const uptime = formatUptime(process.uptime()); + const startTimestamp = Date.now() - (process.uptime() * 1000); + const content = `

Welcome

@@ -9,6 +13,7 @@ export function homeRoute(): Response {

Status

System operational.

+

Uptime: ${uptime}

`; diff --git a/src/web/utils/format.test.ts b/src/web/utils/format.test.ts new file mode 100644 index 0000000..c88bf1d --- /dev/null +++ b/src/web/utils/format.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, it } from "bun:test"; +import { formatUptime } from "./format"; + +describe("formatUptime", () => { + it("formats seconds correctly", () => { + expect(formatUptime(45)).toBe("45s"); + }); + + it("formats minutes and seconds", () => { + expect(formatUptime(65)).toBe("1m 5s"); + }); + + it("formats hours, minutes, and seconds", () => { + expect(formatUptime(3665)).toBe("1h 1m 5s"); + }); + + it("formats days correctly", () => { + expect(formatUptime(90061)).toBe("1d 1h 1m 1s"); + }); + + it("handles zero", () => { + expect(formatUptime(0)).toBe("0s"); + }); +}); diff --git a/src/web/utils/format.ts b/src/web/utils/format.ts new file mode 100644 index 0000000..b03cc65 --- /dev/null +++ b/src/web/utils/format.ts @@ -0,0 +1,20 @@ +/** + * Formats a duration in seconds into a human-readable string. + * Example: 3665 -> "1h 1m 5s" + */ +export function formatUptime(seconds: number): string { + if (seconds < 0) return "0s"; + + const days = Math.floor(seconds / (3600 * 24)); + const hours = Math.floor((seconds % (3600 * 24)) / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + const secs = Math.floor(seconds % 60); + + const parts = []; + if (days > 0) parts.push(`${days}d`); + if (hours > 0) parts.push(`${hours}h`); + if (minutes > 0) parts.push(`${minutes}m`); + parts.push(`${secs}s`); + + return parts.join(" "); +} diff --git a/src/web/views/layout.ts b/src/web/views/layout.ts index 434c60e..e68e4f7 100644 --- a/src/web/views/layout.ts +++ b/src/web/views/layout.ts @@ -29,6 +29,7 @@ export function BaseLayout({ title, content }: LayoutProps): string { + `; } diff --git a/tickets/2026-01-07-responsive-mobile-layout.md b/tickets/2026-01-07-responsive-mobile-layout.md new file mode 100644 index 0000000..b5e2832 --- /dev/null +++ b/tickets/2026-01-07-responsive-mobile-layout.md @@ -0,0 +1,34 @@ +# 2026-01-07-responsive-mobile-layout.md: Responsive Layout & Mobile Optimization + +**Status:** Draft +**Created:** 2026-01-07 +**Tags:** responsive, mobile, layout, css + +## 1. Context & User Story +* **As a:** User accessing the dashboard from a mobile device +* **I want to:** View and navigate the content easily without horizontal scrolling or broken layouts +* **So that:** I can monitor the bot status from my phone while on the go. + +## 2. Technical Requirements +### Data Model Changes +- N/A + +### API / Interface +- N/A + +## 3. Constraints & Validations (CRITICAL) +- **Breakpoints:** Use standard breakpoints (mobile first approach preferred, or standard desktop-first with max-width queries). +- **Touch Targets:** Interactive elements must be at least 44x44px on mobile devices. +- **Viewport:** Ensure meta viewport tag covers all device widths (already present in layout, verify settings). + +## 4. Acceptance Criteria +1. [ ] The navigation bar adapts to mobile screens (collapses into a hamburger menu or utilizes a scrollable tab bar). +2. [ ] Main content padding adjusts for smaller screens to maximize usable space. +3. [ ] Grid/Flex layouts stack vertically on mobile screens. +4. [ ] Typography sizes scale appropriately (smaller headers on mobile). + +## 5. Implementation Plan +- [ ] Add media queries to `style.css` for tablet and mobile breakpoints. +- [ ] Modify the `
` styles to accommodate a more flexible layout. +- [ ] Implement a simple JS toggle for mobile navigation if a hamburger menu is chosen, OR style a horizontal scrollable nav. +- [ ] Adjust `.card` and container margins for mobile contexts. diff --git a/tickets/2026-01-07-ux-enhancements-and-animations.md b/tickets/2026-01-07-ux-enhancements-and-animations.md new file mode 100644 index 0000000..2139618 --- /dev/null +++ b/tickets/2026-01-07-ux-enhancements-and-animations.md @@ -0,0 +1,34 @@ +# 2026-01-07-ux-enhancements-animations.md: UX Enhancements & Micro-Interactions + +**Status:** Draft +**Created:** 2026-01-07 +**Tags:** ux, animation, interactivity, frontend + +## 1. Context & User Story +* **As a:** User interacting with the dashboard +* **I want to:** See smooth transitions and immediate feedback when interacting with elements +* **So that:** The application feels responsive, "alive," and high-quality. + +## 2. Technical Requirements +### Data Model Changes +- N/A + +### API / Interface +- N/A + +## 3. Constraints & Validations (CRITICAL) +- **Performance:** Animations must use `transform` and `opacity` properties to ensure 60fps performance without triggering expensive layout reflows. +- **Accessibility:** Respect `prefers-reduced-motion` media queries to disable animations for sensitive users. +- **Subtlety:** Animations should be fast and subtle (e.g., 150ms-300ms), not distracting. + +## 4. Acceptance Criteria +1. [ ] Content fades in smoothly when the page loads. +2. [ ] Interactive elements (buttons, links, cards) have hover effects (scale, lift, or glow) that provide visual feedback. +3. [ ] A subtle, dynamic background effect (e.g., slow gradient mesh or blur) is implemented to remove the "flat" look. +4. [ ] Loading states (skeletons or spinners) are available for future dynamic content. + +## 5. Implementation Plan +- [ ] Add keyframe animations for entry transitions (fade-in, slide-up) in `style.css`. +- [ ] Apply hover transitions to `.card` and navigation links. +- [ ] Implement a subtle background gradient using `background-image` or pseudo-elements. +- [ ] Add `prefers-reduced-motion` overrides. diff --git a/tickets/2026-01-07-visual-design-system-overhaul.md b/tickets/2026-01-07-visual-design-system-overhaul.md new file mode 100644 index 0000000..7d1928c --- /dev/null +++ b/tickets/2026-01-07-visual-design-system-overhaul.md @@ -0,0 +1,37 @@ +# 2026-01-07-visual-design-system-overhaul.md: Visual Design System Overhaul + +**Status:** Draft +**Created:** 2026-01-07 +**Tags:** ui, css, design-system, aesthetics + +## 1. Context & User Story +* **As a:** User of the Aurora Web Dashboard +* **I want to:** Experience a cohesive, modern, and premium visual design +* **So that:** The application feels professional, trustworthy, and pleasant to use for extended periods. + +## 2. Technical Requirements +### Data Model Changes +- N/A + +### API / Interface +- N/A + +## 3. Constraints & Validations (CRITICAL) +- **CSS Variables:** Must use CSS Custom Properties for all colors, spacing, and typography to ensure theming capabilities. +- **Color Palette:** Use an HSL-based color system (e.g., `--primary-h`, `--primary-s`, `--primary-l`) to allow for opacity manipulations. +- **Typography:** Integrate a modern sans-serif font like 'Inter' or 'Outfit' from Google Fonts. Do not rely on system defaults. +- **Performance:** Load fonts efficiently (display: swap). + +## 4. Acceptance Criteria +1. [ ] `style.css` is refactored to use a comprehensive set of root variables (colors, spacing, radii, shadows). +2. [ ] A modern font (Inter/Outfit) is imported and applied globally. +3. [ ] Hardcoded hex values are removed in favor of CSS variables. +4. [ ] Common components (Cards, Buttons, Inputs, Tables) have distinct, premium styles defined. +5. [ ] The color palette includes primary, secondary, background, surface, and semantic colors (success, error, warning). + +## 5. Implementation Plan +- [ ] Define the HSL color palette and typography in `:root`. +- [ ] Import Google Fonts in `layout.ts` or via `@import` in CSS. +- [ ] Refactor existing `.card` and body styles to use the new tokens. +- [ ] Create utility classes for common spacing/layout needs if necessary (or keep it semantic). +- [ ] Add styles for buttons and links with proper hover/active states. diff --git a/tickets/2026-01-07-web-server-foundation.md b/tickets/2026-01-07-web-server-foundation.md deleted file mode 100644 index 7b34d7a..0000000 --- a/tickets/2026-01-07-web-server-foundation.md +++ /dev/null @@ -1,59 +0,0 @@ -# 2026-01-07-web-server-foundation: Web Server Infrastructure Foundation - -**Status:** Done -**Created:** 2026-01-07 -**Tags:** infrastructure, web, core - -## 1. Context & User Story -* **As a:** Developer -* **I want to:** Establish a lightweight, integrated web server foundation within the existing codebase. -* **So that:** We can serve internal tools (Workbench) or public pages (Leaderboard) with minimal friction, avoiding complex separate build pipelines. - -## 2. Technical Requirements -### Architecture -- **Native Bun Server:** Use `Bun.serve()` for high performance. -- **Exposure:** The server port must be exposed in `docker-compose.yml` to be accessible outside the container. -- **Rendering Strategy:** **Server-Side Rendering (SSR) via Template Literals**. - - *Why?* Zero dependencies. No build step (like Vite/Webpack) required. We can simply write functions that return HTML strings. - - *Client Side:* Minimal Vanilla JS or a lightweight drop-in library (like HTMX or Alpine from CDN) can be used if interactivity is needed later. - -### File Organization (`src/web/`) -We will separate the web infrastructure from game modules to keep concerns clean. -- `src/web/server.ts`: Main server class/entry point. -- `src/web/router.ts`: Simple routing logic. -- `src/web/routes/`: Individual route handlers (e.g., `home.ts`, `health.ts`). -- `src/web/views/`: Reusable HTML template functions (Header, Footer, Layouts). -- `src/web/public/`: Static assets (CSS, Images) served directly. - -### API / Interface -- **GET /health**: Returns `{ status: "ok", uptime: }`. -- **GET /**: Renders a basic HTML landing page using the View system. - -## 3. Constraints & Validations (CRITICAL) -- **Zero Frameworks:** No Express/NestJS. -- **Zero Build Tools:** No Webpack/Vite. The code must be runnable directly by `bun run`. -- **Docker Integration:** Port 3000 (or env `PORT`) must be mapped in Docker Compose. -- **Static Files:** Must implement a handler to check `src/web/public` for file requests. - -## 4. Acceptance Criteria -1. [x] `docker-compose up` exposes port 3000. -2. [x] `http://localhost:3000` loads a styled HTML page (verifying static asset serving + SSR). -3. [x] `http://localhost:3000/health` returns JSON. -4. [x] Folder structure established as defined above. - -## 5. Implementation Plan -- [x] **Infrastructure**: Create `src/web/` directory structure. -- [x] **Core Logic**: Implement `WebServer` class in `src/web/server.ts` with routing and static file serving logic. -- [x] **Integration**: Bind `WebServer.start()` to `src/index.ts`. -- [x] **Docker**: Update `docker-compose.yml` to map port `3000:3000`. -- [x] **Views**: Create a basic `BaseLayout` function in `src/web/views/layout.ts`. -- [x] **Env**: Add `PORT` to `config.ts` / `env.ts`. - -## Implementation Notes -- Created `src/web` directory with `router.ts`, `server.ts` and subdirectories `routes`, `views`, `public`. -- Implemented `WebServer` class using `Bun.serve`. -- Added basic CSS and layout system. -- Added `PORT` to `src/lib/env.ts` (default 3000). -- Integrated into `src/index.ts` to start on boot and graceful shutdown. -- Fixed unrelated typing issues in `src/commands/admin/note.ts` and `src/db/indexes.test.ts` to pass strict CI checks. -- Verified with `bun test` and `bun x tsc`.