182 lines
4.5 KiB
TypeScript
182 lines
4.5 KiB
TypeScript
import payloadConfig from "@/payload.config";
|
|
import { CardPropertyData } from "@/schema/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({
|
|
page,
|
|
name = "",
|
|
location,
|
|
min_price,
|
|
max_price,
|
|
min_area,
|
|
max_area,
|
|
property_type,
|
|
}: FetchPropertyParams = {}) {
|
|
const payload = await getPayload({ config: payloadConfig });
|
|
|
|
const queryCondition: Where = {
|
|
_status: { equals: "published" },
|
|
};
|
|
|
|
if (!!property_type) {
|
|
queryCondition["property_type"] = {
|
|
equals: property_type,
|
|
};
|
|
}
|
|
if (!!name) {
|
|
queryCondition["name"] = {
|
|
contains: name,
|
|
};
|
|
}
|
|
if (!!min_price) {
|
|
queryCondition["base_price"] = {
|
|
greater_than_equal: min_price,
|
|
};
|
|
}
|
|
if (!!max_price) {
|
|
queryCondition["base_price"] = {
|
|
less_than_equal: max_price,
|
|
};
|
|
}
|
|
if (!!min_area) {
|
|
queryCondition["aboutGroup.area"] = {
|
|
greater_than_equal: min_area,
|
|
};
|
|
}
|
|
if (!!max_area) {
|
|
queryCondition["aboutGroup.area"] = {
|
|
less_than_equal: max_area,
|
|
};
|
|
}
|
|
if (!!location) {
|
|
queryCondition["addressGroup.state_code"] = {
|
|
equals: location,
|
|
};
|
|
}
|
|
|
|
const dataQuery = await payload.find({
|
|
collection: "properties",
|
|
page,
|
|
pagination: true,
|
|
limit: 10,
|
|
where: queryCondition,
|
|
});
|
|
|
|
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 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);
|
|
const 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,
|
|
},
|
|
};
|
|
}
|