Compare commits
91 Commits
93bf436e94
...
rebuild
| Author | SHA1 | Date | |
|---|---|---|---|
|
fac25ca67b
|
|||
|
d11f22f5f8
|
|||
|
42f2a5ba21
|
|||
|
31cd1a61ad
|
|||
|
9f63e3a77a
|
|||
|
4c5499d050
|
|||
|
497a108647
|
|||
|
38e6c145e2
|
|||
|
828cc0547e
|
|||
|
c3248099c6
|
|||
|
2aa8c4178a
|
|||
|
52b8db4a5a
|
|||
|
012a0043b3
|
|||
|
625c0c3ed2
|
|||
|
a3e800aa94
|
|||
|
399b7b0798
|
|||
|
0de50822cd
|
|||
|
0177c50651
|
|||
|
f7575f46e4
|
|||
|
a8d90d4882
|
|||
|
a2ffa5055e
|
|||
|
b969932582
|
|||
|
72ace57cb3
|
|||
|
16f9228390
|
|||
|
16d15f7242
|
|||
|
115767c656
|
|||
|
bb3c801908
|
|||
|
e512325115
|
|||
|
aa7d2dbe1b
|
|||
|
01cd8d4b78
|
|||
|
c7c1c6dc41
|
|||
|
bf8b351b64
|
|||
|
58830c5db3
|
|||
|
066e67c64f
|
|||
|
5f5b03a8a0
|
|||
|
cbfbd92d0e
|
|||
|
418fe7773f
|
|||
|
4b6e11d8d2
|
|||
|
0698038523
|
|||
|
297b88016b
|
|||
|
8959223016
|
|||
|
a3e437d966
|
|||
|
19c9fa339b
|
|||
|
8017f009e4
|
|||
|
482d6387fa
|
|||
|
ff36691ada
|
|||
|
8ec4fc0c83
|
|||
|
a07eb4ddf5
|
|||
|
ec6598feb1
|
|||
|
93872030ed
|
|||
|
a610c6abd1
|
|||
|
0a883ce7fb
|
|||
|
f2d8ab81e9
|
|||
|
c546a96c4d
|
|||
|
c82fdf3823
|
|||
|
a46a67793c
|
|||
|
898d3595a0
|
|||
|
3aa6f0473b
|
|||
|
22be68311b
|
|||
|
5d7a25e54f
|
|||
|
16deab5308
|
|||
|
45eb4b0828
|
|||
|
c0a39bdabe
|
|||
|
e25aaf3e5e
|
|||
|
d68e88ec9a
|
|||
|
1a0f52f31f
|
|||
|
1c5e246095
|
|||
|
74970c4c5b
|
|||
|
fffe290360
|
|||
|
3d110e8f48
|
|||
|
0bd83f8000
|
|||
|
910fa3867b
|
|||
|
2e355dbb46
|
|||
|
d3d0d17b3a
|
|||
|
7cecbfe80e
|
|||
|
710cad376e
|
|||
|
5a81cb64f5
|
|||
|
09aee15f60
|
|||
|
f98a4fc2b1
|
|||
|
7879ca82fd
|
|||
|
c1400c0120
|
|||
|
8b086c5aa8
|
|||
|
078e8dcb9a
|
|||
|
5ed21bb13d
|
|||
|
f6dd25c988
|
|||
|
88f36575fb
|
|||
|
f927cc916b
|
|||
|
e5535f1869
|
|||
|
50764bca47
|
|||
|
eca9966e29
|
|||
|
abff31aaee
|
@@ -1,13 +0,0 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
@@ -1,20 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
|
||||
plugins: ['svelte3', '@typescript-eslint'],
|
||||
ignorePatterns: ['*.cjs'],
|
||||
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
|
||||
settings: {
|
||||
'svelte3/typescript': () => require('typescript')
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2017: true,
|
||||
node: true
|
||||
}
|
||||
};
|
||||
27
.gitea/workflows/dev.yaml
Normal file
27
.gitea/workflows/dev.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Build latest image
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build-container:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Login to registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.odit.services
|
||||
username: ${{ vars.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
push: true
|
||||
tags: |
|
||||
${{ vars.REGISTRY }}/lfk/kiosk:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
27
.gitea/workflows/release.yaml
Normal file
27
.gitea/workflows/release.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Build release images
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*.*.*"
|
||||
|
||||
jobs:
|
||||
build-container:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Login to registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.odit.services
|
||||
username: ${{ vars.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
push: true
|
||||
tags: |
|
||||
${{ vars.REGISTRY }}/lfk/kiosk:${{ github.ref_name }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
22
.gitignore
vendored
22
.gitignore
vendored
@@ -1,10 +1,26 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
|
||||
# Output
|
||||
.output
|
||||
.vercel
|
||||
.netlify
|
||||
.wrangler
|
||||
/.svelte-kit
|
||||
/package
|
||||
/build
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Env
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
!.env.test
|
||||
|
||||
# Vite
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
|
||||
# additional
|
||||
tmp
|
||||
@@ -1,13 +0,0 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"pluginSearchDirs": ["."],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
||||
15
Dockerfile
Normal file
15
Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
FROM registry.odit.services/hub/library/node:19.9.0-alpine3.16 AS build
|
||||
ARG NPM_REGISTRY_URL=registry.npmjs.org
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json *.config.cjs *.config.js *.config.ts tsconfig.json .npmrc ./
|
||||
RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
|
||||
RUN pnpm i
|
||||
|
||||
COPY src ./src
|
||||
COPY static ./static
|
||||
RUN pnpm build
|
||||
|
||||
# final image
|
||||
FROM registry.odit.services/library/nginx-brotli:3.15 as final
|
||||
COPY --from=build /app/build /usr/share/nginx/html
|
||||
8
LICENSE
8
LICENSE
@@ -1,8 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
Copyright © 2023 ODIT.Services UG (haftungsbeschränkts) - info@odit.services
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
10
README.md
10
README.md
@@ -1,6 +1,6 @@
|
||||
# create-svelte
|
||||
# sv
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
|
||||
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
|
||||
|
||||
## Creating a project
|
||||
|
||||
@@ -8,10 +8,10 @@ If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npm create svelte@latest
|
||||
npx sv create
|
||||
|
||||
# create a new project in my-app
|
||||
npm create svelte@latest my-app
|
||||
npx sv create my-app
|
||||
```
|
||||
|
||||
## Developing
|
||||
@@ -35,4 +35,4 @@ npm run build
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
||||
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
||||
|
||||
14
components.json
Normal file
14
components.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "https://shadcn-svelte.com/schema.json",
|
||||
"style": "default",
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "src\\app.css",
|
||||
"baseColor": "slate"
|
||||
},
|
||||
"aliases": {
|
||||
"components": "$lib/components",
|
||||
"utils": "$lib/utils"
|
||||
},
|
||||
"typescript": true
|
||||
}
|
||||
6
docker-compose.yml
Normal file
6
docker-compose.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
version: "3"
|
||||
services:
|
||||
httpd:
|
||||
build: .
|
||||
ports:
|
||||
- 8181:80
|
||||
36
eslint.config.js
Normal file
36
eslint.config.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import js from '@eslint/js';
|
||||
import { includeIgnoreFile } from '@eslint/compat';
|
||||
import svelte from 'eslint-plugin-svelte';
|
||||
import globals from 'globals';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import ts from 'typescript-eslint';
|
||||
import svelteConfig from './svelte.config.js';
|
||||
const gitignorePath = fileURLToPath(new URL("./.gitignore", import.meta.url));
|
||||
|
||||
export default ts.config(
|
||||
includeIgnoreFile(gitignorePath),
|
||||
js.configs.recommended,
|
||||
...ts.configs.recommended,
|
||||
...svelte.configs.recommended,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["**/*.svelte", "**/*.svelte.ts", "**/*.svelte.js"],
|
||||
ignores: ["eslint.config.js", "svelte.config.js"],
|
||||
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
extraFileExtensions: ['.svelte'],
|
||||
parser: ts.parser,
|
||||
svelteConfig
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
86
package.json
86
package.json
@@ -1,68 +1,46 @@
|
||||
{
|
||||
"name": "@lfk/kiosk",
|
||||
"name": "kiosk",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"prepare": "svelte-kit sync || echo ''",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --plugin-search-dir . --check . && eslint .",
|
||||
"format": "prettier --plugin-search-dir . --write .",
|
||||
"release": "release-it",
|
||||
"license:export": "license-exporter --markdown && git stage licenses.md"
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@odit/license-exporter": "^0.0.12",
|
||||
"@sveltejs/adapter-static": "^2.0.2",
|
||||
"@sveltejs/kit": "^1.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"auto-changelog": "^2.4.0",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-svelte3": "^4.0.0",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss-load-config": "^4.0.1",
|
||||
"prettier": "^2.8.0",
|
||||
"prettier-plugin-svelte": "^2.8.1",
|
||||
"release-it": "^15.10.1",
|
||||
"svelte": "^3.54.0",
|
||||
"svelte-check": "^3.0.1",
|
||||
"svelte-preprocess": "^4.10.7",
|
||||
"tailwindcss": "^3.1.5",
|
||||
"tslib": "^2.4.1",
|
||||
"@eslint/compat": "^1.2.5",
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
"@sveltejs/kit": "^2.16.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"bits-ui": "0.22.0",
|
||||
"clsx": "^2.1.1",
|
||||
"eslint": "^9.18.0",
|
||||
"eslint-plugin-svelte": "^3.0.0",
|
||||
"globals": "^16.0.0",
|
||||
"lucide-svelte": "^0.483.0",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tailwind-merge": "^3.0.2",
|
||||
"tailwind-variants": "^1.0.0",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^4.2.0"
|
||||
"typescript-eslint": "^8.20.0",
|
||||
"vite": "^6.0.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild"
|
||||
]
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"bwip-js": "^3.4.0"
|
||||
},
|
||||
"release-it": {
|
||||
"git": {
|
||||
"commit": true,
|
||||
"requireCleanWorkingDir": false,
|
||||
"commitMessage": "🚀Bumped version to ${version}",
|
||||
"requireBranch": "dev",
|
||||
"push": true,
|
||||
"tag": true,
|
||||
"tagName": null,
|
||||
"tagAnnotation": "${version}"
|
||||
},
|
||||
"npm": {
|
||||
"publish": false
|
||||
},
|
||||
"hooks": {
|
||||
"after:bump": "pnpx auto-changelog --commit-limit false -p -u --hide-credit && pnpm licenses:export && git add CHANGELOG.md licenses.md"
|
||||
}
|
||||
},
|
||||
"volta": {
|
||||
"node": "19.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"pnpm": "8"
|
||||
"@lucide/svelte": "^0.483.0",
|
||||
"mode-watcher": "^0.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6145
pnpm-lock.yaml
generated
6145
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
||||
const tailwindcss = require('tailwindcss');
|
||||
const autoprefixer = require('autoprefixer');
|
||||
|
||||
const config = {
|
||||
plugins: [
|
||||
//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
|
||||
tailwindcss(),
|
||||
//But others, like autoprefixer, need to run after,
|
||||
autoprefixer
|
||||
]
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
}
|
||||
};
|
||||
49
src/app.css
Normal file
49
src/app.css
Normal file
@@ -0,0 +1,49 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
--primary: 221.2 83.2% 53.3%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
--destructive: 0 72.22% 50.59%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--ring: 221.2 83.2% 53.3%;
|
||||
--radius: 0.75rem;
|
||||
}
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
--card: 222.2 84% 4.9%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
--popover: 222.2 84% 4.9%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
--primary: 217.2 91.2% 59.8%;
|
||||
--primary-foreground: 222.2 47.4% 11.2%;
|
||||
--secondary: 217.2 32.6% 17.5%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
--muted: 217.2 32.6% 17.5%;
|
||||
--muted-foreground: 215 20.2% 65.1%;
|
||||
--accent: 217.2 32.6% 17.5%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--border: 217.2 32.6% 17.5%;
|
||||
--input: 217.2 32.6% 17.5%;
|
||||
--ring: 224.3 76.3% 48%;
|
||||
}
|
||||
}
|
||||
3
src/app.d.ts
vendored
3
src/app.d.ts
vendored
@@ -1,10 +1,11 @@
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
// See https://svelte.dev/docs/kit/types#app.d.ts
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface PageState {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/* Write your global styles here, in PostCSS syntax */
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
25
src/lib/components/ui/button/button.svelte
Normal file
25
src/lib/components/ui/button/button.svelte
Normal file
@@ -0,0 +1,25 @@
|
||||
<script lang="ts">
|
||||
import { Button as ButtonPrimitive } from "bits-ui";
|
||||
import { type Events, type Props, buttonVariants } from "./index.js";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = Props;
|
||||
type $$Events = Events;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let variant: $$Props["variant"] = "default";
|
||||
export let size: $$Props["size"] = "default";
|
||||
export let builders: $$Props["builders"] = [];
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ButtonPrimitive.Root
|
||||
{builders}
|
||||
class={cn(buttonVariants({ variant, size, className }))}
|
||||
type="button"
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
>
|
||||
<slot />
|
||||
</ButtonPrimitive.Root>
|
||||
49
src/lib/components/ui/button/index.ts
Normal file
49
src/lib/components/ui/button/index.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { type VariantProps, tv } from "tailwind-variants";
|
||||
import type { Button as ButtonPrimitive } from "bits-ui";
|
||||
import Root from "./button.svelte";
|
||||
|
||||
const buttonVariants = tv({
|
||||
base: "ring-offset-background focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
outline:
|
||||
"border-input bg-background hover:bg-accent hover:text-accent-foreground border",
|
||||
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 px-4 py-2",
|
||||
sm: "h-9 rounded-md px-3",
|
||||
lg: "h-11 rounded-md px-8",
|
||||
icon: "h-10 w-10",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
});
|
||||
|
||||
type Variant = VariantProps<typeof buttonVariants>["variant"];
|
||||
type Size = VariantProps<typeof buttonVariants>["size"];
|
||||
|
||||
type Props = ButtonPrimitive.Props & {
|
||||
variant?: Variant;
|
||||
size?: Size;
|
||||
};
|
||||
|
||||
type Events = ButtonPrimitive.Events;
|
||||
|
||||
export {
|
||||
Root,
|
||||
type Props,
|
||||
type Events,
|
||||
//
|
||||
Root as Button,
|
||||
type Props as ButtonProps,
|
||||
type Events as ButtonEvents,
|
||||
buttonVariants,
|
||||
};
|
||||
13
src/lib/components/ui/card/card-content.svelte
Normal file
13
src/lib/components/ui/card/card-content.svelte
Normal file
@@ -0,0 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<div class={cn("p-6", className)} {...$$restProps}>
|
||||
<slot />
|
||||
</div>
|
||||
13
src/lib/components/ui/card/card-description.svelte
Normal file
13
src/lib/components/ui/card/card-description.svelte
Normal file
@@ -0,0 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLParagraphElement>;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<p class={cn("text-muted-foreground text-sm", className)} {...$$restProps}>
|
||||
<slot />
|
||||
</p>
|
||||
13
src/lib/components/ui/card/card-footer.svelte
Normal file
13
src/lib/components/ui/card/card-footer.svelte
Normal file
@@ -0,0 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<div class={cn("flex items-center p-6 pt-0", className)} {...$$restProps}>
|
||||
<slot />
|
||||
</div>
|
||||
13
src/lib/components/ui/card/card-header.svelte
Normal file
13
src/lib/components/ui/card/card-header.svelte
Normal file
@@ -0,0 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<div class={cn("flex flex-col space-y-1.5 p-6 pb-0", className)} {...$$restProps}>
|
||||
<slot />
|
||||
</div>
|
||||
21
src/lib/components/ui/card/card-title.svelte
Normal file
21
src/lib/components/ui/card/card-title.svelte
Normal file
@@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import type { HeadingLevel } from "./index.js";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLHeadingElement> & {
|
||||
tag?: HeadingLevel;
|
||||
};
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let tag: $$Props["tag"] = "h3";
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<svelte:element
|
||||
this={tag}
|
||||
class={cn("text-lg font-semibold leading-none tracking-tight", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</svelte:element>
|
||||
16
src/lib/components/ui/card/card.svelte
Normal file
16
src/lib/components/ui/card/card.svelte
Normal file
@@ -0,0 +1,16 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={cn("bg-card text-card-foreground rounded-lg border shadow-sm", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
24
src/lib/components/ui/card/index.ts
Normal file
24
src/lib/components/ui/card/index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import Root from "./card.svelte";
|
||||
import Content from "./card-content.svelte";
|
||||
import Description from "./card-description.svelte";
|
||||
import Footer from "./card-footer.svelte";
|
||||
import Header from "./card-header.svelte";
|
||||
import Title from "./card-title.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
Content,
|
||||
Description,
|
||||
Footer,
|
||||
Header,
|
||||
Title,
|
||||
//
|
||||
Root as Card,
|
||||
Content as CardContent,
|
||||
Description as CardDescription,
|
||||
Footer as CardFooter,
|
||||
Header as CardHeader,
|
||||
Title as CardTitle,
|
||||
};
|
||||
|
||||
export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
||||
35
src/lib/components/ui/checkbox/checkbox.svelte
Normal file
35
src/lib/components/ui/checkbox/checkbox.svelte
Normal file
@@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import { Checkbox as CheckboxPrimitive } from "bits-ui";
|
||||
import Check from "lucide-svelte/icons/check";
|
||||
import Minus from "lucide-svelte/icons/minus";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = CheckboxPrimitive.Props;
|
||||
type $$Events = CheckboxPrimitive.Events;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let checked: $$Props["checked"] = false;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<CheckboxPrimitive.Root
|
||||
class={cn(
|
||||
"border-primary ring-offset-background focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground peer box-content h-4 w-4 shrink-0 rounded-sm border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50",
|
||||
className
|
||||
)}
|
||||
bind:checked
|
||||
{...$$restProps}
|
||||
on:click
|
||||
>
|
||||
<CheckboxPrimitive.Indicator
|
||||
class={cn("flex h-4 w-4 items-center justify-center text-current")}
|
||||
let:isChecked
|
||||
let:isIndeterminate
|
||||
>
|
||||
{#if isChecked}
|
||||
<Check class="h-3.5 w-3.5" />
|
||||
{:else if isIndeterminate}
|
||||
<Minus class="h-3.5 w-3.5" />
|
||||
{/if}
|
||||
</CheckboxPrimitive.Indicator>
|
||||
</CheckboxPrimitive.Root>
|
||||
6
src/lib/components/ui/checkbox/index.ts
Normal file
6
src/lib/components/ui/checkbox/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import Root from "./checkbox.svelte";
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Checkbox,
|
||||
};
|
||||
29
src/lib/components/ui/input/index.ts
Normal file
29
src/lib/components/ui/input/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import Root from "./input.svelte";
|
||||
|
||||
export type FormInputEvent<T extends Event = Event> = T & {
|
||||
currentTarget: EventTarget & HTMLInputElement;
|
||||
};
|
||||
export type InputEvents = {
|
||||
blur: FormInputEvent<FocusEvent>;
|
||||
change: FormInputEvent<Event>;
|
||||
click: FormInputEvent<MouseEvent>;
|
||||
focus: FormInputEvent<FocusEvent>;
|
||||
focusin: FormInputEvent<FocusEvent>;
|
||||
focusout: FormInputEvent<FocusEvent>;
|
||||
keydown: FormInputEvent<KeyboardEvent>;
|
||||
keypress: FormInputEvent<KeyboardEvent>;
|
||||
keyup: FormInputEvent<KeyboardEvent>;
|
||||
mouseover: FormInputEvent<MouseEvent>;
|
||||
mouseenter: FormInputEvent<MouseEvent>;
|
||||
mouseleave: FormInputEvent<MouseEvent>;
|
||||
mousemove: FormInputEvent<MouseEvent>;
|
||||
paste: FormInputEvent<ClipboardEvent>;
|
||||
input: FormInputEvent<InputEvent>;
|
||||
wheel: FormInputEvent<WheelEvent>;
|
||||
};
|
||||
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Input,
|
||||
};
|
||||
42
src/lib/components/ui/input/input.svelte
Normal file
42
src/lib/components/ui/input/input.svelte
Normal file
@@ -0,0 +1,42 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLInputAttributes } from "svelte/elements";
|
||||
import type { InputEvents } from "./index.js";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = HTMLInputAttributes;
|
||||
type $$Events = InputEvents;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let value: $$Props["value"] = undefined;
|
||||
export { className as class };
|
||||
|
||||
// Workaround for https://github.com/sveltejs/svelte/issues/9305
|
||||
// Fixed in Svelte 5, but not backported to 4.x.
|
||||
export let readonly: $$Props["readonly"] = undefined;
|
||||
</script>
|
||||
|
||||
<input
|
||||
class={cn(
|
||||
"border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
bind:value
|
||||
{readonly}
|
||||
on:blur
|
||||
on:change
|
||||
on:click
|
||||
on:focus
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:keydown
|
||||
on:keypress
|
||||
on:keyup
|
||||
on:mouseover
|
||||
on:mouseenter
|
||||
on:mouseleave
|
||||
on:mousemove
|
||||
on:paste
|
||||
on:input
|
||||
on:wheel|passive
|
||||
{...$$restProps}
|
||||
/>
|
||||
7
src/lib/components/ui/label/index.ts
Normal file
7
src/lib/components/ui/label/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import Root from "./label.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Label,
|
||||
};
|
||||
21
src/lib/components/ui/label/label.svelte
Normal file
21
src/lib/components/ui/label/label.svelte
Normal file
@@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { Label as LabelPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = LabelPrimitive.Props;
|
||||
type $$Events = LabelPrimitive.Events;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<LabelPrimitive.Root
|
||||
class={cn(
|
||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:mousedown
|
||||
>
|
||||
<slot />
|
||||
</LabelPrimitive.Root>
|
||||
7
src/lib/components/ui/progress/index.ts
Normal file
7
src/lib/components/ui/progress/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import Root from "./progress.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Progress,
|
||||
};
|
||||
21
src/lib/components/ui/progress/progress.svelte
Normal file
21
src/lib/components/ui/progress/progress.svelte
Normal file
@@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { Progress as ProgressPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ProgressPrimitive.Props;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let max: $$Props["max"] = 100;
|
||||
export let value: $$Props["value"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ProgressPrimitive.Root
|
||||
class={cn("bg-secondary relative h-4 w-full overflow-hidden rounded-full", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<div
|
||||
class="bg-primary h-full w-full flex-1 transition-all"
|
||||
style={`transform: translateX(-${100 - (100 * (value ?? 0)) / (max ?? 1)}%)`}
|
||||
></div>
|
||||
</ProgressPrimitive.Root>
|
||||
1
src/lib/index.ts
Normal file
1
src/lib/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
// place files you want to import through the `$lib` alias in this folder.
|
||||
62
src/lib/utils.ts
Normal file
62
src/lib/utils.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { cubicOut } from "svelte/easing";
|
||||
import type { TransitionConfig } from "svelte/transition";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
type FlyAndScaleParams = {
|
||||
y?: number;
|
||||
x?: number;
|
||||
start?: number;
|
||||
duration?: number;
|
||||
};
|
||||
|
||||
export const flyAndScale = (
|
||||
node: Element,
|
||||
params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 }
|
||||
): TransitionConfig => {
|
||||
const style = getComputedStyle(node);
|
||||
const transform = style.transform === "none" ? "" : style.transform;
|
||||
|
||||
const scaleConversion = (
|
||||
valueA: number,
|
||||
scaleA: [number, number],
|
||||
scaleB: [number, number]
|
||||
) => {
|
||||
const [minA, maxA] = scaleA;
|
||||
const [minB, maxB] = scaleB;
|
||||
|
||||
const percentage = (valueA - minA) / (maxA - minA);
|
||||
const valueB = percentage * (maxB - minB) + minB;
|
||||
|
||||
return valueB;
|
||||
};
|
||||
|
||||
const styleToString = (
|
||||
style: Record<string, number | string | undefined>
|
||||
): string => {
|
||||
return Object.keys(style).reduce((str, key) => {
|
||||
if (style[key] === undefined) return str;
|
||||
return str + `${key}:${style[key]};`;
|
||||
}, "");
|
||||
};
|
||||
|
||||
return {
|
||||
duration: params.duration ?? 200,
|
||||
delay: 0,
|
||||
css: (t) => {
|
||||
const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]);
|
||||
const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]);
|
||||
const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]);
|
||||
|
||||
return styleToString({
|
||||
transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`,
|
||||
opacity: t
|
||||
});
|
||||
},
|
||||
easing: cubicOut
|
||||
};
|
||||
};
|
||||
36
src/routes/(components)/help.svelte
Normal file
36
src/routes/(components)/help.svelte
Normal file
@@ -0,0 +1,36 @@
|
||||
<script>
|
||||
import { Button } from "$lib/components/ui/button";
|
||||
</script>
|
||||
|
||||
<div class="container p-4 mx-auto">
|
||||
<div class="rounded-lg border bg-card text-card-foreground shadow-sm">
|
||||
<div class="p-6 space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-2xl font-bold">Guide</h2>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4">
|
||||
<div class="rounded-md bg-muted p-4">
|
||||
<h3 class="font-medium mb-2">Where am I?</h3>
|
||||
<p>
|
||||
Welcome to the Lauf für Kaya Kiosk application.<br>
|
||||
This tool helps you with signing up runners an getting them started.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-md bg-muted p-4">
|
||||
<h3 class="font-medium mb-2">Basic Functions</h3>
|
||||
<ul class="list-disc pl-5 space-y-1">
|
||||
<li>Register new participants</li>
|
||||
<li>Get your personal selfservice token</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="rounded-md bg-muted p-4">
|
||||
<h3 class="font-medium mb-2">Need More Help?</h3>
|
||||
<p>Contact the event organizers for additional assistance.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
33
src/routes/(components)/login.svelte
Normal file
33
src/routes/(components)/login.svelte
Normal file
@@ -0,0 +1,33 @@
|
||||
<script lang="ts">
|
||||
import { Button } from "$lib/components/ui/button/index.js";
|
||||
import * as Card from "$lib/components/ui/card/index.js";
|
||||
import { Input } from "$lib/components/ui/input/index.js";
|
||||
import { Label } from "$lib/components/ui/label/index.js";
|
||||
|
||||
let { loggedin = $bindable() } = $props();
|
||||
</script>
|
||||
|
||||
<div class="pt-48">
|
||||
<form
|
||||
onsubmit={() => {
|
||||
loggedin = true;
|
||||
}}
|
||||
class="flex justify-center items-center overflow-hidden"
|
||||
>
|
||||
<Card.Root class="w-full max-w-sm">
|
||||
<Card.Header>
|
||||
<Card.Title class="text-2xl">Login</Card.Title>
|
||||
<Card.Description>Please enter kiosk credentials.</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Content class="grid gap-4">
|
||||
<div class="grid gap-2">
|
||||
<Label for="password">Token</Label>
|
||||
<Input id="password" type="password" required autofocus />
|
||||
</div>
|
||||
</Card.Content>
|
||||
<Card.Footer>
|
||||
<Button class="w-full" type="submit">Sign in</Button>
|
||||
</Card.Footer>
|
||||
</Card.Root>
|
||||
</form>
|
||||
</div>
|
||||
BIN
src/routes/(components)/sampleqrlfkselfservice.png
Normal file
BIN
src/routes/(components)/sampleqrlfkselfservice.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 787 B |
259
src/routes/(components)/signup.svelte
Normal file
259
src/routes/(components)/signup.svelte
Normal file
@@ -0,0 +1,259 @@
|
||||
<script lang="ts">
|
||||
import { Button } from "$lib/components/ui/button/index.js";
|
||||
import * as Card from "$lib/components/ui/card/index.js";
|
||||
import Checkbox from "$lib/components/ui/checkbox/checkbox.svelte";
|
||||
import { Input } from "$lib/components/ui/input";
|
||||
import { Label } from "$lib/components/ui/label";
|
||||
import { Progress } from "$lib/components/ui/progress";
|
||||
import sampleQR from "./sampleqrlfkselfservice.png";
|
||||
|
||||
const Steps = {
|
||||
WELCOME: {
|
||||
name: "Welcome",
|
||||
progress: 0,
|
||||
showback: false,
|
||||
},
|
||||
SIGNUP: {
|
||||
name: "Signup",
|
||||
progress: 25,
|
||||
showback: true,
|
||||
},
|
||||
SIGNUP_MAIL: {
|
||||
name: "Signup with Mail",
|
||||
progress: 50,
|
||||
showback: true,
|
||||
},
|
||||
SIGNUP_AGB_ACCEPT: {
|
||||
name: "Accept terms",
|
||||
progress: 75,
|
||||
showback: true,
|
||||
},
|
||||
SIGNUP_SUCCESS: {
|
||||
name: "Done",
|
||||
progress: 100,
|
||||
showback: false,
|
||||
},
|
||||
SIGNIN: {
|
||||
name: "Signin with Barcode",
|
||||
progress: 100,
|
||||
showback: false,
|
||||
},
|
||||
SIGNIN_MAIL: {
|
||||
name: "Signin by Mail",
|
||||
progress: 75,
|
||||
showback: true,
|
||||
},
|
||||
SIGNIN_MAIL_SUCCESS: {
|
||||
name: "Signin by Mail Success",
|
||||
progress: 100,
|
||||
showback: false,
|
||||
},
|
||||
} as const;
|
||||
|
||||
type StepType = (typeof Steps)[keyof typeof Steps];
|
||||
let currentStep = $state<StepType>(Steps.WELCOME);
|
||||
let agbAgreed = $state<boolean>(false);
|
||||
let email = $state<string>("");
|
||||
let firstname = $state<string>("");
|
||||
let lastname = $state<string>("");
|
||||
let remainingseconds = $state<number>(5);
|
||||
</script>
|
||||
|
||||
<div class="pt-48">
|
||||
<div class="flex justify-center items-center overflow-hidden">
|
||||
<Card.Root class="w-full max-w-xl">
|
||||
<Card.Header>
|
||||
<Card.Title class="text-2xl">Welcome</Card.Title>
|
||||
<Card.Description
|
||||
>Let me guide you through the signup process.</Card.Description
|
||||
>
|
||||
{#if currentStep.name !== Steps.WELCOME.name}
|
||||
<Progress value={currentStep.progress} />
|
||||
{/if}
|
||||
</Card.Header>
|
||||
<Card.Content class="grid gap-4">
|
||||
{#if currentStep.name == Steps.WELCOME.name}
|
||||
<div class="grid gap-2">
|
||||
<Button
|
||||
autofocus
|
||||
class="w-full"
|
||||
on:click={() => {
|
||||
currentStep = Steps.SIGNUP;
|
||||
}}>I want to sign up now</Button
|
||||
>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Button
|
||||
variant="secondary"
|
||||
class="w-full"
|
||||
on:click={() => {
|
||||
currentStep = Steps.SIGNIN;
|
||||
}}>I already signed up online</Button
|
||||
>
|
||||
</div>
|
||||
{:else if currentStep.name == Steps.SIGNUP.name}
|
||||
<form
|
||||
class="grid gap-2"
|
||||
onsubmit={() => {
|
||||
currentStep = Steps.SIGNUP_MAIL;
|
||||
}}
|
||||
>
|
||||
<div class="grid gap-2">
|
||||
<Label for="firstname">Please enter your first name</Label>
|
||||
<Input
|
||||
on:keypress={(event) => {
|
||||
console.log(event.key);
|
||||
if (event.key === "Enter") {
|
||||
document.getElementById("lastname")?.focus();
|
||||
}
|
||||
}}
|
||||
bind:value={firstname}
|
||||
id="firstname"
|
||||
type="text"
|
||||
placeholder="Max"
|
||||
required
|
||||
autofocus
|
||||
/>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Label for="lastname">Please enter your last name</Label>
|
||||
<Input
|
||||
bind:value={lastname}
|
||||
id="lastname"
|
||||
type="text"
|
||||
placeholder="Mustermann"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" variant="default" class="w-full"
|
||||
>Continue</Button
|
||||
>
|
||||
</form>
|
||||
{:else if currentStep.name == Steps.SIGNUP_MAIL.name}
|
||||
<form
|
||||
class="grid gap-2"
|
||||
onsubmit={() => {
|
||||
currentStep = Steps.SIGNUP_AGB_ACCEPT;
|
||||
}}
|
||||
>
|
||||
<div class="grid gap-2">
|
||||
<Label for="email"
|
||||
>Enter your email to get an invitation to our selfservice
|
||||
(optional)</Label
|
||||
>
|
||||
<Input
|
||||
autofocus
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
bind:value={email}
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" variant="default" class="w-full"
|
||||
>Continue</Button
|
||||
>
|
||||
</form>
|
||||
{:else if currentStep.name == Steps.SIGNUP_AGB_ACCEPT.name}
|
||||
{#if email !== ""}
|
||||
By registering, you confirm that {email} is your email
|
||||
{/if}
|
||||
<div class="items-top flex space-x-2">
|
||||
<Checkbox bind:checked={agbAgreed} autofocus id="terms1" />
|
||||
<div class="grid gap-1.5 leading-none">
|
||||
<Label
|
||||
for="terms1"
|
||||
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
>
|
||||
Accept terms and conditions
|
||||
</Label>
|
||||
<p class="text-muted-foreground text-sm">
|
||||
You agree to our Terms of Service and Privacy Policy.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
disabled={!agbAgreed}
|
||||
variant="default"
|
||||
class="w-full"
|
||||
on:click={() => {
|
||||
currentStep = Steps.SIGNUP_SUCCESS;
|
||||
}}>Continue</Button
|
||||
>
|
||||
{:else if currentStep.name == Steps.SIGNUP_SUCCESS.name}
|
||||
<p class="text-center">
|
||||
Alright that's it, just walk up to the next available person and
|
||||
tell them your name.<br />
|
||||
You can scan this qr code to login to our selfservice.
|
||||
<!-- TODO: generate actual qr code -->
|
||||
<img class="mx-auto h-56" src={sampleQR} alt="" />
|
||||
</p>
|
||||
{:else if currentStep.name == Steps.SIGNIN.name}
|
||||
Just walk up to the next available person and show them your barcode.
|
||||
{:else if currentStep.name == Steps.SIGNIN_MAIL.name}
|
||||
<div class="grid gap-2">
|
||||
<Label for="email"
|
||||
>No problem, just enter the email address you used to sign up</Label
|
||||
>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
bind:value={email}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Button
|
||||
class="w-full"
|
||||
on:click={() => {
|
||||
console.log("Email: ", email);
|
||||
currentStep = Steps.SIGNIN_MAIL_SUCCESS;
|
||||
}}>Continue</Button
|
||||
>
|
||||
</div>
|
||||
{:else if currentStep.name == Steps.SIGNIN_MAIL_SUCCESS.name}
|
||||
We found your email address, just walk up to the next available person
|
||||
and tell them your name.
|
||||
{/if}
|
||||
</Card.Content>
|
||||
<Card.Footer class="grid gap-2">
|
||||
{#if currentStep.showback}
|
||||
<Button
|
||||
variant="destructive"
|
||||
class="w-full"
|
||||
on:click={() => {
|
||||
switch (currentStep.name) {
|
||||
case Steps.SIGNUP.name:
|
||||
currentStep = Steps.WELCOME;
|
||||
break;
|
||||
case Steps.SIGNUP_MAIL.name:
|
||||
currentStep = Steps.SIGNUP;
|
||||
break;
|
||||
case Steps.SIGNUP_AGB_ACCEPT.name:
|
||||
currentStep = Steps.SIGNUP_MAIL;
|
||||
break;
|
||||
case Steps.SIGNIN.name:
|
||||
currentStep = Steps.WELCOME;
|
||||
break;
|
||||
case Steps.SIGNIN_MAIL.name:
|
||||
currentStep = Steps.SIGNIN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}}>Go Back</Button
|
||||
>
|
||||
{/if}
|
||||
{#if currentStep.progress == 100}
|
||||
<Button
|
||||
variant="default"
|
||||
class="w-full"
|
||||
on:click={() => {
|
||||
currentStep = Steps.WELCOME;
|
||||
}}>Done</Button
|
||||
>
|
||||
{/if}
|
||||
</Card.Footer>
|
||||
</Card.Root>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,5 +1,53 @@
|
||||
<script>
|
||||
import '../app.postcss';
|
||||
<script lang="ts">
|
||||
import "../app.css";
|
||||
import { ModeWatcher } from "mode-watcher";
|
||||
import { Button } from "$lib/components/ui/button";
|
||||
import { Sun, Moon, HelpCircle } from "@lucide/svelte";
|
||||
import { toggleMode } from "mode-watcher";
|
||||
import Help from "./(components)/help.svelte";
|
||||
let { children } = $props();
|
||||
let showHelp = $state(false);
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
<ModeWatcher />
|
||||
|
||||
<div class="overflow-hidden">
|
||||
<div
|
||||
class="fixed top-0 left-0 right-0 z-50 border-b bg-background/80 backdrop-blur-sm"
|
||||
>
|
||||
<div class="container flex items-center justify-between py-2">
|
||||
<h1 class="text-xl font-bold">Lauf für Kaya! Kiosk</h1>
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- <Button on:click={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> -->
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
on:click={() => (showHelp = !showHelp)}
|
||||
>
|
||||
<HelpCircle
|
||||
class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all"
|
||||
/>
|
||||
<span class="sr-only">Show help</span>
|
||||
</Button>
|
||||
<!-- More buttons can be added here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-14">
|
||||
{#if showHelp}
|
||||
<Help />
|
||||
{:else}
|
||||
<!-- This div adds spacing below the fixed navbar -->
|
||||
{@render children()}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export const prerender = true;
|
||||
@@ -1,2 +1,11 @@
|
||||
<h1>Welcome to SvelteKit</h1>
|
||||
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
|
||||
<script lang="ts">
|
||||
import Login from "./(components)/login.svelte";
|
||||
import Signup from "./(components)/signup.svelte";
|
||||
let loggedin = $state(false);
|
||||
</script>
|
||||
|
||||
{#if !loggedin}
|
||||
<Login bind:loggedin />
|
||||
{:else}
|
||||
<Signup />
|
||||
{/if}
|
||||
|
||||
@@ -1,23 +1,18 @@
|
||||
import preprocess from 'svelte-preprocess';
|
||||
import adapter from '@sveltejs/adapter-static';
|
||||
import { vitePreprocess } from '@sveltejs/kit/vite';
|
||||
import adapter from "@sveltejs/adapter-static";
|
||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
||||
// Consult https://svelte.dev/docs/kit/integrations
|
||||
// for more information about preprocessors
|
||||
preprocess: [
|
||||
vitePreprocess(),
|
||||
preprocess({
|
||||
postcss: true
|
||||
})
|
||||
],
|
||||
preprocess: vitePreprocess(),
|
||||
|
||||
kit: {
|
||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
||||
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||
adapter: adapter()
|
||||
},
|
||||
|
||||
alias: {
|
||||
"@/*": "./src/lib/*",
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
const config = {
|
||||
content: ['./src/**/*.{html,js,svelte,ts}'],
|
||||
|
||||
theme: {
|
||||
extend: {}
|
||||
},
|
||||
|
||||
plugins: []
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
64
tailwind.config.ts
Normal file
64
tailwind.config.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { fontFamily } from "tailwindcss/defaultTheme";
|
||||
import type { Config } from "tailwindcss";
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: ["./src/**/*.{html,js,svelte,ts}"],
|
||||
safelist: ["dark"],
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: "2rem",
|
||||
screens: {
|
||||
"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>)",
|
||||
primary: {
|
||||
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>)"
|
||||
},
|
||||
destructive: {
|
||||
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>)"
|
||||
},
|
||||
accent: {
|
||||
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>)"
|
||||
},
|
||||
card: {
|
||||
DEFAULT: "hsl(var(--card) / <alpha-value>)",
|
||||
foreground: "hsl(var(--card-foreground) / <alpha-value>)"
|
||||
}
|
||||
},
|
||||
borderRadius: {
|
||||
lg: "var(--radius)",
|
||||
md: "calc(var(--radius) - 2px)",
|
||||
sm: "calc(var(--radius) - 4px)"
|
||||
},
|
||||
fontFamily: {
|
||||
sans: [...fontFamily.sans]
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -8,9 +8,11 @@
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true
|
||||
"strict": true,
|
||||
"moduleResolution": "bundler"
|
||||
}
|
||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
|
||||
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
|
||||
//
|
||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||
|
||||
Reference in New Issue
Block a user