diff --git a/src/app/(main)/listings-for-rent/page.tsx b/src/app/(main)/listings-for-rent/page.tsx
index bdd1cce..30c8702 100644
--- a/src/app/(main)/listings-for-rent/page.tsx
+++ b/src/app/(main)/listings-for-rent/page.tsx
@@ -30,6 +30,7 @@ export default async function ListingsForRent(props: {
const maxArea = sanitizeNumber(searchParams?.max_area);
const propertiesData = await fetchProperty({
+ property_type: "rent",
page,
name: searchParams?.name,
min_price: minPrice,
diff --git a/src/collections/Properties.ts b/src/collections/Properties.ts
index 8e40c19..6632bb1 100644
--- a/src/collections/Properties.ts
+++ b/src/collections/Properties.ts
@@ -11,7 +11,7 @@ export const Properties: CollectionConfig = {
},
fields: [
{
- name: "propertyType",
+ name: "property_type",
label: "Type",
type: "select",
options: [
@@ -56,20 +56,18 @@ export const Properties: CollectionConfig = {
{
name: "area",
label: "Area (Sqft)",
- type: "text",
+ type: "number",
required: true,
},
{
name: "bathrooms_count",
label: "Total Bathrooms",
- type: "text",
- required: true,
+ type: "number",
},
{
name: "bedrooms_count",
label: "Total Bedrooms",
- type: "text",
- required: true,
+ type: "number",
},
],
},
@@ -79,8 +77,8 @@ export const Properties: CollectionConfig = {
type: "group",
fields: [
{
- name: "country_code",
- label: "Country",
+ name: "state_code",
+ label: "State",
type: "text",
// admin: {
// components: {
@@ -90,11 +88,6 @@ export const Properties: CollectionConfig = {
// },
// },
},
- {
- name: "state_code",
- label: "State",
- type: "text",
- },
{
name: "city_code",
label: "City",
@@ -124,7 +117,7 @@ export const Properties: CollectionConfig = {
},
{
name: "base_price",
- label: "Base Price",
+ label: "Price",
type: "number",
required: true,
},
@@ -147,7 +140,7 @@ export const Properties: CollectionConfig = {
},
{
name: "embed_map_url",
- label: "Embed Map URL",
+ label: "Embed Google Map URL",
type: "text",
},
],
diff --git a/src/components/CardProperty.tsx b/src/components/CardProperty.tsx
index 6ac5ba6..8433d18 100644
--- a/src/components/CardProperty.tsx
+++ b/src/components/CardProperty.tsx
@@ -8,7 +8,7 @@ type CardPropertyProps = {
};
export default function CardProperty({ data }: CardPropertyProps) {
- const href = data?.propertyType === "sell" ? `/listings-for-rent/${data.slug}` : `/listings-for-sell/${data.slug}`;
+ const href = data?.propertyType === "rent" ? `/listings-for-rent/${data.slug}` : `/listings-for-sell/${data.slug}`;
return (
@@ -24,7 +24,7 @@ export default function CardProperty({ data }: CardPropertyProps) {
>
{Array.isArray(data.images) &&
data.images.map((img, idx) => (
-
+
))}
@@ -41,17 +41,19 @@ export default function CardProperty({ data }: CardPropertyProps) {
- -
-
- {data.area} Sq Ft
-
- {data.bathrooms_count && (
+ {!!data.area && (
+ -
+
+ {data.area} Sq Ft
+
+ )}
+ {!!data.bathrooms_count && (
-
{data.bathrooms_count} Bathrooms
)}
- {data.bedrooms_count && (
+ {!!data.bedrooms_count && (
-
{data.bedrooms_count} Bedrooms
diff --git a/src/payload-types.ts b/src/payload-types.ts
index 6a1abbd..1929e8e 100644
--- a/src/payload-types.ts
+++ b/src/payload-types.ts
@@ -239,7 +239,7 @@ export interface PropertyFeature {
*/
export interface Property {
id: number;
- propertyType: 'rent' | 'sell';
+ property_type: 'rent' | 'sell';
name: string;
slug?: string | null;
images: (number | Media)[];
@@ -259,12 +259,11 @@ export interface Property {
};
[k: string]: unknown;
};
- area: string;
- bathrooms_count: string;
- bedrooms_count: string;
+ area: number;
+ bathrooms_count?: number | null;
+ bedrooms_count?: number | null;
};
addressGroup: {
- country_code?: string | null;
state_code?: string | null;
city_code?: string | null;
zip_code: string;
@@ -457,7 +456,7 @@ export interface PropertyFeaturesSelect {
* via the `definition` "properties_select".
*/
export interface PropertiesSelect {
- propertyType?: T;
+ property_type?: T;
name?: T;
slug?: T;
images?: T;
@@ -472,7 +471,6 @@ export interface PropertiesSelect {
addressGroup?:
| T
| {
- country_code?: T;
state_code?: T;
city_code?: T;
zip_code?: T;
diff --git a/src/schema/property.ts b/src/schema/property.ts
index 2268791..a903adb 100644
--- a/src/schema/property.ts
+++ b/src/schema/property.ts
@@ -6,9 +6,9 @@ export type CardPropertyData = {
/**
* in sqft
*/
- area: string;
- bedrooms_count?: string;
- bathrooms_count?: string;
+ area?: number | null;
+ bedrooms_count?: number | null;
+ bathrooms_count?: number | null;
posted_at: string;
propertyType: "rent" | "sell";
};
diff --git a/src/schema/services/property.ts b/src/schema/services/property.ts
index e570b1c..098ac82 100644
--- a/src/schema/services/property.ts
+++ b/src/schema/services/property.ts
@@ -6,4 +6,9 @@ export type FetchPropertyParams = {
min_price?: number;
max_price?: number;
location?: string;
+ property_type?: "rent" | "sell";
+};
+
+export type FetchPropertyDetailParams = {
+ slug: string;
};
diff --git a/src/services/payload/property.ts b/src/services/payload/property.ts
index aaba941..981701f 100644
--- a/src/services/payload/property.ts
+++ b/src/services/payload/property.ts
@@ -1,7 +1,8 @@
import payloadConfig from "@/payload.config";
import { CardPropertyData } from "@/schema/property";
-import { FetchPropertyParams } from "@/schema/services/property";
+import { FetchPropertyDetailParams, FetchPropertyParams } from "@/schema/services/property";
import { formatDate } from "@/utils/datetime";
+import { formatCurrency, getRandomNumber } from "@/utils/general";
import { getPayload, Where } from "payload";
export async function fetchProperty({
@@ -12,6 +13,7 @@ export async function fetchProperty({
max_price,
min_area,
max_area,
+ property_type,
}: FetchPropertyParams = {}) {
const payload = await getPayload({ config: payloadConfig });
@@ -19,6 +21,11 @@ export async function fetchProperty({
_status: { equals: "published" },
};
+ if (!!property_type) {
+ queryCondition["property_type"] = {
+ equals: property_type,
+ };
+ }
if (!!name) {
queryCondition["name"] = {
contains: name,
@@ -60,11 +67,11 @@ export async function fetchProperty({
const formattedData: CardPropertyData[] = dataQuery.docs.map((item) => {
return {
- slug: "",
+ slug: item.slug ?? "",
title: item.name,
price: item.base_price,
area: item.aboutGroup.area,
- propertyType: item.propertyType,
+ propertyType: item.property_type,
bathrooms_count: item.aboutGroup.bathrooms_count,
bedrooms_count: item.aboutGroup.bedrooms_count,
images: item.images.map((img) =>
@@ -79,3 +86,96 @@ export async function fetchProperty({
formattedData,
};
}
+
+export async function fetchPropertySuggestion() {
+ const payload = await getPayload({ config: payloadConfig });
+ const limitPerPage = 2;
+ const countrQuery = await payload.count({
+ collection: "properties",
+ where: { _status: { equals: "published" } },
+ });
+
+ // randomize page
+ let page = 1;
+ const totalDocs = countrQuery.totalDocs;
+ if (totalDocs > limitPerPage) {
+ const totalPage = Math.ceil(totalDocs / limitPerPage);
+ page = getRandomNumber(totalPage);
+ }
+
+ const dataQuery = await payload.find({
+ collection: "properties",
+ page,
+ limit: limitPerPage,
+ });
+
+ const formattedData: CardPropertyData[] = dataQuery.docs.map((item) => {
+ return {
+ slug: item.slug ?? "",
+ title: item.name,
+ price: item.base_price,
+ area: item.aboutGroup.area,
+ propertyType: item.property_type,
+ bathrooms_count: item.aboutGroup.bathrooms_count,
+ bedrooms_count: item.aboutGroup.bedrooms_count,
+ images: item.images.map((img) =>
+ typeof img !== "number" ? { url: img?.url ?? "", alt: img.alt } : { url: "", alt: "" }
+ ),
+ posted_at: formatDate(item.createdAt),
+ };
+ });
+
+ return {
+ ...dataQuery,
+ formattedData,
+ };
+}
+
+export async function fetchPropertyDetail({ slug }: FetchPropertyDetailParams) {
+ const payload = await getPayload({ config: payloadConfig });
+
+ const queryCondition: Where = {
+ _status: { equals: "published" },
+ slug: { equals: slug },
+ };
+
+ const dataQuery = await payload.find({
+ collection: "properties",
+ where: queryCondition,
+ limit: 1,
+ pagination: false,
+ });
+
+ if (!dataQuery?.docs?.[0]) return null;
+
+ const data = dataQuery?.docs?.[0];
+ const postedAt = formatDate(data.createdAt);
+ const images = data.images.map((img) =>
+ typeof img !== "number" ? { url: img?.url ?? "", alt: img.alt } : { url: "", alt: "" }
+ );
+
+ const formattedBasePrice = formatCurrency(data.base_price);
+ let additionalPrice: { name: string; price: string }[] = [];
+ let totalPrice = 0;
+ if (Array.isArray(data.additional_price)) {
+ for (const p of data.additional_price) {
+ additionalPrice.push({
+ name: p.name,
+ price: formatCurrency(p.price),
+ });
+ totalPrice += p.price;
+ }
+ }
+ const formattedTotalPrice = formatCurrency(data.base_price + totalPrice);
+
+ return {
+ data,
+ formattedData: {
+ price: formattedBasePrice,
+ additionalPrice,
+ totalPrice: formattedTotalPrice,
+ images,
+ postedAt,
+ },
+ };
+}