151 lines
4.1 KiB
Svelte
151 lines
4.1 KiB
Svelte
<script lang="ts">
|
|
import { TicketType } from "../data/entities/index";
|
|
import AirportSearchInput from "$lib/domains/airport/view/airport-search-input.svelte";
|
|
import { ticketSearchStore } from "../data/store";
|
|
import FlightDateInput from "./flight-date-input.svelte";
|
|
import FlightDateRangeInput from "./flight-date-range-input.svelte";
|
|
import Icon from "$lib/components/atoms/icon.svelte";
|
|
import SearchIcon from "~icons/solar/magnifer-linear";
|
|
import SwapIcon from "~icons/ant-design/swap-outlined";
|
|
import Button from "$lib/components/ui/button/button.svelte";
|
|
import PassengerAndCabinClassSelect from "./passenger-and-cabin-class-select.svelte";
|
|
import { Label } from "$lib/components/ui/label/index.js";
|
|
import * as RadioGroup from "$lib/components/ui/radio-group/index.js";
|
|
import { airportVM } from "$lib/domains/airport/view/airport.vm.svelte";
|
|
import { browser } from "$app/environment";
|
|
import { onDestroy, onMount } from "svelte";
|
|
|
|
let { onSubmit, rowify = false }: { onSubmit: () => void; rowify?: boolean } =
|
|
$props();
|
|
|
|
let currTicketType = $state($ticketSearchStore.ticketType);
|
|
let isMobileView = $state(false);
|
|
|
|
function checkIfMobile() {
|
|
if (browser) {
|
|
isMobileView = window.innerWidth < 768;
|
|
}
|
|
}
|
|
|
|
function setupResizeListener() {
|
|
if (browser) {
|
|
window.addEventListener("resize", checkIfMobile);
|
|
checkIfMobile(); // Initial check
|
|
|
|
return () => {
|
|
window.removeEventListener("resize", checkIfMobile);
|
|
};
|
|
}
|
|
}
|
|
|
|
$effect(() => {
|
|
ticketSearchStore.update((prev) => {
|
|
return { ...prev, ticketType: currTicketType };
|
|
});
|
|
});
|
|
|
|
let cleanup: any | undefined = $state(undefined);
|
|
|
|
onMount(() => {
|
|
cleanup = setupResizeListener();
|
|
});
|
|
|
|
onDestroy(() => {
|
|
cleanup?.();
|
|
});
|
|
</script>
|
|
|
|
<div class="flex w-full flex-col gap-4">
|
|
<div
|
|
class="flex w-full flex-col items-center justify-between gap-4 lg:grid lg:grid-cols-2 lg:gap-4"
|
|
>
|
|
<RadioGroup.Root
|
|
bind:value={currTicketType}
|
|
class="flex w-full flex-row gap-6 p-2 lg:p-4"
|
|
>
|
|
<div class="flex items-center space-x-2">
|
|
<RadioGroup.Item
|
|
value={TicketType.Return}
|
|
id={TicketType.Return}
|
|
onselect={() => {
|
|
ticketSearchStore.update((prev) => {
|
|
return { ...prev, ticketType: TicketType.Return };
|
|
});
|
|
}}
|
|
/>
|
|
<Label for={TicketType.Return} class="md:text-lg">Return</Label>
|
|
</div>
|
|
<div class="flex items-center space-x-2">
|
|
<RadioGroup.Item
|
|
value={TicketType.OneWay}
|
|
id={TicketType.OneWay}
|
|
onselect={() => {
|
|
ticketSearchStore.update((prev) => {
|
|
return { ...prev, ticketType: TicketType.OneWay };
|
|
});
|
|
}}
|
|
/>
|
|
<Label for={TicketType.OneWay} class="md:text-lg">One Way</Label>
|
|
</div>
|
|
</RadioGroup.Root>
|
|
|
|
<PassengerAndCabinClassSelect />
|
|
</div>
|
|
|
|
<div
|
|
class="flex w-full flex-col items-center justify-between gap-2 lg:grid lg:grid-cols-2 lg:gap-4"
|
|
>
|
|
<div
|
|
class="flex w-full flex-col items-center justify-between gap-2 lg:flex-row"
|
|
>
|
|
<AirportSearchInput
|
|
currentValue={airportVM.departure}
|
|
onChange={(e) => {
|
|
airportVM.setDepartureAirport(e);
|
|
}}
|
|
placeholder="Depart from"
|
|
searchPlaceholder="Departure airport search"
|
|
isMobile={isMobileView}
|
|
fieldType="departure"
|
|
/>
|
|
<div class="hidden w-full max-w-fit md:block">
|
|
<Button
|
|
size="icon"
|
|
variant={rowify ? "outlineWhite" : "defaultInverted"}
|
|
onclick={() => {
|
|
airportVM.swapDepartureAndArrival();
|
|
}}
|
|
>
|
|
<Icon icon={SwapIcon} cls="w-auto h-6" />
|
|
</Button>
|
|
</div>
|
|
|
|
<AirportSearchInput
|
|
currentValue={airportVM.arrival}
|
|
onChange={(e) => {
|
|
airportVM.setArrivalAirport(e);
|
|
}}
|
|
placeholder="Arrive at"
|
|
searchPlaceholder="Arrival airport search"
|
|
isMobile={isMobileView}
|
|
fieldType="arrival"
|
|
/>
|
|
</div>
|
|
|
|
<div
|
|
class="flex w-full flex-col items-center justify-between gap-2 lg:flex-row lg:gap-2"
|
|
>
|
|
{#if $ticketSearchStore.ticketType === TicketType.Return}
|
|
<FlightDateRangeInput />
|
|
{:else}
|
|
<FlightDateInput />
|
|
{/if}
|
|
|
|
<Button onclick={() => onSubmit()} class={"w-full"} variant="default">
|
|
<Icon icon={SearchIcon} cls="w-auto h-4" />
|
|
Search flights
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|