feat: listings for sale, and move detail property url
This commit is contained in:
parent
f5c5f3fd78
commit
73de3fd07d
95
src/app/(main)/listings-for-sale/page.tsx
Normal file
95
src/app/(main)/listings-for-sale/page.tsx
Normal file
@ -0,0 +1,95 @@
|
||||
import HeroImage from "@/components/HeroImage";
|
||||
import Pagination from "@/components/Pagination";
|
||||
import CardProperty from "@/components/properties/CardProperty";
|
||||
import FilterProperty from "@/components/properties/FilterProperty";
|
||||
import { FetchPropertyParams } from "@/schema/services/property";
|
||||
import { fetchProperty } from "@/services/payload/property";
|
||||
import { getDefaultMetadata } from "@/utils/metadata";
|
||||
import { sanitizeNumber, sanitizePageNumber } from "@/utils/sanitize";
|
||||
import { Metadata } from "next";
|
||||
|
||||
const metaDesc = "Explore the latest properties on the Dynamic Realty.";
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const metadata = await getDefaultMetadata();
|
||||
metadata.title = `Listings For Sale - ${metadata.openGraph?.siteName}`;
|
||||
metadata.description = metaDesc;
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
export default async function ListingsForRent(props: {
|
||||
searchParams?: Promise<{ [P in keyof FetchPropertyParams]: string }>;
|
||||
}) {
|
||||
const searchParams = await props?.searchParams;
|
||||
const page = sanitizePageNumber(searchParams?.page);
|
||||
const minPrice = sanitizeNumber(searchParams?.min_price);
|
||||
const maxPrice = sanitizeNumber(searchParams?.max_price);
|
||||
const minArea = sanitizeNumber(searchParams?.min_area);
|
||||
const maxArea = sanitizeNumber(searchParams?.max_area);
|
||||
|
||||
const propertiesData = await fetchProperty({
|
||||
property_type: "sell",
|
||||
page,
|
||||
name: searchParams?.name,
|
||||
min_price: minPrice,
|
||||
max_price: maxPrice,
|
||||
min_area: minArea,
|
||||
max_area: maxArea,
|
||||
location: searchParams?.location,
|
||||
});
|
||||
const isEmpty = propertiesData.formattedData.length <= 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<HeroImage title="Listings For Sale" />
|
||||
|
||||
<section className="section section-md bg-gray-12">
|
||||
<div className="container">
|
||||
<div className="row row-50">
|
||||
<div className="col-lg-7 col-xl-8">
|
||||
<div className="row row-30">
|
||||
<div className="col-12">
|
||||
{isEmpty && (
|
||||
<div className="text-center mt-40">
|
||||
<h3 className="text-spacing-20">No Properties Found</h3>
|
||||
<p className="heading-5 mt-3">Looks like we couldn’t find any listings that match your search.</p>
|
||||
</div>
|
||||
)}
|
||||
{!isEmpty && (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{propertiesData.formattedData.map((p, idx) => (
|
||||
<CardProperty key={idx} data={p} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Pagination */}
|
||||
{propertiesData.totalPages > 1 && (
|
||||
<div className="col-12">
|
||||
<Pagination
|
||||
page={propertiesData.page ?? 1}
|
||||
hasNextPage={propertiesData.hasNextPage}
|
||||
hasPreviousPage={propertiesData.hasPrevPage}
|
||||
totalPages={propertiesData.totalPages}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{/* End Pagination */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-lg-5 col-xl-4">
|
||||
<div className="row row-50">
|
||||
<div className="col-md-6 col-lg-12">
|
||||
<FilterProperty propertyType="rent" searchParams={searchParams} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
@ -61,7 +61,7 @@ export async function generateMetadata(props: { params: Promise<{ slug: string }
|
||||
return metadata;
|
||||
}
|
||||
|
||||
export default async function ListingsForRentDetail({ params }: { params: Promise<{ slug: string }> }) {
|
||||
export default async function PropertyDetail({ params }: { params: Promise<{ slug: string }> }) {
|
||||
const slug = (await params).slug;
|
||||
const propertyDetail = await fetchPropertyDetail({ slug });
|
||||
if (!propertyDetail) return notFound();
|
@ -113,7 +113,7 @@ export default function Header() {
|
||||
</a>
|
||||
</li>
|
||||
<li className="rd-nav-item">
|
||||
<a className="rd-nav-link rd-nav-link-custom" href="/">
|
||||
<a className="rd-nav-link rd-nav-link-custom" href="/listings-for-sale">
|
||||
LISTINGS FOR SALE
|
||||
</a>
|
||||
</li>
|
||||
|
@ -8,7 +8,7 @@ type CardPropertyProps = {
|
||||
};
|
||||
|
||||
export default function CardProperty({ data }: CardPropertyProps) {
|
||||
const href = data?.propertyType === "rent" ? `/listings-for-rent/${data.slug}` : `/listings-for-sell/${data.slug}`;
|
||||
const href = data?.propertyType === "rent" ? `/property/${data.slug}` : `/property/${data.slug}`;
|
||||
return (
|
||||
<div>
|
||||
<article className="product-classic">
|
||||
|
Loading…
x
Reference in New Issue
Block a user