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,
},
};
}