feat(SW-864): add to calendar functionality

This commit is contained in:
Simon Emanuelsson
2024-11-28 14:22:31 +01:00
parent f896f8df76
commit 33de623f41
14 changed files with 233 additions and 47 deletions

View File

@@ -0,0 +1,61 @@
"use client"
import { createEvent } from "ics"
import { useIntl } from "react-intl"
import { dt } from "@/lib/dt"
import { CalendarAddIcon } from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
import useLang from "@/hooks/useLang"
import type { AddToCalendarProps } from "@/types/components/hotelReservation/bookingConfirmation/actions/addToCalendar"
export default function AddToCalendar({
checkInDate,
event,
hotelName,
}: AddToCalendarProps) {
const intl = useIntl()
const lang = useLang()
async function downloadBooking() {
const d = dt(checkInDate).locale(lang).format("YYYY-MM-DD")
const filename = `${hotelName.toLowerCase().split(" ").join("_")}-${d}.ics`
const file: Blob = await new Promise((resolve, reject) => {
createEvent(event, (error, value) => {
if (error) {
reject(error)
}
resolve(new File([value], filename, { type: "text/calendar" }))
})
})
const url = URL.createObjectURL(file)
const anchor = document.createElement("a")
anchor.href = url
anchor.download = filename
document.body.appendChild(anchor)
anchor.click()
document.body.removeChild(anchor)
URL.revokeObjectURL(url)
}
return (
<Button
intent="text"
onPress={downloadBooking}
size="small"
theme="base"
variant="icon"
wrapping
>
<CalendarAddIcon />
{intl.formatMessage({ id: "Add to calendar" })}
</Button>
)
}

View File

@@ -0,0 +1,27 @@
"use client"
import { useIntl } from "react-intl"
import { DownloadIcon } from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
export default function DownloadInvoice() {
const intl = useIntl()
function downloadBooking() {
window.print()
}
return (
<Button
intent="text"
onPress={downloadBooking}
size="small"
theme="base"
variant="icon"
wrapping
>
<DownloadIcon />
{intl.formatMessage({ id: "Download invoice" })}
</Button>
)
}

View File

@@ -0,0 +1,15 @@
"use client"
import { useIntl } from "react-intl"
import { EditIcon } from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
export default function ManageBooking() {
const intl = useIntl()
return (
<Button intent="text" size="small" theme="base" variant="icon" wrapping>
<EditIcon />
{intl.formatMessage({ id: "Manage booking" })}
</Button>
)
}

View File

@@ -1,15 +0,0 @@
.actions {
border-radius: var(--Corner-radius-Medium);
display: grid;
grid-area: actions;
justify-content: flex-start;
}
@media screen and (min-width: 768px) {
.actions {
gap: var(--Spacing-x3);
grid-auto-columns: auto;
grid-auto-flow: column;
grid-template-columns: auto;
}
}

View File

@@ -0,0 +1,15 @@
import { dt } from "@/lib/dt"
import type { DateTime } from "ics"
export function generateDateTime(d: Date): DateTime {
const _d = dt(d).utc()
return [
_d.year(),
// Need to add +1 since month is 0 based
_d.month() + 1,
_d.date(),
_d.hour(),
_d.minute(),
]
}

View File

@@ -1,25 +0,0 @@
import { CalendarAddIcon, DownloadIcon, EditIcon } from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
import { getIntl } from "@/i18n"
import styles from "./actions.module.css"
export default async function Actions() {
const intl = await getIntl()
return (
<div className={styles.actions}>
<Button intent="text" size="small" theme="base" variant="icon" wrapping>
<CalendarAddIcon />
{intl.formatMessage({ id: "Add to calendar" })}
</Button>
<Button intent="text" size="small" theme="base" variant="icon" wrapping>
<EditIcon />
{intl.formatMessage({ id: "Manage booking" })}
</Button>
<Button intent="text" size="small" theme="base" variant="icon" wrapping>
<DownloadIcon />
{intl.formatMessage({ id: "Download invoice" })}
</Button>
</div>
)
}