✅ admin side for now | 🔄 started FE
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
<script lang="ts">
|
||||
import Input from "$lib/components/ui/input/input.svelte";
|
||||
import LabelWrapper from "$lib/components/atoms/label-wrapper.svelte";
|
||||
import { paymentInfoVM } from "./payment.info.vm.svelte";
|
||||
import { chunk } from "$lib/core/array.utils";
|
||||
|
||||
function formatCardNumberForDisplay(value: string) {
|
||||
// return in format "XXXX XXXX XXXX XXXX" from "XXXXXXXXXXXXXXXX"
|
||||
const numbers = value.replace(/\D/g, "");
|
||||
if (numbers.length > 4) {
|
||||
return `${numbers.slice(0, 4)} ${numbers.slice(4, 8)} ${numbers.slice(
|
||||
8,
|
||||
12,
|
||||
)} ${numbers.slice(12, numbers.length)}`;
|
||||
}
|
||||
return numbers.slice(0, 19);
|
||||
}
|
||||
|
||||
function cleanupCardNo(value: string) {
|
||||
return value.replace(/\D/g, "").slice(0, 16);
|
||||
}
|
||||
|
||||
function formatExpiryDate(value: string) {
|
||||
const numbers = value.replace(/\D/g, "");
|
||||
if (numbers.length > 2) {
|
||||
return `${numbers.slice(0, 2)}/${numbers.slice(2, 4)}`;
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
|
||||
function formatCVV(value: string) {
|
||||
return value.replace(/\D/g, "").slice(0, 4);
|
||||
}
|
||||
|
||||
let validationTimeout = $state(undefined as undefined | NodeJS.Timer);
|
||||
|
||||
function debounceValidate() {
|
||||
if (validationTimeout) {
|
||||
clearTimeout(validationTimeout);
|
||||
}
|
||||
validationTimeout = setTimeout(() => {
|
||||
paymentInfoVM.validateAndSubmit();
|
||||
}, 500);
|
||||
}
|
||||
</script>
|
||||
|
||||
<form class="flex flex-col gap-4">
|
||||
<LabelWrapper
|
||||
label="Name on Card"
|
||||
error={paymentInfoVM.errors.cardholderName}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="John Doe"
|
||||
bind:value={paymentInfoVM.cardDetails.cardholderName}
|
||||
oninput={() => debounceValidate()}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
|
||||
<LabelWrapper label="Card Number" error={paymentInfoVM.errors.cardNumber}>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="1234 5678 9012 3456"
|
||||
maxlength={19}
|
||||
value={formatCardNumberForDisplay(
|
||||
paymentInfoVM.cardDetails.cardNumber,
|
||||
)}
|
||||
oninput={(e) => {
|
||||
paymentInfoVM.cardDetails.cardNumber = cleanupCardNo(
|
||||
e.currentTarget.value,
|
||||
);
|
||||
debounceValidate();
|
||||
}}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<LabelWrapper label="Expiry Date" error={paymentInfoVM.errors.expiry}>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="MM/YY"
|
||||
bind:value={paymentInfoVM.cardDetails.expiry}
|
||||
oninput={(e) => {
|
||||
paymentInfoVM.cardDetails.expiry = formatExpiryDate(
|
||||
e.currentTarget.value,
|
||||
);
|
||||
debounceValidate();
|
||||
}}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
|
||||
<LabelWrapper label="CVV" error={paymentInfoVM.errors.cvv}>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="123"
|
||||
bind:value={paymentInfoVM.cardDetails.cvv}
|
||||
oninput={(e) => {
|
||||
paymentInfoVM.cardDetails.cvv = formatCVV(
|
||||
e.currentTarget.value,
|
||||
);
|
||||
debounceValidate();
|
||||
}}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
</div>
|
||||
</form>
|
||||
Reference in New Issue
Block a user