- Delete old Vite+Svelte frontend - Initialize new SvelteKit project with TypeScript - Configure Tailwind CSS v4 + DaisyUI - Implement JWT authentication with auto-refresh - Create login page with form validation (Zod) - Add protected route guards - Update Docker configuration for single-stage build - Add E2E tests with Playwright (6/11 passing) - Fix Svelte 5 reactivity with $state() runes Known issues: - 5 E2E tests failing (timing/async issues) - Token refresh implementation needs debugging - Validation error display timing
150 lines
7.1 KiB
JavaScript
150 lines
7.1 KiB
JavaScript
import { H as head, C as store_get, F as unsubscribe_stores, I as fallback, E as escape_html, J as attr_class, K as attr, L as bind_props } from './exports-yY1xCm4l.js';
|
|
import './state.svelte-CNGpKaVU.js';
|
|
import { z } from 'zod';
|
|
import './utils-FiC4zhrQ.js';
|
|
import 'zod/v3';
|
|
import { a as auth } from './auth-e49oatML.js';
|
|
|
|
// deno-fmt-ignore-file
|
|
// ------------------------------------------------------------------
|
|
// ByteMarker
|
|
// ------------------------------------------------------------------
|
|
var ByteMarker;
|
|
(function (ByteMarker) {
|
|
ByteMarker[ByteMarker["Array"] = 0] = "Array";
|
|
ByteMarker[ByteMarker["BigInt"] = 1] = "BigInt";
|
|
ByteMarker[ByteMarker["Boolean"] = 2] = "Boolean";
|
|
ByteMarker[ByteMarker["Date"] = 3] = "Date";
|
|
ByteMarker[ByteMarker["Constructor"] = 4] = "Constructor";
|
|
ByteMarker[ByteMarker["Function"] = 5] = "Function";
|
|
ByteMarker[ByteMarker["Null"] = 6] = "Null";
|
|
ByteMarker[ByteMarker["Number"] = 7] = "Number";
|
|
ByteMarker[ByteMarker["Object"] = 8] = "Object";
|
|
ByteMarker[ByteMarker["RegExp"] = 9] = "RegExp";
|
|
ByteMarker[ByteMarker["String"] = 10] = "String";
|
|
ByteMarker[ByteMarker["Symbol"] = 11] = "Symbol";
|
|
ByteMarker[ByteMarker["TypeArray"] = 12] = "TypeArray";
|
|
ByteMarker[ByteMarker["Undefined"] = 13] = "Undefined";
|
|
})(ByteMarker || (ByteMarker = {}));
|
|
// ------------------------------------------------------------------
|
|
// State
|
|
// ------------------------------------------------------------------
|
|
BigInt('14695981039346656037');
|
|
[BigInt('1099511628211'), BigInt('18446744073709551616' /* 2 ^ 64 */)];
|
|
Array.from({ length: 256 }).map((_, i) => BigInt(i));
|
|
const F64 = new Float64Array(1);
|
|
new DataView(F64.buffer);
|
|
new Uint8Array(F64.buffer);
|
|
// ------------------------------------------------------------------
|
|
// String
|
|
// ------------------------------------------------------------------
|
|
new TextEncoder();
|
|
|
|
// deno-coverage-ignore-start - parsebox tested
|
|
// deno-fmt-ignore-file
|
|
// ------------------------------------------------------------------
|
|
// Range
|
|
// ------------------------------------------------------------------
|
|
function Range(start, end) {
|
|
return Array.from({ length: end - start + 1 }, (_, i) => String.fromCharCode(start + i));
|
|
}
|
|
[
|
|
...Range(97, 122), // Lowercase
|
|
...Range(65, 90) // Uppercase
|
|
];
|
|
const Zero = '0';
|
|
const NonZero = Range(49, 57); // 1 - 9
|
|
[Zero, ...NonZero];
|
|
// deno-coverage-ignore-stop
|
|
|
|
new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
|
|
|
|
var FetchStatus;
|
|
(function(FetchStatus2) {
|
|
FetchStatus2[FetchStatus2["Idle"] = 0] = "Idle";
|
|
FetchStatus2[FetchStatus2["Submitting"] = 1] = "Submitting";
|
|
FetchStatus2[FetchStatus2["Delayed"] = 2] = "Delayed";
|
|
FetchStatus2[FetchStatus2["Timeout"] = 3] = "Timeout";
|
|
})(FetchStatus || (FetchStatus = {}));
|
|
let LEGACY_MODE = false;
|
|
try {
|
|
if (SUPERFORMS_LEGACY)
|
|
LEGACY_MODE = true;
|
|
} catch {
|
|
}
|
|
let STORYBOOK_MODE = false;
|
|
try {
|
|
if (globalThis.STORIES)
|
|
STORYBOOK_MODE = true;
|
|
} catch {
|
|
}
|
|
let legacyMode = false;
|
|
try {
|
|
if (SUPERFORMS_LEGACY)
|
|
legacyMode = true;
|
|
} catch {
|
|
}
|
|
function LoginForm($$renderer, $$props) {
|
|
$$renderer.component(($$renderer2) => {
|
|
let isLoading = fallback($$props["isLoading"], false);
|
|
let errorMessage = fallback($$props["errorMessage"], null);
|
|
z.object({
|
|
email: z.string().min(1, "Email is required").email("Invalid email format"),
|
|
password: z.string().min(1, "Password is required")
|
|
});
|
|
let formData = { email: "", password: "" };
|
|
let errors = {};
|
|
$$renderer2.push(`<form class="space-y-4">`);
|
|
if (errorMessage) {
|
|
$$renderer2.push("<!--[-->");
|
|
$$renderer2.push(`<div class="alert alert-error" role="alert"><svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 shrink-0 stroke-current" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg> <span>${escape_html(errorMessage)}</span></div>`);
|
|
} else {
|
|
$$renderer2.push("<!--[!-->");
|
|
}
|
|
$$renderer2.push(`<!--]--> <div class="form-control"><label class="label" for="email"><span class="label-text">Email</span></label> <input type="email" id="email"${attr_class("input input-bordered w-full", void 0, { "input-error": errors.email })} placeholder="admin@example.com"${attr("value", formData.email)}${attr("disabled", isLoading, true)}${attr("aria-invalid", errors.email ? "true" : "false")}${attr("aria-describedby", errors.email ? "email-error" : void 0)}/> `);
|
|
if (errors.email) {
|
|
$$renderer2.push("<!--[-->");
|
|
$$renderer2.push(`<span id="email-error" class="label-text-alt text-error">${escape_html(errors.email)}</span>`);
|
|
} else {
|
|
$$renderer2.push("<!--[!-->");
|
|
}
|
|
$$renderer2.push(`<!--]--></div> <div class="form-control"><label class="label" for="password"><span class="label-text">Password</span></label> <input type="password" id="password"${attr_class("input input-bordered w-full", void 0, { "input-error": errors.password })} placeholder="••••••••"${attr("value", formData.password)}${attr("disabled", isLoading, true)}${attr("aria-invalid", errors.password ? "true" : "false")}${attr("aria-describedby", errors.password ? "password-error" : void 0)}/> `);
|
|
if (errors.password) {
|
|
$$renderer2.push("<!--[-->");
|
|
$$renderer2.push(`<span id="password-error" class="label-text-alt text-error">${escape_html(errors.password)}</span>`);
|
|
} else {
|
|
$$renderer2.push("<!--[!-->");
|
|
}
|
|
$$renderer2.push(`<!--]--></div> <button type="submit" class="btn btn-primary w-full"${attr("disabled", isLoading, true)}>`);
|
|
if (isLoading) {
|
|
$$renderer2.push("<!--[-->");
|
|
$$renderer2.push(`<span class="loading loading-spinner loading-sm"></span> Logging in...`);
|
|
} else {
|
|
$$renderer2.push("<!--[!-->");
|
|
$$renderer2.push(`Login`);
|
|
}
|
|
$$renderer2.push(`<!--]--></button></form>`);
|
|
bind_props($$props, { isLoading, errorMessage });
|
|
});
|
|
}
|
|
function _page($$renderer, $$props) {
|
|
$$renderer.component(($$renderer2) => {
|
|
var $$store_subs;
|
|
head("1x05zx6", $$renderer2, ($$renderer3) => {
|
|
$$renderer3.title(($$renderer4) => {
|
|
$$renderer4.push(`<title>Login - Headroom</title>`);
|
|
});
|
|
});
|
|
$$renderer2.push(`<div class="min-h-screen flex items-center justify-center bg-base-200"><div class="card w-full max-w-md bg-base-100 shadow-xl"><div class="card-body"><h1 class="card-title text-2xl text-center justify-center mb-6">Welcome to Headroom</h1> <p class="text-center text-base-content/70 mb-6">Sign in to access your dashboard</p> `);
|
|
LoginForm($$renderer2, {
|
|
isLoading: store_get($$store_subs ??= {}, "$auth", auth).isLoading,
|
|
errorMessage: store_get($$store_subs ??= {}, "$auth", auth).error
|
|
});
|
|
$$renderer2.push(`<!----> <div class="divider"></div> <div class="text-center text-sm text-base-content/60"><p>Demo credentials:</p> <p class="font-mono mt-1">admin@example.com / password</p></div></div></div></div>`);
|
|
if ($$store_subs) unsubscribe_stores($$store_subs);
|
|
});
|
|
}
|
|
|
|
export { _page as default };
|
|
//# sourceMappingURL=_page.svelte-6xG6DlTH.js.map
|