diff --git a/apps/frontend/src/lib/domains/checkout/checkout-steps-indicator.svelte b/apps/frontend/src/lib/domains/checkout/checkout-steps-indicator.svelte
index c6dbab3..5faa2a3 100644
--- a/apps/frontend/src/lib/domains/checkout/checkout-steps-indicator.svelte
+++ b/apps/frontend/src/lib/domains/checkout/checkout-steps-indicator.svelte
@@ -2,16 +2,16 @@
import Icon from "$lib/components/atoms/icon.svelte";
import { buttonVariants } from "$lib/components/ui/button/button.svelte";
import { Sheet, SheetContent, SheetTrigger } from "$lib/components/ui/sheet";
+ import { CheckoutStep } from "$lib/domains/order/data/entities";
import { cn } from "$lib/utils";
import ChevronDownIcon from "~icons/lucide/chevron-down";
import CloseIcon from "~icons/lucide/x";
- import { CheckoutStep } from "../../data/entities";
import { checkoutVM } from "./checkout.vm.svelte";
const checkoutSteps = [
- { id: CheckoutStep.Initial, label: "Passenger Details" },
+ { id: CheckoutStep.Initial, label: "Initial Details" },
{ id: CheckoutStep.Payment, label: "Payment" },
- { id: CheckoutStep.Verification, label: "Verify Details" },
+ { id: CheckoutStep.Verification, label: "Verify" },
{ id: CheckoutStep.Confirmation, label: "Confirmation" },
];
diff --git a/apps/frontend/src/lib/domains/checkout/payment-info-section/billing-details-form.svelte b/apps/frontend/src/lib/domains/checkout/payment-info-section/billing-details-form.svelte
index 07343c8..cc3de96 100644
--- a/apps/frontend/src/lib/domains/checkout/payment-info-section/billing-details-form.svelte
+++ b/apps/frontend/src/lib/domains/checkout/payment-info-section/billing-details-form.svelte
@@ -4,7 +4,7 @@
import * as Select from "$lib/components/ui/select";
import { COUNTRIES_SELECT } from "$lib/core/countries";
import { capitalize } from "$lib/core/string.utils";
- import type { CustomerInfoModel } from "$lib/domains/ticket/data/entities/create.entities";
+ import type { CustomerInfoModel } from "$lib/domains/customerinfo/data";
import { billingDetailsVM } from "./billing.details.vm.svelte";
let { info = $bindable() }: { info: CustomerInfoModel } = $props();
diff --git a/apps/frontend/src/lib/domains/checkout/payment-info-section/billing.details.vm.svelte.ts b/apps/frontend/src/lib/domains/checkout/payment-info-section/billing.details.vm.svelte.ts
index 4da2ac2..3f1ac1f 100644
--- a/apps/frontend/src/lib/domains/checkout/payment-info-section/billing.details.vm.svelte.ts
+++ b/apps/frontend/src/lib/domains/checkout/payment-info-section/billing.details.vm.svelte.ts
@@ -1,5 +1,8 @@
-import { type CustomerInfoModel, Gender } from "$lib/domains/customerinfo/data";
-import { customerInfoModel } from "$lib/domains/passengerinfo/data/entities";
+import {
+ type CustomerInfoModel,
+ customerInfoModel,
+ Gender,
+} from "$lib/domains/customerinfo/data";
import { z } from "zod";
export class BillingDetailsViewModel {
diff --git a/apps/frontend/src/lib/domains/checkout/payment-info-section/index.svelte b/apps/frontend/src/lib/domains/checkout/payment-info-section/index.svelte
index c63a21a..599a2d4 100644
--- a/apps/frontend/src/lib/domains/checkout/payment-info-section/index.svelte
+++ b/apps/frontend/src/lib/domains/checkout/payment-info-section/index.svelte
@@ -2,21 +2,13 @@
import ButtonLoadableText from "$lib/components/atoms/button-loadable-text.svelte";
import Icon from "$lib/components/atoms/icon.svelte";
import Title from "$lib/components/atoms/title.svelte";
- import Button, {
- buttonVariants,
- } from "$lib/components/ui/button/button.svelte";
- import * as Dialog from "$lib/components/ui/dialog";
+ import Button from "$lib/components/ui/button/button.svelte";
import { ckFlowVM } from "$lib/domains/ckflow/view/ckflow.vm.svelte";
+ import { customerInfoVM } from "$lib/domains/customerinfo/view/customerinfo.vm.svelte";
import { CheckoutStep } from "$lib/domains/order/data/entities";
- import { passengerInfoVM } from "$lib/domains/passengerinfo/view/passenger.info.vm.svelte";
- import { flightTicketStore } from "$lib/domains/ticket/data/store";
- import TicketDetailsModal from "$lib/domains/ticket/view/ticket/ticket-details-modal.svelte";
- import { cn } from "$lib/utils";
- import { formatDate } from "@pkg/logic/core/date.utils";
import { onMount } from "svelte";
import { toast } from "svelte-sonner";
import RightArrowIcon from "~icons/solar/arrow-right-broken";
- import ArrowsExchangeIcon from "~icons/tabler/arrows-exchange-2";
import { checkoutVM } from "../checkout.vm.svelte";
import BillingDetailsForm from "./billing-details-form.svelte";
import { billingDetailsVM } from "./billing.details.vm.svelte";
@@ -56,14 +48,6 @@
}, 1000);
}
- let outboundFlight = $derived(
- $flightTicketStore?.flightIteneraries.outbound[0],
- );
- let inboundFlight = $derived(
- $flightTicketStore?.flightIteneraries.inbound[0],
- );
- let isReturnFlight = $derived($flightTicketStore?.flightType === "Return");
-
$effect(() => {
if (!ckFlowVM.flowId || !ckFlowVM.setupDone) return;
if (!paymentInfoVM.cardDetails) return;
@@ -82,79 +66,17 @@
billingDetailsVM.validatePII(billingDetailsVM.billingDetails);
if (billingDetailsVM.isPIIValid()) {
- console.log("Billing details are valid, not setting from pasenger");
+ console.log("Billing details are valid, not setting from initials");
return;
}
- if (passengerInfoVM.passengerInfos.length > 0) {
- billingDetailsVM.setPII(
- passengerInfoVM.passengerInfos[0].passengerPii,
- );
- billingDetailsVM.validatePII(billingDetailsVM.billingDetails);
- toast("Used billing details from primary passenger");
- }
+ if (!customerInfoVM.customerInfo) return;
+ billingDetailsVM.setPII(customerInfoVM.customerInfo);
+ billingDetailsVM.validatePII(billingDetailsVM.billingDetails);
+ toast("Used billing details from initial info");
});
-
-
Trip Summary
-
-
-
-
-
- {outboundFlight?.departure.station.code}
- {#if isReturnFlight}
-
- {outboundFlight?.destination.station.code}
- {:else}
-
- {outboundFlight?.destination.station.code}
- {/if}
-
-
-
-
- {#if isReturnFlight}
-
-
- {formatDate(outboundFlight?.departure.localTime)}
- - {formatDate(inboundFlight.departure.localTime)}
-
-
- {:else}
-
-
- {formatDate(outboundFlight?.departure.localTime)}
-
-
- {/if}
-
-
-
-
-
{}}
- >
-
- View Full Details
-
-
-
-
-
Order Summary
diff --git a/apps/frontend/src/lib/domains/checkout/payment-summary.svelte b/apps/frontend/src/lib/domains/checkout/payment-summary.svelte
index b27cd21..0f4559a 100644
--- a/apps/frontend/src/lib/domains/checkout/payment-summary.svelte
+++ b/apps/frontend/src/lib/domains/checkout/payment-summary.svelte
@@ -4,28 +4,23 @@
convertAndFormatCurrency,
currencyStore,
} from "$lib/domains/currency/view/currency.vm.svelte";
- import { passengerInfoVM } from "$lib/domains/passengerinfo/view/passenger.info.vm.svelte";
- import { flightTicketStore } from "../../data/store";
- import { calculateTicketPrices } from "./total.calculator";
+ import { customerInfoVM } from "../customerinfo/view/customerinfo.vm.svelte";
+ import { productStore } from "../product/store";
+ import { calculateFinalPrices } from "./utils";
- let totals = $state(
- calculateTicketPrices($flightTicketStore, passengerInfoVM.passengerInfos),
+ let priceDetails = $state(
+ calculateFinalPrices($productStore, customerInfoVM.customerInfo),
);
- let changing = $state(false);
+ let calculating = $state(false);
+ // Reactively update price details when product or customer info changes
$effect(() => {
- changing = true;
- totals = calculateTicketPrices(
- $flightTicketStore,
- passengerInfoVM.passengerInfos,
+ calculating = true;
+ priceDetails = calculateFinalPrices(
+ $productStore,
+ customerInfoVM.customerInfo,
);
- changing = false;
- });
-
- flightTicketStore.subscribe((val) => {
- changing = true;
- totals = calculateTicketPrices(val, passengerInfoVM.passengerInfos);
- changing = false;
+ calculating = false;
});
@@ -33,116 +28,69 @@
Payment Summary
- {#if !changing}
-
-
-
Base Ticket Price
-
- Total Ticket Price
- {convertAndFormatCurrency(totals.baseTicketPrice)}
-
-
-
- Price per passenger (x{passengerInfoVM.passengerInfos.length})
-
-
- {convertAndFormatCurrency(totals.pricePerPassenger)}
-
-
-
-
-
- {#if totals.totalBaggageCost > 0}
-
-
Baggage Charges
- {#each totals.passengerBaggageCosts as passengerBaggage}
- {#if passengerBaggage.totalBaggageCost > 0}
-
-
- {passengerBaggage.passengerName}
-
- {#if passengerBaggage.personalBagCost > 0}
-
- Personal Bag
-
- {convertAndFormatCurrency(
- passengerBaggage.personalBagCost,
- )}
-
-
- {/if}
- {#if passengerBaggage.handBagCost > 0}
-
- Hand Baggage
-
- {convertAndFormatCurrency(
- passengerBaggage.handBagCost,
- )}
-
-
- {/if}
- {#if passengerBaggage.checkedBagCost > 0}
-
- Checked Baggage
-
- {convertAndFormatCurrency(
- passengerBaggage.checkedBagCost,
- )}
-
-
- {/if}
-
- {/if}
- {/each}
-
- Total Baggage Charges
- {convertAndFormatCurrency(totals.totalBaggageCost)}
-
+ {#if !calculating}
+
+ {#if $productStore}
+
+
{$productStore.title}
+
{$productStore.description}
{/if}
-
-
+
+
- Subtotal
- {convertAndFormatCurrency(totals.subtotal)}
+ Base Price
+ {convertAndFormatCurrency(priceDetails.basePrice)}
- {#if totals.discountAmount > 0}
+ {#if priceDetails.discountAmount > 0}
Discount
- -{convertAndFormatCurrency(totals.discountAmount)} -{convertAndFormatCurrency(
+ priceDetails.discountAmount,
+ )}
+
+
+ Display Price
+ {convertAndFormatCurrency(
+ priceDetails.displayPrice,
+ )}
{/if}
+
+
+
Total ({$currencyStore.code})
- {convertAndFormatCurrency(totals.finalTotal)}
+ {convertAndFormatCurrency(priceDetails.orderPrice)}
{:else}
-
-
Calculating . . .
+
+ Calculating...
{/if}
+
Important Information:
- Prices include all applicable taxes and fees
- Cancellation and change fees may apply as per our policy
- Additional baggage fees may apply based on airline policy
+ Price includes all applicable taxes and fees
+
+ Cancellation and refund policies may apply as per our terms of
+ service
+
+ Payment will be processed securely upon order confirmation
diff --git a/apps/frontend/src/lib/domains/customerinfo/view/customerinfo.vm.svelte.ts b/apps/frontend/src/lib/domains/customerinfo/view/customerinfo.vm.svelte.ts
index 2d550ff..ff4cd08 100644
--- a/apps/frontend/src/lib/domains/customerinfo/view/customerinfo.vm.svelte.ts
+++ b/apps/frontend/src/lib/domains/customerinfo/view/customerinfo.vm.svelte.ts
@@ -1,12 +1,5 @@
-import { trpcApiStore } from "$lib/stores/api";
-import { toast } from "svelte-sonner";
-import { get } from "svelte/store";
import { z } from "zod";
-import type {
- CreateCustomerInfoPayload,
- CustomerInfoModel,
- UpdateCustomerInfoPayload,
-} from "../data";
+import type { CreateCustomerInfoPayload, CustomerInfoModel } from "../data";
import { customerInfoModel } from "../data";
/**
@@ -32,136 +25,6 @@ export class CustomerInfoViewModel {
this.errors = {};
}
- /**
- * Fetches a single customer info record by ID and sets it as current
- * @param id - Customer info ID to fetch
- * @returns true if successful, false otherwise
- */
- async fetchCustomerInfoById(id: number): Promise
{
- const api = get(trpcApiStore);
- if (!api) {
- toast.error("API client not initialized");
- return false;
- }
-
- this.loading = true;
- try {
- const result = await api.customerInfo.getCustomerInfoById.query({
- id,
- });
- if (result.error) {
- toast.error(result.error.message, {
- description: result.error.userHint,
- });
- return false;
- }
-
- this.customerInfo = result.data || null;
- return true;
- } catch (e) {
- console.error(e);
- toast.error("Failed to fetch customer information", {
- description: "Please try again later",
- });
- return false;
- } finally {
- this.loading = false;
- }
- }
-
- /**
- * Creates a new customer information record
- * @param payload - Customer info data to create
- * @returns Customer info ID if successful, null otherwise
- */
- async createCustomerInfo(
- payload: CreateCustomerInfoPayload,
- ): Promise {
- const api = get(trpcApiStore);
- if (!api) {
- toast.error("API client not initialized");
- return null;
- }
-
- // Validate before submitting
- if (!this.validateCustomerInfo(payload)) {
- toast.error("Please fix validation errors before submitting");
- return null;
- }
-
- this.formLoading = true;
- try {
- const result =
- await api.customerInfo.createCustomerInfo.mutate(payload);
- if (result.error) {
- toast.error(result.error.message, {
- description: result.error.userHint,
- });
- return null;
- }
-
- toast.success("Customer information saved successfully");
- return result.data || null;
- } catch (e) {
- console.error(e);
- toast.error("Failed to save customer information", {
- description: "Please try again later",
- });
- return null;
- } finally {
- this.formLoading = false;
- }
- }
-
- /**
- * Updates the current customer information record
- * @param payload - Customer info data to update (must include id)
- * @returns true if successful, false otherwise
- */
- async updateCustomerInfo(
- payload: UpdateCustomerInfoPayload,
- ): Promise {
- const api = get(trpcApiStore);
- if (!api) {
- toast.error("API client not initialized");
- return false;
- }
-
- if (!payload.id) {
- toast.error("Customer ID is required for update");
- return false;
- }
-
- this.formLoading = true;
- try {
- const result =
- await api.customerInfo.updateCustomerInfo.mutate(payload);
- if (result.error) {
- toast.error(result.error.message, {
- description: result.error.userHint,
- });
- return false;
- }
-
- toast.success("Customer information updated successfully");
-
- // Update local state with the updated data
- if (this.customerInfo && this.customerInfo.id === payload.id) {
- this.customerInfo = { ...this.customerInfo, ...payload };
- }
-
- return true;
- } catch (e) {
- console.error(e);
- toast.error("Failed to update customer information", {
- description: "Please try again later",
- });
- return false;
- } finally {
- this.formLoading = false;
- }
- }
-
/**
* Validates customer information data using Zod schema
* @param info - Customer info to validate
diff --git a/apps/frontend/src/lib/domains/passengerinfo/data/entities.ts b/apps/frontend/src/lib/domains/passengerinfo/data/entities.ts
deleted file mode 100644
index c9225f8..0000000
--- a/apps/frontend/src/lib/domains/passengerinfo/data/entities.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "@pkg/logic/domains/passengerinfo/data/entities";
diff --git a/apps/frontend/src/lib/domains/passengerinfo/data/repository.ts b/apps/frontend/src/lib/domains/passengerinfo/data/repository.ts
deleted file mode 100644
index 39513b4..0000000
--- a/apps/frontend/src/lib/domains/passengerinfo/data/repository.ts
+++ /dev/null
@@ -1,211 +0,0 @@
-import { eq, inArray, type Database } from "@pkg/db";
-import { passengerInfo, passengerPII } from "@pkg/db/schema";
-import { getError, Logger } from "@pkg/logger";
-import { ERROR_CODES, type Result } from "@pkg/result";
-import {
- passengerInfoModel,
- type CustomerInfoModel,
- type PassengerInfo,
-} from "./entities";
-
-export class PassengerInfoRepository {
- private db: Database;
-
- constructor(db: Database) {
- this.db = db;
- }
-
- async createPassengerPii(
- payload: CustomerInfoModel,
- ): Promise> {
- try {
- const out = await this.db
- .insert(passengerPII)
- .values({
- firstName: payload.firstName,
- middleName: payload.middleName,
- lastName: payload.lastName,
- email: payload.email,
- phoneCountryCode: payload.phoneCountryCode,
- phoneNumber: payload.phoneNumber,
- nationality: payload.nationality,
- gender: payload.gender,
- dob: payload.dob,
- passportNo: payload.passportNo,
- passportExpiry: payload.passportExpiry,
-
- country: payload.country,
- state: payload.state,
- city: payload.city,
- address: payload.address,
- zipCode: payload.zipCode,
- address2: payload.address2,
-
- createdAt: new Date(),
- updatedAt: new Date(),
- })
- .returning({ id: passengerInfo.id })
- .execute();
-
- if (!out || out.length === 0) {
- Logger.error("Failed to create passenger info");
- Logger.debug(out);
- Logger.debug(payload);
- return {
- error: getError({
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
- message: "Failed to create passenger info",
- userHint: "Please try again",
- detail: "Failed to create passenger info",
- }),
- };
- }
- return { data: out[0].id };
- } catch (e) {
- return {
- error: getError(
- {
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
- message: "An error occured while creating passenger info",
- userHint: "Please try again later",
- actionable: false,
- detail: "An error occured while creating passenger info",
- },
- e,
- ),
- };
- }
- }
-
- async createPassengerInfo(payload: PassengerInfo): Promise> {
- try {
- const out = await this.db
- .insert(passengerInfo)
- .values({
- passengerType: payload.passengerType,
- passengerPiiId: payload.passengerPiiId,
- paymentInfoId: payload.paymentInfoId,
- seatSelection: payload.seatSelection,
- bagSelection: payload.bagSelection,
- agentsInfo: payload.agentsInfo,
-
- flightTicketInfoId: payload.flightTicketInfoId,
- orderId: payload.orderId,
-
- createdAt: new Date(),
- updatedAt: new Date(),
- })
- .returning({ id: passengerInfo.id })
- .execute();
-
- if (!out || out.length === 0) {
- Logger.error("Failed to create passenger info");
- Logger.debug(out);
- Logger.debug(payload);
- return {
- error: getError({
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
- message: "Failed to create passenger info",
- userHint: "Please try again",
- detail: "Failed to create passenger info",
- }),
- };
- }
- return { data: out[0].id };
- } catch (e) {
- return {
- error: getError(
- {
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
- message: "An error occured while creating passenger info",
- userHint: "Please try again later",
- actionable: false,
- detail: "An error occured while creating passenger info",
- },
- e,
- ),
- };
- }
- }
-
- async getPassengerInfo(id: number): Promise> {
- try {
- const out = await this.db.query.passengerInfo.findFirst({
- where: eq(passengerInfo.id, id),
- with: { passengerPii: true },
- });
- if (!out) {
- Logger.error("Failed to get passenger info");
- Logger.debug(out);
- return {
- error: getError({
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
- message: "Failed to get passenger info",
- userHint: "Please try again",
- detail: "Failed to get passenger info",
- }),
- };
- }
- return { data: out as any as PassengerInfo };
- } catch (e) {
- return {
- error: getError(
- {
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
- message: "An error occured while getting passenger info",
- userHint: "Please try again later",
- actionable: false,
- detail: "An error occured while getting passenger info",
- },
- e,
- ),
- };
- }
- }
-
- async getPassengerInfosByRefOId(
- refOIds: number[],
- ): Promise> {
- try {
- const out = await this.db.query.passengerInfo.findMany({
- where: inArray(passengerInfo.orderId, refOIds),
- with: { passengerPii: true },
- });
- const res = [] as PassengerInfo[];
- for (const each of out) {
- const parsed = passengerInfoModel.safeParse(each);
- if (!parsed.success) {
- Logger.warn(`Error while parsing passenger info`);
- Logger.debug(parsed.error?.errors);
- continue;
- }
- res.push(parsed.data);
- }
- Logger.info(`Returning ${res.length} passenger info by ref OID`);
- return { data: res };
- } catch (e) {
- return {
- error: getError(
- {
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
- message: "An error occured while getting passenger info",
- userHint: "Please try again later",
- actionable: false,
- detail: "An error occured while getting passenger info",
- },
- e,
- ),
- };
- }
- }
-
- async deleteAll(ids: number[]): Promise> {
- Logger.info(`Deleting ${ids.length} passenger info`);
- const out = await this.db
- .delete(passengerInfo)
- .where(inArray(passengerInfo.id, ids));
- Logger.debug(out);
- Logger.info(`Deleted ${out.count} passenger info`);
- return { data: out.count };
- }
-}
diff --git a/apps/frontend/src/lib/domains/passengerinfo/domain/controller.ts b/apps/frontend/src/lib/domains/passengerinfo/domain/controller.ts
deleted file mode 100644
index 3301904..0000000
--- a/apps/frontend/src/lib/domains/passengerinfo/domain/controller.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { Logger } from "@pkg/logger";
-import type { Result } from "@pkg/result";
-import type { PassengerInfo } from "../data/entities";
-import type { PassengerInfoRepository } from "../data/repository";
-
-export class PassengerInfoController {
- repo: PassengerInfoRepository;
-
- constructor(repo: PassengerInfoRepository) {
- this.repo = repo;
- }
-
- async createPassengerInfos(
- payload: PassengerInfo[],
- orderId: number,
- flightTicketInfoId?: number,
- paymentInfoId?: number,
- ): Promise> {
- const made = [] as number[];
- for (const passengerInfo of payload) {
- const piiOut = await this.repo.createPassengerPii(
- passengerInfo.passengerPii,
- );
- if (piiOut.error || !piiOut.data) {
- await this.repo.deleteAll(made);
- return piiOut;
- }
- passengerInfo.passengerPiiId = piiOut.data;
- passengerInfo.paymentInfoId = paymentInfoId;
- passengerInfo.flightTicketInfoId = flightTicketInfoId;
- passengerInfo.orderId = orderId;
- passengerInfo.agentId = undefined;
- const out = await this.repo.createPassengerInfo(passengerInfo);
- if (out.error) {
- await this.repo.deleteAll(made);
- return out;
- }
- }
- return { data: made.length };
- }
-
- async getPassengerInfo(id: number): Promise> {
- return this.repo.getPassengerInfo(id);
- }
-
- async getPassengerInfosByRefOIds(
- refOIds: number[],
- ): Promise> {
- Logger.info(`Querying/Returning Passenger infos for ${refOIds}`);
- return this.repo.getPassengerInfosByRefOId(refOIds);
- }
-}
diff --git a/apps/frontend/src/lib/domains/passengerinfo/view/passenger-pii-form.svelte b/apps/frontend/src/lib/domains/passengerinfo/view/passenger-pii-form.svelte
deleted file mode 100644
index f7eca33..0000000
--- a/apps/frontend/src/lib/domains/passengerinfo/view/passenger-pii-form.svelte
+++ /dev/null
@@ -1,323 +0,0 @@
-
-
-
diff --git a/apps/frontend/src/lib/domains/passengerinfo/view/passenger.info.vm.svelte.ts b/apps/frontend/src/lib/domains/passengerinfo/view/passenger.info.vm.svelte.ts
deleted file mode 100644
index 56755bf..0000000
--- a/apps/frontend/src/lib/domains/passengerinfo/view/passenger.info.vm.svelte.ts
+++ /dev/null
@@ -1,169 +0,0 @@
-import {
- customerInfoModel,
- type BagSelectionInfo,
- type CustomerInfoModel,
- type PassengerInfo,
- type SeatSelectionInfo,
-} from "$lib/domains/ticket/data/entities/create.entities";
-import {
- Gender,
- PassengerType,
- type BagDetails,
- type FlightPriceDetails,
- type PassengerCount,
-} from "$lib/domains/ticket/data/entities/index";
-import { z } from "zod";
-
-export class PassengerInfoViewModel {
- passengerInfos = $state([]);
-
- piiErrors = $state>>>(
- [],
- );
-
- reset() {
- this.passengerInfos = [];
- this.piiErrors = [];
- }
-
- setupPassengerInfo(counts: PassengerCount, forceReset = false) {
- if (this.passengerInfos.length > 0 && !forceReset) {
- return; // since it's already setup
- }
-
- // const _defaultPiiObj = {
- // firstName: "first",
- // middleName: "mid",
- // lastName: "last",
- // email: "first.last@example.com",
- // phoneCountryCode: "+31",
- // phoneNumber: "12345379",
- // passportNo: "f97823h",
- // passportExpiry: "2032-12-12",
- // nationality: "Netherlands",
- // gender: Gender.Male,
- // dob: "2000-12-12",
- // country: "Netherlands",
- // state: "state",
- // city: "city",
- // zipCode: "123098",
- // address: "address",
- // address2: "",
- // } as CustomerInfoModel;
-
- const _defaultPiiObj = {
- firstName: "",
- middleName: "",
- lastName: "",
- email: "",
- phoneCountryCode: "",
- phoneNumber: "",
- passportNo: "",
- passportExpiry: "",
- nationality: "",
- gender: Gender.Male,
- dob: "",
- country: "",
- state: "",
- city: "",
- zipCode: "",
- address: "",
- address2: "",
- } as CustomerInfoModel;
-
- const _defaultPriceObj = {
- currency: "",
- basePrice: 0,
- displayPrice: 0,
- discountAmount: 0,
- } as FlightPriceDetails;
-
- const _defaultSeatSelectionObj = {
- id: "",
- row: "",
- number: 0,
- reserved: false,
- available: false,
- seatLetter: "",
- price: _defaultPriceObj,
- } as SeatSelectionInfo;
-
- const _baseBagDetails = {
- dimensions: { height: 0, length: 0, width: 0 },
- price: 0,
- unit: "kg",
- weight: 0,
- } as BagDetails;
- const _defaultBagSelectionObj = {
- id: 0,
- personalBags: 1,
- handBags: 0,
- checkedBags: 0,
- pricing: {
- personalBags: { ..._baseBagDetails },
- checkedBags: { ..._baseBagDetails },
- handBags: { ..._baseBagDetails },
- },
- } as BagSelectionInfo;
-
- this.passengerInfos = [];
-
- for (let i = 0; i < counts.adults; i++) {
- this.passengerInfos.push({
- id: i,
- passengerType: PassengerType.Adult,
- agentsInfo: false,
- passengerPii: { ..._defaultPiiObj },
- seatSelection: { ..._defaultSeatSelectionObj },
- bagSelection: { ..._defaultBagSelectionObj, id: i },
- });
- this.piiErrors.push({});
- }
-
- for (let i = 0; i < counts.children; i++) {
- this.passengerInfos.push({
- id: i + 1 + counts.adults,
- passengerType: PassengerType.Child,
- agentsInfo: false,
- passengerPii: { ..._defaultPiiObj },
- seatSelection: { ..._defaultSeatSelectionObj },
- bagSelection: { ..._defaultBagSelectionObj, id: i },
- });
- this.piiErrors.push({});
- }
- }
-
- validateAllPII() {
- for (let i = 0; i < this.passengerInfos.length; i++) {
- this.validatePII(this.passengerInfos[i].passengerPii, i);
- }
- }
-
- validatePII(info: CustomerInfoModel, idx: number) {
- try {
- const result = customerInfoModel.parse(info);
- this.piiErrors[idx] = {};
- return result;
- } catch (error) {
- if (error instanceof z.ZodError) {
- this.piiErrors[idx] = error.errors.reduce(
- (acc, curr) => {
- const path = curr.path[0] as keyof CustomerInfoModel;
- acc[path] = curr.message;
- return acc;
- },
- {} as Record,
- );
- }
- return null;
- }
- }
-
- isPIIValid(): boolean {
- return this.piiErrors.every(
- (errorObj) => Object.keys(errorObj).length === 0,
- );
- }
-}
-
-export const passengerInfoVM = new PassengerInfoViewModel();
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/checkout-confirmation-section.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/checkout-confirmation-section.svelte
deleted file mode 100644
index e032f87..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/checkout-confirmation-section.svelte
+++ /dev/null
@@ -1 +0,0 @@
-show checkout confirmation status here
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/checkout-loading-section.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/checkout-loading-section.svelte
deleted file mode 100644
index 80d25e9..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/checkout-loading-section.svelte
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/checkout-steps-indicator.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/checkout-steps-indicator.svelte
deleted file mode 100644
index c6dbab3..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/checkout-steps-indicator.svelte
+++ /dev/null
@@ -1,158 +0,0 @@
-
-
- {
- sheetOpen = to;
- }}
->
- (sheetOpen = true)}
- >
-
-
- Step {activeStepIndex + 1}/{checkoutSteps.length}:
-
-
- {checkoutSteps[activeStepIndex].label}
-
-
-
-
-
- (sheetOpen = false)}
- class="absolute right-4 top-4 grid place-items-center rounded-md border border-neutral-400 p-1 text-neutral-500"
- >
-
-
-
- {#each checkoutSteps as step, index}
-
activeStepIndex}
- onclick={() => {
- handleStepClick(index, step.id);
- sheetOpen = false;
- }}
- >
-
- {index + 1}
-
-
- {step.label}
-
-
- {/each}
-
-
-
-
-
-
- {#each checkoutSteps as step, index}
-
-
handleStepClick(index, step.id)}
- onkeydown={(e) => {
- if (e.key === "Enter" || e.key === " ") {
- handleStepClick(index, step.id);
- }
- }}
- role="button"
- tabindex={index <= activeStepIndex ? 0 : -1}
- >
-
- {index + 1}
-
-
- {step.label}
-
-
- {#if index !== checkoutSteps.length - 1}
-
- {/if}
-
- {/each}
-
-
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/checkout.vm.svelte.ts b/apps/frontend/src/lib/domains/ticket/view/checkout/checkout.vm.svelte.ts
deleted file mode 100644
index ac50fa2..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/checkout.vm.svelte.ts
+++ /dev/null
@@ -1,165 +0,0 @@
-import { ckFlowVM } from "$lib/domains/ckflow/view/ckflow.vm.svelte";
-import { CheckoutStep, newOrderModel } from "$lib/domains/order/data/entities";
-import { passengerInfoVM } from "$lib/domains/passengerinfo/view/passenger.info.vm.svelte";
-import {
- paymentInfoPayloadModel,
- PaymentMethod,
-} from "$lib/domains/paymentinfo/data/entities";
-import { trpcApiStore } from "$lib/stores/api";
-import { toast } from "svelte-sonner";
-import { get } from "svelte/store";
-import { flightTicketStore } from "../../data/store";
-import { paymentInfoVM } from "./payment-info-section/payment.info.vm.svelte";
-import { calculateTicketPrices } from "./total.calculator";
-
-class CheckoutViewModel {
- checkoutStep = $state(CheckoutStep.Initial);
- loading = $state(true);
- continutingToNextStep = $state(false);
-
- checkoutSubmitted = $state(false);
-
- livenessPinger: NodeJS.Timer | undefined = $state(undefined);
-
- reset() {
- this.checkoutStep = CheckoutStep.Initial;
- this.resetPinger();
- }
-
- setupPinger() {
- this.resetPinger();
- this.livenessPinger = setInterval(() => {
- this.ping();
- }, 5_000);
- }
-
- resetPinger() {
- if (this.livenessPinger) {
- clearInterval(this.livenessPinger);
- }
- }
-
- private async ping() {
- const api = get(trpcApiStore);
- if (!api) {
- return false;
- }
- const ticket = get(flightTicketStore);
- if (!ticket || !ticket.refOIds) {
- return false;
- }
- const out = await api.ticket.ping.query({
- tid: ticket.id,
- refOIds: ticket.refOIds,
- });
- }
-
- async checkout() {
- if (this.checkoutSubmitted || this.loading) {
- return;
- }
- this.checkoutSubmitted = true;
-
- const api = get(trpcApiStore);
- if (!api) {
- this.checkoutSubmitted = false;
- return false;
- }
-
- const ticket = get(flightTicketStore);
-
- const prices = calculateTicketPrices(
- ticket,
- passengerInfoVM.passengerInfos,
- );
-
- const validatedPrices = {
- subtotal: isNaN(prices.subtotal) ? 0 : prices.subtotal,
- discountAmount: isNaN(prices.discountAmount)
- ? 0
- : prices.discountAmount,
- finalTotal: isNaN(prices.finalTotal) ? 0 : prices.finalTotal,
- pricePerPassenger: isNaN(prices.pricePerPassenger)
- ? 0
- : prices.pricePerPassenger,
- };
-
- const parsed = newOrderModel.safeParse({
- basePrice: validatedPrices.subtotal,
- discountAmount: validatedPrices.discountAmount,
- displayPrice: validatedPrices.finalTotal,
- orderPrice: validatedPrices.finalTotal, // Same as displayPrice
- fullfilledPrice: validatedPrices.finalTotal, // Same as displayPrice
- pricePerPassenger: validatedPrices.pricePerPassenger,
- flightTicketInfoId: -1,
- paymentInfoId: -1,
- });
-
- if (parsed.error) {
- console.log(parsed.error);
- const err = parsed.error.errors[0];
- toast.error("Failed to perform checkout", {
- description: err.message,
- });
- return false;
- }
-
- const pInfoParsed = paymentInfoPayloadModel.safeParse({
- method: PaymentMethod.Card,
- cardDetails: paymentInfoVM.cardDetails,
- flightTicketInfoId: ticket.id,
- });
- if (pInfoParsed.error) {
- console.log(parsed.error);
- const err = pInfoParsed.error.errors[0];
- toast.error("Failed to perform checkout", {
- description: err.message,
- });
- return false;
- }
-
- try {
- console.log("Creating order");
- this.loading = true;
- const out = await api.order.createOrder.mutate({
- flightTicketId: ticket.id,
- orderModel: parsed.data,
- passengerInfos: passengerInfoVM.passengerInfos,
- paymentInfo: pInfoParsed.data,
- refOIds: ticket.refOIds,
- flowId: ckFlowVM.flowId,
- });
-
- if (out.error) {
- this.loading = false;
- toast.error(out.error.message, {
- description: out.error.userHint,
- });
- return false;
- }
- if (!out.data) {
- this.loading = false;
- toast.error("Failed to create order", {
- description: "Please try again",
- });
- return false;
- }
-
- toast.success("Order created successfully", {
- description: "Redirecting, please wait...",
- });
- setTimeout(() => {
- window.location.href = `/checkout/success?oid=${out.data}`;
- }, 500);
- return true;
- } catch (e) {
- this.checkoutSubmitted = false;
- toast.error("An error occurred during checkout", {
- description: "Please try again",
- });
- return false;
- }
- }
-}
-
-export const checkoutVM = new CheckoutViewModel();
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/initial-info-section.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/initial-info-section.svelte
deleted file mode 100644
index ecd62ad..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/initial-info-section.svelte
+++ /dev/null
@@ -1,146 +0,0 @@
-
-
-{#if $flightTicketStore}
-
-
-
-
- {#if passengerInfoVM.passengerInfos.length > 0}
- {#each passengerInfoVM.passengerInfos as info, idx}
- {@const name =
- info.passengerPii.firstName.length > 0 ||
- info.passengerPii.lastName.length > 0
- ? `${info.passengerPii.firstName} ${info.passengerPii.lastName}`
- : `Passenger #${idx + 1}`}
-
-
-
- {name}
-
-
-
- {capitalize(info.passengerType)}
-
-
-
-
- {/each}
- {/if}
-
-
-{/if}
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/otp-verification-section.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/otp-verification-section.svelte
deleted file mode 100644
index b4e091f..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/otp-verification-section.svelte
+++ /dev/null
@@ -1,132 +0,0 @@
-
-
-
-
-
-
-
-
-
Card Verification Required
-
-
- To complete your payment, please enter the verification code sent by
- your bank or card provider (Visa, Mastercard, etc.). This code may
- have been sent via SMS or email.
-
-
-
-
-
-
-
-
-
-
-
-
-
Need Help?
-
- If you haven't received a verification code from your bank or card
- provider, please check your spam folder or contact your card issuer
- directly. This verification is part of their security process for
- online payments.
-
-
-
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/billing-details-form.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/billing-details-form.svelte
deleted file mode 100644
index 07343c8..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/billing-details-form.svelte
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/billing.details.vm.svelte.ts b/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/billing.details.vm.svelte.ts
deleted file mode 100644
index 1ca39ff..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/billing.details.vm.svelte.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import {
- customerInfoModel,
- type CustomerInfoModel,
-} from "$lib/domains/ticket/data/entities/create.entities";
-import { Gender } from "$lib/domains/ticket/data/entities/index";
-import { z } from "zod";
-
-export class BillingDetailsViewModel {
- // @ts-ignore
- billingDetails = $state(undefined);
-
- piiErrors = $state>>({});
-
- constructor() {
- this.reset();
- }
-
- reset() {
- this.billingDetails = {
- firstName: "",
- middleName: "",
- lastName: "",
- email: "",
- phoneCountryCode: "",
- phoneNumber: "",
- passportNo: "",
- passportExpiry: "",
- nationality: "",
- gender: Gender.Male,
- dob: "",
- country: "",
- state: "",
- city: "",
- zipCode: "",
- address: "",
- address2: "",
- } as CustomerInfoModel;
- this.piiErrors = {};
- }
-
- setPII(info: CustomerInfoModel) {
- this.billingDetails = info;
- }
-
- validatePII(info: CustomerInfoModel) {
- try {
- const result = customerInfoModel.parse(info);
- this.piiErrors = {};
- return result;
- } catch (error) {
- if (error instanceof z.ZodError) {
- this.piiErrors = error.errors.reduce(
- (acc, curr) => {
- const path = curr.path[0] as keyof CustomerInfoModel;
- acc[path] = curr.message;
- return acc;
- },
- {} as Record,
- );
- }
- return null;
- }
- }
-
- isPIIValid(): boolean {
- return Object.keys(this.piiErrors).length === 0;
- }
-}
-
-export const billingDetailsVM = new BillingDetailsViewModel();
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/index.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/index.svelte
deleted file mode 100644
index e48eade..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/index.svelte
+++ /dev/null
@@ -1,198 +0,0 @@
-
-
-
-
-
Trip Summary
-
-
-
-
-
- {outboundFlight?.departure.station.code}
- {#if isReturnFlight}
-
- {outboundFlight?.destination.station.code}
- {:else}
-
- {outboundFlight?.destination.station.code}
- {/if}
-
-
-
-
- {#if isReturnFlight}
-
-
- {formatDate(outboundFlight?.departure.localTime)}
- - {formatDate(inboundFlight.departure.localTime)}
-
-
- {:else}
-
-
- {formatDate(outboundFlight?.departure.localTime)}
-
-
- {/if}
-
-
-
-
-
{}}
- >
-
- View Full Details
-
-
-
-
-
-
-
Order Summary
-
-
-
-
-
-
-
Billing Details
-
-
-
-
-
-
-
-
- Back
-
-
-
-
-
-
-
-
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/order-summary.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/order-summary.svelte
deleted file mode 100644
index 584335e..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/order-summary.svelte
+++ /dev/null
@@ -1,80 +0,0 @@
-
-
-
- {#each passengerInfoVM.passengerInfos as passenger, index}
-
-
-
- Passenger {index + 1} ({capitalize(passenger.passengerType)})
-
-
-
-
-
-
-
-
Name
-
- {passenger.passengerPii.firstName}
- {passenger.passengerPii.lastName}
-
-
-
-
Nationality
-
- {passenger.passengerPii.nationality}
-
-
-
-
Date of Birth
-
{passenger.passengerPii.dob}
-
-
-
-
-
-
- {#if passenger.bagSelection.personalBags > 0}
-
-
- Personal Item
-
- {/if}
- {#if passenger.bagSelection.handBags > 0}
-
-
- {passenger.bagSelection.handBags} x Cabin Bag
-
- {/if}
- {#if passenger.bagSelection.checkedBags > 0}
-
-
-
- {passenger.bagSelection.checkedBags} x Checked Bag
-
-
- {/if}
-
-
-
- {#if passenger.seatSelection.number}
-
-
- Seat {passenger.seatSelection.number}
-
- {/if}
-
-
- {#if index < passengerInfoVM.passengerInfos.length - 1}
-
- {/if}
- {/each}
-
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/payment-form.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/payment-form.svelte
deleted file mode 100644
index 02b149b..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/payment-form.svelte
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/payment.info.vm.svelte.ts b/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/payment.info.vm.svelte.ts
deleted file mode 100644
index 5549678..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-info-section/payment.info.vm.svelte.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import {
- type CardInfo,
- cardInfoModel,
-} from "$lib/domains/paymentinfo/data/entities";
-import { z } from "zod";
-
-const _default = { cardholderName: "", cardNumber: "", expiry: "", cvv: "" };
-
-class PaymentInfoViewModel {
- cardDetails = $state({ ..._default });
-
- errors = $state>>({});
-
- reset() {
- this.cardDetails = { ..._default };
- this.errors = {};
- }
-
- async validateAndSubmit() {
- try {
- const result = cardInfoModel.parse(this.cardDetails);
- this.errors = {};
- return result;
- } catch (error) {
- if (error instanceof z.ZodError) {
- this.errors = error.errors.reduce(
- (acc, curr) => {
- const path = curr.path[0] as keyof CardInfo;
- acc[path] = curr.message;
- return acc;
- },
- {} as Record,
- );
- }
- return null;
- }
- }
-}
-
-export const paymentInfoVM = new PaymentInfoViewModel();
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-summary.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/payment-summary.svelte
deleted file mode 100644
index 32a5ccf..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-summary.svelte
+++ /dev/null
@@ -1,195 +0,0 @@
-
-
-
-
Payment Summary
-
-
- {#if !changing}
-
-
-
Base Ticket Price
-
- Total Ticket Price
- {convertAndFormatCurrency(totals.baseTicketPrice)}
-
-
-
- Price per passenger (x{passengerInfoVM.passengerInfos.length})
-
-
- {convertAndFormatCurrency(totals.pricePerPassenger)}
-
-
-
-
-
- {#if totals.totalBaggageCost > 0}
-
-
Baggage Charges
- {#each totals.passengerBaggageCosts as passengerBaggage}
- {#if passengerBaggage.totalBaggageCost > 0}
-
-
- {passengerBaggage.passengerName}
-
- {#if passengerBaggage.personalBagCost > 0}
-
- Personal Bag
-
- {convertAndFormatCurrency(
- passengerBaggage.personalBagCost,
- )}
-
-
- {/if}
- {#if passengerBaggage.handBagCost > 0}
-
- Hand Baggage
-
- {convertAndFormatCurrency(
- passengerBaggage.handBagCost,
- )}
-
-
- {/if}
- {#if passengerBaggage.checkedBagCost > 0}
-
- Checked Baggage
-
- {convertAndFormatCurrency(
- passengerBaggage.checkedBagCost,
- )}
-
-
- {/if}
-
- {/if}
- {/each}
-
- Total Baggage Charges
- {convertAndFormatCurrency(totals.totalBaggageCost)}
-
-
- {/if}
-
-
-
-
- Subtotal
- {convertAndFormatCurrency(totals.subtotal)}
-
-
-
- {#if totals.discountAmount > 0 && appliedCoupon}
-
-
-
-
- Coupon Applied: {appliedCoupon}
-
-
- {Math.round(
- (totals.discountAmount / totals.subtotal) * 100,
- )}% OFF
-
-
-
- Discount
- -{convertAndFormatCurrency(
- totals.discountAmount,
- )}
-
- {#if $flightTicketStore?.priceDetails?.couponDescription}
-
- {$flightTicketStore.priceDetails.couponDescription}
-
- {/if}
-
- {:else if totals.discountAmount > 0}
-
- Discount
- -{convertAndFormatCurrency(totals.discountAmount)}
-
- {/if}
-
-
-
Total ({$currencyStore.code})
- {convertAndFormatCurrency(totals.finalTotal)}
-
-
- {:else}
-
- Calculating . . .
-
- {/if}
-
-
-
Important Information:
-
- Prices include all applicable taxes and fees
- Cancellation and change fees may apply as per our policy
- Additional baggage fees may apply based on airline policy
- {#if appliedCoupon}
-
- Discount applied via coupon: {appliedCoupon}
-
- {/if}
-
-
-
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-verification-loader.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/payment-verification-loader.svelte
deleted file mode 100644
index b4a6c38..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-verification-loader.svelte
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-verification-section.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/payment-verification-section.svelte
deleted file mode 100644
index dbe52c3..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/payment-verification-section.svelte
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-{#if showOtpVerificationForm}
- {@const done = gototop()}
-
-{:else}
- {@const done2 = gototop()}
-
-{/if}
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/seat-selection-section/index.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/seat-selection-section/index.svelte
deleted file mode 100644
index e6cfa2c..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/seat-selection-section/index.svelte
+++ /dev/null
@@ -1,224 +0,0 @@
-
-
-{#if seatSelectionVM.loading}
-
-{:else}
-
-
-
-
Select Your Seats
-
- Skip & Continue
-
-
-
-
-
- Select passenger to assign seat:
-
-
- {#each passengerInfoVM.passengerInfos as passenger}
-
- seatSelectionVM.setCurrentPassenger(passenger.id)}
- >
- {passenger.passengerPii.firstName}
- {passenger.passengerPii.lastName}
-
- {/each}
-
-
-
-
-
-
-
- Flight {seatSelectionVM.currentFlightIndex + 1} of {seatSelectionVM
- .seatMaps.length}
-
-
- {currentFlight.departure.station.code} → {currentFlight
- .destination.station.code}
-
-
-
- seatSelectionVM.previousFlight()}
- >
- Prev Flight
-
- seatSelectionVM.nextFlight()}
- >
- Next Flight
-
-
-
-
-
-
-
-
-
-
-
- {#each ["A", "B", "C", "", "D", "E", "F"] as letter}
-
- {letter}
-
- {/each}
-
-
- {#each seatSelectionVM.seatMaps[seatSelectionVM.currentFlightIndex].seats as row}
-
-
- {row[0].row}
-
- {#each row as seat}
-
- seatSelectionVM.selectSeat(
- currentFlight.flightId,
- seat,
- )}
- >
- {seatSelectionVM.getSeatDisplay(
- currentFlight.flightId,
- seat.id,
- )}
-
- {#if seat.number === 3}
-
- {/if}
- {/each}
-
- {/each}
-
-
-
-
-
-
-
-
-
-
- Back
-
-
- Continue to Payment
-
-
-
-
-{/if}
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/seat-selection-section/seat.selection.vm.svelte.ts b/apps/frontend/src/lib/domains/ticket/view/checkout/seat-selection-section/seat.selection.vm.svelte.ts
deleted file mode 100644
index f3c1a2b..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/seat-selection-section/seat.selection.vm.svelte.ts
+++ /dev/null
@@ -1,164 +0,0 @@
-import { flightTicketStore } from "$lib/domains/ticket/data/store";
-import { passengerInfoVM } from "$lib/domains/passengerinfo/view/passenger.info.vm.svelte";
-import { get } from "svelte/store";
-import type {
- FlightSeatMap,
- SeatSelectionInfo,
-} from "$lib/domains/passengerinfo/data/entities";
-import { toast } from "svelte-sonner";
-
-type SeatAssignments = Record<
- string,
- { [seatId: string]: { passengerId: number; passengerInitials: string } }
->;
-
-export class SeatSelectionVM {
- loading = $state(true);
- currentFlightIndex = $state(0);
- seatMaps = $state([]);
-
- currentPassengerId = $state(null);
-
- seatAssignments = $state({});
-
- reset() {
- this.loading = true;
- this.currentFlightIndex = 0;
- this.seatMaps = [];
- this.currentPassengerId = null;
- this.seatAssignments = {};
- }
-
- async fetchSeatMaps() {
- this.loading = true;
- await new Promise((resolve) => setTimeout(resolve, 1000));
-
- const info = get(flightTicketStore);
-
- const flights = [
- ...info.flightIteneraries.outbound,
- ...info.flightIteneraries.inbound,
- ];
-
- this.seatMaps = flights.map((flight) => ({
- flightId: flight.flightId,
- seats: this.generateMockSeatMap(),
- }));
-
- this.loading = false;
- }
-
- private generateMockSeatMap(): SeatSelectionInfo[][] {
- const rows = 20;
- const seatsPerRow = 6;
- const seatMap: SeatSelectionInfo[][] = [];
- const seatLetters = ["A", "B", "C", "D", "E", "F"];
-
- for (let row = 0; row < rows; row++) {
- const seatRow: SeatSelectionInfo[] = [];
- const rowNumber = row + 1; // Row numbers start from 1
-
- for (let seat = 0; seat < seatsPerRow; seat++) {
- const random = Math.random();
- seatRow.push({
- id: `${rowNumber}${seatLetters[seat]}`,
- row: rowNumber.toString(),
- number: seat + 1,
- seatLetter: seatLetters[seat],
- available: random > 0.3,
- reserved: random < 0.2,
- price: {
- currency: "USD",
- basePrice: 25,
- discountAmount: 0,
- displayPrice: 25,
- },
- });
- }
- seatMap.push(seatRow);
- }
-
- return seatMap;
- }
-
- selectSeat(flightId: string, seat: SeatSelectionInfo) {
- if (this.currentPassengerId === null) {
- return toast.error("Please select a passenger first");
- }
-
- if (!seat.available || seat.reserved) {
- return toast.error("Seat is not available");
- }
- const passenger = passengerInfoVM.passengerInfos.find(
- (p) => p.id === this.currentPassengerId,
- );
-
- if (!passenger) {
- return toast.error("Passenger not found", {
- description: "Please try refreshing page or book ticket again",
- });
- }
-
- // Get passenger initials
- const initials =
- `${passenger.passengerPii.firstName[0]}${passenger.passengerPii.lastName[0]}`.toUpperCase();
-
- // Update seat assignments
- if (!this.seatAssignments[flightId]) {
- this.seatAssignments[flightId] = {};
- }
-
- // Remove any previous seat assignment for this passenger on this flight
- Object.entries(this.seatAssignments[flightId]).forEach(
- ([seatId, assignment]) => {
- if (assignment.passengerId === this.currentPassengerId) {
- delete this.seatAssignments[flightId][seatId];
- }
- },
- );
-
- // Assign new seat
- this.seatAssignments[flightId][seat.id] = {
- passengerId: this.currentPassengerId,
- passengerInitials: initials,
- };
-
- passenger.seatSelection = {
- id: seat.id,
- row: seat.row,
- number: seat.number,
- seatLetter: seat.seatLetter,
- available: seat.available,
- reserved: seat.reserved,
- price: seat.price,
- };
- }
-
- isSeatAssigned(flightId: string, seatId: string) {
- return this.seatAssignments[flightId]?.[seatId] !== undefined;
- }
-
- getSeatDisplay(flightId: string, seatId: string) {
- return (
- this.seatAssignments[flightId]?.[seatId]?.passengerInitials ??
- `${seatId[seatId.length - 1]}${seatId.slice(0, -1)}`
- );
- }
-
- setCurrentPassenger(passengerId: number) {
- this.currentPassengerId = passengerId;
- }
- nextFlight() {
- if (this.currentFlightIndex < this.seatMaps.length - 1) {
- this.currentFlightIndex++;
- }
- }
-
- previousFlight() {
- if (this.currentFlightIndex > 0) {
- this.currentFlightIndex--;
- }
- }
-}
-
-export const seatSelectionVM = new SeatSelectionVM();
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/total.calculator.ts b/apps/frontend/src/lib/domains/ticket/view/checkout/total.calculator.ts
deleted file mode 100644
index 8503e11..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/total.calculator.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import type { PassengerInfo } from "$lib/domains/passengerinfo/data/entities";
-import type { FlightTicket } from "../../data/entities";
-
-export interface BaggageCost {
- passengerId: number;
- passengerName: string;
- personalBagCost: number;
- handBagCost: number;
- checkedBagCost: number;
- totalBaggageCost: number;
-}
-
-export interface PriceBreakdown {
- baseTicketPrice: number;
- pricePerPassenger: number;
- passengerBaggageCosts: BaggageCost[];
- totalBaggageCost: number;
- subtotal: number;
- discountAmount: number;
- finalTotal: number;
-}
-
-export function calculateTicketPrices(
- ticket: FlightTicket,
- passengerInfos: PassengerInfo[],
-): PriceBreakdown {
- if (!ticket || !passengerInfos || passengerInfos.length === 0) {
- return {
- baseTicketPrice: 0,
- pricePerPassenger: 0,
- passengerBaggageCosts: [],
- totalBaggageCost: 0,
- subtotal: 0,
- discountAmount: 0,
- finalTotal: 0,
- };
- }
-
- const displayPrice = ticket.priceDetails?.displayPrice ?? 0;
- const originalBasePrice = ticket.priceDetails?.basePrice ?? 0;
- const baseTicketPrice = Math.max(displayPrice, originalBasePrice);
- const pricePerPassenger =
- passengerInfos.length > 0
- ? baseTicketPrice / passengerInfos.length
- : baseTicketPrice;
-
- const passengerBaggageCosts: BaggageCost[] = passengerInfos.map(
- (passenger) => {
- // const personalBagCost =
- // (passenger.bagSelection.personalBags || 0) *
- // (ticket?.bagsInfo.details.personalBags.price ?? 0);
- // const handBagCost =
- // (passenger.bagSelection.handBags || 0) *
- // (ticket?.bagsInfo.details.handBags.price ?? 0);
- // const checkedBagCost =
- // (passenger.bagSelection.checkedBags || 0) *
- // (ticket?.bagsInfo.details.checkedBags.price ?? 0);
-
- return {
- passengerId: passenger.id,
- passengerName: `${passenger.passengerPii.firstName} ${passenger.passengerPii.lastName}`,
- personalBagCost: 0,
- handBagCost: 0,
- checkedBagCost: 0,
- totalBaggageCost: 0,
- // totalBaggageCost: personalBagCost + handBagCost + checkedBagCost,
- };
- },
- );
-
- // const totalBaggageCost = passengerBaggageCosts.reduce(
- // (acc, curr) => acc + curr.totalBaggageCost,
- // 0,
- // );
- const totalBaggageCost = 0;
-
- const subtotal = baseTicketPrice + totalBaggageCost;
-
- const discountAmount =
- originalBasePrice > displayPrice
- ? (ticket?.priceDetails.discountAmount ?? 0)
- : 0;
-
- const finalTotal = subtotal - discountAmount;
-
- return {
- baseTicketPrice,
- pricePerPassenger,
- passengerBaggageCosts,
- totalBaggageCost,
- subtotal,
- discountAmount,
- finalTotal,
- };
-}
diff --git a/apps/frontend/src/lib/domains/ticket/view/checkout/update-price-dialog.svelte b/apps/frontend/src/lib/domains/ticket/view/checkout/update-price-dialog.svelte
deleted file mode 100644
index a12d71d..0000000
--- a/apps/frontend/src/lib/domains/ticket/view/checkout/update-price-dialog.svelte
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
- The price has changed!
-
- Ticket prices change throughout the day and, unfortunately, the
- price has been changed since last we had checked. You can continue
- with the new price or check out alternative trips.
-
-
-
-
-
New Price
-
-
- {convertAndFormatCurrency(
- ckFlowVM.updatedPrices?.displayPrice ?? 0,
- )}
-
-
-
- cancelBooking()}
- >
- Go Back
-
- onPriceUpdateConfirm()}
- >
-
-
-
-
-
diff --git a/apps/frontend/src/lib/trpc/router/index.ts b/apps/frontend/src/lib/trpc/router/index.ts
index 7c23ff4..dcc1b5d 100644
--- a/apps/frontend/src/lib/trpc/router/index.ts
+++ b/apps/frontend/src/lib/trpc/router/index.ts
@@ -1,7 +1,6 @@
import { authRouter } from "$lib/domains/auth/domain/router";
import { ckflowRouter } from "$lib/domains/ckflow/domain/router";
import { currencyRouter } from "$lib/domains/currency/domain/router";
-import { customerInfoRouter } from "$lib/domains/customerinfo/router";
import { orderRouter } from "$lib/domains/order/domain/router";
import { productRouter } from "$lib/domains/product/router";
import { userRouter } from "$lib/domains/user/domain/router";
@@ -14,7 +13,6 @@ export const router = createTRPCRouter({
order: orderRouter,
ckflow: ckflowRouter,
product: productRouter,
- customerInfo: customerInfoRouter,
});
export type Router = typeof router;