fix: property list and detail UI slicing
This commit is contained in:
parent
12e7941f6c
commit
f574fdc66d
@ -588,9 +588,9 @@ a:hover {
|
|||||||
color: #967244;
|
color: #967244;
|
||||||
}
|
}
|
||||||
|
|
||||||
a[href*='tel'], a[href*='mailto'] {
|
/* a[href*='tel'], a[href*='mailto'] {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
} */
|
||||||
|
|
||||||
.link-default, .link-default:active, .link-default:focus {
|
.link-default, .link-default:active, .link-default:focus {
|
||||||
color: #424445;
|
color: #424445;
|
||||||
@ -1177,7 +1177,7 @@ a.privacy-link {
|
|||||||
padding: 12px 11px;
|
padding: 12px 11px;
|
||||||
color: #9cc1ff;
|
color: #9cc1ff;
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
background-color: #31323c;
|
background-color: var(--color-colorContactForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-callboard a, .block-callboard a:focus, .block-callboard a:active {
|
.block-callboard a, .block-callboard a:focus, .block-callboard a:active {
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
--color-colorText1: var(--color-colorExt10);
|
--color-colorText1: var(--color-colorExt10);
|
||||||
--color-colorText2: var(--color-colorExt20);
|
--color-colorText2: var(--color-colorExt20);
|
||||||
--color-colorLoaderBackground: var(--color-colorExt20);
|
--color-colorLoaderBackground: var(--color-colorExt20);
|
||||||
|
--color-colorPriceTag: var(--color-colorExt30);
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
|
594
src/app/(main)/listings-for-rent/[slug]/page.tsx
Normal file
594
src/app/(main)/listings-for-rent/[slug]/page.tsx
Normal file
@ -0,0 +1,594 @@
|
|||||||
|
import CardProperty from "@/components/CardProperty";
|
||||||
|
import HeroImage from "@/components/HeroImage";
|
||||||
|
import { CardPropertyData } from "@/schema/property";
|
||||||
|
import { formatCurrency } from "@/utils/general";
|
||||||
|
|
||||||
|
const similarPropertiesData: CardPropertyData[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "401 Biscayne Boulevard, Miami",
|
||||||
|
slug: "401-biscayne-boulevard",
|
||||||
|
images: [
|
||||||
|
{ url: "/images/featured-properties-01-480x287.jpg", alt: "biscayne boulevard" },
|
||||||
|
{ url: "/images/featured-properties-01-480x287.jpg", alt: "biscayne boulevard" },
|
||||||
|
{ url: "/images/featured-properties-01-480x287.jpg", alt: "biscayne boulevard" },
|
||||||
|
],
|
||||||
|
price: 5000,
|
||||||
|
propertyType: "rent",
|
||||||
|
posted_at: "",
|
||||||
|
area: 480,
|
||||||
|
bathrooms_count: 2,
|
||||||
|
bedrooms_count: 2,
|
||||||
|
is_available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "402 Biscayne Boulevard, Miami",
|
||||||
|
slug: "402-biscayne-boulevard",
|
||||||
|
images: [{ url: "/images/featured-properties-01-480x287.jpg", alt: "biscayne boulevard" }],
|
||||||
|
price: 5000,
|
||||||
|
propertyType: "rent",
|
||||||
|
posted_at: "",
|
||||||
|
area: 480,
|
||||||
|
bathrooms_count: 2,
|
||||||
|
bedrooms_count: 2,
|
||||||
|
is_available: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function ListingsForRentDetail() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<HeroImage title="Lorem Ipsum, Dolor" />
|
||||||
|
|
||||||
|
<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="slick-slider-1">
|
||||||
|
<div className="slick-slider-price">$5000\mo</div>
|
||||||
|
<div
|
||||||
|
className="slick-slider carousel-parent"
|
||||||
|
id="parent-carousel"
|
||||||
|
data-arrows="true"
|
||||||
|
data-loop="true"
|
||||||
|
data-dots="false"
|
||||||
|
data-swipe="true"
|
||||||
|
data-fade="true"
|
||||||
|
data-items="1"
|
||||||
|
data-child="#child-carousel"
|
||||||
|
data-for="#child-carousel"
|
||||||
|
>
|
||||||
|
<div className="item">
|
||||||
|
<img src="/images/single-property-1-763x443.jpg" alt="" width="763" height="443" />
|
||||||
|
</div>
|
||||||
|
<div className="item">
|
||||||
|
<img src="/images/single-property-2-763x443.jpg" alt="" width="763" height="443" />
|
||||||
|
</div>
|
||||||
|
<div className="item">
|
||||||
|
<img src="/images/single-property-3-763x443.jpg" alt="" width="763" height="443" />
|
||||||
|
</div>
|
||||||
|
<div className="item">
|
||||||
|
<img src="/images/single-property-4-763x443.jpg" alt="" width="763" height="443" />
|
||||||
|
</div>
|
||||||
|
<div className="item">
|
||||||
|
<img src="/images/single-property-5-763x443.jpg" alt="" width="763" height="443" />
|
||||||
|
</div>
|
||||||
|
<div className="item">
|
||||||
|
<img src="/images/single-property-6-763x443.jpg" alt="" width="763" height="443" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="slick-slider carousel-child"
|
||||||
|
id="child-carousel"
|
||||||
|
data-arrows="true"
|
||||||
|
data-loop="true"
|
||||||
|
data-dots="false"
|
||||||
|
data-swipe="true"
|
||||||
|
data-items="1"
|
||||||
|
data-sm-items="3"
|
||||||
|
data-md-items="4"
|
||||||
|
data-lg-items="4"
|
||||||
|
data-xl-items="5"
|
||||||
|
data-slide-to-scroll="1"
|
||||||
|
data-for="#parent-carousel"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div className="slick-slide-inner bg-[url(/images/single-property-1-763x443.jpg)]"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="slick-slide-inner bg-[url(/images/single-property-1-763x443.jpg)]"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="slick-slide-inner bg-[url(/images/single-property-1-763x443.jpg)]"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="slick-slide-inner bg-[url(/images/single-property-1-763x443.jpg)]"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="slick-slide-inner bg-[url(/images/single-property-1-763x443.jpg)]"></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="slick-slide-inner bg-[url(/images/single-property-1-763x443.jpg)]"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="features-block">
|
||||||
|
<div className="features-block-inner">
|
||||||
|
<div className="features-block-item">
|
||||||
|
<ul className="features-block-list">
|
||||||
|
<li>
|
||||||
|
<span className="icon hotel-icon-10"></span>
|
||||||
|
<span>2 Bathrooms</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="icon hotel-icon-05"></span>
|
||||||
|
<span>2 Bedrooms</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="icon mdi mdi-vector-square"></span>
|
||||||
|
<span>480 Sq Ft</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="features-block-item">
|
||||||
|
<a className="link link-1" href="#">
|
||||||
|
<span className="icon mdi mdi-heart-outline"></span>Add to Favorites
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
Choose this property if you are looking for a modern house near the ocean shore. With 2 bathrooms and 2
|
||||||
|
bedrooms as well as a single garage, it is a perfect option for a small family.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This home has been completely renovated within the past year and features amazing views and sunsets of
|
||||||
|
the local lake, solid wood cabinets (and loads of them), granite counters with colored glass backsplash,
|
||||||
|
sliding glass doors across the entire family room allowing beautiful views of the lake etc. Its
|
||||||
|
affordable price serves as a great bonus for a family looking for an opportunity to save money on Miami
|
||||||
|
MyHome.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="card-group-custom card-group-corporate"
|
||||||
|
id="accordion1"
|
||||||
|
role="tablist"
|
||||||
|
aria-multiselectable="false"
|
||||||
|
>
|
||||||
|
<article className="card card-custom card-corporate">
|
||||||
|
<div className="card-header" id="accordion1-heading-1" role="tab">
|
||||||
|
<div className="card-title">
|
||||||
|
<a
|
||||||
|
className="card-link"
|
||||||
|
role="button"
|
||||||
|
data-toggle="collapse"
|
||||||
|
href="#accordion1-collapse-1"
|
||||||
|
aria-controls="accordion1-collapse-1"
|
||||||
|
aria-expanded="true"
|
||||||
|
>
|
||||||
|
<span>Address</span>
|
||||||
|
<div className="card-arrow"></div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="show visible!"
|
||||||
|
id="accordion1-collapse-1"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="accordion1-heading-1"
|
||||||
|
data-parent="#accordion1"
|
||||||
|
>
|
||||||
|
<div className="card-body">
|
||||||
|
<div className="layout-1">
|
||||||
|
<dl className="list-terms-inline">
|
||||||
|
<dt>Address:</dt>
|
||||||
|
<dd>Biscayne Blvd</dd>
|
||||||
|
</dl>
|
||||||
|
<dl className="list-terms-inline">
|
||||||
|
<dt>State/County:</dt>
|
||||||
|
<dd>Florida</dd>
|
||||||
|
</dl>
|
||||||
|
<dl className="list-terms-inline">
|
||||||
|
<dt>City:</dt>
|
||||||
|
<dd>Miami</dd>
|
||||||
|
</dl>
|
||||||
|
<dl className="list-terms-inline">
|
||||||
|
<dt>Zip:</dt>
|
||||||
|
<dd>8322</dd>
|
||||||
|
</dl>
|
||||||
|
<dl className="list-terms-inline">
|
||||||
|
<dt>Country:</dt>
|
||||||
|
<dd>United States</dd>
|
||||||
|
</dl>
|
||||||
|
<dl className="list-terms-inline">
|
||||||
|
<dt>Area:</dt>
|
||||||
|
<dd>Lake Worth</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="card-group-custom card-group-corporate"
|
||||||
|
id="accordion2"
|
||||||
|
role="tablist"
|
||||||
|
aria-multiselectable="false"
|
||||||
|
>
|
||||||
|
<article className="card card-custom card-corporate">
|
||||||
|
<div className="card-header" id="accordion2-heading-1" role="tab">
|
||||||
|
<div className="card-title">
|
||||||
|
<a
|
||||||
|
className="card-link"
|
||||||
|
role="button"
|
||||||
|
data-toggle="collapse"
|
||||||
|
href="#accordion2-collapse-1"
|
||||||
|
aria-controls="accordion2-collapse-1"
|
||||||
|
aria-expanded="true"
|
||||||
|
>
|
||||||
|
<span>Features</span>
|
||||||
|
<div className="card-arrow"></div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="show visible!"
|
||||||
|
id="accordion2-collapse-1"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="accordion2-heading-1"
|
||||||
|
data-parent="#accordion2"
|
||||||
|
>
|
||||||
|
<div className="card-body">
|
||||||
|
<ul className="list-marked-2 layout-2">
|
||||||
|
<li>2 Stories</li>
|
||||||
|
<li>Basketball Court</li>
|
||||||
|
<li>Lawn</li>
|
||||||
|
<li>Gym</li>
|
||||||
|
<li>Fireplace</li>
|
||||||
|
<li>Sprinklers</li>
|
||||||
|
<li>Private Space</li>
|
||||||
|
<li>Balcony</li>
|
||||||
|
<li>Laundry</li>
|
||||||
|
<li>Ocean View</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="card-group-custom card-group-corporate"
|
||||||
|
id="accordion0"
|
||||||
|
role="tablist"
|
||||||
|
aria-multiselectable="false"
|
||||||
|
>
|
||||||
|
<article className="card card-custom card-corporate">
|
||||||
|
<div className="card-header" id="accordion0-heading-0" role="tab">
|
||||||
|
<div className="card-title">
|
||||||
|
<a
|
||||||
|
className="card-link"
|
||||||
|
role="button"
|
||||||
|
data-toggle="collapse"
|
||||||
|
href="#accordion0-collapse-0"
|
||||||
|
aria-controls="accordion0-collapse-0"
|
||||||
|
aria-expanded="true"
|
||||||
|
>
|
||||||
|
<span>Pricing Detail</span>
|
||||||
|
<div className="card-arrow"></div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="show visible!"
|
||||||
|
id="accordion0-collapse-0"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="accordion0-heading-0"
|
||||||
|
data-parent="#accordion0"
|
||||||
|
>
|
||||||
|
<div className="card-body">
|
||||||
|
<div className="layout-1 columns-1!">
|
||||||
|
<dl className="list-terms-inline w-full flex justify-between">
|
||||||
|
<dt>Base Rent</dt>
|
||||||
|
<dd>{formatCurrency(2700)}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div className="layout-1 columns-1!">
|
||||||
|
<dl className="list-terms-inline w-full flex justify-between">
|
||||||
|
<dt>Smart Home</dt>
|
||||||
|
<dd>{formatCurrency(20)}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div className="layout-1 columns-1!">
|
||||||
|
<dl className="list-terms-inline w-full flex justify-between">
|
||||||
|
<dt>Utility Service</dt>
|
||||||
|
<dd>{formatCurrency(5)}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div className="layout-1 columns-1! mt-2">
|
||||||
|
<dl className="list-terms-inline w-full flex justify-between">
|
||||||
|
<dd className="font-semibold!">Est. total monthly*</dd>
|
||||||
|
<dd className="font-semibold!">{formatCurrency(2900)}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="block-group-item">
|
||||||
|
<h3>Property Map</h3>
|
||||||
|
<div className="row row-30">
|
||||||
|
<div className="col-12">
|
||||||
|
<iframe
|
||||||
|
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3360.4823498818855!2d-83.68565822483802!3d32.61997607372962!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x88f3e6ce99781991%3A0xabfd803ad30f6d12!2s100%20N%20Houston%20Lake%20Blvd%2C%20Centerville%2C%20GA%2031028%2C%20USA!5e0!3m2!1sen!2sid!4v1744883077476!5m2!1sen!2sid"
|
||||||
|
width={"100%"}
|
||||||
|
height={450}
|
||||||
|
style={{ border: 0 }}
|
||||||
|
loading="lazy"
|
||||||
|
referrerPolicy="no-referrer-when-downgrade"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="blog-post-solo-footer mt-20">
|
||||||
|
<div className="blog-post-solo-footer-left">
|
||||||
|
<ul className="blog-post-solo-footer-list">
|
||||||
|
<li>
|
||||||
|
<span className="icon mdi mdi-clock"></span>
|
||||||
|
<a href="#">February 10, 2021</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="blog-post-solo-footer-right">
|
||||||
|
<ul className="blog-post-solo-footer-list-1">
|
||||||
|
<li>
|
||||||
|
<span>Share this post</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<ul className="list-inline-1">
|
||||||
|
<li>
|
||||||
|
<a className="icon link-default fa-facebook" href="#"></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a className="icon link-default fa-twitter" href="#"></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a className="icon link-default fa-google-plus" href="#"></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a className="icon link-default fa-pinterest-p" href="#"></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="block-group-item">
|
||||||
|
<h3>Similar Properties</h3>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
{similarPropertiesData.map((p) => (
|
||||||
|
<CardProperty key={p.id} data={p} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-lg-5 col-xl-4">
|
||||||
|
<div className="row row-50">
|
||||||
|
<div className="col-md-6 col-lg-12">
|
||||||
|
<div className="block-info">
|
||||||
|
<h3>Find Your Property</h3>
|
||||||
|
<form
|
||||||
|
className="rd-mailform form-select"
|
||||||
|
data-form-output="form-output-global"
|
||||||
|
data-form-type="contact"
|
||||||
|
method="post"
|
||||||
|
action="bat/rd-mailform.php"
|
||||||
|
>
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Choose Location"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">Alaska</option>
|
||||||
|
<option value="3">Arizona</option>
|
||||||
|
<option value="4">Arkansas</option>
|
||||||
|
<option value="5">California</option>
|
||||||
|
<option value="6">Colorado</option>
|
||||||
|
<option value="7">Connecticut</option>
|
||||||
|
<option value="8">Delaware</option>
|
||||||
|
<option value="9">Florida</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Property Status"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">Low</option>
|
||||||
|
<option value="3">Middle</option>
|
||||||
|
<option value="4">Primary</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Property Type"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">Low</option>
|
||||||
|
<option value="3">Middle</option>
|
||||||
|
<option value="4">Primary</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap-group">
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Min Price"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">100 $</option>
|
||||||
|
<option value="3">200 $</option>
|
||||||
|
<option value="4">300 $</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Max Price"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">1000 $</option>
|
||||||
|
<option value="3">2000 $</option>
|
||||||
|
<option value="4">3000 $</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap-group">
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Min Area"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">100 Sq Ft</option>
|
||||||
|
<option value="3">200 Sq Ft</option>
|
||||||
|
<option value="4">300 Sq Ft</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Max Area"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">1000 Sq Ft</option>
|
||||||
|
<option value="3">2000 Sq Ft</option>
|
||||||
|
<option value="4">3000 Sq Ft</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="form-button">
|
||||||
|
<button className="button button-block button-primary" type="submit">
|
||||||
|
Search
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6 col-lg-12">
|
||||||
|
<article className="block-callboard">
|
||||||
|
<div className="block-callboard-body">
|
||||||
|
<h3 className="block-callboard-title">Request a Showing</h3>
|
||||||
|
<form
|
||||||
|
className="rd-form rd-mailform"
|
||||||
|
data-form-output="form-output-global"
|
||||||
|
data-form-type="contact"
|
||||||
|
method="post"
|
||||||
|
action="bat/rd-mailform.php"
|
||||||
|
>
|
||||||
|
<div className="row row-20">
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="form-wrap">
|
||||||
|
<input
|
||||||
|
className="form-input"
|
||||||
|
id="contact-name"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
data-constraints="@Required"
|
||||||
|
/>
|
||||||
|
<label className="form-label" htmlFor="contact-name">
|
||||||
|
Your Name
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="form-wrap">
|
||||||
|
<input
|
||||||
|
className="form-input"
|
||||||
|
id="contact-email"
|
||||||
|
type="email"
|
||||||
|
name="email"
|
||||||
|
data-constraints="@Email @Required"
|
||||||
|
/>
|
||||||
|
<label className="form-label" htmlFor="contact-email">
|
||||||
|
E-mail
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="form-wrap">
|
||||||
|
<input
|
||||||
|
className="form-input"
|
||||||
|
id="contact-phone"
|
||||||
|
type="text"
|
||||||
|
name="phone"
|
||||||
|
data-constraints="@PhoneNumber"
|
||||||
|
/>
|
||||||
|
<label className="form-label" htmlFor="contact-phone">
|
||||||
|
Phone
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="form-wrap">
|
||||||
|
<label className="form-label" htmlFor="contact-message">
|
||||||
|
Message
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
className="form-input"
|
||||||
|
id="contact-message"
|
||||||
|
name="message"
|
||||||
|
data-constraints="@Required"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<button className="button button-block button-secondary" type="submit">
|
||||||
|
Send message
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
292
src/app/(main)/listings-for-rent/page.tsx
Normal file
292
src/app/(main)/listings-for-rent/page.tsx
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
import CardProperty from "@/components/CardProperty";
|
||||||
|
import HeroImage from "@/components/HeroImage";
|
||||||
|
import Pagination from "@/components/Pagination";
|
||||||
|
import { CardPropertyData } from "@/schema/property";
|
||||||
|
import { getDefaultMetadata } from "@/utils/metadata";
|
||||||
|
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 Rent - ${metadata.openGraph?.siteName}`;
|
||||||
|
metadata.description = metaDesc;
|
||||||
|
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const propertiesData: CardPropertyData[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "401 Biscayne Boulevard, Miami",
|
||||||
|
slug: "401-biscayne-boulevard",
|
||||||
|
images: [
|
||||||
|
{ url: "/images/featured-properties-01-480x287.jpg", alt: "biscayne boulevard" },
|
||||||
|
{ url: "/images/featured-properties-01-480x287.jpg", alt: "biscayne boulevard" },
|
||||||
|
{ url: "/images/featured-properties-01-480x287.jpg", alt: "biscayne boulevard" },
|
||||||
|
],
|
||||||
|
price: 5000,
|
||||||
|
propertyType: "rent",
|
||||||
|
posted_at: "",
|
||||||
|
area: 480,
|
||||||
|
bathrooms_count: 2,
|
||||||
|
bedrooms_count: 2,
|
||||||
|
is_available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "402 Biscayne Boulevard, Miami",
|
||||||
|
slug: "402-biscayne-boulevard",
|
||||||
|
images: [{ url: "/images/featured-properties-01-480x287.jpg", alt: "biscayne boulevard" }],
|
||||||
|
price: 5000,
|
||||||
|
propertyType: "rent",
|
||||||
|
posted_at: "",
|
||||||
|
area: 480,
|
||||||
|
bathrooms_count: 2,
|
||||||
|
bedrooms_count: 2,
|
||||||
|
is_available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "403 Biscayne Boulevard, Miami",
|
||||||
|
slug: "403-biscayne-boulevard",
|
||||||
|
images: [{ url: "/images/featured-properties-01-480x287.jpg", alt: "biscayne boulevard" }],
|
||||||
|
price: 5000,
|
||||||
|
propertyType: "rent",
|
||||||
|
posted_at: "",
|
||||||
|
area: 480,
|
||||||
|
bathrooms_count: 2,
|
||||||
|
bedrooms_count: 2,
|
||||||
|
is_available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: "404 Biscayne Boulevard, Miami",
|
||||||
|
slug: "404-biscayne-boulevard",
|
||||||
|
images: [{ url: "/images/featured-properties-01-480x287.jpg", alt: "biscayne boulevard" }],
|
||||||
|
price: 5000,
|
||||||
|
propertyType: "rent",
|
||||||
|
posted_at: "",
|
||||||
|
area: 480,
|
||||||
|
bathrooms_count: 2,
|
||||||
|
bedrooms_count: 2,
|
||||||
|
is_available: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function ListingsForRent() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<HeroImage title="Listings For Rent" />
|
||||||
|
|
||||||
|
<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">
|
||||||
|
<ul className="block-info-1">
|
||||||
|
<li>
|
||||||
|
<div className="form-wrap-group-1">
|
||||||
|
<div className="form-wrap">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Publication Date"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">Monday</option>
|
||||||
|
<option value="3">Tuesday</option>
|
||||||
|
<option value="4">Wednesday</option>
|
||||||
|
<option value="5">Thursday</option>
|
||||||
|
<option value="6">Friday</option>
|
||||||
|
<option value="7">Saturday</option>
|
||||||
|
<option value="8">Sunday</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Price Low to High"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="1">Price Low to High</option>
|
||||||
|
<option value="2">Price High to Low</option>
|
||||||
|
<option value="3">Most Popular</option>
|
||||||
|
<option value="4">Top Rated</option>
|
||||||
|
<option value="5">Best Sellers</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
{propertiesData.map((p) => (
|
||||||
|
<CardProperty key={p.id} data={p} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
{/* <ul className="pagination-custom">
|
||||||
|
<li>
|
||||||
|
<a className="active" href="#">
|
||||||
|
1
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#">2</a>
|
||||||
|
</li>
|
||||||
|
</ul> */}
|
||||||
|
<Pagination hasNextPage={true} hasPreviousPage={true} totalPages={10} page={3} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-lg-5 col-xl-4">
|
||||||
|
<div className="row row-50">
|
||||||
|
<div className="col-md-6 col-lg-12">
|
||||||
|
<div className="block-info">
|
||||||
|
<h3>Find Your Property</h3>
|
||||||
|
<form
|
||||||
|
className="rd-mailform form-select"
|
||||||
|
data-form-output="form-output-global"
|
||||||
|
data-form-type="contact"
|
||||||
|
method="post"
|
||||||
|
action="bat/rd-mailform.php"
|
||||||
|
>
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Choose Location"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">Alaska</option>
|
||||||
|
<option value="3">Arizona</option>
|
||||||
|
<option value="4">Arkansas</option>
|
||||||
|
<option value="5">California</option>
|
||||||
|
<option value="6">Colorado</option>
|
||||||
|
<option value="7">Connecticut</option>
|
||||||
|
<option value="8">Delaware</option>
|
||||||
|
<option value="9">Florida</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Property Status"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">Low</option>
|
||||||
|
<option value="3">Middle</option>
|
||||||
|
<option value="4">Primary</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Property Type"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">Low</option>
|
||||||
|
<option value="3">Middle</option>
|
||||||
|
<option value="4">Primary</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap-group">
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Min Price"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">100 $</option>
|
||||||
|
<option value="3">200 $</option>
|
||||||
|
<option value="4">300 $</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Max Price"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">1000 $</option>
|
||||||
|
<option value="3">2000 $</option>
|
||||||
|
<option value="4">3000 $</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap-group">
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Min Area"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">100 Sq Ft</option>
|
||||||
|
<option value="3">200 Sq Ft</option>
|
||||||
|
<option value="4">300 Sq Ft</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
<div className="form-wrap form-wrap-validation">
|
||||||
|
<select
|
||||||
|
className="form-input select-filter"
|
||||||
|
data-style="modern"
|
||||||
|
data-placeholder="Max Area"
|
||||||
|
data-minimum-results-for-search="Infinity"
|
||||||
|
data-constraints="@Required"
|
||||||
|
>
|
||||||
|
<option label="placeholder"></option>
|
||||||
|
<option value="2">1000 Sq Ft</option>
|
||||||
|
<option value="3">2000 Sq Ft</option>
|
||||||
|
<option value="4">3000 Sq Ft</option>
|
||||||
|
</select>
|
||||||
|
<span className="select-arrow"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="form-button">
|
||||||
|
<button className="button button-block button-primary" type="submit">
|
||||||
|
Search
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
63
src/components/CardProperty.tsx
Normal file
63
src/components/CardProperty.tsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { CardPropertyData } from "@/schema/property";
|
||||||
|
import { formatCurrency } from "@/utils/general";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
type CardPropertyProps = {
|
||||||
|
data: CardPropertyData;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function CardProperty({ data }: CardPropertyProps) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<article className="product-classic">
|
||||||
|
<div className="product-classic-media">
|
||||||
|
<div
|
||||||
|
className="owl-carousel"
|
||||||
|
data-items="1"
|
||||||
|
data-nav="true"
|
||||||
|
data-stage-padding="0"
|
||||||
|
data-loop="false"
|
||||||
|
data-margin="0"
|
||||||
|
data-mouse-drag="false"
|
||||||
|
>
|
||||||
|
{Array.isArray(data.images) &&
|
||||||
|
data.images.map((img, idx) => (
|
||||||
|
<Image key={idx} src={img.url} alt={img.alt ?? ""} width="480" height="287" />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="product-classic-price bg-colorPriceTag/80!">
|
||||||
|
<span>
|
||||||
|
{formatCurrency(data.price)}
|
||||||
|
{data.propertyType === "rent" && `/mo`}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h4 className="product-classic-title">
|
||||||
|
<Link href="/listings-for-rent/slug">{data.title}</Link>
|
||||||
|
</h4>
|
||||||
|
<div className="product-classic-divider"></div>
|
||||||
|
<ul className="product-classic-list">
|
||||||
|
<li>
|
||||||
|
<span className="icon mdi mdi-vector-square"></span>
|
||||||
|
<span>{data.area} Sq Ft</span>
|
||||||
|
</li>
|
||||||
|
{data.bathrooms_count && (
|
||||||
|
<li>
|
||||||
|
<span className="icon hotel-icon-10"></span>
|
||||||
|
<span>{data.bathrooms_count} Bathrooms</span>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{data.bedrooms_count && (
|
||||||
|
<li>
|
||||||
|
<span className="icon hotel-icon-05"></span>
|
||||||
|
<span>{data.bedrooms_count} Bedrooms</span>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
120
src/components/Pagination.tsx
Normal file
120
src/components/Pagination.tsx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
|
||||||
|
interface PaginationProps {
|
||||||
|
page: number;
|
||||||
|
hasPreviousPage: boolean;
|
||||||
|
hasNextPage: boolean;
|
||||||
|
totalPages: number;
|
||||||
|
usePathParams?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Pagination({
|
||||||
|
page,
|
||||||
|
hasPreviousPage,
|
||||||
|
hasNextPage,
|
||||||
|
totalPages,
|
||||||
|
usePathParams = false,
|
||||||
|
}: PaginationProps) {
|
||||||
|
const activePage = page;
|
||||||
|
const pathName = usePathname();
|
||||||
|
|
||||||
|
// Function to handle page change
|
||||||
|
const handlePageChange = (page: string | number) => {
|
||||||
|
if (typeof page === "string") return;
|
||||||
|
if (typeof window === "undefined") return;
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
const searchParams = new URLSearchParams(url.search);
|
||||||
|
|
||||||
|
if (usePathParams) {
|
||||||
|
let updatedPath = "";
|
||||||
|
if (pathName.includes("/page")) {
|
||||||
|
updatedPath = pathName.replace(/\/page\/\d+/, `/page/${page}`);
|
||||||
|
} else {
|
||||||
|
updatedPath = `${pathName}/page/${page}`;
|
||||||
|
}
|
||||||
|
window.location.href = `${updatedPath}?${searchParams}`;
|
||||||
|
} else {
|
||||||
|
searchParams.set("page", `${page}`);
|
||||||
|
window.location.href = `${pathName}/?${searchParams}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPageNumbers = () => {
|
||||||
|
const pages = [];
|
||||||
|
const showEllipsisStart = activePage > 4;
|
||||||
|
const showEllipsisEnd = activePage < totalPages - 3;
|
||||||
|
|
||||||
|
if (totalPages <= 7) {
|
||||||
|
// Show all pages if total is 7 or less
|
||||||
|
for (let i = 1; i <= totalPages; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Always show first page
|
||||||
|
pages.push(1);
|
||||||
|
|
||||||
|
if (showEllipsisStart) {
|
||||||
|
pages.push("...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show pages around current page
|
||||||
|
const start = showEllipsisStart ? Math.max(2, activePage - 1) : 2;
|
||||||
|
const end = showEllipsisEnd ? Math.min(totalPages - 1, activePage + 1) : totalPages - 1;
|
||||||
|
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showEllipsisEnd) {
|
||||||
|
pages.push("...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always show last page
|
||||||
|
pages.push(totalPages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pages;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul className={"pagination-custom"}>
|
||||||
|
{/* Previous Page Button */}
|
||||||
|
{hasPreviousPage && (
|
||||||
|
<>
|
||||||
|
<li className="cursor-pointer">
|
||||||
|
<a
|
||||||
|
onClick={() => activePage > 1 && handlePageChange(activePage - 1)}
|
||||||
|
className={activePage === 1 ? "disabled" : ""}
|
||||||
|
>
|
||||||
|
{"<"}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{getPageNumbers().map((page, key) => (
|
||||||
|
<li key={key} className="cursor-pointer">
|
||||||
|
<a onClick={() => handlePageChange(page)} className={activePage === page ? "active" : ""}>
|
||||||
|
{page}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Next Page Button */}
|
||||||
|
{hasNextPage && (
|
||||||
|
<>
|
||||||
|
<li className="cursor-pointer">
|
||||||
|
<a
|
||||||
|
onClick={() => activePage < totalPages && handlePageChange(activePage + 1)}
|
||||||
|
className={activePage === totalPages ? "disabled" : ""}
|
||||||
|
>
|
||||||
|
{">"}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
@ -118,7 +118,7 @@ export default function Header() {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li className="rd-nav-item">
|
<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-rent">
|
||||||
LISTINGS FOR RENT
|
LISTINGS FOR RENT
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
16
src/schema/property.ts
Normal file
16
src/schema/property.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export type CardPropertyData = {
|
||||||
|
id: number;
|
||||||
|
slug?: string | null;
|
||||||
|
title: string;
|
||||||
|
price: number;
|
||||||
|
images?: { url: string; alt?: string }[];
|
||||||
|
/**
|
||||||
|
* in sqft
|
||||||
|
*/
|
||||||
|
area: number;
|
||||||
|
bedrooms_count?: number;
|
||||||
|
bathrooms_count?: number;
|
||||||
|
posted_at: string;
|
||||||
|
propertyType: "rent" | "sell";
|
||||||
|
is_available: boolean;
|
||||||
|
};
|
@ -5,3 +5,22 @@ export function limitString(text: string) {
|
|||||||
export function getRandomNumber(range: number): number {
|
export function getRandomNumber(range: number): number {
|
||||||
return Math.floor(Math.random() * range) + 1;
|
return Math.floor(Math.random() * range) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatCurrency(num: number): string {
|
||||||
|
return Intl.NumberFormat("en-US", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "USD",
|
||||||
|
|
||||||
|
// These options can be used to round to whole numbers.
|
||||||
|
trailingZeroDisplay: "stripIfInteger", // This is probably what most people
|
||||||
|
// want. It will only stop printing
|
||||||
|
// the fraction when the input
|
||||||
|
// amount is a round number (int)
|
||||||
|
// already. If that's not what you
|
||||||
|
// need, have a look at the options
|
||||||
|
// below.
|
||||||
|
//minimumFractionDigits: 0, // This suffices for whole numbers, but will
|
||||||
|
// print 2500.10 as $2,500.1
|
||||||
|
//maximumFractionDigits: 0, // Causes 2500.99 to be printed as $2,501
|
||||||
|
}).format(num);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user