feat: online side widget

This commit is contained in:
trafficlunar 2025-07-21 22:25:56 +01:00
parent 75bf26a279
commit b807b7c577
8 changed files with 67 additions and 21 deletions

View file

@ -17,7 +17,7 @@
});
</script>
<section class="font-mono !py-2.5 min-w-40 h-min">
<section class="side">
<legend>clock</legend>
<span class="block font-bold text-lg">{clock}</span>

View file

@ -2,22 +2,7 @@
import { Area, Axis, Chart, Highlight, LinearGradient, Svg, Tooltip } from "layerchart";
import { scaleTime } from "d3-scale";
import { onMount } from "svelte";
interface ApiResponse {
online: boolean;
uptimeStart: number;
totals: {
keys: number;
clicks: number;
};
graph: {
timestamp: string;
cpu: number;
ram: number;
keys: number;
clicks: number;
}[];
}
import { computerData } from "../states.svelte";
type GraphData = {
timestamp: Date;
@ -44,8 +29,8 @@
let uptimeStart: Date;
const get = async () => {
const request = await fetch("https://api.trafficlunar.net/computer");
const data = (await request.json()) as ApiResponse;
const data = computerData.data; // no point in this; looks better
if (!data) return;
online = data.online;
uptimeStart = new Date(data.uptimeStart * 1000); // convert to milliseconds

View file

@ -0,0 +1,31 @@
<script lang="ts">
import { onMount } from "svelte";
import { computerData } from "../states.svelte";
onMount(() => {
const get = async () => {
const request = await fetch("https://api.trafficlunar.net/computer");
const data = (await request.json()) as ApiResponse;
computerData.data = data;
};
get();
const interval = setInterval(get, 30000);
return () => clearInterval(interval);
});
</script>
<section class="side">
<legend>status</legend>
<div class="flex justify-center items-center absolute -top-2 right-2 -z-10">
<div class="size-4 rounded-full {computerData.data?.online ? 'bg-green' : 'bg-red'}"></div>
<div
class="size-4 rounded-full absolute animate-duration-2s animate-delay-2s {computerData.data?.online ? 'bg-green animate-ping' : 'bg-red'}"
></div>
</div>
<span>I'M</span>
<span class={`font-black ${computerData.data?.online ? "text-green" : "text-red"}`}>{computerData.data?.online ? "ONLINE" : "OFFLINE"}.</span>
<p class="text-surface2 text-xs mt-1">feel free to reach out!</p>
</section>

View file

@ -9,7 +9,7 @@ import LastFMIcon from "../assets/icons/socials/lastfm.svg";
import MailIcon from "../assets/icons/socials/mail.svg";
---
<section class="!p-2 min-w-40">
<section class="side !p-2">
<legend>socials</legend>
<ul class="grid grid-cols-4 [&_a]:flex [&_a]:justify-center [&_a]:size-full [&_a]:py-1">
<li class="z-50">

View file

@ -6,6 +6,7 @@ import "../style.css";
import Socials from "../components/Socials.astro";
import Clock from "../components/Clock.svelte";
import Online from "../components/Online.svelte";
import Footer from "../components/Footer.astro";
import KawaiiLogo from "../assets/kawaii.svg";
@ -49,6 +50,7 @@ import Lunar from "../assets/lunar.svg";
<div class="flex flex-col justify-center w-fit max-[60rem]:flex-row max-[60rem]:mt-0 max-[60rem]:gap-2">
<Socials />
<Clock client:only />
<Online client:only />
</div>
</div>

9
src/states.svelte.ts Normal file
View file

@ -0,0 +1,9 @@
type ComputerData = {
data: ApiResponse | undefined;
};
// prevents sending 2 requests to the same route in my API
// check Online.svelte for where data is fetched
export let computerData = $state<ComputerData>({
data: undefined,
});

View file

@ -76,7 +76,11 @@ body {
}
section {
@apply bg-base-darker p-4 rounded-lg relative border border-surface0 shadow-md;
@apply bg-base-darker p-4 rounded-lg relative border border-surface0 shadow-md h-min;
}
section.side {
@apply w-40 font-mono py-2.5;
}
section:has(legend) {

15
src/types.d.ts vendored Normal file
View file

@ -0,0 +1,15 @@
interface ApiResponse {
online: boolean;
uptimeStart: number;
totals: {
keys: number;
clicks: number;
};
graph: {
timestamp: string;
cpu: number;
ram: number;
keys: number;
clicks: number;
}[];
}