a.... LOT of Refactoring ~ 30% done???
This commit is contained in:
@@ -4,238 +4,121 @@
|
||||
import Input from "$lib/components/ui/input/input.svelte";
|
||||
import * as Select from "$lib/components/ui/select";
|
||||
import { COUNTRIES_SELECT } from "$lib/core/countries";
|
||||
import type { SelectOption } from "$lib/core/data.types";
|
||||
import { capitalize } from "$lib/core/string.utils";
|
||||
import type { CustomerInfo } from "$lib/domains/ticket/data/entities/create.entities";
|
||||
import { Gender } from "$lib/domains/ticket/data/entities/index";
|
||||
import { PHONE_COUNTRY_CODES } from "@pkg/logic/core/data/phonecc";
|
||||
import type { CustomerInfoModel } from "../data";
|
||||
import { customerInfoVM } from "./customerinfo.vm.svelte";
|
||||
|
||||
let { info = $bindable(), idx }: { info: CustomerInfo; idx: number } =
|
||||
$props();
|
||||
|
||||
const genderOpts = [
|
||||
{ label: capitalize(Gender.Male), value: Gender.Male },
|
||||
{ label: capitalize(Gender.Female), value: Gender.Female },
|
||||
{ label: capitalize(Gender.Other), value: Gender.Other },
|
||||
] as SelectOption[];
|
||||
let { info = $bindable() }: { info: CustomerInfoModel } = $props();
|
||||
|
||||
function onSubmit(e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
passengerInfoVM.validatePII(info, idx);
|
||||
customerInfoVM.validateCustomerInfo(info);
|
||||
}
|
||||
|
||||
let validationTimeout = $state(undefined as undefined | NodeJS.Timer);
|
||||
|
||||
function debounceValidate() {
|
||||
if (validationTimeout) {
|
||||
clearTimeout(validationTimeout);
|
||||
}
|
||||
validationTimeout = setTimeout(() => {
|
||||
passengerInfoVM.validatePII(info, idx);
|
||||
}, 500);
|
||||
customerInfoVM.debounceValidate(info);
|
||||
}
|
||||
</script>
|
||||
|
||||
<form action="#" class="flex w-full flex-col gap-4" onsubmit={onSubmit}>
|
||||
<!-- Name Fields -->
|
||||
<div class="flex flex-col gap-4 md:flex-row">
|
||||
<LabelWrapper
|
||||
label="First Name"
|
||||
error={passengerInfoVM.piiErrors[idx].firstName}
|
||||
>
|
||||
<LabelWrapper label="First Name" error={customerInfoVM.errors.firstName}>
|
||||
<Input
|
||||
placeholder="First Name"
|
||||
bind:value={info.firstName}
|
||||
required
|
||||
oninput={() => debounceValidate()}
|
||||
minlength={1}
|
||||
maxlength={64}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
|
||||
<LabelWrapper
|
||||
label="Middle Name"
|
||||
error={passengerInfoVM.piiErrors[idx].middleName}
|
||||
error={customerInfoVM.errors.middleName}
|
||||
>
|
||||
<Input
|
||||
placeholder="Middle Name"
|
||||
placeholder="Middle Name (Optional)"
|
||||
bind:value={info.middleName}
|
||||
oninput={() => debounceValidate()}
|
||||
required
|
||||
maxlength={64}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
|
||||
<LabelWrapper
|
||||
label="Last Name"
|
||||
error={passengerInfoVM.piiErrors[idx].lastName}
|
||||
>
|
||||
<LabelWrapper label="Last Name" error={customerInfoVM.errors.lastName}>
|
||||
<Input
|
||||
placeholder="Last Name"
|
||||
bind:value={info.lastName}
|
||||
required
|
||||
oninput={() => debounceValidate()}
|
||||
minlength={1}
|
||||
maxlength={64}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
</div>
|
||||
|
||||
<LabelWrapper label="Email" error={passengerInfoVM.piiErrors[idx].email}>
|
||||
<!-- Email Field -->
|
||||
<LabelWrapper label="Email" error={customerInfoVM.errors.email}>
|
||||
<Input
|
||||
placeholder="Email"
|
||||
bind:value={info.email}
|
||||
type="email"
|
||||
oninput={() => debounceValidate()}
|
||||
required
|
||||
maxlength={128}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
|
||||
<div class="flex flex-col gap-4 md:flex-row lg:flex-col xl:flex-row">
|
||||
<LabelWrapper
|
||||
label="Phone Number"
|
||||
error={passengerInfoVM.piiErrors[idx].phoneNumber}
|
||||
>
|
||||
<div class="flex gap-2">
|
||||
<Select.Root
|
||||
type="single"
|
||||
required
|
||||
onValueChange={(code) => {
|
||||
info.phoneCountryCode = code;
|
||||
}}
|
||||
name="phoneCode"
|
||||
>
|
||||
<Select.Trigger class="w-20">
|
||||
{#if info.phoneCountryCode}
|
||||
{info.phoneCountryCode}
|
||||
{:else}
|
||||
Select
|
||||
{/if}
|
||||
</Select.Trigger>
|
||||
<Select.Content>
|
||||
{#each PHONE_COUNTRY_CODES as { country, phoneCode }}
|
||||
<Select.Item value={phoneCode}>
|
||||
<span class="flex items-center gap-2">
|
||||
{phoneCode} ({country})
|
||||
</span>
|
||||
</Select.Item>
|
||||
{/each}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
|
||||
<Input
|
||||
placeholder="Phone Number"
|
||||
type="tel"
|
||||
bind:value={info.phoneNumber}
|
||||
required
|
||||
oninput={() => debounceValidate()}
|
||||
class="flex-1"
|
||||
/>
|
||||
</div>
|
||||
</LabelWrapper>
|
||||
|
||||
<LabelWrapper
|
||||
label="Passport Expiry"
|
||||
error={passengerInfoVM.piiErrors[idx].passportExpiry}
|
||||
>
|
||||
<Input
|
||||
placeholder="Passport Expiry"
|
||||
value={info.passportExpiry}
|
||||
type="date"
|
||||
<!-- Phone Number Field -->
|
||||
<LabelWrapper label="Phone Number" error={customerInfoVM.errors.phoneNumber}>
|
||||
<div class="flex gap-2">
|
||||
<Select.Root
|
||||
type="single"
|
||||
required
|
||||
oninput={(v) => {
|
||||
// @ts-ignore
|
||||
info.passportExpiry = v.target.value;
|
||||
onValueChange={(code) => {
|
||||
info.phoneCountryCode = code;
|
||||
debounceValidate();
|
||||
}}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
<LabelWrapper
|
||||
label="Passport/ID No"
|
||||
error={passengerInfoVM.piiErrors[idx].passportNo}
|
||||
>
|
||||
name="phoneCode"
|
||||
>
|
||||
<Select.Trigger class="w-28">
|
||||
{#if info.phoneCountryCode}
|
||||
{info.phoneCountryCode}
|
||||
{:else}
|
||||
Select
|
||||
{/if}
|
||||
</Select.Trigger>
|
||||
<Select.Content>
|
||||
{#each PHONE_COUNTRY_CODES as { country, phoneCode }}
|
||||
<Select.Item value={phoneCode}>
|
||||
<span class="flex items-center gap-2">
|
||||
{phoneCode} ({country})
|
||||
</span>
|
||||
</Select.Item>
|
||||
{/each}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
|
||||
<Input
|
||||
placeholder="Passport or ID card no."
|
||||
bind:value={info.passportNo}
|
||||
placeholder="Phone Number"
|
||||
type="tel"
|
||||
bind:value={info.phoneNumber}
|
||||
required
|
||||
oninput={() => debounceValidate()}
|
||||
class="flex-1"
|
||||
minlength={1}
|
||||
maxlength={20}
|
||||
required
|
||||
oninput={() => debounceValidate()}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
</div>
|
||||
</div>
|
||||
</LabelWrapper>
|
||||
|
||||
<!-- Address Section -->
|
||||
<Title size="h5">Address Information</Title>
|
||||
|
||||
<div class="flex flex-col gap-4 md:flex-row">
|
||||
<LabelWrapper
|
||||
label="Nationality"
|
||||
error={passengerInfoVM.piiErrors[idx].nationality}
|
||||
>
|
||||
<Select.Root
|
||||
type="single"
|
||||
required
|
||||
onValueChange={(e) => {
|
||||
info.nationality = e;
|
||||
debounceValidate();
|
||||
}}
|
||||
name="role"
|
||||
>
|
||||
<Select.Trigger class="w-full">
|
||||
{capitalize(
|
||||
info.nationality.length > 0 ? info.nationality : "Select",
|
||||
)}
|
||||
</Select.Trigger>
|
||||
<Select.Content>
|
||||
{#each COUNTRIES_SELECT as country}
|
||||
<Select.Item value={country.value}>
|
||||
{country.label}
|
||||
</Select.Item>
|
||||
{/each}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</LabelWrapper>
|
||||
<LabelWrapper
|
||||
label="Gender"
|
||||
error={passengerInfoVM.piiErrors[idx].gender}
|
||||
>
|
||||
<Select.Root
|
||||
type="single"
|
||||
required
|
||||
onValueChange={(e) => {
|
||||
info.gender = e as Gender;
|
||||
debounceValidate();
|
||||
}}
|
||||
name="role"
|
||||
>
|
||||
<Select.Trigger class="w-full">
|
||||
{capitalize(info.gender.length > 0 ? info.gender : "Select")}
|
||||
</Select.Trigger>
|
||||
<Select.Content>
|
||||
{#each genderOpts as gender}
|
||||
<Select.Item value={gender.value}>
|
||||
{gender.label}
|
||||
</Select.Item>
|
||||
{/each}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</LabelWrapper>
|
||||
|
||||
<LabelWrapper
|
||||
label="Date of Birth"
|
||||
error={passengerInfoVM.piiErrors[idx].dob}
|
||||
>
|
||||
<Input
|
||||
placeholder="Date of Birth"
|
||||
bind:value={info.dob}
|
||||
type="date"
|
||||
required
|
||||
oninput={() => debounceValidate()}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
</div>
|
||||
|
||||
<!-- and now for the address info - country, state, city, zip code, address and address 2 -->
|
||||
|
||||
<Title size="h5">Address Info</Title>
|
||||
|
||||
<div class="flex flex-col gap-4 md:flex-row">
|
||||
<LabelWrapper
|
||||
label="Country"
|
||||
error={passengerInfoVM.piiErrors[idx].country}
|
||||
>
|
||||
<LabelWrapper label="Country" error={customerInfoVM.errors.country}>
|
||||
<Select.Root
|
||||
type="single"
|
||||
required
|
||||
@@ -243,7 +126,7 @@
|
||||
info.country = e;
|
||||
debounceValidate();
|
||||
}}
|
||||
name="role"
|
||||
name="country"
|
||||
>
|
||||
<Select.Trigger class="w-full">
|
||||
{capitalize(
|
||||
@@ -260,63 +143,60 @@
|
||||
</Select.Root>
|
||||
</LabelWrapper>
|
||||
|
||||
<LabelWrapper label="State" error={passengerInfoVM.piiErrors[idx].state}>
|
||||
<LabelWrapper label="State" error={customerInfoVM.errors.state}>
|
||||
<Input
|
||||
placeholder="State"
|
||||
placeholder="State/Province"
|
||||
bind:value={info.state}
|
||||
required
|
||||
oninput={() => debounceValidate()}
|
||||
minlength={1}
|
||||
maxlength={128}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-4 md:flex-row">
|
||||
<LabelWrapper label="City" error={passengerInfoVM.piiErrors[idx].city}>
|
||||
<LabelWrapper label="City" error={customerInfoVM.errors.city}>
|
||||
<Input
|
||||
placeholder="City"
|
||||
bind:value={info.city}
|
||||
required
|
||||
minlength={1}
|
||||
maxlength={80}
|
||||
maxlength={128}
|
||||
oninput={() => debounceValidate()}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
|
||||
<LabelWrapper
|
||||
label="Zip Code"
|
||||
error={passengerInfoVM.piiErrors[idx].zipCode}
|
||||
>
|
||||
<LabelWrapper label="Zip Code" error={customerInfoVM.errors.zipCode}>
|
||||
<Input
|
||||
placeholder="Zip Code"
|
||||
placeholder="Zip/Postal Code"
|
||||
bind:value={info.zipCode}
|
||||
required
|
||||
minlength={1}
|
||||
maxlength={21}
|
||||
oninput={() => debounceValidate()}
|
||||
maxlength={12}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
</div>
|
||||
|
||||
<LabelWrapper label="Address" error={passengerInfoVM.piiErrors[idx].address}>
|
||||
<LabelWrapper label="Address" error={customerInfoVM.errors.address}>
|
||||
<Input
|
||||
placeholder="Address"
|
||||
placeholder="Street Address"
|
||||
bind:value={info.address}
|
||||
required
|
||||
minlength={1}
|
||||
maxlength={128}
|
||||
oninput={() => debounceValidate()}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
|
||||
<LabelWrapper
|
||||
label="Address 2"
|
||||
error={passengerInfoVM.piiErrors[idx].address2}
|
||||
label="Address 2 (Optional)"
|
||||
error={customerInfoVM.errors.address2}
|
||||
>
|
||||
<Input
|
||||
placeholder="Address 2"
|
||||
placeholder="Apartment, suite, etc. (Optional)"
|
||||
bind:value={info.address2}
|
||||
required
|
||||
minlength={1}
|
||||
maxlength={128}
|
||||
oninput={() => debounceValidate()}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user