Merged in feat(SW-1275)-cancel-booking-my-stay (pull request #1376)

Feat(SW-1275) cancel booking my stay

* feat(SW-1276) UI implementation Desktop part 1 for MyStay

* feat(SW-1276) UI implementation Desktop part 2 for MyStay

* feat(SW-1276) UI implementation Mobile part 1 for MyStay

* refactor: move files from MyStay/MyStay to MyStay

* feat(SW-1276) Sidepeek implementation

* feat(SW-1276): Refactoring

* feat(SW-1276) UI implementation Mobile part 2 for MyStay

* feat(SW-1276): translations

* feat(SW-1276) fixed skeleton

* feat(SW-1276): Added missing translations

* feat(SW-1276) fixed translations

* feat(SW-1275) cancel modal

* feat(SW-1275): Mutate cancel booking

* feat(SW-1275) added translations

* feat(SW-1275) match current cancellationReason

* feat(SW-1275) Added modal for manage stay

* feat(SW-1275) Added missing icon

* feat(SW-1275) New Dont cancel button

* feat(SW-1275) Added preperation for Cancellation number

* feat(SW-1275): added --modal-box-shadow

* feat(SW-1718) Add to calendar

* feat(SW-1718) general add to calendar


Approved-by: Niclas Edenvin
This commit is contained in:
Pontus Dreij
2025-02-21 09:06:15 +00:00
parent 8ed521de3f
commit a0286603db
45 changed files with 1358 additions and 104 deletions

View File

@@ -0,0 +1,29 @@
"use client"
import { useIntl } from "react-intl"
import { CalendarAddIcon } from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
import styles from "../actionPanel.module.css"
export default function AddToCalendarButton({
onPress,
}: {
onPress: () => void
}) {
const intl = useIntl()
return (
<Button
variant="icon"
intent="text"
theme="base"
className={styles.button}
onPress={onPress}
>
{intl.formatMessage({ id: "Add to calendar" })}
<CalendarAddIcon width={24} height={24} color="burgundy" />
</Button>
)
}

View File

@@ -0,0 +1,42 @@
.actionPanel {
display: flex;
gap: var(--Spacing-x3);
padding: var(--Spacing-x3);
}
.menu {
width: 432px;
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
}
.actionPanel .menu .button {
width: 100%;
color: var(--Scandic-Brand-Burgundy);
justify-content: space-between !important;
padding: var(--Spacing-x1) 0 !important;
}
.info {
width: 256px;
background-color: var(--Base-Background-Primary-Normal);
padding: var(--Spacing-x3);
text-align: right;
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
align-items: flex-end;
}
.tag {
text-transform: uppercase;
font-size: 12px;
font-weight: 600;
color: var(--Main-Red-60);
font-family: var(--typography-Caption-Labels-fontFamily);
}
.link {
margin-top: auto;
}

View File

@@ -0,0 +1,149 @@
import { useIntl } from "react-intl"
import { customerService } from "@/constants/currentWebHrefs"
import AddToCalendar from "@/components/HotelReservation/AddToCalendar"
import { generateDateTime } from "@/components/HotelReservation/BookingConfirmation/Header/Actions/helpers"
import {
CalendarIcon,
ChevronRightIcon,
CreditCard,
CrossCircleOutlineIcon,
DownloadIcon,
} from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
import Link from "@/components/TempDesignSystem/Link"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import useLang from "@/hooks/useLang"
import AddToCalendarButton from "./Actions/AddToCalendarButton"
import styles from "./actionPanel.module.css"
import type { EventAttributes } from "ics"
import type { Hotel } from "@/types/hotel"
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
export default function ActionPanel({
booking,
hotel,
showCancelButton,
onCancelClick,
}: {
booking: BookingConfirmation["booking"]
hotel: Hotel
showCancelButton: boolean
onCancelClick: () => void
}) {
const intl = useIntl()
const lang = useLang()
const event: EventAttributes = {
busyStatus: "FREE",
categories: ["booking", "hotel", "stay"],
created: generateDateTime(booking.createDateTime),
description: hotel.hotelContent.texts.descriptions.medium,
end: generateDateTime(booking.checkOutDate),
endInputType: "utc",
geo: {
lat: hotel.location.latitude,
lon: hotel.location.longitude,
},
location: `${hotel.address.streetAddress}, ${hotel.address.zipCode} ${hotel.address.city} ${hotel.address.country}`,
start: generateDateTime(booking.checkInDate),
startInputType: "utc",
status: "CONFIRMED",
title: hotel.name,
url: hotel.contactInformation.websiteUrl,
}
return (
<div className={styles.actionPanel}>
<div className={styles.menu}>
<Button
variant="icon"
onClick={onCancelClick}
intent="text"
className={styles.button}
>
{intl.formatMessage({ id: "Modify dates" })}
<CalendarIcon width={24} height={24} color="burgundy" />
</Button>
<Button
variant="icon"
onClick={onCancelClick}
intent="text"
className={styles.button}
>
{intl.formatMessage({ id: "Guarantee late arrival" })}
<CreditCard width={24} height={24} color="burgundy" />
</Button>
<AddToCalendar
checkInDate={booking.checkInDate}
event={event}
hotelName={hotel.name}
renderButton={(onPress) => <AddToCalendarButton onPress={onPress} />}
/>
<Button
variant="icon"
onClick={onCancelClick}
intent="text"
className={styles.button}
>
{intl.formatMessage({ id: "Download invoice" })}
<DownloadIcon width={24} height={24} color="burgundy" />
</Button>
{showCancelButton && (
<Button
variant="icon"
onClick={onCancelClick}
intent="text"
className={styles.button}
>
{intl.formatMessage({ id: "Cancel stay" })}
<CrossCircleOutlineIcon width={24} height={24} color="burgundy" />
</Button>
)}
</div>
<div className={styles.info}>
<div>
<span className={styles.tag}>
{intl.formatMessage({ id: "Reference number" })}
</span>
<Subtitle color="burgundy" textAlign="right">
{booking.confirmationNumber}
</Subtitle>
</div>
<div className={styles.hotel}>
<Body color="uiTextHighContrast" textAlign="right">
{hotel.name}
</Body>
<Body color="uiTextHighContrast" textAlign="right">
{hotel.address.streetAddress}
</Body>
<Body color="uiTextHighContrast" textAlign="right">
{hotel.address.city}
</Body>
<Body color="uiTextHighContrast" asChild>
<Link href={`tel:${hotel.contactInformation.phoneNumber}`}>
{hotel.contactInformation.phoneNumber}
</Link>
</Body>
</div>
<Link
href={customerService[lang]}
variant="icon"
className={styles.link}
>
<Caption color="burgundy">
{intl.formatMessage({ id: "Customer support" })}
</Caption>
<ChevronRightIcon width={20} height={20} color="burgundy" />
</Link>
</div>
</div>
)
}