autofocus + more signup logic
This commit is contained in:
parent
2aa8c4178a
commit
c3248099c6
@ -24,6 +24,7 @@
|
|||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-plugin-svelte": "^3.0.0",
|
"eslint-plugin-svelte": "^3.0.0",
|
||||||
"globals": "^16.0.0",
|
"globals": "^16.0.0",
|
||||||
|
"lucide-svelte": "^0.483.0",
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
|
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@ -48,6 +48,9 @@ importers:
|
|||||||
globals:
|
globals:
|
||||||
specifier: ^16.0.0
|
specifier: ^16.0.0
|
||||||
version: 16.0.0
|
version: 16.0.0
|
||||||
|
lucide-svelte:
|
||||||
|
specifier: ^0.483.0
|
||||||
|
version: 0.483.0(svelte@5.25.2)
|
||||||
svelte:
|
svelte:
|
||||||
specifier: ^5.0.0
|
specifier: ^5.0.0
|
||||||
version: 5.25.2
|
version: 5.25.2
|
||||||
@ -1002,6 +1005,11 @@ packages:
|
|||||||
lru-cache@10.4.3:
|
lru-cache@10.4.3:
|
||||||
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
||||||
|
|
||||||
|
lucide-svelte@0.483.0:
|
||||||
|
resolution: {integrity: sha512-MyMgEVLlFfPbyodGpkB+KCpyPkpjI7EKiFw1crA92B1ZXRK5hq5vTsGWAm9Nt3GAKHunoNc5MVsq3EOCz0DZSQ==}
|
||||||
|
peerDependencies:
|
||||||
|
svelte: ^3 || ^4 || ^5.0.0-next.42
|
||||||
|
|
||||||
magic-string@0.30.17:
|
magic-string@0.30.17:
|
||||||
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
|
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
|
||||||
|
|
||||||
@ -2332,6 +2340,10 @@ snapshots:
|
|||||||
|
|
||||||
lru-cache@10.4.3: {}
|
lru-cache@10.4.3: {}
|
||||||
|
|
||||||
|
lucide-svelte@0.483.0(svelte@5.25.2):
|
||||||
|
dependencies:
|
||||||
|
svelte: 5.25.2
|
||||||
|
|
||||||
magic-string@0.30.17:
|
magic-string@0.30.17:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.5.0
|
'@jridgewell/sourcemap-codec': 1.5.0
|
||||||
|
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,
|
||||||
|
};
|
@ -8,25 +8,26 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="pt-48">
|
<div class="pt-48">
|
||||||
<div class="flex justify-center items-center overflow-hidden">
|
<form
|
||||||
|
onsubmit={() => {
|
||||||
|
loggedin = true;
|
||||||
|
}}
|
||||||
|
class="flex justify-center items-center overflow-hidden"
|
||||||
|
>
|
||||||
<Card.Root class="w-full max-w-sm">
|
<Card.Root class="w-full max-w-sm">
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
<Card.Title class="text-2xl">Login</Card.Title>
|
<Card.Title class="text-2xl">Login</Card.Title>
|
||||||
<Card.Description
|
<Card.Description>Please enter kiosk credentials.</Card.Description>
|
||||||
>Please enter kiosk credentials.</Card.Description
|
|
||||||
>
|
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content class="grid gap-4">
|
<Card.Content class="grid gap-4">
|
||||||
<div class="grid gap-2">
|
<div class="grid gap-2">
|
||||||
<Label for="password">Token</Label>
|
<Label for="password">Token</Label>
|
||||||
<Input id="password" type="password" required />
|
<Input id="password" type="password" required autofocus />
|
||||||
</div>
|
</div>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
<Card.Footer>
|
<Card.Footer>
|
||||||
<Button class="w-full" on:click={() => (loggedin = true)}
|
<Button class="w-full" type="submit">Sign in</Button>
|
||||||
>Sign in</Button
|
|
||||||
>
|
|
||||||
</Card.Footer>
|
</Card.Footer>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
</div>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Button } from "$lib/components/ui/button/index.js";
|
import { Button } from "$lib/components/ui/button/index.js";
|
||||||
import * as Card from "$lib/components/ui/card/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 { Input } from "$lib/components/ui/input";
|
||||||
import { Label } from "$lib/components/ui/label";
|
import { Label } from "$lib/components/ui/label";
|
||||||
import { Progress } from "$lib/components/ui/progress";
|
import { Progress } from "$lib/components/ui/progress";
|
||||||
@ -21,7 +22,7 @@
|
|||||||
progress: 50,
|
progress: 50,
|
||||||
showback: true,
|
showback: true,
|
||||||
},
|
},
|
||||||
SIGNUP_MAIL_ACCEPT: {
|
SIGNUP_AGB_ACCEPT: {
|
||||||
name: "Accept terms",
|
name: "Accept terms",
|
||||||
progress: 75,
|
progress: 75,
|
||||||
showback: true,
|
showback: true,
|
||||||
@ -56,6 +57,8 @@
|
|||||||
type StepType = (typeof Steps)[keyof typeof Steps];
|
type StepType = (typeof Steps)[keyof typeof Steps];
|
||||||
let currentStep = $state<StepType>(Steps.WELCOME);
|
let currentStep = $state<StepType>(Steps.WELCOME);
|
||||||
let email = $state<string>("");
|
let email = $state<string>("");
|
||||||
|
let firstname = $state<string>("");
|
||||||
|
let lastname = $state<string>("");
|
||||||
let remainingseconds = $state<number>(5);
|
let remainingseconds = $state<number>(5);
|
||||||
|
|
||||||
// Function to handle automatic return to welcome screen
|
// Function to handle automatic return to welcome screen
|
||||||
@ -74,7 +77,7 @@
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
import { onDestroy } from 'svelte';
|
import { onDestroy } from "svelte";
|
||||||
|
|
||||||
// Watch for changes to currentStep
|
// Watch for changes to currentStep
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
@ -102,6 +105,7 @@
|
|||||||
{#if currentStep.name == Steps.WELCOME.name}
|
{#if currentStep.name == Steps.WELCOME.name}
|
||||||
<div class="grid gap-2">
|
<div class="grid gap-2">
|
||||||
<Button
|
<Button
|
||||||
|
autofocus
|
||||||
class="w-full"
|
class="w-full"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
currentStep = Steps.SIGNUP;
|
currentStep = Steps.SIGNUP;
|
||||||
@ -118,42 +122,85 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
{:else if currentStep.name == Steps.SIGNUP.name}
|
{:else if currentStep.name == Steps.SIGNUP.name}
|
||||||
<div class="grid gap-2">
|
<form
|
||||||
<Label for="firstname">Please enter your first name</Label>
|
class="grid gap-2"
|
||||||
<Input id="firstname" type="text" placeholder="Max" required />
|
onsubmit={() => {
|
||||||
</div>
|
|
||||||
<div class="grid gap-2">
|
|
||||||
<Label for="lastname">Please enter your last name</Label>
|
|
||||||
<Input
|
|
||||||
id="lastname"
|
|
||||||
type="text"
|
|
||||||
placeholder="Mustermann"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
variant="default"
|
|
||||||
class="w-full"
|
|
||||||
on:click={() => {
|
|
||||||
currentStep = Steps.SIGNUP_MAIL;
|
currentStep = Steps.SIGNUP_MAIL;
|
||||||
}}>Continue</Button
|
}}
|
||||||
>
|
>
|
||||||
{:else if currentStep.name == Steps.SIGNUP_MAIL.name}
|
<div class="grid gap-2">
|
||||||
<div class="grid gap-2">
|
<Label for="firstname">Please enter your first name</Label>
|
||||||
<Label for="email"
|
<Input
|
||||||
>Enter your email to get an invitation to our selfservice
|
on:keypress={(event) => {
|
||||||
(optional)</Label
|
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
|
||||||
>
|
>
|
||||||
<Input id="email" type="email" placeholder="m@example.com" />
|
</form>
|
||||||
</div>
|
{:else if currentStep.name == Steps.SIGNUP_MAIL.name}
|
||||||
<Button
|
<form
|
||||||
variant="default"
|
class="grid gap-2"
|
||||||
class="w-full"
|
onsubmit={() => {
|
||||||
on:click={() => {
|
currentStep = Steps.SIGNUP_AGB_ACCEPT;
|
||||||
currentStep = Steps.SIGNUP_MAIL_ACCEPT;
|
}}
|
||||||
}}>Continue</Button
|
|
||||||
>
|
>
|
||||||
{:else if currentStep.name == Steps.SIGNUP_MAIL_ACCEPT.name}
|
<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 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
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
@ -163,13 +210,15 @@
|
|||||||
>
|
>
|
||||||
{:else if currentStep.name == Steps.SIGNUP_SUCCESS.name}
|
{:else if currentStep.name == Steps.SIGNUP_SUCCESS.name}
|
||||||
<p class="text-center">
|
<p class="text-center">
|
||||||
Alright that's it, just walk up to the next available person and tell them your name.<br>
|
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.
|
You can scan this qr code to login to our selfservice.
|
||||||
</p>
|
</p>
|
||||||
TODO:
|
TODO:
|
||||||
{:else if currentStep.name == Steps.SIGNIN.name}
|
{:else if currentStep.name == Steps.SIGNIN.name}
|
||||||
<div class="grid gap-2">
|
<div class="grid gap-2">
|
||||||
<Button
|
<Button
|
||||||
|
autofocus
|
||||||
class="w-full"
|
class="w-full"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
currentStep = Steps.SIGNIN_BARCODE;
|
currentStep = Steps.SIGNIN_BARCODE;
|
||||||
@ -210,7 +259,8 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
{:else if currentStep.name == Steps.SIGNIN_MAIL_SUCCESS.name}
|
{: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.
|
We found your email address, just walk up to the next available person
|
||||||
|
and tell them your name.
|
||||||
{/if}
|
{/if}
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
<Card.Footer class="grid gap-4">
|
<Card.Footer class="grid gap-4">
|
||||||
@ -226,6 +276,9 @@
|
|||||||
case Steps.SIGNUP_MAIL.name:
|
case Steps.SIGNUP_MAIL.name:
|
||||||
currentStep = Steps.SIGNUP;
|
currentStep = Steps.SIGNUP;
|
||||||
break;
|
break;
|
||||||
|
case Steps.SIGNUP_AGB_ACCEPT.name:
|
||||||
|
currentStep = Steps.SIGNUP_MAIL;
|
||||||
|
break;
|
||||||
case Steps.SIGNIN.name:
|
case Steps.SIGNIN.name:
|
||||||
currentStep = Steps.WELCOME;
|
currentStep = Steps.WELCOME;
|
||||||
break;
|
break;
|
||||||
@ -246,9 +299,8 @@
|
|||||||
variant="default"
|
variant="default"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
currentStep=Steps.WELCOME;
|
currentStep = Steps.WELCOME;
|
||||||
}
|
}}>Done</Button
|
||||||
}>Done</Button
|
|
||||||
>
|
>
|
||||||
<p class="text-center">
|
<p class="text-center">
|
||||||
Returning to the home screen in {remainingseconds} seconds...
|
Returning to the home screen in {remainingseconds} seconds...
|
||||||
|
Loading…
x
Reference in New Issue
Block a user