Asked claude opus to make an audit of code and use coding guidelines etc. This is the fix

This commit is contained in:
2026-03-09 22:26:16 -04:00
parent 75d88f441c
commit b702839f8e
15 changed files with 459 additions and 1291 deletions

View File

@@ -1,5 +1,6 @@
<script>
import { getSystemInfo, reboot, getOTAStatus, getUpcomingTasks } from "./lib/api.js";
import { formatUptime, formatBytes, formatRelativeDate, isOverdue } from "./lib/utils.js";
import OTAUpdate from "./lib/OTAUpdate.svelte";
import Sidebar from "./lib/Sidebar.svelte";
import TaskManager from "./lib/TaskManager.svelte";
@@ -32,49 +33,7 @@
let upcomingData = $state({ users: [] });
/** Format uptime seconds into human-readable string */
function formatUptime(seconds) {
const d = Math.floor(seconds / 86400);
const h = Math.floor((seconds % 86400) / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = seconds % 60;
const parts = [];
if (d > 0) parts.push(`${d}d`);
if (h > 0) parts.push(`${h}h`);
if (m > 0) parts.push(`${m}m`);
parts.push(`${s}s`);
return parts.join(" ");
}
/** Format bytes into human-readable string */
function formatBytes(bytes) {
if (bytes >= 1048576) return `${(bytes / 1048576).toFixed(1)} MB`;
if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;
return `${bytes} B`;
}
function formatRelativeDate(timestamp) {
const now = Date.now() / 1000;
const diff = timestamp - now;
const absDiff = Math.abs(diff);
if (absDiff < 3600) {
const mins = Math.round(absDiff / 60);
return diff < 0 ? `${mins}m ago` : `in ${mins}m`;
}
if (absDiff < 86400) {
const hours = Math.round(absDiff / 3600);
return diff < 0 ? `${hours}h ago` : `in ${hours}h`;
}
const days = Math.round(absDiff / 86400);
return diff < 0 ? `${days}d ago` : `in ${days}d`;
}
function isOverdue(timestamp) {
return timestamp < Date.now() / 1000;
}
let isFetching = false;
let isFetching = false; // mutex, not reactive
let lastKnownFirmware = null;
let lastKnownSlot = null;
async function fetchAll(silent = false) {
@@ -158,7 +117,7 @@
]);
</script>
<div class="app-layout">
<div class="flex min-h-screen bg-bg-primary">
<Sidebar
{currentView}
isOpen={mobileMenuOpen}
@@ -168,25 +127,25 @@
{#if mobileMenuOpen}
<button
class="mobile-backdrop"
class="fixed inset-0 bg-black/40 backdrop-blur z-[999] border-none p-0 cursor-pointer"
onclick={() => mobileMenuOpen = false}
aria-label="Close menu"
></button>
{/if}
<main class="main-content">
<main class="main-gradient-bg flex-1 p-8 h-screen overflow-y-auto max-md:p-4 max-md:h-auto">
<!-- Mobile Top Bar -->
<header class="mobile-header">
<header class="hidden max-md:flex items-center justify-between px-4 py-3 bg-bg-card border-b border-border sticky top-0 z-50 backdrop-blur-[10px] max-md:-mx-4 max-md:-mt-4 max-md:mb-5">
<!-- svelte-ignore a11y_consider_explicit_label -->
<button class="hamburger" onclick={() => mobileMenuOpen = true}>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
<button class="bg-transparent border-none text-text-primary p-2 cursor-pointer" onclick={() => mobileMenuOpen = true}>
<svg class="w-6 h-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</button>
<span class="mobile-title">Calendink</span>
<div style="width: 40px;"></div> <!-- Spacer -->
<span class="font-bold text-base tracking-[-0.02em] text-accent">Calendink</span>
<div class="w-10"></div> <!-- Spacer -->
</header>
<div class="w-full max-w-6xl mx-auto space-y-8">
@@ -378,7 +337,7 @@
</div>
<!-- Updates & Maintenance Card -->
<OTAUpdate onReboot={() => { status = "rebooting"; isRecovering = true; }} />
<OTAUpdate otaInfo={otaStatus} {systemInfo} onReboot={() => { status = "rebooting"; isRecovering = true; }} />
</div>
</div>
@@ -426,87 +385,3 @@
</div>
<Spinner />
<style>
.app-layout {
display: flex;
min-height: 100vh;
background: var(--color-bg-primary);
}
.main-content {
flex: 1;
padding: 32px;
height: 100vh;
overflow-y: auto;
background: radial-gradient(circle at top right, var(--color-bg-card), transparent 40%),
var(--color-bg-primary);
}
.mobile-header {
display: none;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: var(--color-bg-card);
border-bottom: 1px solid var(--color-border);
position: sticky;
top: 0;
z-index: 50;
backdrop-filter: blur(10px);
}
.hamburger {
background: none;
border: none;
color: var(--color-text-primary);
padding: 8px;
cursor: pointer;
}
.hamburger svg {
width: 24px;
height: 24px;
}
.mobile-title {
font-weight: 700;
font-size: 16px;
letter-spacing: -0.02em;
color: var(--color-accent);
}
.mobile-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(4px);
z-index: 999;
border: none;
padding: 0;
cursor: pointer;
animation: fadeIn 0.2s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@media (max-width: 768px) {
.main-content {
padding: 16px;
height: auto;
}
.mobile-header {
display: flex;
margin: -16px -16px 20px -16px;
}
.mobile-backdrop {
display: block;
}
}
</style>