feat: add SoonestStays
This commit is contained in:
@@ -9,8 +9,22 @@ import { LangParams, PageArgs } from "@/types/params"
|
|||||||
export default async function MyStays({ params }: PageArgs<LangParams>) {
|
export default async function MyStays({ params }: PageArgs<LangParams>) {
|
||||||
return (
|
return (
|
||||||
<MaxWidth className={styles.container} tag="main">
|
<MaxWidth className={styles.container} tag="main">
|
||||||
<UpcomingStays lang={params.lang} />
|
<UpcomingStays
|
||||||
<PreviousStays lang={params.lang} />
|
lang={params.lang}
|
||||||
|
title={"Upcoming stays"}
|
||||||
|
subtitle={
|
||||||
|
"Excited about your next trip? So are we. Below are your upcoming stays with us, complete with all the details you need to make each visit perfect. Can't wait to welcome you back, friend!"
|
||||||
|
}
|
||||||
|
link={null}
|
||||||
|
/>
|
||||||
|
<PreviousStays
|
||||||
|
lang={params.lang}
|
||||||
|
title={"Previous stays"}
|
||||||
|
subtitle={
|
||||||
|
"Revisit your stays and rekindle those our moments together, with ease."
|
||||||
|
}
|
||||||
|
link={null}
|
||||||
|
/>
|
||||||
</MaxWidth>
|
</MaxWidth>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import NextLevelBenefitsBlock from "@/components/MyPages/Blocks/Benefits/NextLev
|
|||||||
import Overview from "@/components/MyPages/Blocks/Overview"
|
import Overview from "@/components/MyPages/Blocks/Overview"
|
||||||
import Shortcuts from "@/components/MyPages/Blocks/Shortcuts"
|
import Shortcuts from "@/components/MyPages/Blocks/Shortcuts"
|
||||||
import UpcomingStays from "@/components/MyPages/Blocks/Stays/Upcoming"
|
import UpcomingStays from "@/components/MyPages/Blocks/Stays/Upcoming"
|
||||||
|
import SoonestStays from "@/components/MyPages/Blocks/Stays/Soonest"
|
||||||
import { renderOptions } from "@/components/JsonToHtml/renderOptions"
|
import { renderOptions } from "@/components/JsonToHtml/renderOptions"
|
||||||
|
|
||||||
function DynamicComponent({
|
function DynamicComponent({
|
||||||
@@ -27,7 +28,8 @@ function DynamicComponent({
|
|||||||
}) {
|
}) {
|
||||||
const componentProps = {
|
const componentProps = {
|
||||||
title: content.title,
|
title: content.title,
|
||||||
preamble: content.preamble,
|
// TODO: rename preamble to subtitle in Contentstack
|
||||||
|
subtitle: content.preamble,
|
||||||
link: content.link.linkConnection.edges.length
|
link: content.link.linkConnection.edges.length
|
||||||
? {
|
? {
|
||||||
href: content.link.linkConnection.edges[0].node.url,
|
href: content.link.linkConnection.edges[0].node.url,
|
||||||
@@ -40,22 +42,14 @@ function DynamicComponent({
|
|||||||
return <Overview user={user} />
|
return <Overview user={user} />
|
||||||
case DynamicContentComponents.previous_stays:
|
case DynamicContentComponents.previous_stays:
|
||||||
return null
|
return null
|
||||||
|
case DynamicContentComponents.soonest_stays:
|
||||||
|
return <SoonestStays lang={lang} {...componentProps} />
|
||||||
case DynamicContentComponents.upcoming_stays:
|
case DynamicContentComponents.upcoming_stays:
|
||||||
return <UpcomingStays lang={lang} {...componentProps} />
|
return <UpcomingStays lang={lang} {...componentProps} />
|
||||||
case DynamicContentComponents.current_benefits:
|
case DynamicContentComponents.current_benefits:
|
||||||
return (
|
return <CurrentBenefitsBlock {...componentProps} />
|
||||||
<CurrentBenefitsBlock
|
|
||||||
title={content.title}
|
|
||||||
preamble={content.preamble}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
case DynamicContentComponents.next_benefits:
|
case DynamicContentComponents.next_benefits:
|
||||||
return (
|
return <NextLevelBenefitsBlock {...componentProps} />
|
||||||
<NextLevelBenefitsBlock
|
|
||||||
title={content.title}
|
|
||||||
preamble={content.preamble}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -94,7 +88,6 @@ export default function Content({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
case ContentEntries.AccountPageContentTextContent:
|
case ContentEntries.AccountPageContentTextContent:
|
||||||
console.log({ item })
|
|
||||||
return (
|
return (
|
||||||
<JsonToHtml
|
<JsonToHtml
|
||||||
embeds={[]}
|
embeds={[]}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
.title {
|
.title {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
@@ -11,7 +15,7 @@
|
|||||||
color: var(--some-red-color, #ed2027);
|
color: var(--some-red-color, #ed2027);
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.cardSubtitle {
|
||||||
font-family: var(--ff-fira-sans);
|
font-family: var(--ff-fira-sans);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|||||||
@@ -8,12 +8,14 @@ import styles from "./current.module.css"
|
|||||||
|
|
||||||
export type CurrentLevelProps = {
|
export type CurrentLevelProps = {
|
||||||
title: string
|
title: string
|
||||||
preamble?: string
|
subtitle?: string
|
||||||
|
link: { text: string; href: string } | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function CurrentBenefitsBlock({
|
export default async function CurrentBenefitsBlock({
|
||||||
title,
|
title,
|
||||||
preamble,
|
subtitle,
|
||||||
|
link,
|
||||||
}: CurrentLevelProps) {
|
}: CurrentLevelProps) {
|
||||||
const benefits = await serverClient().user.benefits.current()
|
const benefits = await serverClient().user.benefits.current()
|
||||||
|
|
||||||
@@ -23,8 +25,13 @@ export default async function CurrentBenefitsBlock({
|
|||||||
<Title as="h4" level="h2" className={styles.title} uppercase>
|
<Title as="h4" level="h2" className={styles.title} uppercase>
|
||||||
{title}
|
{title}
|
||||||
</Title>
|
</Title>
|
||||||
{preamble && <p className={styles.preamble}>{preamble}</p>}
|
{link && (
|
||||||
|
<Link className={styles.link} href={link.href}>
|
||||||
|
{link.text}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</header>
|
</header>
|
||||||
|
{subtitle && <p className={styles.subtitle}>{subtitle}</p>}
|
||||||
|
|
||||||
<div className={styles.cardContainer}>
|
<div className={styles.cardContainer}>
|
||||||
{benefits.map((benefit) => (
|
{benefits.map((benefit) => (
|
||||||
@@ -33,7 +40,7 @@ export default async function CurrentBenefitsBlock({
|
|||||||
<span className={styles.value}>{benefit.value}</span>{" "}
|
<span className={styles.value}>{benefit.value}</span>{" "}
|
||||||
{benefit.explanation}
|
{benefit.explanation}
|
||||||
</Title>
|
</Title>
|
||||||
<p className={styles.subtitle}>{benefit.subtitle}</p>
|
<p className={styles.cardSubtitle}>{benefit.subtitle}</p>
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,12 +10,14 @@ import styles from "./next.module.css"
|
|||||||
|
|
||||||
export type NextLevelProps = {
|
export type NextLevelProps = {
|
||||||
title: string
|
title: string
|
||||||
preamble?: string
|
subtitle?: string
|
||||||
|
link: { href: string; text: string } | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function NextLevelBenefitsBlock({
|
export default async function NextLevelBenefitsBlock({
|
||||||
title,
|
title,
|
||||||
preamble,
|
subtitle,
|
||||||
|
link,
|
||||||
}: NextLevelProps) {
|
}: NextLevelProps) {
|
||||||
const { nextLevel, perks } = await serverClient().user.benefits.nextLevel()
|
const { nextLevel, perks } = await serverClient().user.benefits.nextLevel()
|
||||||
|
|
||||||
@@ -24,9 +26,14 @@ export default async function NextLevelBenefitsBlock({
|
|||||||
<header className={styles.header}>
|
<header className={styles.header}>
|
||||||
<Title as="h4" level="h2" uppercase className={styles.title}>
|
<Title as="h4" level="h2" uppercase className={styles.title}>
|
||||||
{title}
|
{title}
|
||||||
|
{link && (
|
||||||
|
<Link className={styles.link} href={link.href}>
|
||||||
|
{link.text}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</Title>
|
</Title>
|
||||||
{preamble && <p className={styles.preamble}>{preamble}</p>}
|
|
||||||
</header>
|
</header>
|
||||||
|
{subtitle && <p className={styles.subtitle}>{subtitle}</p>}
|
||||||
<div className={styles.cardContainer}>
|
<div className={styles.cardContainer}>
|
||||||
{perks.map((perk) => (
|
{perks.map((perk) => (
|
||||||
<article key={perk.id} className={styles.card}>
|
<article key={perk.id} className={styles.card}>
|
||||||
@@ -36,7 +43,7 @@ export default async function NextLevelBenefitsBlock({
|
|||||||
</Button>
|
</Button>
|
||||||
<div>
|
<div>
|
||||||
<span className={styles.level}>As our {nextLevel}</span>{" "}
|
<span className={styles.level}>As our {nextLevel}</span>{" "}
|
||||||
<p className={styles.subtitle}>{perk.explanation}</p>
|
<p className={styles.cardSubtitle}>{perk.explanation}</p>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
gap: 1.5rem;
|
gap: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
.cardContainer {
|
.cardContainer {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.4rem;
|
gap: 0.4rem;
|
||||||
@@ -31,7 +35,7 @@
|
|||||||
font-style: italic; /* font-family: var(--ff-biro-script-plus); */
|
font-style: italic; /* font-family: var(--ff-biro-script-plus); */
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.cardSubtitle {
|
||||||
font-size: var(--typography-Subtitle-Mobile-fontSize, 18px);
|
font-size: var(--typography-Subtitle-Mobile-fontSize, 18px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +58,7 @@
|
|||||||
font-weight: var(--typography-Script-Desktop-fontWeight);
|
font-weight: var(--typography-Script-Desktop-fontWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.cardSubtitle {
|
||||||
font-size: var(--typography-Subtitle-Desktop-fontSize, 18px);
|
font-size: var(--typography-Subtitle-Desktop-fontSize, 18px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,3 +2,17 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-bottom: 2.5rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 950px) {
|
||||||
|
.subtitle {
|
||||||
|
width: 60%;
|
||||||
|
padding-top: 2.5rem;
|
||||||
|
padding-bottom: 5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,18 +1,29 @@
|
|||||||
|
import Link from "next/link"
|
||||||
|
|
||||||
import Title from "@/components/Title"
|
import Title from "@/components/Title"
|
||||||
|
|
||||||
import styles from "./header.module.css"
|
import styles from "./header.module.css"
|
||||||
|
|
||||||
import type { HeaderProps } from "@/types/components/myPages/myStays/title"
|
import type { HeaderProps } from "@/types/components/myPages/myStays/title"
|
||||||
|
|
||||||
export default function Header({ title, subtitle }: HeaderProps) {
|
export default function Header({ title, subtitle, link }: HeaderProps) {
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<header className={styles.header}>
|
<header className={styles.header}>
|
||||||
<Title as="h3" level="h2" weight="semiBold" uppercase>
|
<Title className={styles.title} as="h3" weight="semiBold" uppercase>
|
||||||
{title}
|
{title}
|
||||||
</Title>
|
</Title>
|
||||||
<Title as="h5" level="h3" weight="regular">
|
{link && (
|
||||||
|
<Link className={styles.link} href={link.href}>
|
||||||
|
{link.text}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</header>
|
||||||
|
{subtitle && (
|
||||||
|
<Title as="h5" weight="regular" className={styles.subtitle}>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
</Title>
|
</Title>
|
||||||
</header>
|
)}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import { Lang } from "@/constants/languages"
|
||||||
import { _ } from "@/lib/translation"
|
import { _ } from "@/lib/translation"
|
||||||
import { trpc } from "@/lib/trpc/client"
|
import { trpc } from "@/lib/trpc/client"
|
||||||
|
|
||||||
@@ -11,9 +12,20 @@ import StayList from "../StayList"
|
|||||||
import EmptyPreviousStaysBlock from "./EmptyPreviousStays"
|
import EmptyPreviousStaysBlock from "./EmptyPreviousStays"
|
||||||
|
|
||||||
import type { Page } from "@/types/components/myPages/myStays/page"
|
import type { Page } from "@/types/components/myPages/myStays/page"
|
||||||
import type { LangParams } from "@/types/params"
|
|
||||||
|
|
||||||
export default function PreviousStays({ lang }: LangParams) {
|
type PreviousStaysProps = {
|
||||||
|
lang: Lang
|
||||||
|
title: string
|
||||||
|
subtitle?: string
|
||||||
|
link: { href: string; text: string } | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PreviousStays({
|
||||||
|
lang,
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
link,
|
||||||
|
}: PreviousStaysProps) {
|
||||||
const { data, isFetching, fetchNextPage, hasNextPage } =
|
const { data, isFetching, fetchNextPage, hasNextPage } =
|
||||||
trpc.user.stays.previous.useInfiniteQuery(
|
trpc.user.stays.previous.useInfiniteQuery(
|
||||||
{},
|
{},
|
||||||
@@ -28,12 +40,8 @@ export default function PreviousStays({ lang }: LangParams) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Header
|
<Header title={title} subtitle={subtitle} link={link} />
|
||||||
title={_("Previous stays")}
|
|
||||||
subtitle={_(
|
|
||||||
"Revisit your stays and rekindle those our moments together, with ease."
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{data?.pages.length ? (
|
{data?.pages.length ? (
|
||||||
<ListContainer>
|
<ListContainer>
|
||||||
<StayList
|
<StayList
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
.button {
|
||||||
|
background-color: var(--some-red-color, #ed2027);
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grayTitle {
|
||||||
|
color: var(--some-grey-color, #727272);
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 25rem;
|
||||||
|
gap: 2.5rem;
|
||||||
|
background-color: var(--some-grey-color, #f2f2f2);
|
||||||
|
border-radius: 0.8rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
padding: 0 2rem;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import Link from "next/link"
|
||||||
|
|
||||||
|
import { _ } from "@/lib/translation"
|
||||||
|
|
||||||
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
|
import Title from "@/components/Title"
|
||||||
|
|
||||||
|
import styles from "./emptyUpcomingStays.module.css"
|
||||||
|
|
||||||
|
export default function EmptyUpcomingStaysBlock() {
|
||||||
|
return (
|
||||||
|
<section className={styles.container}>
|
||||||
|
<Title level="h3" as="h5" uppercase>
|
||||||
|
{_(" You have no upcoming stays.")}
|
||||||
|
<span className={styles.grayTitle}>
|
||||||
|
{" "}
|
||||||
|
{_("Where should you go next?")}
|
||||||
|
</span>
|
||||||
|
</Title>
|
||||||
|
<Button intent="primary" bgcolor="quarternary" asChild type="button">
|
||||||
|
<Link className={styles.link} href={"#"} key="getInspired">
|
||||||
|
{_("Get inspired")}
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
35
components/MyPages/Blocks/Stays/Soonest/index.tsx
Normal file
35
components/MyPages/Blocks/Stays/Soonest/index.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { Lang } from "@/constants/languages"
|
||||||
|
import { serverClient } from "@/lib/trpc/server"
|
||||||
|
|
||||||
|
import Header from "../Header"
|
||||||
|
import StayList from "../StayList"
|
||||||
|
import EmptyUpcomingStaysBlock from "./EmptyUpcomingStays"
|
||||||
|
|
||||||
|
import styles from "./soonest.module.css"
|
||||||
|
|
||||||
|
type UpcomingStaysProps = {
|
||||||
|
lang: Lang
|
||||||
|
title: string
|
||||||
|
subtitle?: string
|
||||||
|
link: { text: string; href: string } | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function UpcomingStays({
|
||||||
|
lang,
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
link,
|
||||||
|
}: UpcomingStaysProps) {
|
||||||
|
const stays = await serverClient().user.stays.soonestUpcoming()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className={styles.container}>
|
||||||
|
<Header title={title} subtitle={subtitle} link={link}></Header>
|
||||||
|
{stays.length ? (
|
||||||
|
<StayList lang={lang} stays={stays} />
|
||||||
|
) : (
|
||||||
|
<EmptyUpcomingStaysBlock />
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.container {
|
||||||
|
max-width: var(--max-width);
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import { Lang } from "@/constants/languages"
|
||||||
import { _ } from "@/lib/translation"
|
import { _ } from "@/lib/translation"
|
||||||
import { trpc } from "@/lib/trpc/client"
|
import { trpc } from "@/lib/trpc/client"
|
||||||
|
|
||||||
@@ -11,9 +12,20 @@ import StayList from "../StayList"
|
|||||||
import EmptyUpcomingStaysBlock from "./EmptyUpcomingStays"
|
import EmptyUpcomingStaysBlock from "./EmptyUpcomingStays"
|
||||||
|
|
||||||
import type { Page } from "@/types/components/myPages/myStays/page"
|
import type { Page } from "@/types/components/myPages/myStays/page"
|
||||||
import type { LangParams } from "@/types/params"
|
|
||||||
|
|
||||||
export default function UpcomingStays({ lang }: LangParams) {
|
type UpcomingStaysProps = {
|
||||||
|
lang: Lang
|
||||||
|
title: string
|
||||||
|
subtitle?: string
|
||||||
|
link: { text: string; href: string } | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function UpcomingStays({
|
||||||
|
lang,
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
link,
|
||||||
|
}: UpcomingStaysProps) {
|
||||||
const { data, hasNextPage, isFetching, fetchNextPage } =
|
const { data, hasNextPage, isFetching, fetchNextPage } =
|
||||||
trpc.user.stays.upcoming.useInfiniteQuery(
|
trpc.user.stays.upcoming.useInfiniteQuery(
|
||||||
{},
|
{},
|
||||||
@@ -28,12 +40,8 @@ export default function UpcomingStays({ lang }: LangParams) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Header
|
<Header title={title} subtitle={subtitle} link={link} />
|
||||||
title={_("Upcoming stays")}
|
|
||||||
subtitle={_(
|
|
||||||
"Excited about your next trip? So are we. Below are your upcoming stays with us, complete with all the details you need to make each visit perfect. Can't wait to welcome you back, friend!"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{data?.pages.length ? (
|
{data?.pages.length ? (
|
||||||
<ListContainer>
|
<ListContainer>
|
||||||
<StayList
|
<StayList
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
import Link from "next/link"
|
|
||||||
import Stay from "./Stay"
|
|
||||||
import Title from "@/components/MyPages/Title"
|
|
||||||
|
|
||||||
import styles from "./upcoming.module.css"
|
|
||||||
|
|
||||||
import type { LangParams } from "@/types/params"
|
|
||||||
import type { StaysProps } from "@/types/components/myPages/myPage/stays"
|
|
||||||
|
|
||||||
export default function UpcomingStays({
|
|
||||||
lang,
|
|
||||||
stays,
|
|
||||||
title,
|
|
||||||
preamble,
|
|
||||||
link,
|
|
||||||
}: StaysProps & LangParams) {
|
|
||||||
return (
|
|
||||||
<section className={styles.container}>
|
|
||||||
<header className={styles.header}>
|
|
||||||
<Title level="h2" as="h4" uppercase>
|
|
||||||
{title}
|
|
||||||
</Title>
|
|
||||||
{link && (
|
|
||||||
<Link className={styles.link} href={link.href}>
|
|
||||||
{link.text}
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</header>
|
|
||||||
{preamble}
|
|
||||||
<section className={styles.stays}>
|
|
||||||
{stays.map((stay) => (
|
|
||||||
<Stay key={stay.hotel} {...stay} lang={lang} />
|
|
||||||
))}
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { badRequestError } from "@/server/errors/trpc"
|
|
||||||
import { publicProcedure, router } from "@/server/trpc"
|
|
||||||
import { request } from "@/lib/graphql/request"
|
|
||||||
import { Lang } from "@/constants/languages"
|
import { Lang } from "@/constants/languages"
|
||||||
import GetAccountPage from "@/lib/graphql/Query/AccountPage.graphql"
|
import GetAccountPage from "@/lib/graphql/Query/AccountPage.graphql"
|
||||||
|
import { request } from "@/lib/graphql/request"
|
||||||
|
import { badRequestError } from "@/server/errors/trpc"
|
||||||
|
import { publicProcedure, router } from "@/server/trpc"
|
||||||
|
|
||||||
import type { GetAccountPageData } from "@/types/requests/myPages/accountpage"
|
import type { GetAccountPageData } from "@/types/requests/myPages/accountpage"
|
||||||
|
|
||||||
export const accountPageQueryRouter = router({
|
export const accountPageQueryRouter = router({
|
||||||
getOverview: publicProcedure
|
getOverview: publicProcedure
|
||||||
.input(z.object({ lang: z.nativeEnum(Lang) }))
|
.input(z.object({ lang: z.nativeEnum(Lang) }))
|
||||||
|
|||||||
@@ -7,3 +7,10 @@ export const staysInput = z
|
|||||||
cursor: z.number().nullish(),
|
cursor: z.number().nullish(),
|
||||||
})
|
})
|
||||||
.default({})
|
.default({})
|
||||||
|
|
||||||
|
|
||||||
|
export const soonestUpcomingStaysInput = z
|
||||||
|
.object({
|
||||||
|
limit: z.number().int().positive(),
|
||||||
|
})
|
||||||
|
.default({ limit: 3 })
|
||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
} from "@/server/errors/trpc"
|
} from "@/server/errors/trpc"
|
||||||
import { protectedProcedure, router } from "@/server/trpc"
|
import { protectedProcedure, router } from "@/server/trpc"
|
||||||
|
|
||||||
import { staysInput } from "./input"
|
import { soonestUpcomingStaysInput, staysInput } from "./input"
|
||||||
import { getUserSchema } from "./output"
|
import { getUserSchema } from "./output"
|
||||||
import {
|
import {
|
||||||
benefits,
|
benefits,
|
||||||
@@ -85,6 +85,12 @@ export const userQueryRouter = router({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
stays: router({
|
stays: router({
|
||||||
|
soonestUpcoming: protectedProcedure
|
||||||
|
.input(soonestUpcomingStaysInput)
|
||||||
|
.query(async ({ input }) => {
|
||||||
|
return upcomingStays.slice(0, input.limit)
|
||||||
|
}),
|
||||||
|
|
||||||
previous: protectedProcedure.input(staysInput).query(async (opts) => {
|
previous: protectedProcedure.input(staysInput).query(async (opts) => {
|
||||||
const { perPage, page, cursor } = opts.input
|
const { perPage, page, cursor } = opts.input
|
||||||
let nextCursor: typeof cursor | undefined = undefined
|
let nextCursor: typeof cursor | undefined = undefined
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
import type { Stay, User } from "@/types/user"
|
|
||||||
|
|
||||||
export type StaysProps = {
|
|
||||||
title: string
|
|
||||||
preamble: string
|
|
||||||
link: {
|
|
||||||
href: string
|
|
||||||
text: string
|
|
||||||
} | null
|
|
||||||
stays: User["stays"]
|
|
||||||
}
|
|
||||||
|
|
||||||
export type StayProps = Stay
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export type HeaderProps = {
|
export type HeaderProps = {
|
||||||
title: string
|
title: string
|
||||||
subtitle: string
|
subtitle?: string
|
||||||
|
link: { href: string; text: string } | null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { RTEDocument } from "@/types/rte/node"
|
|||||||
|
|
||||||
export enum DynamicContentComponents {
|
export enum DynamicContentComponents {
|
||||||
membership_overview = "membership_overview",
|
membership_overview = "membership_overview",
|
||||||
|
soonest_stays = "soonest_stays",
|
||||||
previous_stays = "previous_stays",
|
previous_stays = "previous_stays",
|
||||||
upcoming_stays = "upcoming_stays",
|
upcoming_stays = "upcoming_stays",
|
||||||
current_benefits = "current_benefits",
|
current_benefits = "current_benefits",
|
||||||
|
|||||||
Reference in New Issue
Block a user