Skip to content

Commit

Permalink
Update listings when new search filter is applied
Browse files Browse the repository at this point in the history
refs #49
  • Loading branch information
franthormel committed Aug 31, 2024
1 parent 5cfd24c commit 376d801
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 48 deletions.
7 changes: 7 additions & 0 deletions app/api/listings/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { fetchMatchedListings } from "@/app/listings/actions";

export async function GET(request: Request) {
// TODO: Read search filters from request, try HTTP headers?
const listings = await fetchMatchedListings();
return Response.json({ listings });
}
1 change: 1 addition & 0 deletions app/listings/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const prismaListingMapper = (dbListing: PrismaListing) => {
return listing;
};

// TODO: Expost this as an endpoint through Route Handlers
export async function fetchMatchedListings(
filters: ListingsSearchFilters = DEFAULT_LIST_FILTERS
): Promise<Listing[]> {
Expand Down
18 changes: 15 additions & 3 deletions app/listings/content.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
"use client"

import { useContext } from "react"
import { useContext, useEffect } from "react"
import { ListingSortCompareFunctions, makeSearchFiltersRequest } from "./functions"
import ListingsList from "./list"
import { ListingsListCountSort } from "./list-count-sort"
import { ListingsMap } from "./map"
import ListingsPagination from "./pagination"
import { ListingsContext } from "./provider"
import { Listing, ListingSortCompareFunctions } from "./types"
import { Listing } from "./types"

interface ListingsContentInterface {
listings: Listing[]
}

export default function ListingsContent(props: ListingsContentInterface) {
// TODO: Use context filter values, try to use useMemo if applicable
// TODO: try to use useMemo if applicable
const context = useContext(ListingsContext);

useEffect(() => {
async function updateListings() {
const searchFiltersRequest = makeSearchFiltersRequest(context.searchFilters);
// TODO: Look for a way to pass search filters into HTTP request, try HTTP headers?
const listings = await fetch("/api/listings");
const json = await listings.json()
console.log(json);
}
updateListings()
}, [context.searchFilters])

const sortedListings = props.listings.sort(ListingSortCompareFunctions.choose(context.sort.value))

return (
Expand Down
3 changes: 0 additions & 3 deletions app/listings/function.ts

This file was deleted.

67 changes: 67 additions & 0 deletions app/listings/functions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
Listing,
ListingSort,
ListingsSearchFilters,
ListingsSearchFiltersRequest,
} from "./types";

export function countListingsToSkip(currentPage: number, countPerPage: number) {
return (currentPage - 1) * countPerPage;
}

export function makeSearchFiltersRequest(
original: ListingsSearchFilters
): ListingsSearchFiltersRequest {
return {
price: {
min: original.price.min.value,
max: original.price.max.value,
},
beds: original.beds.value,
baths: original.baths.value,
area: {
min: original.area.min.value,
max: original.area.max.value,
},
};
}

type ListingSortCompareFunction = (a: Listing, b: Listing) => number;

export class ListingSortCompareFunctions {
static #NEWEST: ListingSortCompareFunction = (a, b) => {
if (a.createdDate < b.createdDate) {
return 1;
}

if (a.createdDate === b.createdDate) {
return 0;
}

return -1;
};

static #PRICE_DESC: ListingSortCompareFunction = (a, b) => {
return b.price.value - a.price.value;
};

static #PRICE_ASC: ListingSortCompareFunction = (a, b) => {
return a.price.value - b.price.value;
};

static choose(sort: ListingSort): ListingSortCompareFunction {
switch (sort) {
case ListingSort.NEWEST:
return ListingSortCompareFunctions.#NEWEST;
break;
case ListingSort.PRICE_DESC:
return ListingSortCompareFunctions.#PRICE_DESC;
break;
case ListingSort.PRICE_ASC:
return ListingSortCompareFunctions.#PRICE_ASC;
break;
default:
return ListingSortCompareFunctions.#NEWEST;
}
}
}
2 changes: 1 addition & 1 deletion app/listings/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import CardListing from "@/components/card-listing";
import { CURRENCY_FORMATTER } from "@/lib/formatter/currency";
import { useContext } from "react";
import { LISTINGS_PER_PAGE } from "./constants";
import { countListingsToSkip } from "./function";
import { countListingsToSkip } from "./functions";
import { ListingsContext } from "./provider";
import { Listing } from "./types";

Expand Down
53 changes: 13 additions & 40 deletions app/listings/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,46 +61,6 @@ export enum ListingSort {
PRICE_ASC = "Price (low to high)",
}

type ListingSortCompareFunction = (a: Listing, b: Listing) => number;

export class ListingSortCompareFunctions {
static #NEWEST: ListingSortCompareFunction = (a, b) => {
if (a.createdDate < b.createdDate) {
return 1;
}

if (a.createdDate === b.createdDate) {
return 0;
}

return -1;
};

static #PRICE_DESC: ListingSortCompareFunction = (a, b) => {
return b.price.value - a.price.value;
};

static #PRICE_ASC: ListingSortCompareFunction = (a, b) => {
return a.price.value - b.price.value;
};

static choose(sort: ListingSort): ListingSortCompareFunction {
switch (sort) {
case ListingSort.NEWEST:
return ListingSortCompareFunctions.#NEWEST;
break;
case ListingSort.PRICE_DESC:
return ListingSortCompareFunctions.#PRICE_DESC;
break;
case ListingSort.PRICE_ASC:
return ListingSortCompareFunctions.#PRICE_ASC;
break;
default:
return ListingSortCompareFunctions.#NEWEST;
}
}
}

export type ListingContextType<Type> = {
value: Type;
change: (value: Type) => void;
Expand All @@ -118,6 +78,19 @@ export interface ListingsSearchFilters {
area: ContenTypeNumberRange;
}

export interface ListingsSearchFiltersRequest {
price: {
min: number;
max: number;
};
beds: BedsBathsOption;
baths: BedsBathsOption;
area: {
min: number;
max: number;
};
}

export enum BedsBathsOption {
ANY = "Any",
ONE = "1",
Expand Down
2 changes: 1 addition & 1 deletion tests/app/listings.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { countListingsToSkip } from "../../app/listings/function";
import { countListingsToSkip } from "../../app/listings/functions";

describe("Listings", () => {
test.each([
Expand Down

0 comments on commit 376d801

Please sign in to comment.