abstracting the xstate towards a more generic flow
This commit is contained in:
		| @@ -36,13 +36,26 @@ | ||||
| 			initial: 'start', | ||||
| 			context: { | ||||
| 				name: '', | ||||
| 				email: '' | ||||
| 				email: '', | ||||
| 				constraints: {} // <- New addition | ||||
| 			}, | ||||
| 			states: { | ||||
| 				start: { | ||||
| 					meta: { | ||||
| 						title: 'Welcome!', | ||||
| 						description: 'Start your registration process by clicking next.' | ||||
| 					}, | ||||
| 					on: { NEXT: 'nameInput' } | ||||
| 				}, | ||||
| 				nameInput: { | ||||
| 					meta: { | ||||
| 						title: 'Name Input', | ||||
| 						description: 'Please enter your name.', | ||||
| 						fieldLabel: 'Name' | ||||
| 					}, | ||||
| 					entry: assign({ | ||||
| 						constraints: (context) => constraints.name || {} | ||||
| 					}), | ||||
| 					on: { | ||||
| 						NEXT: { | ||||
| 							target: 'emailInput', | ||||
| @@ -52,6 +65,14 @@ | ||||
| 					} | ||||
| 				}, | ||||
| 				emailInput: { | ||||
| 					meta: { | ||||
| 						title: 'Email Input', | ||||
| 						description: 'Please enter your email address.', | ||||
| 						fieldLabel: 'Email' | ||||
| 					}, | ||||
| 					entry: assign({ | ||||
| 						constraints: (context) => constraints.email || {} | ||||
| 					}), | ||||
| 					on: { | ||||
| 						NEXT: { | ||||
| 							target: 'summary', | ||||
| @@ -61,19 +82,45 @@ | ||||
| 					} | ||||
| 				}, | ||||
| 				summary: { | ||||
| 					meta: { | ||||
| 						title: 'Summary', | ||||
| 						description: 'Review your details before submission.' | ||||
| 					}, | ||||
| 					on: { | ||||
| 						SUBMIT: 'submitting' | ||||
| 					} | ||||
| 				}, | ||||
| 				submitting: { | ||||
| 					meta: { | ||||
| 						title: 'Submitting...' | ||||
| 					}, | ||||
| 					invoke: { | ||||
| 						src: 'createUserService', | ||||
| 						onDone: 'success', | ||||
| 						onError: 'failure' | ||||
| 						onError: { | ||||
| 							target: 'failure', | ||||
| 							actions: assign({ | ||||
| 								error: (context, event) => event.data | ||||
| 							}) | ||||
| 						} | ||||
| 					} | ||||
| 				}, | ||||
| 				success: {}, | ||||
| 				failure: {} | ||||
| 				success: { | ||||
| 					meta: { | ||||
| 						title: 'Success' | ||||
| 					}, | ||||
| 					on: { | ||||
| 						RESTART: 'start' | ||||
| 					} | ||||
| 				}, | ||||
| 				failure: { | ||||
| 					meta: { | ||||
| 						title: 'Submission Failed' | ||||
| 					}, | ||||
| 					on: { | ||||
| 						RESTART: 'start' | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -86,7 +133,10 @@ | ||||
| 				}) | ||||
| 			}, | ||||
| 			services: { | ||||
| 				createUserService: (context) => createUser(context.name, context.email) | ||||
| 				createUserService: (context) => { | ||||
| 					console.log('Attempting to create user...'); | ||||
| 					return createUser(context.name, context.email); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	); | ||||
| @@ -100,24 +150,30 @@ | ||||
| </script> | ||||
|  | ||||
| <main> | ||||
| 	<h1 class="text-2xl"> | ||||
| 		{$state.value in stateMachine.states && stateMachine.states[$state.value].meta | ||||
| 			? stateMachine.states[$state.value].meta.title | ||||
| 			: 'Unknown state'} | ||||
| 	</h1> | ||||
| 	<p> | ||||
| 		{$state.value in stateMachine.states ? stateMachine.states[$state.value].meta.description : ''} | ||||
| 	</p> | ||||
|  | ||||
| 	{#if $state.value === 'start'} | ||||
| 		<!-- Step 1 --> | ||||
| 		<div> | ||||
| 			<h1 class="text-2xl">Step 1 - Start</h1> | ||||
| 		<button class="px-4 py-2 mt-4 text-white bg-blue-500 rounded" on:click={() => send('NEXT')}> | ||||
| 			Next | ||||
| 		</button> | ||||
| 		</div> | ||||
| 	{:else if $state.value === 'nameInput'} | ||||
| 		<!-- Step 2 --> | ||||
| 		<div> | ||||
| 			<h1 class="text-2xl">Step 2 - Name Input</h1> | ||||
| 		<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> | ||||
| 					<label for="name" class="block mb-2 font-semibold text-white" | ||||
| 						>{$state.value in stateMachine.states | ||||
| 							? stateMachine.states[$state.value].meta.fieldLabel | ||||
| 							: ''}</label | ||||
| 					> | ||||
| 				{/if} | ||||
|  | ||||
| 				<input | ||||
| @@ -126,7 +182,7 @@ | ||||
| 					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} | ||||
| 					{...$state.context.constraints} | ||||
| 				/> | ||||
| 			</div> | ||||
| 			<button | ||||
| @@ -138,16 +194,17 @@ | ||||
| 				Next | ||||
| 			</button> | ||||
| 		</form> | ||||
| 		</div> | ||||
| 	{:else if $state.value === 'emailInput'} | ||||
| 		<div> | ||||
| 			<h1 class="text-2xl">Step 3 - Email Input</h1> | ||||
| 		<form on:submit|preventDefault={handleSubmit} class="w-full max-w-md"> | ||||
| 			<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> | ||||
| 					<label for="email" class="block mb-2 font-semibold text-white" | ||||
| 						>{$state.value in stateMachine.states | ||||
| 							? stateMachine.states[$state.value].meta.fieldLabel | ||||
| 							: ''}</label | ||||
| 					> | ||||
| 				{/if} | ||||
|  | ||||
| 				<input | ||||
| @@ -156,7 +213,7 @@ | ||||
| 					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} | ||||
| 					{...$state.context.constraints} | ||||
| 				/> | ||||
| 			</div> | ||||
| 			<button | ||||
| @@ -168,33 +225,31 @@ | ||||
| 				Next | ||||
| 			</button> | ||||
| 		</form> | ||||
| 		</div> | ||||
|  | ||||
| 		<!-- Add a Summary Section --> | ||||
| 	{:else if $state.value === 'summary'} | ||||
| 		<div> | ||||
| 			<h1 class="text-2xl">Summary</h1> | ||||
| 		<p>Name: {$form.name}</p> | ||||
| 		<p>Email: {$form.email}</p> | ||||
| 			<button class="px-4 py-2 mt-4 text-white bg-blue-500 rounded" on:click={() => send('SUBMIT')}> | ||||
| 		<button | ||||
| 			class="px-4 py-2 mt-4 text-white bg-blue-500 rounded" | ||||
| 			on:click={() => { | ||||
| 				console.log('Submit button clicked'); | ||||
| 				send('SUBMIT'); | ||||
| 			}} | ||||
| 		> | ||||
| 			Submit | ||||
| 		</button> | ||||
| 		</div> | ||||
| 	{:else if $state.value === 'submitting'} | ||||
| 		<div> | ||||
| 			<h1 class="text-2xl">Submitting...</h1> | ||||
| 		</div> | ||||
| 		<!-- You can optionally add a spinner or some visual indication here --> | ||||
| 	{:else if $state.value === 'success'} | ||||
| 		<div> | ||||
| 			<h1 class="text-2xl">User created successfully!</h1> | ||||
| 			<!-- You can add a button to reset the form or navigate to another page --> | ||||
| 		</div> | ||||
| 	{:else if $state.value === 'failure'} | ||||
| 		<div> | ||||
| 			<h1 class="text-2xl">Failed to create user. Please try again.</h1> | ||||
| 			<button class="px-4 py-2 mt-4 text-white bg-red-500 rounded" on:click={() => send('SUBMIT')}> | ||||
| 				Retry | ||||
| 		<p>Thank you for your submission!</p> | ||||
| 		<button class="px-4 py-2 mt-4 text-white bg-green-500 rounded" on:click={() => send('RESTART')}> | ||||
| 			Start Again | ||||
| 		</button> | ||||
| 	{:else if $state.value === 'failure'} | ||||
| 		<p class="text-red-500"> | ||||
| 			Error: {$state.context.error?.message || 'An unknown error occurred.'} | ||||
| 		</p> | ||||
| 		<button class="px-4 py-2 mt-4 text-white bg-red-500 rounded" on:click={() => send('RESTART')}> | ||||
| 			Try Again | ||||
| 		</button> | ||||
| 		</div> | ||||
| 	{/if} | ||||
| </main> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user