chore: add load more functionality, with refactored css
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
.container {
|
||||
max-width: var(--max-width);
|
||||
display: grid;
|
||||
gap: 2rem;
|
||||
}
|
||||
@media screen and (min-width: 950px) {
|
||||
.container {
|
||||
gap: 7rem;
|
||||
}
|
||||
}
|
||||
5
components/MyPages/Blocks/Stays/Container/index.tsx
Normal file
5
components/MyPages/Blocks/Stays/Container/index.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import styles from "./container.module.css"
|
||||
|
||||
export default function Container({ children }: React.PropsWithChildren) {
|
||||
return <section className={styles.container}>{children}</section>
|
||||
}
|
||||
@@ -1,13 +1,18 @@
|
||||
.subtitle {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 2.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 950px) {
|
||||
.subtitle {
|
||||
width: 60%;
|
||||
padding-top: 2.5rem;
|
||||
padding-bottom: 5rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
gap: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,15 @@ import Title from "@/components/MyPages/Title"
|
||||
|
||||
import styles from "./header.module.css"
|
||||
|
||||
import { HeaderProps } from "@/types/components/myPages/stays/title"
|
||||
import type { HeaderProps } from "@/types/components/myPages/myStays/title"
|
||||
|
||||
export default function Header({ title, subtitle }: HeaderProps) {
|
||||
return (
|
||||
<header className={styles.header}>
|
||||
<Title as="h3" weight="semiBold" uppercase>
|
||||
<Title as="h3" level="h2" weight="semiBold" uppercase>
|
||||
{title}
|
||||
</Title>
|
||||
<Title as="h5" weight="regular" className={styles.subtitle}>
|
||||
<Title as="h5" level="h3" weight="regular" className={styles.subtitle}>
|
||||
{subtitle}
|
||||
</Title>
|
||||
</header>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.container {
|
||||
display: grid;
|
||||
gap: 3rem;
|
||||
}
|
||||
5
components/MyPages/Blocks/Stays/ListContainer/index.tsx
Normal file
5
components/MyPages/Blocks/Stays/ListContainer/index.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import styles from "./container.module.css"
|
||||
|
||||
export default function ListContainer({ children }: React.PropsWithChildren) {
|
||||
return <section className={styles.container}>{children}</section>
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import { _ } from "@/lib/translation"
|
||||
|
||||
import Title from "@/components/MyPages/Title"
|
||||
|
||||
import styles from "./emptyPreviousStays.module.css"
|
||||
@@ -6,7 +8,7 @@ export default function EmptyPreviousStaysBlock() {
|
||||
return (
|
||||
<section className={styles.container}>
|
||||
<Title level="h3" as="h5" uppercase>
|
||||
You have no previous stays.
|
||||
{_("You have no previous stays.")}{" "}
|
||||
</Title>
|
||||
</section>
|
||||
)
|
||||
@@ -1,28 +1,52 @@
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
"use client"
|
||||
|
||||
import EmptyPreviousStaysBlock from "../EmptyPreviousStays"
|
||||
import { _ } from "@/lib/translation"
|
||||
import { trpc } from "@/lib/trpc/client"
|
||||
|
||||
import Container from "../Container"
|
||||
import Header from "../Header"
|
||||
import ListContainer from "../ListContainer"
|
||||
import ShowMoreButton from "../ShowMoreButton"
|
||||
import StayList from "../StayList"
|
||||
import EmptyPreviousStaysBlock from "./EmptyPreviousStays"
|
||||
|
||||
import styles from "./previous.module.css"
|
||||
|
||||
import type { Page } from "@/types/components/myPages/myStays/page"
|
||||
import type { LangParams } from "@/types/params"
|
||||
|
||||
export default async function PreviousStays({ lang }: LangParams) {
|
||||
const stays = await serverClient().user.stays.previous()
|
||||
export default function PreviousStays({ lang }: LangParams) {
|
||||
const { data, isFetching, fetchNextPage, hasNextPage } =
|
||||
trpc.user.stays.previous.useInfiniteQuery(
|
||||
{},
|
||||
{
|
||||
getNextPageParam: (lastPage: Page) => lastPage.nextCursor,
|
||||
}
|
||||
)
|
||||
|
||||
function loadMoreData() {
|
||||
fetchNextPage()
|
||||
}
|
||||
|
||||
return (
|
||||
<section className={styles.container}>
|
||||
<Container>
|
||||
<Header
|
||||
title="Your previous stays."
|
||||
subtitle="Revisit your stays and rekindle those our moments together, with ease."
|
||||
title={_("Previous stays")}
|
||||
subtitle={_(
|
||||
"Revisit your stays and rekindle those our moments together, with ease."
|
||||
)}
|
||||
></Header>
|
||||
|
||||
{stays.length ? (
|
||||
<StayList lang={lang} stays={stays} />
|
||||
{data?.pages.length ? (
|
||||
<ListContainer>
|
||||
<StayList
|
||||
lang={lang}
|
||||
stays={data?.pages.flatMap((page) => page.data) ?? []}
|
||||
/>
|
||||
{hasNextPage ? (
|
||||
<ShowMoreButton disabled={isFetching} loadMoreData={loadMoreData} />
|
||||
) : null}
|
||||
</ListContainer>
|
||||
) : (
|
||||
<EmptyPreviousStaysBlock />
|
||||
)}
|
||||
</section>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.container {
|
||||
max-width: var(--max-width);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
24
components/MyPages/Blocks/Stays/ShowMoreButton/index.tsx
Normal file
24
components/MyPages/Blocks/Stays/ShowMoreButton/index.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
|
||||
import styles from "./button.module.css"
|
||||
|
||||
import type { ShowMoreButtonParams } from "@/types/components/myPages/myStays/button"
|
||||
|
||||
export default function ShowMoreButton({
|
||||
disabled,
|
||||
loadMoreData,
|
||||
}: ShowMoreButtonParams) {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Button
|
||||
disabled={disabled}
|
||||
intent="primary"
|
||||
bgcolor="white"
|
||||
type="button"
|
||||
onClick={loadMoreData}
|
||||
>
|
||||
Show more
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -5,12 +5,12 @@ import Title from "@/components/MyPages/Title"
|
||||
|
||||
import styles from "./stay.module.css"
|
||||
|
||||
import type { StayCardProps } from "@/types/components/myPages/stays/stayCard"
|
||||
import type { StayCardProps } from "@/types/components/myPages/myStays/stayCard"
|
||||
|
||||
export default function StayCard({
|
||||
stay,
|
||||
lang,
|
||||
showDayCount = false,
|
||||
shouldShowDayCount = false,
|
||||
}: StayCardProps) {
|
||||
const { dateArrive, dateDepart, guests, hotel } = stay
|
||||
|
||||
@@ -25,7 +25,7 @@ export default function StayCard({
|
||||
return (
|
||||
<article className={styles.stay}>
|
||||
<div className={styles.imageContainer}>
|
||||
{showDayCount ? (
|
||||
{shouldShowDayCount ? (
|
||||
<div className={styles.badge}>
|
||||
<time className={styles.time}>In {daysUntilArrival} days</time>
|
||||
</div>
|
||||
|
||||
@@ -1,29 +1,15 @@
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
|
||||
import StayCard from "../StayCard"
|
||||
|
||||
import styles from "./stayList.module.css"
|
||||
|
||||
import { StayListProps } from "@/types/components/myPages/stays/stayList"
|
||||
import { StayListProps } from "@/types/components/myPages/myStays/stayList"
|
||||
|
||||
export default function StayList({ lang, stays }: StayListProps) {
|
||||
return (
|
||||
<section>
|
||||
<section className={styles.stays}>
|
||||
{stays.map((stay) => (
|
||||
<StayCard
|
||||
key={stay.uid}
|
||||
stay={stay}
|
||||
lang={lang}
|
||||
showDayCount={true}
|
||||
/>
|
||||
))}
|
||||
</section>
|
||||
<div className={styles.buttonContainer}>
|
||||
<Button intent="primary" type="button">
|
||||
Show more
|
||||
</Button>
|
||||
</div>
|
||||
<section className={styles.stays}>
|
||||
{stays.map((stay) => (
|
||||
<StayCard key={stay.uid} stay={stay} lang={lang} />
|
||||
))}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,18 +15,8 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.buttonContainer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 950px) {
|
||||
.stays {
|
||||
grid-template-columns: repeat(auto-fit, minmax(25rem, 1fr));
|
||||
}
|
||||
|
||||
.buttonContainer {
|
||||
margin-top: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.redTitle {
|
||||
color: var(--some-red-color, #ed2027);
|
||||
.grayTitle {
|
||||
color: var(--some-grey-color, #727272);
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import Link from "next/link"
|
||||
|
||||
import { _ } from "@/lib/translation"
|
||||
|
||||
import Title from "@/components/MyPages/Title"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
|
||||
@@ -9,17 +11,15 @@ export default function EmptyUpcomingStaysBlock() {
|
||||
return (
|
||||
<section className={styles.container}>
|
||||
<Title level="h3" as="h5" uppercase>
|
||||
You have no upcoming stays.
|
||||
<span className={styles.redTitle}> Where should you go next?</span>
|
||||
{_(" You have no upcoming stays.")}
|
||||
<span className={styles.grayTitle}>
|
||||
{" "}
|
||||
{_("Where should you go next?")}
|
||||
</span>
|
||||
</Title>
|
||||
<Button
|
||||
intent={"primary"}
|
||||
className={styles.button}
|
||||
asChild
|
||||
type="button"
|
||||
>
|
||||
<Button intent={"primary"} bgcolor={"quarternary"} asChild type="button">
|
||||
<Link className={styles.link} href={"#"} key={"getInspired"}>
|
||||
Get inspired
|
||||
{_("Get inspired")}
|
||||
</Link>
|
||||
</Button>
|
||||
</section>
|
||||
@@ -1,29 +1,52 @@
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
"use client"
|
||||
|
||||
import EmptyUpcomingStaysBlock from "../EmptyUpcomingStays"
|
||||
import { _ } from "@/lib/translation"
|
||||
import { trpc } from "@/lib/trpc/client"
|
||||
|
||||
import Container from "../Container"
|
||||
import Header from "../Header"
|
||||
import ListContainer from "../ListContainer"
|
||||
import ShowMoreButton from "../ShowMoreButton"
|
||||
import StayList from "../StayList"
|
||||
import EmptyUpcomingStaysBlock from "./EmptyUpcomingStays"
|
||||
|
||||
import styles from "./upcoming.module.css"
|
||||
|
||||
import type { Page } from "@/types/components/myPages/myStays/page"
|
||||
import type { LangParams } from "@/types/params"
|
||||
|
||||
export default async function UpcomingStays({ lang }: LangParams) {
|
||||
const stays = await serverClient().user.stays.upcoming()
|
||||
export default function UpcomingStays({ lang }: LangParams) {
|
||||
const { data, hasNextPage, isFetching, fetchNextPage } =
|
||||
trpc.user.stays.upcoming.useInfiniteQuery(
|
||||
{},
|
||||
{
|
||||
getNextPageParam: (lastPage: Page) => lastPage.nextCursor,
|
||||
}
|
||||
)
|
||||
|
||||
function loadMoreData() {
|
||||
fetchNextPage()
|
||||
}
|
||||
|
||||
return (
|
||||
<section className={styles.container}>
|
||||
<Container>
|
||||
<Header
|
||||
title="Your 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!"
|
||||
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!"
|
||||
)}
|
||||
></Header>
|
||||
{stays.length ? (
|
||||
<StayList lang={lang} stays={stays} />
|
||||
{data?.pages.length ? (
|
||||
<ListContainer>
|
||||
<StayList
|
||||
lang={lang}
|
||||
stays={data?.pages.flatMap((page) => page.data) ?? []}
|
||||
/>
|
||||
{hasNextPage ? (
|
||||
<ShowMoreButton disabled={isFetching} loadMoreData={loadMoreData} />
|
||||
) : null}
|
||||
</ListContainer>
|
||||
) : (
|
||||
<EmptyUpcomingStaysBlock />
|
||||
)}
|
||||
</section>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.container {
|
||||
max-width: var(--max-width);
|
||||
}
|
||||
Reference in New Issue
Block a user