Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

828 frontend dynamically fetch lodge prices on frontend #829

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion client/src/app/Home.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,13 @@ const meta: Meta<typeof HomeComponent> = {
export default meta

export const DefaultHomePage = () => {
return <HomeComponent pricingData={[]} />
return (
<HomeComponent
membershipPricingData={[]}
lodgePricing={{
normal: 69,
moreExpensive: 420
}}
/>
)
}
35 changes: 29 additions & 6 deletions client/src/app/HomeComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
import { Footer } from "@/components/generic/Footer/Footer"
import { HomePage } from "@/models/sanity/HomePage/Utils"
import { Prices } from "@/services/AppData/AppDataService"
import {
LodgePricingProps,
MembershipPrices
} from "@/services/AppData/AppDataService"
import AboutSection from "./sections/AboutSection"
import BenefitSection from "./sections/BenefitSection"
import LandingSection from "./sections/LandingSection"
import PricingSection from "./sections/PricingSection"
import { benefits } from "./sections/utils/Benefits"
import { pricingBannerContent } from "./sections/utils/Pricing"
import { lodgeBookingPricingBannerMessages } from "./sections/utils/Pricing"

export type HomeProps = {
pricingData: Prices[]
/**
* Fetched prices for how much each type of membership costs
*/
membershipPricingData: MembershipPrices[]
/**
* Fetched prices showing how much it costs to book the lodge
*/
lodgePricing: LodgePricingProps
content?: HomePage
}

/**
* @deprecated do not use, use `WrappedHomeComponent` instead
*/
const HomeComponent = ({ pricingData, content }: HomeProps) => {
const HomeComponent = ({
membershipPricingData,
lodgePricing,
content
}: HomeProps) => {
return (
<>
<div>
Expand All @@ -35,8 +49,17 @@ const HomeComponent = ({ pricingData, content }: HomeProps) => {
/>
<PricingSection
note={content?.pricing?.discount}
pricings={pricingData}
bannerContent={pricingBannerContent}
pricings={membershipPricingData}
bannerContent={{
headline: lodgeBookingPricingBannerMessages.headline,
priceInformation:
lodgeBookingPricingBannerMessages.priceInformation(
lodgePricing.normal
),
disclaimer: lodgeBookingPricingBannerMessages.priceInformation(
lodgePricing.moreExpensive
)
}}
/>
</div>
<div className="pt-14">
Expand Down
3 changes: 3 additions & 0 deletions client/src/app/bookings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import { PortableText } from "@portabletext/react"
import { Policies, POLICIES_GROQ_QUERY } from "@/models/sanity/Policies/Utils"
import BookingPolicyStorage from "./BookingPolicyStorage"
import { PolicyWithTextBlocks } from "@/components/composite/Booking/BookingContext"
import AppDataService from "@/services/AppData/AppDataService"

const BookingPage = async () => {
const lodgeInfo = await sanityQuery<LodgeInformation[]>(
LODGE_INFORMATION_GROQ_QUERY
)

const lodgePrices = await AppDataService.getLodgePrices()
/**
* We assume there will be only one based on the way {@link LodgeInformation}
* is set up in sanity
Expand Down Expand Up @@ -55,6 +57,7 @@ const BookingPage = async () => {
<>
<BookingInformationAndCreation
enableNetworkRequests
lodgePricing={lodgePrices}
lodgeInfoProps={{
children: <RenderedContent />,
imageSrcs: processedImages
Expand Down
15 changes: 11 additions & 4 deletions client/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import AppDataService, { Prices } from "@/services/AppData/AppDataService"
import AppDataService, {
MembershipPrices
} from "@/services/AppData/AppDataService"
import HomeComponent from "./HomeComponent"
import { sanityQuery } from "../../sanity/lib/utils"
import { HOME_PAGE_GROQ_QUERY, HomePage } from "@/models/sanity/HomePage/Utils"

const Home = async () => {
let pricingData: Prices[]
let pricingData: MembershipPrices[]
try {
pricingData = await AppDataService.getMembershipPricingDetails()
} catch (e) {
pricingData = []
}

const lodgePricing = await AppDataService.getLodgePrices()

const [content] = await sanityQuery<HomePage[]>(HOME_PAGE_GROQ_QUERY)
console.log(content)

return (
<>
<HomeComponent pricingData={pricingData} content={content} />
<HomeComponent
membershipPricingData={pricingData}
content={content}
lodgePricing={lodgePricing}
/>
</>
)
}
Expand Down
12 changes: 8 additions & 4 deletions client/src/app/sections/PricingSection.story.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { Meta } from "@storybook/react"

import PricingSection from "./PricingSection"
import { pricingBannerContent, pricingNote } from "./utils/Pricing"
import { HomeProps } from "../HomeComponent"

const meta: Meta<typeof PricingSection> = {
Expand All @@ -10,12 +9,17 @@ const meta: Meta<typeof PricingSection> = {

export default meta

export const DefaultPricingSection = ({ pricingData: data }: HomeProps) => {
export const DefaultPricingSection = ({
membershipPricingData: data
}: HomeProps) => {
return (
<PricingSection
pricings={data}
note={pricingNote}
bannerContent={pricingBannerContent}
note={"THis is an optional disclaimer"}
bannerContent={{
priceInformation: "asdkjasdjkaslk",
headline: "LOL STRAIGHT ZHAO"
}}
/>
)
}
6 changes: 3 additions & 3 deletions client/src/app/sections/PricingSection.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import PricingBanner from "@/components/generic/PricingBanner/PricingBanner"
import PricingCard from "@/components/generic/PricingCard/PricingCard"
import { PricingBannerContent } from "@/components/utils/types"
import { Prices } from "@/services/AppData/AppDataService"
import { MembershipPrices } from "@/services/AppData/AppDataService"
import Link from "next/link"
import HomeSectionHeading from "./utils/HomeSectionHeading"
import HomeSectionWrapper from "./utils/HomeSectionWrapper"

interface IPricingSection {
note?: string
pricings: Prices[]
bannerContent?: PricingBannerContent
pricings: MembershipPrices[]
bannerContent: PricingBannerContent
}

const PricingSection = ({ note, pricings, bannerContent }: IPricingSection) => (
Expand Down
37 changes: 28 additions & 9 deletions client/src/app/sections/utils/Pricing.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
import { Pricing, PricingBannerContent } from "@/components/utils/types"
import { MembershipPricing } from "@/components/utils/types"

export const pricingNote =
"*We have a discounted membership price on offer until Sunday 17th March so lock in now for a year of awesome memories!"
/**
* An object containing messages for the pricing banner.
*/
export const lodgeBookingPricingBannerMessages = {
/**
* The headline message for the pricing banner.
*/
headline: "Great nightly rates" as const,

export const pricingBannerContent: PricingBannerContent = {
headline: "Great nightly rates",
priceInformation: "$40 per night*",
disclaimer: "*$60 when booking a single Friday or Saturday"
}
/**
* A function that returns a formatted price information string.
*
* @param {number} normalPrice - The normal price per night.
* @returns {string} The formatted price information string.
*/
priceInformation: (normalPrice: number) =>
`$${normalPrice} per night*` as const,

export const Pricings: Pricing[] = [
/**
* A function that returns a formatted disclaimer message.
*
* @param {number} moreExpensivePrice - The price when booking a single Friday or Saturday.
* @returns {string} The formatted disclaimer message.
*/
disclaimer: (moreExpensivePrice: number) =>
`*$${moreExpensivePrice} when booking a single Friday or Saturday` as const
} as const

export const MembershipPricings: MembershipPricing[] = [
{
title: "UoA Student",
discountedPrice: "$45",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ type Story = StoryObj<typeof meta>

export const DefaultCreateBookingPage: Story = {
decorators: [(Story) => <Story />],
args: {}
args: {
lodgePrices: {
normal: 69,
moreExpensive: 420
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import { Timestamp } from "firebase/firestore"
import Checkbox from "@/components/generic/Checkbox/Checkbox"
import { DateRange, DateUtils } from "@/components/utils/DateUtils"
import { LodgePricingProps } from "@/services/AppData/AppDataService"

/*
* Swaps around dates if invalid
Expand Down Expand Up @@ -67,10 +68,9 @@ export interface ICreateBookingSection {
* If a request related to creating/fetching a booking is in progress
*/
isPending?: boolean
}

const NORMAL_PRICE = 40 as const
const SPECIAL_PRICE = 60 as const
lodgePrices: LodgePricingProps
}

/**
* A notification to the user informing the actual
Expand Down Expand Up @@ -110,13 +110,20 @@ export const CreateBookingSection = ({
handleBookingCreation,
handleAllergyChange,
hasExistingSession,
isPending
isPending,
lodgePrices
}: ICreateBookingSection) => {
const [selectedDateRange, setSelectedDateRange] = useState<DateRange>({
startDate: new Date(),
endDate: new Date()
})

/**
* Derive prices from the props
*/
const NORMAL_PRICE = lodgePrices.normal
const SPECIAL_PRICE = lodgePrices.moreExpensive

const [isValidForCreation, setIsValidForCreation] = useState<boolean>(false)

const { startDate: currentStartDate, endDate: currentEndDate } =
Expand Down Expand Up @@ -220,7 +227,7 @@ export const CreateBookingSection = ({
: NORMAL_PRICE

return `$${requiredPrice} * ${nights} night${nights > 1 ? "s" : ""} = $${requiredPrice * nights}` as const
}, [currentStartDate, currentEndDate])
}, [currentStartDate, currentEndDate, SPECIAL_PRICE, NORMAL_PRICE])

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
import { useAppData } from "@/store/Store"
import { SignUpNotif } from "@/components/generic/SignUpNotif/SignUpNotif"
import { useAvailableBookingsQuery } from "@/services/Booking/BookingQueries"
import { CreateBookingSection } from "./BookingCreation"
import { CreateBookingSection, ICreateBookingSection } from "./BookingCreation"
import { useContext, useEffect } from "react"
import { BookingContext } from "../BookingContext"

/**
* @deprecated not for direct consumption on pages, use `BookingInformationAndCreation` instead
*/
export const ProtectedCreateBookingSection = () => {
export const ProtectedCreateBookingSection = ({
lodgePrices
}: Pick<ICreateBookingSection, "lodgePrices">) => {
const [{ currentUser, currentUserClaims }] = useAppData()

const { data } = useAvailableBookingsQuery()
Expand Down Expand Up @@ -38,6 +40,7 @@ export const ProtectedCreateBookingSection = () => {
handleAllergyChange={setAllergies}
hasExistingSession={!!clientSecret}
isPending={isPending}
lodgePrices={lodgePrices}
/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "../BookingCreation/BookingCreation"
import { ProtectedCreateBookingSection } from "../BookingCreation/ProtectedCreateBookingSection"
import { useSearchParams } from "next/navigation"
import { LodgePricingProps } from "@/services/AppData/AppDataService"

/**
* Utility type determining what should be displayed to the user in {@link BookingInformationAndCreation}
Expand All @@ -34,6 +35,11 @@ interface IBookingInformationAndCreation {
* uses the implementation of{@link CreateBookingSection}
*/
enableNetworkRequests?: boolean

/**
* How much each the different types of bookings cost, based on {@link LodgePricingProps}
*/
lodgePricing: LodgePricingProps
}

/**
Expand All @@ -43,7 +49,8 @@ interface IBookingInformationAndCreation {
const BookingInformationAndCreation = ({
bookingCreationProps,
lodgeInfoProps,
enableNetworkRequests
enableNetworkRequests,
lodgePricing
}: IBookingInformationAndCreation) => {
const params = useSearchParams()

Expand All @@ -66,9 +73,14 @@ const BookingInformationAndCreation = ({
)
case "booking-creation":
if (enableNetworkRequests) {
return <ProtectedCreateBookingSection />
return <ProtectedCreateBookingSection lodgePrices={lodgePricing} />
} else {
return <CreateBookingSection {...bookingCreationProps} />
return (
<CreateBookingSection
{...bookingCreationProps}
lodgePrices={lodgePricing}
/>
)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/utils/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type Benefit = {
/**
* For use with the pricing cards that have the `home` variant
*/
export type Pricing = {
export type MembershipPricing = {
title: string
originalPrice?: string
discountedPrice: string
Expand Down
Loading
Loading