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

Both: Enable users to search by number of ratings #43

Merged
merged 1 commit into from
Apr 12, 2024
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
1 change: 1 addition & 0 deletions backend/src/controllers/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const setRoomsFilter: RequestHandler = (req, _res, next) => {
'price',
'maxNumOfGuests',
'numOfBathrooms',
'ratings',
],
};

Expand Down
115 changes: 0 additions & 115 deletions frontend/app/search/_components/sub-search.tsx

This file was deleted.

23 changes: 23 additions & 0 deletions frontend/app/search/_components/sub-search/amenities.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import AmenitiesComp from "@/app/hotels/new/_components/amenities";

import { UseFormReturn } from "react-hook-form";
import { SearchData } from "../../_types";

interface AmenitiesProps {
form: UseFormReturn<SearchData, any, undefined>;
type: "hotels" | "rooms";
}

export default function Amenities({ form, type }: AmenitiesProps) {
return (
<section className="!border-b-0">
<h3>Filter by Amenities</h3>
<AmenitiesComp
form={form}
listClassName="md:grid-cols-[repeat(auto-fill,minmax(30rem,_1fr))] max-h-[22rem] overflow-y-auto"
defaultChecks={form.getValues("amenities")}
target={type === "hotels" ? "hotel" : "room"}
/>
</section>
);
}
33 changes: 33 additions & 0 deletions frontend/app/search/_components/sub-search/beds.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { FormField } from "@/components/custom/form-field";
import { UseFormReturn } from "react-hook-form";
import { SearchData } from "../../_types";

interface BedProps {
form: UseFormReturn<SearchData, any, undefined>;
}

export default function Beds({ form }: BedProps) {
return (
<section>
<h3>Number of beds</h3>
<div className="grid grid-cols-2 gap-2">
<FormField
input={{
...form.register("beds.gte"),
type: "number",
min: 1,
}}
label="Minimum"
/>
<FormField
input={{
...form.register("beds.lte"),
type: "number",
min: 1,
}}
label="Maximum"
/>
</div>
</section>
);
}
33 changes: 33 additions & 0 deletions frontend/app/search/_components/sub-search/budget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { FormField } from "@/components/custom/form-field";
import { UseFormReturn } from "react-hook-form";
import { SearchData } from "../../_types";

interface BudgetProps {
form: UseFormReturn<SearchData, any, undefined>;
}

export default function Budget({ form }: BudgetProps) {
return (
<section>
<h3>Your budget per 24 hours</h3>
<div className="grid grid-cols-2 gap-2">
<FormField
input={{
...form.register("price.gte"),
type: "number",
min: 0,
}}
label="Minimum"
/>
<FormField
input={{
...form.register("price.lte"),
type: "number",
min: 0,
}}
label="Maximum"
/>
</div>
</section>
);
}
37 changes: 37 additions & 0 deletions frontend/app/search/_components/sub-search/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use client";

import { SearchData } from "./../../_types";
import { useFormContext } from "react-hook-form";
import ToggleContainer from "./../toggle-container";
import Type from "./type";
import Budget from "./budget";
import Beds from "./beds";
import Amenities from "./amenities";
import Ratings from "./ratings";

export default function SubSearch() {
const form = useFormContext<SearchData>();
const type = form.watch("type");

return (
// <ToggleContainer title="Filter" className="md:col-start-1 md:col-end-2">
<div className="bg-background p-4 md:p-0 md:bg-transparent md:max-w-[15rem] md:w-full md:flex-1 md:min-w-[12rem] md:self-start md:sticky md:top-48 md:py-0 md:pl-0 md:mr-4 md:flex-shrink-0">
<ToggleContainer
title="Filter"
// className="md:max-w-[15rem] md:w-full md:flex-1 md:sticky md:top-40 md:left-0"
>
<div className="[&>*]:px-2 [&>*]:border-b [&>*]:py-3 md:border-gray-200">
<Type form={form} />
<Ratings form={form} />
{type === "rooms" && (
<>
<Budget form={form} />
<Beds form={form} />
</>
)}
<Amenities form={form} type={type} />
</div>
</ToggleContainer>
</div>
);
}
47 changes: 47 additions & 0 deletions frontend/app/search/_components/sub-search/ratings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import RatingStar from "@/components/custom/rating-star";
import { SearchData } from "../../_types";
import { Controller, UseFormReturn } from "react-hook-form";
import { FormRadioField } from "@/components/custom/form-radio-field";

