From 976e52ace60a4afb3965d05458575869d0e6e786 Mon Sep 17 00:00:00 2001 From: Francis Anthony Date: Wed, 7 Aug 2024 12:45:59 +0800 Subject: [PATCH] Refactor data fetching composition refs #49 --- app/listings/actions.ts | 72 +++++++++++++++++----------------------- app/listings/content.tsx | 43 +++++------------------- app/listings/list.tsx | 16 ++++++++- app/listings/map.tsx | 7 ++-- app/listings/page.tsx | 4 ++- app/listings/types.ts | 32 ++++++++++++++++++ 6 files changed, 95 insertions(+), 79 deletions(-) diff --git a/app/listings/actions.ts b/app/listings/actions.ts index 6cae29d7..8f1d1728 100644 --- a/app/listings/actions.ts +++ b/app/listings/actions.ts @@ -1,52 +1,42 @@ "use server"; import prisma from "@/lib/db"; -import { LISTINGS_PER_PAGE } from "./constants"; -import { countListingsToSkip } from "./function"; -import { Listing } from "./types"; +import { Listing, PrismaListing } from "./types"; -export async function countMatchedListings(): Promise { - // TODO: Add filter param values - return await prisma.listing.count(); -} +const prismaListingMapper = (dbListing: PrismaListing) => { + const dbListingPrice = dbListing.prices + .filter((dbListingPrice) => dbListingPrice.isCurrent) + .at(0)! + .value.toNumber(); + const dbListingAddress = dbListing.address!; + const listing: Listing = { + id: dbListing.id, + imageUrls: dbListing.imageUrls, + beds: dbListing.beds, + baths: dbListing.baths, + area: dbListing.area.toNumber(), + createdDate: dbListing.createdDate, + address: { + addressLine: dbListingAddress.addressLine, + city: dbListingAddress.city, + state: dbListingAddress.state, + longitude: dbListingAddress.longitude.toNumber(), + latitude: dbListingAddress.latitude.toNumber(), + }, + price: { + value: dbListingPrice, + }, + }; + return listing; +}; -export async function fetchListingsByPage( - currentPage: number -): Promise { - const dbListings = await prisma.listing.findMany({ - skip: countListingsToSkip(currentPage, LISTINGS_PER_PAGE), - take: LISTINGS_PER_PAGE, +export async function fetchMatchedListings(): Promise { + // TODO: Add filter param values + const prismaListings = await prisma.listing.findMany({ include: { address: true, prices: true, }, }); - const processedListings = dbListings.map((dbListing) => { - const dbListingPrice = dbListing.prices - .filter((dbListingPrice) => dbListingPrice.isCurrent) - .at(0)! - .value.toNumber(); - const dbListingAddress = dbListing.address!; - const listing: Listing = { - id: dbListing.id, - imageUrls: dbListing.imageUrls, - beds: dbListing.beds, - baths: dbListing.baths, - area: dbListing.area.toNumber(), - createdDate: dbListing.createdDate, - address: { - addressLine: dbListingAddress.addressLine, - city: dbListingAddress.city, - state: dbListingAddress.state, - longitude: dbListingAddress.longitude.toNumber(), - latitude: dbListingAddress.latitude.toNumber(), - }, - price: { - value: dbListingPrice, - }, - }; - return listing; - }); - - return processedListings; + return prismaListings.map(prismaListingMapper); } diff --git a/app/listings/content.tsx b/app/listings/content.tsx index 46d0576b..766d3c45 100644 --- a/app/listings/content.tsx +++ b/app/listings/content.tsx @@ -1,47 +1,22 @@ -"use client" - -import { useContext, useEffect, useState } from "react" -import { countMatchedListings, fetchListingsByPage } from "./actions" import ListingsList from "./list" import { ListingsListTop } from "./list-top" import { ListingsMap } from "./map" import ListingsPagination from "./pagination" -import { ListingsContext } from "./provider" import { Listing } from "./types" -export default function ListingsContent() { - const [listings, setListings] = useState([]) - const [listingsCount, setListingsCount] = useState(0) - - const context = useContext(ListingsContext) - const currentPage = context.pagination.currentPage.value - - // Change pagination - useEffect(() => { - async function updateListings() { - const newListings = await fetchListingsByPage(currentPage) - setListings(newListings) - } - updateListings() - }, [currentPage]) - - - // Count how many listings - useEffect(() => { - async function countListings() { - const newListingsCount = await countMatchedListings() - setListingsCount(newListingsCount) - } - countListings() - }, []) +interface ListingsContentInterface { + listings: Listing[] +} +export default function ListingsContent(props: ListingsContentInterface) { return (
- + {/* TODO: Display listings as pins */} +
- - - + + +
) diff --git a/app/listings/list.tsx b/app/listings/list.tsx index 90c67e35..9585a19a 100644 --- a/app/listings/list.tsx +++ b/app/listings/list.tsx @@ -2,6 +2,10 @@ import CardListing from "@/components/card-listing"; import { CURRENCY_FORMATTER } from "@/lib/formatter/currency"; +import { useContext, useEffect, useMemo, useState } from "react"; +import { LISTINGS_PER_PAGE } from "./constants"; +import { countListingsToSkip } from "./function"; +import { ListingsContext } from "./provider"; import { Listing } from "./types"; export interface ListingsListProps { @@ -9,10 +13,20 @@ export interface ListingsListProps { } export default function ListingsList(props: ListingsListProps) { + const { pagination } = useContext(ListingsContext); + const currentPage = pagination.currentPage.value; + + const memoListings = useMemo(() => { + const start = countListingsToSkip(currentPage, LISTINGS_PER_PAGE); + const end = start + LISTINGS_PER_PAGE; + const newListings = props.listings.slice(start, end); + return newListings; + }, [currentPage]) + return (
- {props.listings.map((listing) => { + {memoListings.map((listing) => { const priceFormatted = CURRENCY_FORMATTER.format(listing.price.value) return ( ) diff --git a/app/listings/page.tsx b/app/listings/page.tsx index 1d57ff6b..12c6cd83 100644 --- a/app/listings/page.tsx +++ b/app/listings/page.tsx @@ -1,13 +1,15 @@ +import { fetchMatchedListings } from "./actions"; import ListingsContent from "./content"; import ListingsProvider from "./provider"; import { ListingsSearchFilters } from "./search-filters"; export default async function Listings() { + const listings = await fetchMatchedListings(); return (
- +
); diff --git a/app/listings/types.ts b/app/listings/types.ts index 33848d54..bcd65733 100644 --- a/app/listings/types.ts +++ b/app/listings/types.ts @@ -1,5 +1,37 @@ import { Decimal } from "@prisma/client/runtime/library"; +export interface PrismaListing { + id: string; + deposit: Decimal | null; + imageUrls: string[]; + description: string; + beds: number; + baths: number; + area: Decimal; + availableDate: Date | null; + createdDate: Date; + userId: string; + address: { + id: string; + addressLine: string; + city: string; + state: string; + zipcode: string | null; + country: string; + latitude: Decimal; + longitude: Decimal; + listingId: string; + } | null; + prices: { + id: string; + value: Decimal; + startDate: Date; + endDate: Date; + isCurrent: boolean; + listingId: string; + }[]; +} + interface ListingPrice { value: number; }