Created basic Recipies UI flow mocks

This commit is contained in:
Samuel Andert 2023-07-28 15:41:05 +02:00
parent a4dec279dc
commit e1fd73a7e8
7 changed files with 301 additions and 1 deletions

View File

@ -0,0 +1,105 @@
<script lang="ts">
import { Stepper, Step } from '@skeletonlabs/skeleton';
import { recipeStore } from '$lib/components/recipies/recipeStore';
import { createMessage } from '$lib/services/messages/messages';
let name = '';
let email = '';
let lockedState = true;
function logOperation(text) {
const message = {
text: text,
sender: 'user',
type: 'chat'
};
createMessage(message);
}
function operation1() {
if (name) {
recipeStore.update((state) => {
state.context.name = name;
state.step = 1;
return state;
});
logOperation('Name added: ' + name);
} else {
alert('Error: Please enter a name');
}
}
function operation2() {
if (email) {
recipeStore.update((state) => {
state.context.email = email;
state.step = 2;
return state;
});
logOperation('Email added: ' + email);
} else {
alert('Error: Please enter an email');
}
}
function completeAndPrepareForRestart() {
logOperation('Recipe Completed. Preparing for restart...');
recipeStore.update((state) => {
state.step = 3;
return state;
});
}
function restartRecipe() {
name = '';
email = '';
recipeStore.set({
id: 'createUser',
step: 0,
context: {},
error: null
});
}
$: lockedState = ($recipeStore.step === 0 && !name) || ($recipeStore.step === 1 && !email);
function onStepHandler(e) {
if (e.detail.state.current === 1) {
operation1();
} else if (e.detail.state.current === 2) {
operation2();
} else if (e.detail.state.current === 3) {
completeAndPrepareForRestart();
}
}
</script>
<div class="flex items-center justify-center w-full h-full">
<Stepper on:step={onStepHandler} start={$recipeStore.step} class="w-full max-w-2xl">
<Step locked={lockedState}>
<svelte:fragment slot="header">Enter Name</svelte:fragment>
<div>
<label for="name">Name:</label>
<input type="text" class="text-black" bind:value={name} />
</div>
</Step>
<Step locked={lockedState}>
<svelte:fragment slot="header">Enter Email</svelte:fragment>
<div>
<label for="email">Email:</label>
<input type="text" class="text-black" bind:value={email} />
</div>
</Step>
<Step>
<svelte:fragment slot="header">Completed</svelte:fragment>
<h2>Recipe Completed</h2>
<p>Your Name: {$recipeStore.context.name}</p>
<p>Your Email: {$recipeStore.context.email}</p>
</Step>
<Step>
<svelte:fragment slot="header">Restart</svelte:fragment>
<h2>Ready to start over?</h2>
<button on:click={restartRecipe}>Restart</button>
</Step>
</Stepper>
</div>

View File

