feat: Enable selection of verified agents for CMS featured cards and update user search to filter by verification status.
This commit is contained in:
@@ -223,7 +223,7 @@ export default function CmsPage() {
|
|||||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Agent search with debounce
|
// Agent search with debounce — searches only verified agents
|
||||||
function handleAgentSearch(query: string) {
|
function handleAgentSearch(query: string) {
|
||||||
setAgentSearchQuery(query);
|
setAgentSearchQuery(query);
|
||||||
if (agentSearchTimeout.current) clearTimeout(agentSearchTimeout.current);
|
if (agentSearchTimeout.current) clearTimeout(agentSearchTimeout.current);
|
||||||
@@ -236,7 +236,7 @@ export default function CmsPage() {
|
|||||||
setShowAgentDropdown(true);
|
setShowAgentDropdown(true);
|
||||||
agentSearchTimeout.current = setTimeout(async () => {
|
agentSearchTimeout.current = setTimeout(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await usersService.getUsers({ role: 'AGENT', search: query, limit: 10 });
|
const res = await usersService.getUsers({ role: 'AGENT', search: query, limit: 10, verificationStatus: 'APPROVED' });
|
||||||
setAgentSearchResults(res.users);
|
setAgentSearchResults(res.users);
|
||||||
} catch {
|
} catch {
|
||||||
setAgentSearchResults([]);
|
setAgentSearchResults([]);
|
||||||
@@ -263,6 +263,26 @@ export default function CmsPage() {
|
|||||||
setShowAgentDropdown(false);
|
setShowAgentDropdown(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select agent for Featured Agent Cards (different format)
|
||||||
|
function selectFeaturedAgent(user: User) {
|
||||||
|
const data = editContent as FeaturesContent;
|
||||||
|
if ((data.featuredAgents || []).length >= 3) return;
|
||||||
|
const profile = user.profile;
|
||||||
|
const agent = user.agentProfile;
|
||||||
|
const name = profile ? `${profile.firstName} ${profile.lastName}`.trim() : '';
|
||||||
|
const role = agent?.agentType?.name || agent?.headline || '';
|
||||||
|
const location = profile ? [profile.city, profile.state].filter(Boolean).join(', ') : '';
|
||||||
|
const experience = agent?.yearsOfExperience ? `${agent.yearsOfExperience}+ years in real estate.` : '';
|
||||||
|
const rating = '';
|
||||||
|
const imageUrl = profile?.avatar || '';
|
||||||
|
|
||||||
|
const newAgent: FeaturedAgentItem = { name, role, rating, location, experience, imageUrl };
|
||||||
|
setEditContent({ ...data, featuredAgents: [...(data.featuredAgents || []), newAgent] });
|
||||||
|
setAgentSearchQuery('');
|
||||||
|
setAgentSearchResults([]);
|
||||||
|
setShowAgentDropdown(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
function recordFor(pageSlug: string, sectionKey: string): CmsContentRecord | undefined {
|
function recordFor(pageSlug: string, sectionKey: string): CmsContentRecord | undefined {
|
||||||
const source = pageSlug === 'about' ? aboutRecords : pageSlug === 'faq' ? faqRecords : records;
|
const source = pageSlug === 'about' ? aboutRecords : pageSlug === 'faq' ? faqRecords : records;
|
||||||
@@ -442,6 +462,51 @@ export default function CmsPage() {
|
|||||||
{/* Featured Agents Tab */}
|
{/* Featured Agents Tab */}
|
||||||
{featuresTab === 'agents' && (
|
{featuresTab === 'agents' && (
|
||||||
<div>
|
<div>
|
||||||
|
{/* Search agents from database */}
|
||||||
|
{(data.featuredAgents || []).length < 3 && (
|
||||||
|
<div ref={agentSearchRef} className="relative mb-4">
|
||||||
|
<label className="block text-sm font-medium text-[#00293d] mb-1">Search verified agents from database</label>
|
||||||
|
<div className="relative">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className={inputCls}
|
||||||
|
value={agentSearchQuery}
|
||||||
|
onChange={(e) => handleAgentSearch(e.target.value)}
|
||||||
|
onFocus={() => { if (agentSearchResults.length > 0) setShowAgentDropdown(true); }}
|
||||||
|
placeholder="Search agents by name or email..."
|
||||||
|
/>
|
||||||
|
{isSearchingAgents && (
|
||||||
|
<div className="absolute right-3 top-1/2 -translate-y-1/2">
|
||||||
|
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-[#f5a623]"></div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{showAgentDropdown && agentSearchQuery.length >= 2 && (
|
||||||
|
<div className="absolute z-10 w-full mt-1 bg-white border border-[#e5e7eb] rounded-lg shadow-lg max-h-60 overflow-y-auto">
|
||||||
|
{isSearchingAgents && agentSearchResults.length === 0 ? (
|
||||||
|
<div className="px-4 py-3 text-sm text-[#666666]">Searching...</div>
|
||||||
|
) : agentSearchResults.length === 0 ? (
|
||||||
|
<div className="px-4 py-3 text-sm text-[#666666]">No verified agents found</div>
|
||||||
|
) : (
|
||||||
|
agentSearchResults.map((user) => (
|
||||||
|
<button
|
||||||
|
key={user.id}
|
||||||
|
type="button"
|
||||||
|
onClick={() => selectFeaturedAgent(user)}
|
||||||
|
className="w-full px-4 py-3 text-left hover:bg-[#f9fafb] border-b border-[#e5e7eb] last:border-b-0"
|
||||||
|
>
|
||||||
|
<p className="text-sm font-medium text-[#00293d]">
|
||||||
|
{user.profile ? `${user.profile.firstName} ${user.profile.lastName}`.trim() : user.email}
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-[#666666]">{user.email} {user.agentProfile?.agentType?.name ? `• ${user.agentProfile.agentType.name}` : ''}</p>
|
||||||
|
</button>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
<label className="block text-sm font-medium text-[#00293d]">Featured Agent Cards ({(data.featuredAgents || []).length}/3)</label>
|
<label className="block text-sm font-medium text-[#00293d]">Featured Agent Cards ({(data.featuredAgents || []).length}/3)</label>
|
||||||
{(data.featuredAgents || []).length < 3 && (
|
{(data.featuredAgents || []).length < 3 && (
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ export interface UserFilters {
|
|||||||
role?: string;
|
role?: string;
|
||||||
status?: string;
|
status?: string;
|
||||||
search?: string;
|
search?: string;
|
||||||
|
verificationStatus?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Users Service
|
// Users Service
|
||||||
|
|||||||
Reference in New Issue
Block a user