Add favicon, font, tweak styles
|
@ -48,9 +48,11 @@
|
|||
"vite": "^5.4.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource-variable/smooch-sans": "^5.1.1",
|
||||
"better-sqlite3": "^11.8.0",
|
||||
"drizzle-orm": "^0.38.4",
|
||||
"lucide-svelte": "^0.473.0",
|
||||
"mode-watcher": "^0.5.0",
|
||||
"nanoid": "^5.0.9",
|
||||
"spotify-web-api-node": "^5.0.2",
|
||||
"svelte-kit-sessions": "^0.4.0"
|
||||
|
|
20
pnpm-lock.yaml
generated
|
@ -8,6 +8,9 @@ importers:
|
|||
|
||||
.:
|
||||
dependencies:
|
||||
'@fontsource-variable/smooch-sans':
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1
|
||||
better-sqlite3:
|
||||
specifier: ^11.8.0
|
||||
version: 11.8.1
|
||||
|
@ -17,6 +20,9 @@ importers:
|
|||
lucide-svelte:
|
||||
specifier: ^0.473.0
|
||||
version: 0.473.0(svelte@5.19.0)
|
||||
mode-watcher:
|
||||
specifier: ^0.5.0
|
||||
version: 0.5.0(svelte@5.19.0)
|
||||
nanoid:
|
||||
specifier: ^5.0.9
|
||||
version: 5.0.9
|
||||
|
@ -599,6 +605,9 @@ packages:
|
|||
'@floating-ui/utils@0.2.9':
|
||||
resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
|
||||
|
||||
'@fontsource-variable/smooch-sans@5.1.1':
|
||||
resolution: {integrity: sha512-ADcY3Pjkvu74x4T+p2gNIo8Ba7DGrX1IhQgJFefztWB8Tf5nX7Qb+tqAbtW7O/KYWJi4EjzrxCefHBM1PfOOsg==}
|
||||
|
||||
'@humanfs/core@0.19.1':
|
||||
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
|
@ -1692,6 +1701,11 @@ packages:
|
|||
mkdirp-classic@0.5.3:
|
||||
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
||||
|
||||
mode-watcher@0.5.0:
|
||||
resolution: {integrity: sha512-5E6fh/aXhAVv+U+DbeM0hCmskQE9u7WSmvnCRijJB/MJu7HtB73sjiCaZ9n1M8QHmzLrBFo8XBAUcWXkDm8Z9A==}
|
||||
peerDependencies:
|
||||
svelte: ^4.0.0 || ^5.0.0-next.1
|
||||
|
||||
mri@1.2.0:
|
||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -2612,6 +2626,8 @@ snapshots:
|
|||
|
||||
'@floating-ui/utils@0.2.9': {}
|
||||
|
||||
'@fontsource-variable/smooch-sans@5.1.1': {}
|
||||
|
||||
'@humanfs/core@0.19.1': {}
|
||||
|
||||
'@humanfs/node@0.16.6':
|
||||
|
@ -3644,6 +3660,10 @@ snapshots:
|
|||
|
||||
mkdirp-classic@0.5.3: {}
|
||||
|
||||
mode-watcher@0.5.0(svelte@5.19.0):
|
||||
dependencies:
|
||||
svelte: 5.19.0
|
||||
|
||||
mri@1.2.0: {}
|
||||
|
||||
mrmime@2.0.0: {}
|
||||
|
|
|
@ -2,8 +2,13 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<meta name="apple-mobile-web-app-title" content="Kasterpalu" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
|
|
|
@ -26,17 +26,17 @@
|
|||
}}
|
||||
onconsider={handleDndConsider}
|
||||
onfinalize={handleDndFinalize}
|
||||
class="grid grid-cols-3 items-center gap-14"
|
||||
class="grid grid-cols-3 items-center gap-4 sm:gap-8 md:gap-10 lg:gap-14"
|
||||
>
|
||||
{#each items as item, i (item.id)}
|
||||
<div animate:flip={{ duration: flipDurationMs, easing: expoOut }}>
|
||||
<Card.Root
|
||||
class="overflow-hidden rounded-xl border bg-card text-card-foreground shadow {type ===
|
||||
'names'
|
||||
? 'border-orange-300'
|
||||
? 'border-red-400 '
|
||||
: type === 'artists'
|
||||
? 'border-cyan-300'
|
||||
: 'border-purple-300'}"
|
||||
? 'border-purple-400 '
|
||||
: 'border-blue-400'}"
|
||||
>
|
||||
{#if image}
|
||||
<Card.Content class="p-0">
|
||||
|
@ -45,7 +45,13 @@
|
|||
</Card.Content>
|
||||
{:else}
|
||||
<Card.Content>
|
||||
<p class="text-center">
|
||||
<p
|
||||
class="text-center {type === 'names'
|
||||
? 'text-red-900 dark:text-red-200'
|
||||
: type === 'artists'
|
||||
? 'text-purple-900 dark:text-purple-200'
|
||||
: ''}"
|
||||
>
|
||||
{#if type === 'artists'}
|
||||
{truncate(item.value, 30)}
|
||||
{:else}
|
||||
|
|
|
@ -17,7 +17,6 @@ class SpotifyAPI {
|
|||
|
||||
return await this.api.clientCredentialsGrant().then(
|
||||
(data) => {
|
||||
console.log(data.body);
|
||||
if (!data.body['expires_in'] || !data.body['access_token']) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,39 @@
|
|||
<script lang="ts">
|
||||
import '../app.css';
|
||||
import '@fontsource-variable/smooch-sans';
|
||||
|
||||
import { ModeWatcher, toggleMode } from 'mode-watcher';
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import Sun from 'lucide-svelte/icons/sun';
|
||||
import Moon from 'lucide-svelte/icons/moon';
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<div class="flex min-h-screen flex-col items-center justify-center">
|
||||
<header class="mb-24 flex flex-col items-center">
|
||||
<h1 class="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl">Paku biiti</h1>
|
||||
<p class="text-xl text-muted-foreground">
|
||||
Lohista kokku õiged albumi <span class="text-orange-400">nimed</span>,
|
||||
<span class="text-cyan-400">artistid</span> ja <span class="text-purple-400">pildid</span>.
|
||||
<ModeWatcher />
|
||||
|
||||
<header class="container absolute top-0 flex justify-between py-6">
|
||||
<a href="/">
|
||||
<img src="/favicon.svg" alt="Mihkel Martin Kasterpalu logo" class="h-10" />
|
||||
</a>
|
||||
<Button onclick={toggleMode} variant="outline" size="icon">
|
||||
<Sun
|
||||
class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0"
|
||||
/>
|
||||
<Moon
|
||||
class="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100"
|
||||
/>
|
||||
<span class="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
</header>
|
||||
|
||||
<div class="container flex min-h-screen flex-col items-center justify-center py-4">
|
||||
<header class="font-title mb-24 flex flex-col items-center">
|
||||
<h1 class="mb-1 scroll-m-20 text-6xl font-extrabold tracking-tight lg:text-7xl">Paku biiti</h1>
|
||||
<p class="text-2xl font-semibold text-muted-foreground">
|
||||
Lohista kokku õiged albumi <span class="text-red-600 dark:text-red-400">nimed</span>,
|
||||
<span class="text-purple-600 dark:text-purple-400">artistid</span> ja
|
||||
<span class="text-blue-600 dark:text-blue-400">pildid</span>.
|
||||
</p>
|
||||
</header>
|
||||
<main class="w-full max-w-3xl">
|
||||
|
|
|
@ -30,17 +30,17 @@
|
|||
</script>
|
||||
|
||||
{#snippet footer(loading: boolean)}
|
||||
<div class="flex justify-evenly">
|
||||
<p class="text-lg font-semibold">Skoor: {data.stage}</p>
|
||||
<div class="mt-8 flex items-center justify-evenly">
|
||||
<p class="font-title text-lg font-semibold">Skoor: {data.stage}</p>
|
||||
{#if loading}
|
||||
<Button disabled>
|
||||
<Button disabled class="min-w-[4.5rem]">
|
||||
<LoaderCircle class="animate-spin" />
|
||||
Oota korra
|
||||
Oota
|
||||
</Button>
|
||||
{:else}
|
||||
<Button type="submit">Saada</Button>
|
||||
<Button type="submit" class="min-w-[4.5rem]">Saada</Button>
|
||||
{/if}
|
||||
<p class="text-lg font-semibold">Parim: {data.highscore}</p>
|
||||
<p class="font-title text-lg font-semibold">Parim: {data.highscore}</p>
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
|
@ -74,16 +74,14 @@
|
|||
action="?/submit"
|
||||
method="POST"
|
||||
use:enhance
|
||||
class="grid w-full gap-6 px-8 transition-all {loading || data?.playing === false
|
||||
? 'grayscale'
|
||||
: ''}"
|
||||
class="grid w-full gap-6 transition-all {loading || data?.playing === false ? 'grayscale' : ''}"
|
||||
>
|
||||
{#if data?.streamed?.albums}
|
||||
{#await data.streamed.albums}
|
||||
{#each { length: 2 } as _}
|
||||
<section class="grid grid-cols-3 items-center gap-14">
|
||||
{#each { length: 3 } as _}
|
||||
<Skeleton class="h-[6rem] w-full rounded-xl " />
|
||||
<Skeleton class="h-[5.25rem] w-full rounded-xl " />
|
||||
{/each}
|
||||
</section>
|
||||
<Separator />
|
||||
|
|
BIN
static/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
static/favicon-96x96.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
static/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 1.5 KiB |
18
static/favicon.svg
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="1480" height="1480" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg id="SvgjsSvg1026" class="img-fluid" width="1480" height="1480" cursor="move"
|
||||
style="transform-origin:50% 50% 0px;transform:matrix(1, 0, 0, 1, -4, -2);transition:none"
|
||||
viewBox="0 0 14800 14800" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="SvgjsG1025" style="transform:none">
|
||||
<g style="transform:none">
|
||||
<path id="SvgjsPath1024"
|
||||
d="m7170 14789c-113-3-232-7-265-8l-60-1 550-550-1300-1301-1300-1300 25 6c26 5 297 69 2204 515l1119 262 877-877v-20c0-11-196-785-434-1720-239-935-433-1701-431-1703 1-2 611 598 1356 1333l1353 1336 913-913c502-502 913-916 913-919 0-6-5948-5922-5959-5927-3-1-377 369-830 822l-823 823 639 2519c352 1386 639 2520 638 2522-2 2-488-114-1081-257-3433-828-3987-961-4002-961h-17l-480 480-479 480-7-8c-4-4-23-68-42-142-142-542-221-1089-236-1635l-6-240 14-500 15-165c58-610 171-1144 357-1700 554-1656 1707-3085 3216-3988 1082-648 2291-1002 3553-1041l245-8 247 8 246 8 169 16c232 22 648 79 661 91 2 1-65 69-149 151-404 393-664 761-823 1165l-46 116-34 134c-19 73-42 174-52 223l-16 90-10 410 16 113c18 120 60 300 74 314l9 9 718-256c395-141 721-258 726-260l7-5-14-53-15-52-12-220 17-85 18-85 58-142 52-78 52-79 85-86 86-86 56-36 55-36 62-21 61-21h44 43l48 16 47 16 60 55 59 55 30 61 30 62 42 160 10 320-204 2608 777 777 2533-2533 107 144c385 515 707 1093 948 1704l75 190 70 215c199 608 307 1171 352 1830l11 155v315 315l-11 155c-70 1025-326 1967-775 2855-825 1630-2206 2890-3904 3559-648 256-1308 412-2036 481l-160 15-190 5c-104 3-224 7-265 8-41 2-167 0-280-4z" />
|
||||
<path id="SvgjsPath1023"
|
||||
d="m11586 2508c9-69 65-831 72-987l7-164 167 125c91 69 230 179 308 243l141 119-348 348c-191 191-349 348-350 348s0-15 3-32z" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="SvgjsG1022" fill="#fff" style="transform:none"></g>
|
||||
</svg>
|
||||
<style>@media (prefers-color-scheme: light) { :root { filter: none; } }
|
||||
@media (prefers-color-scheme: dark) { :root { filter: invert(100%); } }</style>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
21
static/site.webmanifest
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "Kasterpalu",
|
||||
"short_name": "Kasterpalu",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/web-app-manifest-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "/web-app-manifest-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
BIN
static/web-app-manifest-192x192.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
static/web-app-manifest-512x512.png
Normal file
After Width: | Height: | Size: 10 KiB |
|
@ -1,96 +1,97 @@
|
|||
import { fontFamily } from "tailwindcss/defaultTheme";
|
||||
import type { Config } from "tailwindcss";
|
||||
import tailwindcssAnimate from "tailwindcss-animate";
|
||||
import { fontFamily } from 'tailwindcss/defaultTheme';
|
||||
import type { Config } from 'tailwindcss';
|
||||
import tailwindcssAnimate from 'tailwindcss-animate';
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: ["./src/**/*.{html,js,svelte,ts}"],
|
||||
safelist: ["dark"],
|
||||
darkMode: ['class'],
|
||||
content: ['./src/**/*.{html,js,svelte,ts}'],
|
||||
safelist: ['dark'],
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: "2rem",
|
||||
padding: '2rem',
|
||||
screens: {
|
||||
"2xl": "1400px"
|
||||
'2xl': '1400px'
|
||||
}
|
||||
},
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border) / <alpha-value>)",
|
||||
input: "hsl(var(--input) / <alpha-value>)",
|
||||
ring: "hsl(var(--ring) / <alpha-value>)",
|
||||
background: "hsl(var(--background) / <alpha-value>)",
|
||||
foreground: "hsl(var(--foreground) / <alpha-value>)",
|
||||
border: 'hsl(var(--border) / <alpha-value>)',
|
||||
input: 'hsl(var(--input) / <alpha-value>)',
|
||||
ring: 'hsl(var(--ring) / <alpha-value>)',
|
||||
background: 'hsl(var(--background) / <alpha-value>)',
|
||||
foreground: 'hsl(var(--foreground) / <alpha-value>)',
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary) / <alpha-value>)",
|
||||
foreground: "hsl(var(--primary-foreground) / <alpha-value>)"
|
||||
DEFAULT: 'hsl(var(--primary) / <alpha-value>)',
|
||||
foreground: 'hsl(var(--primary-foreground) / <alpha-value>)'
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: "hsl(var(--secondary) / <alpha-value>)",
|
||||
foreground: "hsl(var(--secondary-foreground) / <alpha-value>)"
|
||||
DEFAULT: 'hsl(var(--secondary) / <alpha-value>)',
|
||||
foreground: 'hsl(var(--secondary-foreground) / <alpha-value>)'
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: "hsl(var(--destructive) / <alpha-value>)",
|
||||
foreground: "hsl(var(--destructive-foreground) / <alpha-value>)"
|
||||
DEFAULT: 'hsl(var(--destructive) / <alpha-value>)',
|
||||
foreground: 'hsl(var(--destructive-foreground) / <alpha-value>)'
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: "hsl(var(--muted) / <alpha-value>)",
|
||||
foreground: "hsl(var(--muted-foreground) / <alpha-value>)"
|
||||
DEFAULT: 'hsl(var(--muted) / <alpha-value>)',
|
||||
foreground: 'hsl(var(--muted-foreground) / <alpha-value>)'
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: "hsl(var(--accent) / <alpha-value>)",
|
||||
foreground: "hsl(var(--accent-foreground) / <alpha-value>)"
|
||||
DEFAULT: 'hsl(var(--accent) / <alpha-value>)',
|
||||
foreground: 'hsl(var(--accent-foreground) / <alpha-value>)'
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: "hsl(var(--popover) / <alpha-value>)",
|
||||
foreground: "hsl(var(--popover-foreground) / <alpha-value>)"
|
||||
DEFAULT: 'hsl(var(--popover) / <alpha-value>)',
|
||||
foreground: 'hsl(var(--popover-foreground) / <alpha-value>)'
|
||||
},
|
||||
card: {
|
||||
DEFAULT: "hsl(var(--card) / <alpha-value>)",
|
||||
foreground: "hsl(var(--card-foreground) / <alpha-value>)"
|
||||
DEFAULT: 'hsl(var(--card) / <alpha-value>)',
|
||||
foreground: 'hsl(var(--card-foreground) / <alpha-value>)'
|
||||
},
|
||||
sidebar: {
|
||||
DEFAULT: "hsl(var(--sidebar-background))",
|
||||
foreground: "hsl(var(--sidebar-foreground))",
|
||||
primary: "hsl(var(--sidebar-primary))",
|
||||
"primary-foreground": "hsl(var(--sidebar-primary-foreground))",
|
||||
accent: "hsl(var(--sidebar-accent))",
|
||||
"accent-foreground": "hsl(var(--sidebar-accent-foreground))",
|
||||
border: "hsl(var(--sidebar-border))",
|
||||
ring: "hsl(var(--sidebar-ring))",
|
||||
},
|
||||
DEFAULT: 'hsl(var(--sidebar-background))',
|
||||
foreground: 'hsl(var(--sidebar-foreground))',
|
||||
primary: 'hsl(var(--sidebar-primary))',
|
||||
'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
|
||||
accent: 'hsl(var(--sidebar-accent))',
|
||||
'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
|
||||
border: 'hsl(var(--sidebar-border))',
|
||||
ring: 'hsl(var(--sidebar-ring))'
|
||||
}
|
||||
},
|
||||
borderRadius: {
|
||||
xl: "calc(var(--radius) + 4px)",
|
||||
lg: "var(--radius)",
|
||||
md: "calc(var(--radius) - 2px)",
|
||||
sm: "calc(var(--radius) - 4px)"
|
||||
xl: 'calc(var(--radius) + 4px)',
|
||||
lg: 'var(--radius)',
|
||||
md: 'calc(var(--radius) - 2px)',
|
||||
sm: 'calc(var(--radius) - 4px)'
|
||||
},
|
||||
fontFamily: {
|
||||
sans: [...fontFamily.sans]
|
||||
sans: [...fontFamily.sans],
|
||||
title: ['Smooch Sans Variable', ...fontFamily.sans]
|
||||
},
|
||||
keyframes: {
|
||||
"accordion-down": {
|
||||
from: { height: "0" },
|
||||
to: { height: "var(--bits-accordion-content-height)" },
|
||||
'accordion-down': {
|
||||
from: { height: '0' },
|
||||
to: { height: 'var(--bits-accordion-content-height)' }
|
||||
},
|
||||
"accordion-up": {
|
||||
from: { height: "var(--bits-accordion-content-height)" },
|
||||
to: { height: "0" },
|
||||
},
|
||||
"caret-blink": {
|
||||
"0%,70%,100%": { opacity: "1" },
|
||||
"20%,50%": { opacity: "0" },
|
||||
'accordion-up': {
|
||||
from: { height: 'var(--bits-accordion-content-height)' },
|
||||
to: { height: '0' }
|
||||
},
|
||||
'caret-blink': {
|
||||
'0%,70%,100%': { opacity: '1' },
|
||||
'20%,50%': { opacity: '0' }
|
||||
}
|
||||
},
|
||||
animation: {
|
||||
"accordion-down": "accordion-down 0.2s ease-out",
|
||||
"accordion-up": "accordion-up 0.2s ease-out",
|
||||
"caret-blink": "caret-blink 1.25s ease-out infinite",
|
||||
},
|
||||
},
|
||||
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||
'caret-blink': 'caret-blink 1.25s ease-out infinite'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [tailwindcssAnimate],
|
||||
plugins: [tailwindcssAnimate]
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|