This should fix it... turns out prerendering broke the status
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m36s
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m36s
This commit is contained in:
63
src/components/StatusIndicator.tsx
Normal file
63
src/components/StatusIndicator.tsx
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { createSignal, createEffect, onCleanup } from "solid-js";
|
||||||
|
|
||||||
|
type StatusColor = "green" | "yellow" | "red";
|
||||||
|
|
||||||
|
interface StatusResponse {
|
||||||
|
text: string;
|
||||||
|
color: StatusColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const colorClasses: Record<StatusColor, string> = {
|
||||||
|
green: "bg-success",
|
||||||
|
yellow: "bg-warning",
|
||||||
|
red: "bg-error",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function StatusIndicator() {
|
||||||
|
const [statusText, setStatusText] = createSignal("Accepting new clients");
|
||||||
|
const [statusColor, setStatusColor] = createSignal<StatusColor>("green");
|
||||||
|
const [isLoaded, setIsLoaded] = createSignal(false);
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
const controller = new AbortController();
|
||||||
|
|
||||||
|
const fetchStatus = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/status", {
|
||||||
|
signal: controller.signal,
|
||||||
|
});
|
||||||
|
if (response.ok) {
|
||||||
|
const data: StatusResponse = await response.json();
|
||||||
|
setStatusText(data.text);
|
||||||
|
setStatusColor(data.color);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error && error.name !== "AbortError") {
|
||||||
|
console.error("Failed to fetch status:", error);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setIsLoaded(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchStatus();
|
||||||
|
|
||||||
|
onCleanup(() => controller.abort());
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
class={`inline-flex items-center gap-2 bg-white/10 text-white px-4 py-2 rounded-full text-sm font-medium mb-8 border border-white/10 transition-opacity duration-300 ${isLoaded() ? "opacity-100" : "opacity-0"}`}
|
||||||
|
>
|
||||||
|
<span class="relative flex h-2 w-2">
|
||||||
|
<span
|
||||||
|
class={`animate-ping absolute inline-flex h-full w-full rounded-full ${colorClasses[statusColor()]} opacity-75`}
|
||||||
|
></span>
|
||||||
|
<span
|
||||||
|
class={`relative inline-flex rounded-full h-2 w-2 ${colorClasses[statusColor()]}`}
|
||||||
|
></span>
|
||||||
|
</span>
|
||||||
|
{statusText()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,23 +1,7 @@
|
|||||||
---
|
---
|
||||||
import { siteConfig } from "../../config/site";
|
import { siteConfig } from "../../config/site";
|
||||||
import { Icon } from "astro-icon/components";
|
import { Icon } from "astro-icon/components";
|
||||||
|
import StatusIndicator from "../StatusIndicator.tsx";
|
||||||
const statusText = process.env.STATUS_TEXT
|
|
||||||
? process.env.STATUS_TEXT
|
|
||||||
: import.meta.env.STATUS_TEXT || "Accepting new clients";
|
|
||||||
|
|
||||||
const statusColorConfig = (
|
|
||||||
process.env.STATUS_COLOR
|
|
||||||
? process.env.STATUS_COLOR
|
|
||||||
: import.meta.env.STATUS_COLOR || "green"
|
|
||||||
) as "green" | "yellow" | "red";
|
|
||||||
|
|
||||||
const statusColor =
|
|
||||||
{
|
|
||||||
green: "bg-success",
|
|
||||||
yellow: "bg-warning",
|
|
||||||
red: "bg-error",
|
|
||||||
}[statusColorConfig] || "bg-success";
|
|
||||||
|
|
||||||
const rotatingText = (siteConfig.hero as any).rotatingText as
|
const rotatingText = (siteConfig.hero as any).rotatingText as
|
||||||
| { text: string; className: string }[]
|
| { text: string; className: string }[]
|
||||||
@@ -32,19 +16,7 @@ const rotatingText = (siteConfig.hero as any).rotatingText as
|
|||||||
|
|
||||||
<div class="relative max-w-7xl mx-auto px-6 py-20 lg:py-32">
|
<div class="relative max-w-7xl mx-auto px-6 py-20 lg:py-32">
|
||||||
<div class="text-center max-w-4xl mx-auto">
|
<div class="text-center max-w-4xl mx-auto">
|
||||||
<div
|
<StatusIndicator client:load />
|
||||||
class="inline-flex items-center gap-2 bg-white/10 text-white px-4 py-2 rounded-full text-sm font-medium mb-8 border border-white/10"
|
|
||||||
>
|
|
||||||
<span class="relative flex h-2 w-2">
|
|
||||||
<span
|
|
||||||
class={`animate-ping absolute inline-flex h-full w-full rounded-full ${statusColor} opacity-75`}
|
|
||||||
></span>
|
|
||||||
<span
|
|
||||||
class={`relative inline-flex rounded-full h-2 w-2 ${statusColor}`}
|
|
||||||
></span>
|
|
||||||
</span>
|
|
||||||
{statusText}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1
|
<h1
|
||||||
class="text-4xl sm:text-5xl lg:text-6xl xl:text-7xl font-extrabold text-white leading-tight tracking-tight mb-6"
|
class="text-4xl sm:text-5xl lg:text-6xl xl:text-7xl font-extrabold text-white leading-tight tracking-tight mb-6"
|
||||||
|
|||||||
26
src/pages/api/status.ts
Normal file
26
src/pages/api/status.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import type { APIRoute } from "astro";
|
||||||
|
|
||||||
|
export const prerender = false;
|
||||||
|
|
||||||
|
export const GET: APIRoute = async () => {
|
||||||
|
const statusText = process.env.STATUS_TEXT
|
||||||
|
? process.env.STATUS_TEXT
|
||||||
|
: import.meta.env.STATUS_TEXT || "Accepting new clients";
|
||||||
|
const statusColor = process.env.STATUS_COLOR
|
||||||
|
? process.env.STATUS_COLOR
|
||||||
|
: import.meta.env.STATUS_COLOR || "green";
|
||||||
|
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
text: statusText,
|
||||||
|
color: statusColor,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Cache-Control": "no-cache, no-store, must-revalidate",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user