@ -0,0 +1,68 @@
<script lang="ts">
import { superForm } from 'sveltekit-superforms/client';
import { TreeSchema } from '$lib/types/treeSchema'; // Import the TreeType schema
import { afterUpdate } from 'svelte';
import { writable } from 'svelte/store';
const initialFormData = { name: '', age: '' }; // Replace email with age
const { form, errors, validate, constraints, capture, restore } = superForm(initialFormData, {
validators: TreeSchema, // Use TreeSchema
warnings: {
noValidationAndConstraints: false
},
validationMethod: 'oninput',
clearOnSubmit: 'errors-and-message'
});
export const snapshot = { capture, restore };
const successMessage = writable<string | null>(null);
async function handleSubmit() {
const validationResult = await validate();
if (!validationResult.valid) {
return;
}
console.log(form);
successMessage.set('Form submitted successfully!');
}
function handleReset() {
form.set({});
successMessage.set(null);
}
afterUpdate(() => {
const messageContainer = document.getElementById('message-container');
if (messageContainer) {
messageContainer.scrollIntoView({ behavior: 'smooth' });
}
});
</script>
{#if $successMessage}
<!-- Success message code remains the same -->
{:else}
<form on:submit|preventDefault={handleSubmit} class="w-full max-w-md">
<!-- Name field remains the same -->
<div class="mb-4">
{#if $errors.age}
<span class="block mb-2 font-semibold text-red-500">{$errors.age}</span>
{:else}
<label for="age" class="block mb-2 font-semibold text-white">Age</label>
{/if}
<input
name="age"
type="number"
class="w-full px-3 py-2 bg-transparent border-gray-100 rounded-md border-1 ring-0 ring-white focus:outline-none focus:ring-2 focus:ring-blue-500"
bind:value={$form.age}
aria-invalid={$errors.age ? 'true' : undefined}
{...constraints.age}
/>
</div>
<!-- Submit button code remains the same -->
</form>
{/if}

View File

@ -0,0 +1,69 @@
<script lang="ts">
import { superForm } from 'sveltekit-superforms/client';
import { UserSchema } from '$lib/types/UserSchema';
import currentStep from './Recipies.svelte';
const initialFormData = { name: '', email: '' };
const { form, errors, validate, constraints } = superForm(initialFormData, {
validators: UserSchema,
warnings: {
noValidationAndConstraints: false
},
validationMethod: 'oninput',
clearOnSubmit: 'errors-and-message'
});
async function handleSubmit() {
const validationResult = await validate();
if (validationResult.valid) {
console.log(form);
currentStep.update((val) => val + 1); // move to the next step
}
}
</script>
<form on:submit|preventDefault={handleSubmit} class="w-full max-w-md">
<div class="mb-4">
{#if $errors.name}
<span class="block mb-2 font-semibold text-red-500">{$errors.name}</span>
{:else}
<label for="name" class="block mb-2 font-semibold text-white">Name</label>
{/if}
<input
name="name"
type="text"
class="w-full px-3 py-2 bg-transparent border-gray-100 rounded-md border-1 ring-0 ring-white focus:outline-none focus:ring-2 focus:ring-blue-500"
bind:value={$form.name}
aria-invalid={$errors.name ? 'true' : undefined}
{...constraints.name}
/>
</div>
<div class="mb-4">
{#if $errors.email}
<span class="block mb-2 font-semibold text-red-500">{$errors.email}</span>
{:else}
<label for="email" class="block mb-2 font-semibold text-white">Email</label>
{/if}
<input
name="email"
type="email"
class="w-full px-3 py-2 bg-transparent border-gray-100 rounded-md border-1 ring-0 ring-white focus:outline-none focus:ring-2 focus:ring-blue-500"
bind:value={$form.email}
aria-invalid={$errors.email ? 'true' : undefined}
{...constraints.email}
/>
</div>
<button
type="submit"
class="w-full px-4 py-2 mt-4 text-white bg-blue-500 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
disabled={$errors.name || $errors.email}
>
Submit
</button>
</form>

View File

@ -0,0 +1,8 @@
import { writable } from 'svelte/store';
export const recipeStore = writable({
id: 'createUser',
step: 0,
context: {},
error: null
});

View File

@ -0,0 +1,13 @@
// userService.ts
export function createUser(name: string, email: string): Promise<string> {
return new Promise((resolve, reject) => {
// Simulating an API call.
setTimeout(() => {
if (name && email) {
resolve('User created successfully');
} else {
reject(new Error('Failed to create user'));
}
}, 2000);
});
}

View File

@ -0,0 +1,18 @@
import { z } from 'zod';
// Define custom validation messages
const validationMessages = {
name: {
minLength: 'Name must be at least 3 characters.',
maxLength: 'Name must contain at most 50 characters.',
},
age: {
min: 'Age must be at least 0 years.',
max: 'Age must be at most 5000 years.'
}
};
export const TreeSchema = z.object({
name: z.string().min(3, validationMessages.name.minLength).max(50, validationMessages.name.maxLength),
age: z.number().min(0, validationMessages.age.min).max(5000, validationMessages.age.max)
});

View File

@ -3,7 +3,26 @@
let composite = { let composite = {
id: 'test', id: 'test',
component: 'Flows' layout: {
areas: `
"top bottom"
`,
columns: '1fr 500px',
rows: '1fr'
},
children: [
{
id: 'recipietest',
component: 'Recipies',
slot: 'top'
},
{
id: 'bottommessage',
component: 'Messages',
slot: 'bottom',
map: { messages: '@data:queryMessages' }
}
]
}; };
</script> </script>