diff --git a/src/app/(agent)/agent/dashboard/page.tsx b/src/app/(agent)/agent/dashboard/page.tsx index 0a954e6..b6d1046 100644 --- a/src/app/(agent)/agent/dashboard/page.tsx +++ b/src/app/(agent)/agent/dashboard/page.tsx @@ -81,6 +81,8 @@ const defaultProfileCardData: ProfileCardData = { bio: '', expertise: [], serviceAreas: [], + city: null, + state: null, }; // Default availability data when no field values are available @@ -316,7 +318,11 @@ export default function AgentDashboard() { lastName={agentProfile.lastName} isVerified={agentProfile.isVerified} title={agentProfile.agentType?.name || 'Real Estate Agent'} - location={profileCardData.serviceAreas?.[0] || (agentProfile as unknown as { city?: string }).city || 'United States'} + location={ + profileCardData.city && profileCardData.state + ? `${profileCardData.city}, ${profileCardData.state}` + : profileCardData.city || profileCardData.state || profileCardData.serviceAreas?.[0] || 'United States' + } memberSince={formatMemberSince((agentProfile as unknown as { createdAt?: string }).createdAt)} bio={profileCardData.bio || agentProfile.bio || ''} expertise={profileCardData.expertise} diff --git a/src/app/(user)/user/profiles/page.tsx b/src/app/(user)/user/profiles/page.tsx index a2c994e..0a0fee0 100644 --- a/src/app/(user)/user/profiles/page.tsx +++ b/src/app/(user)/user/profiles/page.tsx @@ -101,22 +101,63 @@ function ProfileCard({ profile }: ProfileCardProps) { } }; - // Get location string - prefer city/state/country over serviceAreas + // Get location string - check dynamic field values first, then fallback to legacy columns const getLocation = () => { - if (profile.city && profile.state) { - return `${profile.city}, ${profile.state}`; + let cityValue: string | null = null; + let stateValue: string | null = null; + + // Helper to format snake_case to Title Case + const formatValue = (v: string) => v.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(' '); + + // First, check fieldValues for state and city (dynamic profile fields) + if (profile.fieldValues && profile.fieldValues.length > 0) { + const stateField = profile.fieldValues.find(fv => fv.field.slug === 'state'); + const cityField = profile.fieldValues.find(fv => fv.field.slug === 'city'); + + if (stateField && stateField.jsonValue) { + const value = stateField.jsonValue; + if (Array.isArray(value) && value.length > 0) { + // For multiselect, join all selected values + stateValue = value.map(v => formatValue(String(v))).join(', '); + } else if (typeof value === 'string' && value.trim()) { + stateValue = formatValue(value); + } + } + + if (cityField && cityField.jsonValue) { + const value = cityField.jsonValue; + if (Array.isArray(value) && value.length > 0) { + // For multiselect, join all selected values + cityValue = value.map(v => formatValue(String(v))).join(', '); + } else if (typeof value === 'string' && value.trim()) { + cityValue = formatValue(value); + } + } } - if (profile.city && profile.country) { - return `${profile.city}, ${profile.country}`; + + // Fallback to legacy profile columns if dynamic fields not found + if (!cityValue && profile.city) { + cityValue = profile.city; } - if (profile.state && profile.country) { - return `${profile.state}, ${profile.country}`; + if (!stateValue && profile.state) { + stateValue = profile.state; } - if (profile.city) { - return profile.city; + + // Build location string + if (cityValue && stateValue) { + return `${cityValue}, ${stateValue}`; } - if (profile.state) { - return profile.state; + if (cityValue && profile.country) { + return `${cityValue}, ${profile.country}`; + } + if (stateValue && profile.country) { + return `${stateValue}, ${profile.country}`; + } + if (cityValue) { + return cityValue; + } + if (stateValue) { + return stateValue; } if (profile.country) { return profile.country; @@ -131,9 +172,17 @@ function ProfileCard({ profile }: ProfileCardProps) { const getExpertiseTags = (): string[] => { const tags: string[] = []; + // Fields to exclude from tags (they're displayed elsewhere, e.g., state/city shown in location) + const excludedFieldSlugs = ['state', 'city', 'description']; + // Add from fieldValues (dynamic profile fields like client_specialization, property_type, loan_type) if (profile.fieldValues && profile.fieldValues.length > 0) { profile.fieldValues.forEach((fv) => { + // Skip excluded fields + if (excludedFieldSlugs.includes(fv.field.slug)) { + return; + } + const value = fv.jsonValue; if (Array.isArray(value)) { // For multi-select fields, add all selected values diff --git a/src/utils/profileDataMapper.ts b/src/utils/profileDataMapper.ts index 8521c83..b57a5c3 100644 --- a/src/utils/profileDataMapper.ts +++ b/src/utils/profileDataMapper.ts @@ -130,6 +130,8 @@ export interface ProfileCardData { bio: string; expertise: string[]; serviceAreas: string[]; + city: string | null; + state: string | null; } // Dynamic field data structure for SpecializationSection component @@ -206,7 +208,31 @@ export function mapFieldValuesToAvailability(fieldValues: FieldValueResponse[]): } /** - * Maps field values to profile card data (bio, expertise, service areas) + * Helper to format snake_case values to Title Case + */ +function formatSnakeCaseToTitleCase(value: string): string { + return value + .split('_') + .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(' '); +} + +/** + * Extract all values from a field that may be an array (multiselect) or string + * Returns formatted values joined by comma, or null if empty + */ +function extractAllValues(value: unknown): string | null { + if (Array.isArray(value) && value.length > 0) { + return value.map(v => formatSnakeCaseToTitleCase(String(v))).join(', '); + } + if (typeof value === 'string' && value.trim()) { + return formatSnakeCaseToTitleCase(value); + } + return null; +} + +/** + * Maps field values to profile card data (bio, expertise, service areas, location) */ export function mapFieldValuesToProfileCard(fieldValues: FieldValueResponse[]): ProfileCardData { // Get bio/description from various possible fields @@ -226,10 +252,16 @@ export function mapFieldValuesToProfileCard(fieldValues: FieldValueResponse[]): const licensedAreas = getFieldValue(fieldValues, 'licensed_areas') as string[] | undefined; const coverageAreas = getFieldValue(fieldValues, 'coverage_areas') as string[] | undefined; + // Get city and state from dynamic fields (multiselect fields) + const cityValue = getFieldValue(fieldValues, 'city'); + const stateValue = getFieldValue(fieldValues, 'state'); + return { bio: description || descrption || biography || bio || '', expertise: aboutMeExpertise || expertiseAreas || specializations || areasOfExpertise || [], serviceAreas: serviceAreas || licensedAreas || coverageAreas || [], + city: extractAllValues(cityValue), + state: extractAllValues(stateValue), }; }