interface RatingsProps {
form: UseFormReturn<SearchData, any, undefined>;
}

const ratings = [4.5, 4, 3.5, 3, 2.5, 2, 1.5, 1, 0.5, 0].map((rate) => ({
id: `${rate}`,
value: `${rate}`,
label: (
<span className="flex items-center justify-start">
<RatingStar rating={rate} className="mr-1" />
<span className="font-light">{rate} & up</span>
</span>
),
}));

export default function Ratings({ form }: RatingsProps) {
return (
<section>
<h3>Ratings</h3>
<div className="max-h-[8.55rem] overflow-y-auto">
<Controller
name="ratings"
control={form.control}
render={({ field }) => (
<FormRadioField
label="Search by this only:"
labelClassName="sr-only"
options={ratings}
radioGroup={{
className: "capitalize space-y-1",
onValueChange: field.onChange,
name: "ratings",
value: form.watch("ratings") || "",
defaultValue: "",
}}
/>
)}
/>
</div>
</section>
);
}
44 changes: 44 additions & 0 deletions frontend/app/search/_components/sub-search/type.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Controller, UseFormReturn } from "react-hook-form";
import { SearchData } from "../../_types";
import { FormRadioField } from "@/components/custom/form-radio-field";

interface TypeProps {
form: UseFormReturn<SearchData, any, undefined>;
}

const types = [
{
id: "hotels",
value: "hotels",
},
{
id: "rooms",
value: "rooms",
},
];

export default function Type({ form }: TypeProps) {
return (
<section>
<h3 className="">Search Type</h3>
<Controller
name="type"
control={form.control}
render={({ field }) => (
<FormRadioField
label="Search by this only:"
labelClassName="sr-only"
options={types}
radioGroup={{
className: "capitalize space-y-1",
onValueChange: field.onChange,
name: "type",
value: form.watch("type") || "",
defaultValue: "hotels",
}}
/>
)}
/>
</section>
);
}
4 changes: 4 additions & 0 deletions frontend/app/search/_hooks/use-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export const useResult = () => {
search["price[lte]"] = +search.maxPrice;
delete search.maxPrice;
}
if (search.ratings) {
search["ratings[gte]"] = search.ratings;
delete search.ratings;
}
// TODO: Implement searching by booking date
if (search.from) delete search.from;
if (search.to) delete search.to;
Expand Down
1 change: 1 addition & 0 deletions frontend/app/search/_types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface SearchData {
city: string;
name: string;
type: "hotels" | "rooms";
ratings: string;
amenities: string[];
price: {
gte: number | string;
Expand Down
2 changes: 2 additions & 0 deletions frontend/app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default function Page() {
city: searchParams.get("city") || "",
name: searchParams.get("name") || "",
type: searchParams.get("type") === "rooms" ? "rooms" : "hotels",
ratings: searchParams.get("ratings") || "",
amenities: searchParams.get("amenities")?.split(",") || [],
price: {
gte: Number(searchParams.get("minPrice")) || "",
Expand Down Expand Up @@ -50,6 +51,7 @@ export default function Page() {
maxPrice: +data.price.lte,
minBeds: +data.beds.gte,
maxBeds: +data.beds.lte,
ratings: +data.ratings,
// page: 1,
// limit: 5,
} as any;
Expand Down
4 changes: 2 additions & 2 deletions frontend/components/custom/form-radio-field.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { forwardRef } from "react";
import { forwardRef, ReactNode } from "react";
import { Label } from "@/components/ui/label";
import {
RadioGroup,
Expand All @@ -11,7 +11,7 @@ import {
interface FormRadioFieldProps {
label: string;
options: {
label?: string;
label?: ReactNode;
id: string;
value: string;
}[];
Expand Down
Loading