From 614bd04405e1b049bc50670b7d2fe5aacaf16fd9 Mon Sep 17 00:00:00 2001 From: liyunze <50455574+liyunze-coding@users.noreply.github.com> Date: Thu, 5 Nov 2026 17:39:35 +0800 Subject: [PATCH] left column done --- frontend/README.md | 4 +- frontend/index.html | 9 +- frontend/public/images/logos/instagram.svg | 47 ++++ frontend/public/images/logos/tiktok.svg | 29 +++ frontend/public/images/logos/tiktok.webp | Bin 0 -> 25720 bytes frontend/public/images/logos/twitch.svg | 22 ++ frontend/public/images/logos/youtube.svg | 16 ++ frontend/src/app.css | 45 ++-- frontend/src/lib/api.ts | 89 +++---- frontend/src/lib/types.ts | 42 ++-- frontend/src/main.ts | 12 +- frontend/src/routes/MediaKit.svelte | 256 ++++++++++++--------- frontend/src/routes/MediaKit_copy.svelte | 117 ++++++++++ frontend/svelte.config.js | 2 +- frontend/vite.config.ts | 12 +- 15 files changed, 494 insertions(+), 208 deletions(-) create mode 100644 frontend/public/images/logos/instagram.svg create mode 100644 frontend/public/images/logos/tiktok.svg create mode 100644 frontend/public/images/logos/tiktok.webp create mode 100644 frontend/public/images/logos/twitch.svg create mode 100644 frontend/public/images/logos/youtube.svg create mode 100644 frontend/src/routes/MediaKit_copy.svelte diff --git a/frontend/README.md b/frontend/README.md index e6cd94f..a45e2a0 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -42,6 +42,6 @@ If you have state that's important to retain within a component, consider creati ```ts // store.ts // An extremely simple external store -import { writable } from 'svelte/store' -export default writable(0) +import { writable } from "svelte/store"; +export default writable(0); ``` diff --git a/frontend/index.html b/frontend/index.html index 18611f1..eda6b2d 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -4,10 +4,15 @@ - + RythonDev — Media Kit - +
diff --git a/frontend/public/images/logos/instagram.svg b/frontend/public/images/logos/instagram.svg new file mode 100644 index 0000000..8f7c8c7 --- /dev/null +++ b/frontend/public/images/logos/instagram.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/images/logos/tiktok.svg b/frontend/public/images/logos/tiktok.svg new file mode 100644 index 0000000..6e142b5 --- /dev/null +++ b/frontend/public/images/logos/tiktok.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + diff --git a/frontend/public/images/logos/tiktok.webp b/frontend/public/images/logos/tiktok.webp new file mode 100644 index 0000000000000000000000000000000000000000..b63df840839cda2dd6b9a3936bcd7de3266a733b GIT binary patch literal 25720 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 V0ScM+erfmt3Yp2qiOv83004KM*}4D# literal 0 HcmV?d00001 diff --git a/frontend/public/images/logos/twitch.svg b/frontend/public/images/logos/twitch.svg new file mode 100644 index 0000000..a2b6304 --- /dev/null +++ b/frontend/public/images/logos/twitch.svg @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file diff --git a/frontend/public/images/logos/youtube.svg b/frontend/public/images/logos/youtube.svg new file mode 100644 index 0000000..c7e566f --- /dev/null +++ b/frontend/public/images/logos/youtube.svg @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/frontend/src/app.css b/frontend/src/app.css index b188655..20bb472 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -1,38 +1,39 @@ @import "tailwindcss"; @font-face { - font-family: "Fredoka"; - src: url("/fonts/Fredoka-Regular.ttf") format("truetype"); - font-weight: normal; - font-style: normal; - font-display: swap; + font-family: "Fredoka"; + src: url("/fonts/Fredoka-Regular.ttf") format("truetype"); + font-weight: normal; + font-style: normal; + font-display: swap; } @font-face { - font-family: "Antonio"; - src: url("/fonts/Antonio-Bold.ttf") format("truetype"); - font-weight: bold; - font-style: normal; - font-display: swap; + font-family: "Antonio"; + src: url("/fonts/Antonio-Bold.ttf") format("truetype"); + font-weight: bold; + font-style: normal; + font-display: swap; } /* Montserrat Fonts */ @font-face { - font-family: "Montserrat"; - src: url("/fonts/Montserrat-Bold.ttf") format("truetype"); - font-weight: bold; - font-style: normal; - font-display: swap; + font-family: "Montserrat"; + src: url("/fonts/Montserrat-Bold.ttf") format("truetype"); + font-weight: bold; + font-style: normal; + font-display: swap; } @font-face { - font-family: "Montserrat"; - src: url("/fonts/Montserrat-Regular.ttf") format("truetype"); - font-weight: normal; - font-style: normal; - font-display: swap; + font-family: "Montserrat"; + src: url("/fonts/Montserrat-Regular.ttf") format("truetype"); + font-weight: normal; + font-style: normal; + font-display: swap; } -html, body { - font-family: Montserrat; +html, +body { + font-family: Montserrat; } diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 317e8da..474207c 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -1,78 +1,85 @@ -import type { AdminState, MediaKit, Platform } from './types' +import type { AdminState, MediaKit, Platform } from "./types"; -const TOKEN_KEY = 'rythondev_admin_token' +const TOKEN_KEY = "rythondev_admin_token"; function authHeaders(): Record { - const token = localStorage.getItem(TOKEN_KEY) - return token ? { Authorization: `Basic ${token}` } : {} + const token = localStorage.getItem(TOKEN_KEY); + return token ? { Authorization: `Basic ${token}` } : {}; } export function getStoredToken(): string | null { - return localStorage.getItem(TOKEN_KEY) + return localStorage.getItem(TOKEN_KEY); } export function clearStoredToken(): void { - localStorage.removeItem(TOKEN_KEY) + localStorage.removeItem(TOKEN_KEY); } export async function fetchMediaKit(): Promise { - const res = await fetch('/api/media-kit') - if (!res.ok) throw new Error('Failed to load media kit') - return res.json() + const res = await fetch("/api/media-kit"); + if (!res.ok) throw new Error("Failed to load media kit"); + return res.json(); } -export async function verifyAdmin(username: string, password: string): Promise { - const token = btoa(`${username}:${password}`) - const res = await fetch('/api/admin/verify', { +export async function verifyAdmin( + username: string, + password: string, +): Promise { + const token = btoa(`${username}:${password}`); + const res = await fetch("/api/admin/verify", { headers: { Authorization: `Basic ${token}` }, - }) + }); - if (!res.ok) return false + if (!res.ok) return false; - localStorage.setItem(TOKEN_KEY, token) - return true + localStorage.setItem(TOKEN_KEY, token); + return true; } export async function fetchAdminState(): Promise { - const res = await fetch('/api/admin/state', { headers: authHeaders() }) + const res = await fetch("/api/admin/state", { headers: authHeaders() }); if (res.status === 401) { - clearStoredToken() - throw new Error('unauthorized') + clearStoredToken(); + throw new Error("unauthorized"); } - if (!res.ok) throw new Error('Failed to load admin state') - return res.json() + if (!res.ok) throw new Error("Failed to load admin state"); + return res.json(); } -export async function updateContent(content: Record): Promise> { - const res = await fetch('/api/admin/content', { - method: 'PUT', - headers: { 'Content-Type': 'application/json', ...authHeaders() }, +export async function updateContent( + content: Record, +): Promise> { + const res = await fetch("/api/admin/content", { + method: "PUT", + headers: { "Content-Type": "application/json", ...authHeaders() }, body: JSON.stringify(content), - }) + }); if (res.status === 401) { - clearStoredToken() - throw new Error('unauthorized') + clearStoredToken(); + throw new Error("unauthorized"); } - if (!res.ok) throw new Error('Failed to save content') + if (!res.ok) throw new Error("Failed to save content"); - const data = await res.json() - return data.content + const data = await res.json(); + return data.content; } -export async function updatePlatforms(platforms: Platform[]): Promise { - const res = await fetch('/api/admin/platforms', { - method: 'PUT', - headers: { 'Content-Type': 'application/json', ...authHeaders() }, +export async function updatePlatforms( + platforms: Platform[], +): Promise { + const res = await fetch("/api/admin/platforms", { + method: "PUT", + headers: { "Content-Type": "application/json", ...authHeaders() }, body: JSON.stringify(platforms), - }) + }); if (res.status === 401) { - clearStoredToken() - throw new Error('unauthorized') + clearStoredToken(); + throw new Error("unauthorized"); } - if (!res.ok) throw new Error('Failed to save platforms') + if (!res.ok) throw new Error("Failed to save platforms"); - const data = await res.json() - return data.platforms + const data = await res.json(); + return data.platforms; } diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts index 4a451e8..8137711 100644 --- a/frontend/src/lib/types.ts +++ b/frontend/src/lib/types.ts @@ -1,32 +1,32 @@ export interface Platform { - name: string - handle: string - url: string - followers: number + name: string; + handle: string; + url: string; + followers: number; } export interface TwitchData { - configured?: boolean - found?: boolean - login?: string - display_name?: string - profile_image_url?: string - followers?: number - live?: boolean - title?: string - game_name?: string - viewer_count?: number - updated_at?: number - message?: string + configured?: boolean; + found?: boolean; + login?: string; + display_name?: string; + profile_image_url?: string; + followers?: number; + live?: boolean; + title?: string; + game_name?: string; + viewer_count?: number; + updated_at?: number; + message?: string; } export interface MediaKit { - content: Record - platforms: Platform[] - twitch: TwitchData | null + content: Record; + platforms: Platform[]; + twitch: TwitchData | null; } export interface AdminState { - content: Record - platforms: Platform[] + content: Record; + platforms: Platform[]; } diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 664a057..d47b930 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -1,9 +1,9 @@ -import { mount } from 'svelte' -import './app.css' -import App from './App.svelte' +import { mount } from "svelte"; +import "./app.css"; +import App from "./App.svelte"; const app = mount(App, { - target: document.getElementById('app')!, -}) + target: document.getElementById("app")!, +}); -export default app +export default app; diff --git a/frontend/src/routes/MediaKit.svelte b/frontend/src/routes/MediaKit.svelte index 76f40c3..3e7dc83 100644 --- a/frontend/src/routes/MediaKit.svelte +++ b/frontend/src/routes/MediaKit.svelte @@ -1,117 +1,159 @@ {#if error} -
-
- {error} -
-
-{:else if !data} -
-
Loading…
-
-{:else} -
-
- {#if content.profile_image_url} - {content.brand_name - {/if} -
-

- {content.brand_name ?? 'RythonDev'} -

- {#if content.tagline} -

{content.tagline}

- {/if} -
-
- -
-

About

-

- {content.about ?? ''} -

- {#if content.email} - {content.email} +
- {/if} -
- -
-

Twitch

- {#if twitch?.configured && twitch?.found} -
-
- Followers - {formatCount(twitch?.followers)} -
+ {error}
- {:else} -

{twitch?.message ?? 'Twitch stats are unavailable.'}

- {/if} -
- -
-

Platforms

- -
-
+ +{:else if !data} +
+
Loading…
+
+{:else} +
+ +
+
+
+ Hi there, I'm
+ RythonDev +
+
+
+
{/if} + + diff --git a/frontend/src/routes/MediaKit_copy.svelte b/frontend/src/routes/MediaKit_copy.svelte new file mode 100644 index 0000000..488e77c --- /dev/null +++ b/frontend/src/routes/MediaKit_copy.svelte @@ -0,0 +1,117 @@ + + +{#if error} +
+
+ {error} +
+
+{:else if !data} +
+
Loading…
+
+{:else} +
+
+ {#if content.profile_image_url} + {content.brand_name + {/if} +
+

+ {content.brand_name ?? 'RythonDev'} +

+ {#if content.tagline} +

{content.tagline}

+ {/if} +
+
+ +
+

About

+

+ {content.about ?? ''} +

+ {#if content.email} + {content.email} + {/if} +
+ +
+

Twitch

+ {#if twitch?.configured && twitch?.found} +
+
+ Followers + {formatCount(twitch?.followers)} +
+
+ {:else} +

{twitch?.message ?? 'Twitch stats are unavailable.'}

+ {/if} +
+ +
+

Platforms

+ +
+
+{/if} diff --git a/frontend/svelte.config.js b/frontend/svelte.config.js index 0cf7db3..ed45953 100644 --- a/frontend/svelte.config.js +++ b/frontend/svelte.config.js @@ -1,2 +1,2 @@ /** @type {import("@sveltejs/vite-plugin-svelte").SvelteConfig} */ -export default {} +export default {}; diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 73a4303..f4a35bb 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,16 +1,16 @@ -import { svelte } from '@sveltejs/vite-plugin-svelte' -import tailwindcss from '@tailwindcss/vite' -import { defineConfig } from 'vite' +import { svelte } from "@sveltejs/vite-plugin-svelte"; +import tailwindcss from "@tailwindcss/vite"; +import { defineConfig } from "vite"; // https://vite.dev/config/ export default defineConfig({ plugins: [tailwindcss(), svelte()], server: { proxy: { - '/api': { - target: 'http://localhost:3000', + "/api": { + target: "http://localhost:3000", changeOrigin: true, }, }, }, -}) +});