Files
domain-wall/apps/frontend/src/lib/domains/ticket/view/checkout/payment-summary.svelte
2025-10-20 17:07:41 +03:00

196 lines
5.9 KiB
Svelte

<script lang="ts">
import Title from "$lib/components/atoms/title.svelte";
import {
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 { Badge } from "$lib/components/ui/badge";
import Icon from "$lib/components/atoms/icon.svelte";
import TagIcon from "~icons/lucide/tag"; // Import a tag/coupon icon
let totals = $state(
calculateTicketPrices($flightTicketStore, passengerInfoVM.passengerInfos),
);
let changing = $state(false);
let appliedCoupon = $state(
$flightTicketStore?.priceDetails?.appliedCoupon || null,
);
let couponDescription = $state("");
$effect(() => {
changing = true;
totals = calculateTicketPrices(
$flightTicketStore,
passengerInfoVM.passengerInfos,
);
appliedCoupon = $flightTicketStore?.priceDetails?.appliedCoupon || null;
changing = false;
});
flightTicketStore.subscribe((val) => {
changing = true;
totals = calculateTicketPrices(val, passengerInfoVM.passengerInfos);
appliedCoupon = val?.priceDetails?.appliedCoupon || null;
changing = false;
});
</script>
<div class="flex flex-col gap-4 rounded-lg bg-white p-4 drop-shadow-lg md:p-8">
<Title size="h4" weight="medium">Payment Summary</Title>
<div class="h-0.5 w-full border-t-2 border-gray-200"></div>
{#if !changing}
<!-- Base Ticket Price Breakdown -->
<div class="flex flex-col gap-2">
<Title size="p" weight="medium">Base Ticket Price</Title>
<div class="flex justify-between text-sm">
<span>Total Ticket Price</span>
<span>{convertAndFormatCurrency(totals.baseTicketPrice)}</span>
</div>
<div class="ml-4 text-sm text-gray-600">
<span>
Price per passenger (x{passengerInfoVM.passengerInfos.length})
</span>
<span class="float-right">
{convertAndFormatCurrency(totals.pricePerPassenger)}
</span>
</div>
</div>
<!-- Baggage Costs -->
{#if totals.totalBaggageCost > 0}
<div class="mt-2 flex flex-col gap-2 border-t pt-2">
<Title size="p" weight="medium">Baggage Charges</Title>
{#each totals.passengerBaggageCosts as passengerBaggage}
{#if passengerBaggage.totalBaggageCost > 0}
<div class="flex flex-col gap-1">
<span class="text-sm font-medium">
{passengerBaggage.passengerName}
</span>
{#if passengerBaggage.personalBagCost > 0}
<div
class="ml-4 flex justify-between text-sm text-gray-600"
>
<span>Personal Bag</span>
<span>
{convertAndFormatCurrency(
passengerBaggage.personalBagCost,
)}
</span>
</div>
{/if}
{#if passengerBaggage.handBagCost > 0}
<div
class="ml-4 flex justify-between text-sm text-gray-600"
>
<span>Hand Baggage</span>
<span>
{convertAndFormatCurrency(
passengerBaggage.handBagCost,
)}
</span>
</div>
{/if}
{#if passengerBaggage.checkedBagCost > 0}
<div
class="ml-4 flex justify-between text-sm text-gray-600"
>
<span>Checked Baggage</span>
<span>
{convertAndFormatCurrency(
passengerBaggage.checkedBagCost,
)}
</span>
</div>
{/if}
</div>
{/if}
{/each}
<div class="flex justify-between text-sm font-medium">
<span>Total Baggage Charges</span>
<span
>{convertAndFormatCurrency(totals.totalBaggageCost)}</span
>
</div>
</div>
{/if}
<!-- Final Total -->
<div class="mt-4 flex flex-col gap-2 border-t pt-4">
<div class="flex justify-between text-sm">
<span>Subtotal</span>
<span>{convertAndFormatCurrency(totals.subtotal)}</span>
</div>
<!-- Coupon section -->
{#if totals.discountAmount > 0 && appliedCoupon}
<div class="my-2 flex flex-col gap-1 rounded-lg bg-green-50 p-3">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2 text-green-700">
<Icon icon={TagIcon} cls="h-4 w-4" />
<span class="font-medium"
>Coupon Applied: {appliedCoupon}</span
>
</div>
<Badge
variant="outline"
class="border-green-600 px-2 py-0.5 text-green-600"
>
{Math.round(
(totals.discountAmount / totals.subtotal) * 100,
)}% OFF
</Badge>
</div>
<div class="mt-1 flex justify-between text-sm text-green-600">
<span>Discount</span>
<span
>-{convertAndFormatCurrency(
totals.discountAmount,
)}</span
>
</div>
{#if $flightTicketStore?.priceDetails?.couponDescription}
<p class="mt-1 text-xs text-green-700">
{$flightTicketStore.priceDetails.couponDescription}
</p>
{/if}
</div>
{:else if totals.discountAmount > 0}
<div class="flex justify-between text-sm text-green-600">
<span>Discount</span>
<span>-{convertAndFormatCurrency(totals.discountAmount)}</span
>
</div>
{/if}
<div class="flex justify-between font-medium">
<Title size="h5" weight="medium"
>Total ({$currencyStore.code})</Title
>
<span>{convertAndFormatCurrency(totals.finalTotal)}</span>
</div>
</div>
{:else}
<div class="grid place-items-center p-2 text-center">
<span>Calculating . . .</span>
</div>
{/if}
<div class="mt-4 rounded-lg bg-gray-50 p-4 text-xs text-gray-600">
<p class="mb-2 font-medium">Important Information:</p>
<ul class="list-disc space-y-1 pl-4">
<li>Prices include all applicable taxes and fees</li>
<li>Cancellation and change fees may apply as per our policy</li>
<li>Additional baggage fees may apply based on airline policy</li>
{#if appliedCoupon}
<li class="text-green-600">
Discount applied via coupon: {appliedCoupon}
</li>
{/if}
</ul>
</div>
</div>