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);
|
||||
}, []);
|
||||
|
||||
// Agent search with debounce
|
||||
// Agent search with debounce — searches only verified agents
|
||||
function handleAgentSearch(query: string) {
|
||||
setAgentSearchQuery(query);
|
||||
if (agentSearchTimeout.current) clearTimeout(agentSearchTimeout.current);
|
||||
@@ -236,7 +236,7 @@ export default function CmsPage() {
|
||||
setShowAgentDropdown(true);
|
||||
agentSearchTimeout.current = setTimeout(async () => {
|
||||
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);
|
||||
} catch {
|
||||
setAgentSearchResults([]);
|
||||
@@ -263,6 +263,26 @@ export default function CmsPage() {
|
||||
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
|
||||
function recordFor(pageSlug: string, sectionKey: string): CmsContentRecord | undefined {
|
||||
const source = pageSlug === 'about' ? aboutRecords : pageSlug === 'faq' ? faqRecords : records;
|
||||
@@ -442,6 +462,51 @@ export default function CmsPage() {
|
||||
{/* Featured Agents Tab */}
|
||||
{featuresTab === 'agents' && (
|
||||
<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">
|
||||
<label className="block text-sm font-medium text-[#00293d]">Featured Agent Cards ({(data.featuredAgents || []).length}/3)</label>
|
||||
{(data.featuredAgents || []).length < 3 && (
|
||||
|
||||
Reference in New Issue
Block a user