add projects and metrics routes

This commit is contained in:
ngn
2025-01-09 00:30:59 +03:00
parent dee3ef4d85
commit ac307de76c
32 changed files with 781 additions and 492 deletions

View File

@ -22,12 +22,16 @@ async function GET(fetch, url) {
return json["result"];
}
async function visitor(fetch) {
return GET(fetch, api_url("/visitor"));
async function get_metrics(fetch) {
return GET(fetch, api_url("/metrics"));
}
async function services(fetch) {
async function get_services(fetch) {
return GET(fetch, api_url("/services"));
}
export { version, api_url, visitor, services };
async function get_projects(fetch) {
return GET(fetch, api_url("/projects"));
}
export { version, api_url, get_metrics, get_services, get_projects };

View File

@ -1,74 +0,0 @@
<script>
import { click } from "$lib/util.js";
export let title;
export let url;
let current = "";
let i = 0;
while (title.length > i) {
let c = title[i];
setTimeout(
() => {
current += c;
},
100 * (i + 1)
);
i += 1;
}
</script>
<a on:click={click} data-sveltekit-preload-data href={url}>
<div class="title">
{current}
</div>
<div class="content">
<slot></slot>
</div>
</a>
<style>
a {
display: flex;
flex-direction: column;
width: 100%;
background: var(--dark-three);
box-shadow: var(--box-shadow);
border-radius: var(--radius);
cursor: pointer;
transition: 0.4s;
text-decoration: none;
border: solid 1px var(--border-color);
}
a:hover > .title {
text-shadow: var(--text-shadow);
}
.title {
border: solid 1px var(--dark-two);
background: var(--dark-two);
padding: 25px;
border-radius: 7px 7px 0px 0px;
font-size: 20px;
font-family:
Consolas,
Monaco,
Lucida Console,
Liberation Mono,
DejaVu Sans Mono,
Bitstream Vera Sans Mono,
Courier New,
monospace;
color: white;
}
.content {
background: var(--dark-three);
padding: 30px;
padding-top: 30px;
color: white;
border-radius: 5px;
font-size: 25px;
}
</style>

View File

@ -1,14 +1,15 @@
<script>
import { color, date_from_ts } from "$lib/util.js";
import { get_metrics } from "$lib/api.js";
import Link from "$lib/link.svelte";
import { onMount } from "svelte";
import { visitor } from "$lib/api.js";
import { color } from "$lib/util.js";
import { _ } from "svelte-i18n";
let visitor_count = 0;
let data = {};
onMount(async () => {
visitor_count = await visitor(fetch);
data = await get_metrics(fetch);
});
</script>
@ -33,8 +34,13 @@
</div>
<div class="useless">
<span>
{$_("footer.number", { values: { count: visitor_count } })}
{#if visitor_count % 1000 == 0}
{$_("footer.number", {
values: {
number: data.number,
since: date_from_ts(data.since),
},
})}
{#if data.number % 1000 == 0}
<span style="color: var(--{color()})">({$_("footer.congrat")})</span>
{/if}
</span>

View File

@ -1,6 +1,7 @@
<script>
import { locale } from "svelte-i18n";
import { language, set_lang } from "$lib/util.js";
import languages from "$lib/lang.js";
let icon = "",
indx = 0,
len = languages.length;
@ -9,18 +10,20 @@
if (indx >= languages.length) indx = 0;
icon = languages[indx].icon;
locale.set(languages[indx++].code);
set_lang(languages[indx++].code);
}
for (indx = 0; indx < len; indx++) {
if (languages[indx].code == $locale.slice(0, 2)) {
if (languages[indx].code == $language) {
icon = languages[indx++].icon;
break;
}
}
</script>
<button on:click={next}>{icon}</button>
<button on:click={next}>
{icon}
</button>
<style>
button {

View File

@ -2,8 +2,8 @@
import Icon from "$lib/icon.svelte";
import Link from "$lib/link.svelte";
import { color, time_from_ts } from "$lib/util.js";
import { _, locale } from "svelte-i18n";
import { color, time_from_ts, language } from "$lib/util.js";
import { _ } from "svelte-i18n";
export let service = {};
let style = "";
@ -15,7 +15,7 @@
<div class="info">
<div class="title">
<h1>{service.name}</h1>
<p>{service.desc[$locale.slice(0, 2)]}</p>
<p>{service.desc[$language]}</p>
</div>
<div class="links">
<Link highlight={false} link={service.clear}><Icon icon="nf-oct-link" /></Link>

View File

@ -1,6 +1,9 @@
import { browser } from "$app/environment";
import { locale } from "svelte-i18n";
import languages from "$lib/lang.js";
import { writable, get } from "svelte/store";
const default_lang = "en";
const default_language = languages[0].code;
const colors = [
"yellow",
"cyan",
@ -10,8 +13,33 @@ const colors = [
// "blue" (looks kinda ass)
];
let language = writable(default_language);
let colors_pos = -1;
function browser_lang() {
if (browser) return window.navigator.language.slice(0, 2).toLowerCase();
else return get(language);
}
function set_lang(lang) {
language.set(default_language);
if (lang === null || lang === undefined) {
if (browser) set_lang(browser_lang());
return;
}
lang = lang.slice(0, 2);
for (let i = 0; i < languages.length; i++) {
if (lang === languages[i].code) {
language.set(lang);
locale.set(lang);
return;
}
}
}
function urljoin(url, path = null, query = {}) {
let url_len = url.length;
@ -42,13 +70,40 @@ function click() {
audio.play();
}
function browser_lang() {
if (browser) return window.navigator.language.slice(0, 2).toLowerCase();
return default_lang;
}
function time_from_ts(ts) {
return new Date(ts * 1000).toLocaleTimeString();
if (ts === 0 || ts === undefined) return;
let ts_date = new Date(ts * 1000);
let ts_zone = ts_date.toString().match(/([A-Z]+[\+-][0-9]+)/)[1];
return (
new Intl.DateTimeFormat(browser_lang(), {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}).format(ts_date) + ` (${ts_zone})`
);
}
export { urljoin, frontend_url, browser_lang, click, color, time_from_ts };
function date_from_ts(ts) {
if (ts === 0 || ts === undefined) return;
return new Intl.DateTimeFormat(browser_lang(), {
month: "2-digit",
year: "2-digit",
day: "2-digit",
}).format(new Date(ts * 1000));
}
export {
default_language,
browser_lang,
language,
set_lang,
urljoin,
frontend_url,
click,
color,
time_from_ts,
date_from_ts,
};