Updates and more
Dieser Commit ist enthalten in:
Ursprung
b5a54d087b
Commit
e97e86f9ac
38
astro-i18n.adapter.ts
Normale Datei
38
astro-i18n.adapter.ts
Normale Datei
@ -0,0 +1,38 @@
|
||||
import type { AstroIntegration } from "astro";
|
||||
import { mkdir, rename, access, constants } from 'node:fs/promises'
|
||||
import {rm} from "fs/promises";
|
||||
|
||||
const locales = ["de"];
|
||||
|
||||
export default function configureI18n(): AstroIntegration {
|
||||
return {
|
||||
name: "astro-i18n-renamer",
|
||||
hooks: {
|
||||
"astro:build:done": async ({pages, dir, logger, routes}) => {
|
||||
for (let page of pages) {
|
||||
let [locale, ...rest] = page.pathname.split("/");
|
||||
if (locales.includes(locale)) {
|
||||
let path = rest.join("/");
|
||||
let oldPath = `${dir.pathname}${page.pathname}`
|
||||
let newPath = `${dir.pathname}${path}`
|
||||
try {
|
||||
await access(cutPrefix(newPath), constants.R_OK | constants.W_OK)
|
||||
} catch (e) {
|
||||
await mkdir(cutPrefix(newPath), {recursive: true});
|
||||
}
|
||||
|
||||
await rename(`${cutPrefix(oldPath)}index.html`, `${cutPrefix(newPath)}index.${locale}.html`)
|
||||
}
|
||||
}
|
||||
|
||||
for (let locale of locales) {
|
||||
await rm(`${cutPrefix(dir.pathname)}${locale}`, {recursive: true, force: true})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cutPrefix(path: string): string {
|
||||
return process.platform === "win32" ? path.substring(1) : path
|
||||
}
|
@ -5,17 +5,17 @@ export default defineAstroI18nConfig({
|
||||
secondaryLocales: ["de"], // other supported locales
|
||||
fallbackLocale: "en", // fallback locale (on missing translation)
|
||||
trailingSlash: "never", // "never" or "always"
|
||||
run: "server", //"client+server" or "server"
|
||||
run: "client+server", //"client+server" or "server"
|
||||
showPrimaryLocale: false, // "/en/about" vs "/about"
|
||||
translationLoadingRules: [], // per page group loading
|
||||
translationDirectory: {
|
||||
i18n: "i18n",
|
||||
}, // translation directory names
|
||||
translationDirectory: {}, // translation directory names
|
||||
translations: {}, // { [translation_group1]: { [locale1]: {}, ... } }
|
||||
routes: {
|
||||
de: {
|
||||
about: "ueber-uns",
|
||||
join: "jetzt-spielen"
|
||||
join: "jetzt-spielen",
|
||||
imprint: "impressum",
|
||||
"code-of-conduct": "verhaltensrichtlinien",
|
||||
}
|
||||
}, // { [secondary_locale1]: { about: "about-translated", ... } }
|
||||
})
|
@ -1,6 +1,7 @@
|
||||
import { defineConfig, sharpImageService } from 'astro/config';
|
||||
import svelte from "@astrojs/svelte";
|
||||
import tailwind from "@astrojs/tailwind";
|
||||
import configureI18n from "./astro-i18n.adapter";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
@ -8,7 +9,8 @@ export default defineConfig({
|
||||
image: {
|
||||
service: sharpImageService(),
|
||||
},
|
||||
integrations: [svelte(), tailwind()],
|
||||
compressHTML: true,
|
||||
integrations: [svelte(), tailwind(), configureI18n()],
|
||||
vite: {
|
||||
|
||||
}
|
||||
|
20
package.json
20
package.json
@ -18,23 +18,25 @@
|
||||
"@astrojs/svelte": "^4.0.3",
|
||||
"@astrojs/tailwind": "^5.0.2",
|
||||
"@astropub/icons": "^0.2.0",
|
||||
"@types/color": "^3.0.5",
|
||||
"@types/node": "^20.8.10",
|
||||
"cssnano": "^6.0.1",
|
||||
"esbuild": "^0.19.4",
|
||||
"esbuild": "^0.19.5",
|
||||
"postcss-nesting": "^12.0.1",
|
||||
"sass": "^1.69.3",
|
||||
"svelte": "^4.2.1",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwindcss": "^3.3.3"
|
||||
"sass": "^1.69.5",
|
||||
"svelte": "^4.2.2",
|
||||
"tailwind-merge": "^2.0.0",
|
||||
"tailwindcss": "^3.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/lang-markdown": "^6.2.2",
|
||||
"@ddietr/codemirror-themes": "^1.4.2",
|
||||
"astro": "^3.3.0",
|
||||
"astro-i18n": "^2.0.4",
|
||||
"astro": "^3.4.3",
|
||||
"astro-i18n": "^2.1.18",
|
||||
"color": "^4.2.3",
|
||||
"flowbite": "^1.8.1",
|
||||
"flowbite-svelte": "^0.44.18",
|
||||
"flowbite-svelte-icons": "^0.4.4",
|
||||
"flowbite-svelte": "^0.44.19",
|
||||
"flowbite-svelte-icons": "^0.4.5",
|
||||
"moment": "^2.29.4",
|
||||
"sharp": "^0.32.6",
|
||||
"svelte-awesome": "^3.2.1",
|
||||
|
11
src/components/PlayerCount.svelte
Normale Datei
11
src/components/PlayerCount.svelte
Normale Datei
@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
|
||||
import {server} from "./stores/server.ts";
|
||||
</script>
|
||||
|
||||
{#await $server}
|
||||
{:then data}
|
||||
{data.players.online}
|
||||
{:catch error}
|
||||
Error
|
||||
{/await}
|
19
src/components/ServerStatus.svelte
Normale Datei
19
src/components/ServerStatus.svelte
Normale Datei
@ -0,0 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { t } from "astro-i18n"
|
||||
import {server} from "./stores/server.ts";
|
||||
|
||||
function generateVersionString(version: string): string {
|
||||
let versions = version.split(" ").slice(1)
|
||||
return `${versions[0].replace(",", "")} - ${versions[versions.length - 1]}`
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await $server}
|
||||
<p>{t("status.loading")}</p>
|
||||
{:then data}
|
||||
<h2>{t("status.status")}: <span class="text-green-500">{t("status.online")}</span></h2>
|
||||
<h2>{t("status.players", { count: `${data.players.online}/${data.players.max}`})}</h2>
|
||||
<h2>{t("status.version", { version: generateVersionString(data.version.name)})}</h2>
|
||||
{:catch error}
|
||||
<h1>{t("status.status")}: <span class="text-red-500">{t("status.offline")}</span></h1>
|
||||
{/await}
|
@ -33,7 +33,7 @@ export function cachedFamily<T, K>(normal: K, init: (arg0: T) => Promise<K>): (a
|
||||
const stores: Map<T, Cached<K>> = new Map();
|
||||
return (arg: T) => {
|
||||
if(stores.has(arg)) {
|
||||
return stores.get(arg);
|
||||
return stores.get(arg)!!;
|
||||
} else {
|
||||
const store = writable<K>(normal);
|
||||
let first = true;
|
||||
|
4
src/components/stores/server.ts
Normale Datei
4
src/components/stores/server.ts
Normale Datei
@ -0,0 +1,4 @@
|
||||
import {readable} from "svelte/store";
|
||||
import type {Readable} from "svelte/store";
|
||||
|
||||
export const server = readable(fetch(import.meta.env.PUBLIC_API_SERVER + "/data/server").then(res => res.json()))
|
@ -1,5 +1,5 @@
|
||||
// @ts-ignore
|
||||
import { defineCollection, z } from 'astro:content';
|
||||
import {defineCollection, reference, z} from 'astro:content';
|
||||
|
||||
export const pages = defineCollection({
|
||||
type: "content",
|
||||
@ -10,6 +10,30 @@ export const pages = defineCollection({
|
||||
})
|
||||
})
|
||||
|
||||
export const help = defineCollection({
|
||||
type: "content",
|
||||
schema: z.object({
|
||||
title: z.string().min(1).max(80),
|
||||
description: z.string().min(1).max(120),
|
||||
tags: z.array(z.string()),
|
||||
related: z.array(reference('help')).optional()
|
||||
})
|
||||
})
|
||||
|
||||
export const event = defineCollection({
|
||||
type: "content",
|
||||
schema: z.object({
|
||||
name: z.string(),
|
||||
start: z.date(),
|
||||
end: z.date(),
|
||||
mode: z.string().optional(),
|
||||
leader: z.string().array().optional(),
|
||||
eventId: z.number().gte(0)
|
||||
})
|
||||
})
|
||||
|
||||
export const collections = {
|
||||
'pages': pages
|
||||
'pages': pages,
|
||||
'help': help,
|
||||
'event': event
|
||||
}
|
||||
|
9
src/content/help/en/how-to.md
Normale Datei
9
src/content/help/en/how-to.md
Normale Datei
@ -0,0 +1,9 @@
|
||||
---
|
||||
title: How To
|
||||
description: How to do anything on SteamWar
|
||||
tags:
|
||||
- how-to
|
||||
slug: how-to
|
||||
---
|
||||
|
||||
# How to
|
@ -2,8 +2,8 @@
|
||||
"home": {
|
||||
"page": "SteamWar - Startseite",
|
||||
"subtitle": {
|
||||
"1": "Spieler Online: ",
|
||||
"2": "WarGears, AirShips, WarShips"
|
||||
"1": "WarGears, AirShips, WarShips",
|
||||
"2": "Spieler Online: "
|
||||
},
|
||||
"join": "Jetzt Spielen",
|
||||
"benefits": {
|
||||
@ -34,6 +34,10 @@
|
||||
"Arch": "Architekt"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"loading": "Lade...",
|
||||
"players": "Spieler: {# count #}"
|
||||
},
|
||||
"navbar": {
|
||||
"links": {
|
||||
"home": {
|
||||
@ -42,7 +46,7 @@
|
||||
"downloads": "Downloads",
|
||||
"faq": "FAQ"
|
||||
},
|
||||
"announcements": "Ankünigungen",
|
||||
"announcements": "Ankündigungen",
|
||||
"rules": {
|
||||
"title": "Regeln",
|
||||
"gamemode": "Spielmodi",
|
||||
@ -60,7 +64,8 @@
|
||||
"help": {
|
||||
"title": "Hilfe",
|
||||
"docs": "Dokumentation"
|
||||
}
|
||||
},
|
||||
"account": "Konto"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,8 +30,17 @@
|
||||
"title": "Help",
|
||||
"center": "Helpcenter",
|
||||
"docs": "Docs"
|
||||
},
|
||||
"account": "Account"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"loading": "Loading...",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline",
|
||||
"players": "Players: {# count #}",
|
||||
"version": "Version: {# version #}"
|
||||
},
|
||||
"home": {
|
||||
"page": "SteamWar - Home",
|
||||
@ -40,8 +49,8 @@
|
||||
"second": "War"
|
||||
},
|
||||
"subtitle": {
|
||||
"1": "Players Online: ",
|
||||
"2": "WarGears, AirShips, WarShips",
|
||||
"1": "WarGears, AirShips, WarShips",
|
||||
"2": "Players Online: ",
|
||||
"3": "Version: 1.12 - 1.20"
|
||||
},
|
||||
"join": "Join Now",
|
||||
|
@ -3,8 +3,11 @@ import { Image } from "astro:assets";
|
||||
import Basic from "./Basic.astro";
|
||||
import '../styles/button.css';
|
||||
import localLogo from "../images/logo.png"
|
||||
import {YoutubeSolid, DiscordSolid} from "flowbite-svelte-icons"
|
||||
import {l, t} from "astro-i18n";
|
||||
import {YoutubeSolid, DiscordSolid, CaretDownOutline} from "flowbite-svelte-icons"
|
||||
import {t} from "astro-i18n";
|
||||
import {l} from "../util/util"
|
||||
|
||||
import ServerStatus from "../components/ServerStatus.svelte";
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
@ -22,11 +25,14 @@ const { title } = Astro.props;
|
||||
{t("navbar.title")}
|
||||
</h1>
|
||||
</a>
|
||||
<div class="flex items-center flex-wrap">
|
||||
<div class="flex justify-center flex-wrap">
|
||||
<div class="btn-dropdown my-1">
|
||||
<a class="btn btn-gray" href={l("/")}>
|
||||
<div class="btn btn-gray" tabindex="1">
|
||||
<a href={l("/")}>
|
||||
<span class="btn__text">{t("navbar.links.home.title")}</span>
|
||||
</a>
|
||||
<CaretDownOutline class="ml-2 mt-auto" />
|
||||
</div>
|
||||
<div>
|
||||
<a class="btn btn-gray" href={l("/about")}>{t("navbar.links.home.about")}</a>
|
||||
<a class="btn btn-gray">{t("navbar.links.home.downloads")}</a>
|
||||
@ -37,9 +43,12 @@ const { title } = Astro.props;
|
||||
<span class="btn__text">{t("navbar.links.announcements")}</span>
|
||||
</a>
|
||||
<div class="btn-dropdown my-1">
|
||||
<a class="btn btn-gray" rel="prefetch" href={l("/blog")}>
|
||||
<div class="btn btn-gray" tabindex="1">
|
||||
<a rel="prefetch" href={l("/blog")}>
|
||||
<span class="btn__text">{t("navbar.links.rules.title")}</span>
|
||||
</a>
|
||||
<CaretDownOutline class="ml-2 mt-auto" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="px-2 text-gray-300">{t("navbar.links.rules.gamemode")}</h2>
|
||||
<a class="btn btn-gray">{t("navbar.links.rules.wg")}</a>
|
||||
@ -55,14 +64,20 @@ const { title } = Astro.props;
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-dropdown my-1">
|
||||
<a class="btn btn-gray" rel="prefetch">
|
||||
<div class="btn btn-gray" tabindex="1">
|
||||
<a rel="prefetch">
|
||||
<span class="btn__text">{t("navbar.links.help.title")}</span>
|
||||
</a>
|
||||
<CaretDownOutline class="ml-2 mt-auto" />
|
||||
</div>
|
||||
<div>
|
||||
<a class="btn btn-gray">{t("navbar.links.help.center")}</a>
|
||||
<a class="btn btn-gray" href={l("/help")}>{t("navbar.links.help.center")}</a>
|
||||
<a class="btn btn-gray">{t("navbar.links.help.docs")}</a>
|
||||
</div>
|
||||
</div>
|
||||
<a class="btn my-1" href={l("/login")}>
|
||||
<span class="btn__text">{t("navbar.links.account")}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav-bar>
|
||||
@ -91,10 +106,11 @@ const { title } = Astro.props;
|
||||
<main class="flex-1">
|
||||
<slot />
|
||||
</main>
|
||||
<footer class="bg-gray-900 w-screen h-80 mt-4 rounded-t-2xl flex flex-col dark:bg-neutral-900">
|
||||
<div class="flex-1 flex justify-evenly mt-4 ">
|
||||
<footer class="bg-gray-900 w-screen min-h-80 mt-4 rounded-t-2xl flex flex-col dark:bg-neutral-900">
|
||||
<div class="flex-1 flex justify-evenly items-center md:items-start mt-4 md:flex-row flex-col">
|
||||
<div class="footer-card">
|
||||
<h1>Serverstatus</h1>
|
||||
<ServerStatus client:only="svelte" />
|
||||
</div>
|
||||
<div class="footer-card">
|
||||
<h1>Links</h1>
|
||||
@ -121,7 +137,7 @@ const { title } = Astro.props;
|
||||
|
||||
<style>
|
||||
.footer-card {
|
||||
@apply w-36 text-gray-400 flex flex-col;
|
||||
@apply w-40 text-gray-400 flex flex-col;
|
||||
>h1 {
|
||||
@apply text-xl font-bold text-gray-100;
|
||||
}
|
||||
@ -139,6 +155,6 @@ const { title } = Astro.props;
|
||||
}
|
||||
|
||||
.match {
|
||||
width: clamp(75%, 25rem, 100vw);
|
||||
width: min(100vw, 70em);
|
||||
}
|
||||
</style>
|
||||
|
@ -2,14 +2,16 @@
|
||||
import { getCollection } from 'astro:content'
|
||||
import NavbarLayout from "../layouts/NavbarLayout.astro";
|
||||
import {astroI18n, createGetStaticPaths} from "astro-i18n";
|
||||
import localBau from "../images/2023-10-08_20.43.43.png";
|
||||
import {Image} from "astro:assets";
|
||||
|
||||
export const getStaticPaths = async () => {
|
||||
export const getStaticPaths = createGetStaticPaths(async () => {
|
||||
let posts = await getCollection("pages");
|
||||
|
||||
return posts.filter(value => value.id.split("/")[0] === astroI18n.locale).map((page) => ({
|
||||
props: { page }, params: { slug: page.slug }
|
||||
}) )
|
||||
}
|
||||
})
|
||||
|
||||
const { page } = Astro.props;
|
||||
const { Content } = await page.render();
|
||||
@ -17,16 +19,19 @@ const { Content } = await page.render();
|
||||
|
||||
|
||||
<NavbarLayout title={page.data.title}>
|
||||
<div>
|
||||
<Image src={localBau} alt="Bau" width="1920" height="1080" class="w-screen h-screen dark:brightness-75 fixed -z-10 object-cover" draggable="false" />
|
||||
<article>
|
||||
<h1 class="text-left">{page.data.title}</h1>
|
||||
<Content />
|
||||
</article>
|
||||
</div>
|
||||
</NavbarLayout>
|
||||
|
||||
<style is:global>
|
||||
article {
|
||||
width: clamp(75%, 25rem, 100vw);
|
||||
@apply mx-auto bg-gray-100 px-4 py-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14
|
||||
width: min(100vw, 75em);
|
||||
@apply mx-auto bg-gray-100 p-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14
|
||||
dark:text-white dark:bg-neutral-900;
|
||||
|
||||
p {
|
||||
@ -65,6 +70,10 @@ const { Content } = await page.render();
|
||||
@apply list-disc;
|
||||
}
|
||||
|
||||
code {
|
||||
@apply dark:text-neutral-400 text-neutral-800;
|
||||
}
|
||||
|
||||
pre.astro-code {
|
||||
@apply w-fit p-4 rounded-md border-2 border-gray-600 my-4;
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
---
|
||||
import NavBarLayout from '../layouts/NavbarLayout.astro'
|
||||
---
|
||||
|
||||
<NavBarLayout title="Blog">
|
||||
<h1>Blog!</h1>
|
||||
</NavBarLayout>
|
3
src/pages/event/[...slug].astro
Normale Datei
3
src/pages/event/[...slug].astro
Normale Datei
@ -0,0 +1,3 @@
|
||||
---
|
||||
|
||||
---
|
72
src/pages/help/[...slug].astro
Normale Datei
72
src/pages/help/[...slug].astro
Normale Datei
@ -0,0 +1,72 @@
|
||||
---
|
||||
import { getCollection } from 'astro:content'
|
||||
import NavbarLayout from "../../layouts/NavbarLayout.astro";
|
||||
import {astroI18n, createGetStaticPaths} from "astro-i18n";
|
||||
|
||||
export const getStaticPaths = createGetStaticPaths(async () => {
|
||||
let posts = await getCollection("help");
|
||||
|
||||
return posts.filter(value => value.id.split("/")[0] === astroI18n.locale).map((page) => ({
|
||||
props: { page }, params: { slug: page.slug }
|
||||
}) )
|
||||
})
|
||||
|
||||
const { page } = Astro.props;
|
||||
const { Content } = await page.render();
|
||||
---
|
||||
|
||||
|
||||
<NavbarLayout title={page.data.title}>
|
||||
<article>
|
||||
<h1 class="text-left">{page.data.title}</h1>
|
||||
<Content />
|
||||
</article>
|
||||
</NavbarLayout>
|
||||
|
||||
<style is:global>
|
||||
article {
|
||||
width: clamp(75%, 25rem, 100vw);
|
||||
@apply mx-auto bg-gray-100 px-4 py-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14
|
||||
dark:text-white dark:bg-neutral-900;
|
||||
|
||||
p {
|
||||
@apply my-4 leading-7;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply text-4xl font-bold mt-4 text-center;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@apply text-3xl font-bold mt-4;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@apply text-2xl font-bold mt-4;
|
||||
}
|
||||
|
||||
h4 {
|
||||
@apply text-xl font-bold mt-4;
|
||||
}
|
||||
|
||||
a {
|
||||
@apply text-blue-500 hover:text-blue-700;
|
||||
}
|
||||
|
||||
ol>li, ul>li {
|
||||
@apply ml-4;
|
||||
}
|
||||
|
||||
ol {
|
||||
@apply list-decimal;
|
||||
}
|
||||
|
||||
ul {
|
||||
@apply list-disc;
|
||||
}
|
||||
|
||||
pre.astro-code {
|
||||
@apply w-fit p-4 rounded-md border-2 border-gray-600 my-4;
|
||||
}
|
||||
}
|
||||
</style>
|
26
src/pages/help/index.astro
Normale Datei
26
src/pages/help/index.astro
Normale Datei
@ -0,0 +1,26 @@
|
||||
---
|
||||
import {getCollection} from "astro:content";
|
||||
import {astroI18n} from "astro-i18n";
|
||||
|
||||
import NavbarLayout from "../../layouts/NavbarLayout.astro";
|
||||
import {l} from "../../util/util";
|
||||
let posts = await getCollection("help", entry => entry.id.split("/")[0] === astroI18n.locale);
|
||||
---
|
||||
|
||||
<NavbarLayout title="Helpcenter">
|
||||
<div>
|
||||
<h1>Helpcenter</h1>
|
||||
{posts.map(value => (
|
||||
<a href={l("/help/" + value.slug)}>
|
||||
<h2>{value.data.title}</h2>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</NavbarLayout>
|
||||
|
||||
<style>
|
||||
div {
|
||||
@apply mx-auto bg-gray-100 px-4 py-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14
|
||||
dark:text-white dark:bg-neutral-900;
|
||||
}
|
||||
</style>
|
@ -4,7 +4,9 @@ import NavbarLayout from "../layouts/NavbarLayout.astro";
|
||||
import { Image } from "astro:assets";
|
||||
import localBau from "../images/2023-10-08_20.43.43.png";
|
||||
import {CaretRight, Archive, Rocket, Bell} from "@astropub/icons"
|
||||
import {astroI18n, l, t} from "astro-i18n";
|
||||
import {astroI18n, t} from "astro-i18n";
|
||||
import {l} from "../util/util"
|
||||
import PlayerCount from "../components/PlayerCount.svelte";
|
||||
|
||||
const teamMember = await fetch("http://localhost:1337/data/team").then(value => value.json())
|
||||
|
||||
@ -38,13 +40,13 @@ function mapMap<T, K, J>(i: Map<T, K>, fn: (key: T, value: K) => J): J[] {
|
||||
<div class="w-screen h-screen relative mb-4">
|
||||
<Image src={localBau} alt="Bau" width="1920" height="1080" class="w-screen object-cover rounded-b-2xl shadow-2xl dark:brightness-75" style="height: calc(100vh + 1rem)" draggable="false" />
|
||||
<drop-in class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col items-center">
|
||||
<h1 class="text-2xl sm:text-8xl font-extrabold text-white -translate-y-16 opacity-0 barlow" style="transition: transform .7s ease-out, opacity .7s linear; text-shadow: 2px 2px 5px black;">
|
||||
<h1 class="text-4xl sm:text-6xl md:text-8xl font-extrabold text-white -translate-y-16 opacity-0 barlow" style="transition: transform .7s ease-out, opacity .7s linear; text-shadow: 2px 2px 5px black;">
|
||||
<span class="text-yellow-400">{t("home.title.first")}</span>
|
||||
<span class="text-neutral-600">{t("home.title.second")}</span>
|
||||
</h1>
|
||||
<text-carousel class="h-20 w-full relative select-none">
|
||||
<h2 class="-translate-y-16">{t("home.subtitle.1")}<player-count /></h2>
|
||||
<h2>{t("home.subtitle.2")}</h2>
|
||||
<h2 class="-translate-y-16">{t("home.subtitle.1")}</h2>
|
||||
<h2>{t("home.subtitle.2")}<PlayerCount client:only="svelte" /></h2>
|
||||
<h2>{t("home.subtitle.3")}</h2>
|
||||
</text-carousel>
|
||||
<a href={l("join")} class="btn mt-32 px-8 flex opacity-0 -translate-y-16" style="transition: transform .3s ease-out, opacity .3s linear">{t("home.join")} <CaretRight width="24" heigth="24" /></a>
|
||||
@ -81,12 +83,6 @@ function mapMap<T, K, J>(i: Map<T, K>, fn: (key: T, value: K) => J): J[] {
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerCount extends HTMLElement {
|
||||
connectedCallback() {
|
||||
this.innerText = String(Math.floor(Math.random() * 100))
|
||||
}
|
||||
}
|
||||
|
||||
class DropIn extends HTMLElement {
|
||||
connectedCallback() {
|
||||
for (let child of this.children) {
|
||||
@ -101,7 +97,6 @@ function mapMap<T, K, J>(i: Map<T, K>, fn: (key: T, value: K) => J): J[] {
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("player-count", PlayerCount);
|
||||
customElements.define("text-carousel", TextCarousel);
|
||||
customElements.define("drop-in", DropIn);
|
||||
</script>
|
||||
|
42
src/pages/login.astro
Normale Datei
42
src/pages/login.astro
Normale Datei
@ -0,0 +1,42 @@
|
||||
---
|
||||
import NavbarLayout from "../layouts/NavbarLayout.astro";
|
||||
import localBau from "../images/2023-10-08_20.43.43.png";
|
||||
import {Image} from "astro:assets";
|
||||
|
||||
---
|
||||
|
||||
<NavbarLayout title="Login">
|
||||
<Image src={localBau} alt="Bau" width="1920" height="1080" class="w-screen h-screen dark:brightness-75 fixed -z-10 object-cover" draggable="false" />
|
||||
<div class="h-screen mx-auto p-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14 flex flex-col justify-center items-center
|
||||
dark:text-white " style="width: min(100vw, 75em);">
|
||||
<div class="bg-gray-100 dark:bg-neutral-900 p-12 rounded-2xl shadow-2xl border-2 border-gray-600 flex flex-col">
|
||||
<h1 class="text-4xl text-white text-center">Login</h1>
|
||||
<div class="ml-2 flex flex-col">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="Username..." />
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="****************" />
|
||||
</div>
|
||||
<button class="btn mt-4 !mx-0 justify-center">Login</button>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
import {l} from "../util/util";
|
||||
|
||||
if (localStorage.getItem("sw-api-token") !== null) {
|
||||
window.location.href = l("/account")
|
||||
}
|
||||
</script>
|
||||
</NavbarLayout>
|
||||
|
||||
<style>
|
||||
input {
|
||||
@apply border-2 rounded-md p-2 shadow-2xl w-80
|
||||
dark:bg-neutral-800
|
||||
focus:outline-none focus:ring-2 focus:ring-neutral-500 focus:border-transparent;
|
||||
}
|
||||
|
||||
label {
|
||||
@apply text-neutral-300;
|
||||
}
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
.btn {
|
||||
@apply bg-yellow-400 font-bold py-2 px-4 rounded cursor-pointer select-none mx-2 text-black;
|
||||
@apply bg-yellow-400 font-bold py-2 px-4 rounded cursor-pointer select-none mx-2 text-black flex flex-row;
|
||||
@apply hover:bg-yellow-300 hover:text-black hover:shadow-2xl hover:scale-105;
|
||||
transition: all 0.5s cubic-bezier(.2,3,.67,.6),
|
||||
background-color .1s ease-in-out,
|
||||
@ -16,11 +16,11 @@
|
||||
@apply relative mx-2;
|
||||
|
||||
>:nth-child(1) {
|
||||
@apply block !mx-0;
|
||||
@apply !mx-0;
|
||||
}
|
||||
|
||||
>:nth-child(2) {
|
||||
@apply hidden absolute top-full left-1/2 -translate-x-1/2 bg-gray-800 list-none text-white rounded py-2 flex-col text-sm;
|
||||
@apply hidden absolute top-full left-1/2 -translate-x-1/2 bg-gray-800 list-none text-white rounded py-2 flex-col text-sm z-20;
|
||||
}
|
||||
|
||||
&:hover,&:focus-within {
|
||||
|
@ -1,14 +1,18 @@
|
||||
import { l as proxyL } from 'astro-i18n'
|
||||
|
||||
import { randomBytes } from 'crypto'
|
||||
const locales = ["de"];
|
||||
|
||||
const usedIds = new Set<string>()
|
||||
export const l = (route: string) => {
|
||||
const transPath = proxyL(route)
|
||||
|
||||
export const getRandomId = () => {
|
||||
while (true) {
|
||||
const id = randomBytes(4).toString('hex')
|
||||
if (!usedIds.has(id)) {
|
||||
usedIds.add(id)
|
||||
return id
|
||||
if(import.meta.env.DEV) {
|
||||
return transPath;
|
||||
}
|
||||
|
||||
let [empty, locale, ...rest] = transPath.split("/");
|
||||
if (locales.includes(locale)) {
|
||||
return "/" + rest.join("/");
|
||||
}
|
||||
|
||||
return transPath;
|
||||
}
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren