Merge pull request 'fix: properties feature, add InputState and InputCity payload custom components' (#10) from dev into main

Reviewed-on: #10
This commit is contained in:
RizqiSyahrendra 2025-04-23 15:48:42 +00:00
commit 8da6335543
7 changed files with 79 additions and 49 deletions

View File

@ -9,6 +9,7 @@ import FilterProperty from "@/components/properties/FilterProperty";
import { getDefaultMetadata } from "@/utils/metadata";
import { sanitizeBlogContentIntoStringPreview } from "@/utils/sanitize";
import { Metadata } from "next";
import { State } from "country-state-city";
export async function generateMetadata(props: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const metadata = await getDefaultMetadata();
@ -67,6 +68,9 @@ export default async function PropertyDetail({ params }: { params: Promise<{ slu
if (!propertyDetail) return notFound();
const { data, formattedData } = propertyDetail;
const stateName = !!data?.addressGroup.state_code
? State.getStateByCodeAndCountry(data.addressGroup.state_code, "US")?.name
: "";
const isEmbedMapUrlValid = !!data?.embed_map_url && data.embed_map_url.includes("www.google.com/maps/embed");
const headersList = await headers();
const fullUrl = headersList.get("x-full-url");
@ -207,8 +211,8 @@ export default async function PropertyDetail({ params }: { params: Promise<{ slu
<dd>{data?.addressGroup?.address ?? ""}</dd>
</dl>
<dl className="list-terms-inline">
<dt>State/County:</dt>
<dd>{data?.addressGroup?.state_code ?? ""}</dd>
<dt>State:</dt>
<dd>{stateName}</dd>
</dl>
<dl className="list-terms-inline">
<dt>City:</dt>

View File

@ -21,6 +21,8 @@ import { StrikethroughFeatureClient as StrikethroughFeatureClient_e70f5e05f09f93
import { UnderlineFeatureClient as UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { BoldFeatureClient as BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { ItalicFeatureClient as ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
import { default as default_4ee76229d13ecca9be829e8a71d2a59d } from '../../../components/payload-custom/InputState'
import { default as default_d6f7a60d9f647737f677c5b38081a35f } from '../../../components/payload-custom/InputCity'
import { default as default_aa89fa9464216e16b81a3e716c94a23a } from '../../../components/LogoAdmin'
import { S3ClientUploadHandler as S3ClientUploadHandler_f97aa6c64367fa259c5bc0567239ef24 } from '@payloadcms/storage-s3/client'
@ -48,6 +50,8 @@ export const importMap = {
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
"/components/payload-custom/InputState#default": default_4ee76229d13ecca9be829e8a71d2a59d,
"/components/payload-custom/InputCity#default": default_d6f7a60d9f647737f677c5b38081a35f,
"/components/LogoAdmin#default": default_aa89fa9464216e16b81a3e716c94a23a,
"@payloadcms/storage-s3/client#S3ClientUploadHandler": S3ClientUploadHandler_f97aa6c64367fa259c5bc0567239ef24
}

View File

@ -81,18 +81,25 @@ export const Properties: CollectionConfig = {
name: "state_code",
label: "State",
type: "text",
// admin: {
// components: {
// Field: {
// path: "/components/payload-custom/InputCountry",
// },
// },
// },
admin: {
components: {
Field: {
path: "/components/payload-custom/InputState",
},
},
},
},
{
name: "city_code",
label: "City",
type: "text",
admin: {
components: {
Field: {
path: "/components/payload-custom/InputCity",
},
},
},
},
{
name: "zip_code",

View File

@ -0,0 +1,34 @@
"use client";
import type { SelectFieldClientComponent } from "payload";
import { SelectField, useField, useFormFields } from "@payloadcms/ui";
import { City } from "country-state-city";
import { useEffect } from "react";
const InputCity: SelectFieldClientComponent = ({ field, ...props }) => {
const stateCode = useFormFields(([fields]) => fields["addressGroup.state_code"]);
const { setValue } = useField();
useEffect(() => {
if (!stateCode?.value) {
setValue("");
}
}, [stateCode?.value]);
if (!stateCode?.value) {
// @ts-ignore
field.admin = { ...field.admin, description: "Please select the state before select the city." };
field.options = [];
} else {
// @ts-ignore
field.admin = { ...field.admin, description: "" };
field.options = City.getCitiesOfState("US", stateCode.value as string).map((c) => ({
value: c.name,
label: c.name,
}));
}
return <SelectField field={field} {...props} />;
};
export default InputCity;

View File

@ -1,37 +0,0 @@
"use client";
import React from "react";
import { useField } from "@payloadcms/ui";
import { TextFieldClientComponent } from "payload";
const InputCountry: TextFieldClientComponent = ({ path, field }) => {
const { value, setValue } = useField({ path });
const { showError } = useField();
return (
<div className={`field-type select ${showError ? "has-error" : ""}`}>
{/* @ts-ignore */}
<span>jancok</span>
{/* <label htmlFor={field.name} required={field.required}></label> */}
<div className="select-input-wrapper">
<select
name={field.name}
// @ts-ignore
value={value}
onChange={(e) => setValue(e.target.value)}
disabled={field.admin?.readOnly}
>
<option value="">-- Select --</option>
{/* {field.map((opt) => (
<option key={opt.value} value={opt.value}>
{opt.label}
</option>
))} */}
</select>
</div>
{/* {field.admin && <FieldDescription value={admin.description} />}
{showError && <Error message={errorMessage} />} */}
</div>
);
};
export default InputCountry;

View File

@ -0,0 +1,14 @@
"use client";
import type { SelectFieldClientComponent } from "payload";
import { SelectField } from "@payloadcms/ui";
import React from "react";
import { State } from "country-state-city";
const InputState: SelectFieldClientComponent = ({ field, ...props }) => {
const statesData = State.getStatesOfCountry("US").map((st) => ({ value: st.isoCode, label: st.name }));
field.options = statesData;
return <SelectField field={field} {...props} />;
};
export default InputState;

View File

@ -10,7 +10,10 @@ type FilterPropertyProps = {
};
export default function FilterProperty({ propertyType, searchParams }: FilterPropertyProps) {
const statesData = State.getStatesOfCountry("US").map((st) => ({ value: st.name, label: st.name }));
const statesData = State.getStatesOfCountry("US").map((st) => ({ value: st.isoCode, label: st.name }));
const selectedStateName = !!searchParams?.location
? State.getStateByCodeAndCountry(searchParams.location, "US")?.name
: "";
return (
<>
@ -25,8 +28,9 @@ export default function FilterProperty({ propertyType, searchParams }: FilterPro
name="location"
placeholder="Choose Location"
options={statesData}
defaultInputValue={searchParams?.location}
defaultValue={searchParams?.location}
defaultValue={
!!searchParams?.location ? { value: searchParams?.location, label: selectedStateName } : undefined
}
isSearchable
isClearable
/>