From b9ac38356c7b6c548830b7674013b61a9baf9408 Mon Sep 17 00:00:00 2001 From: nicktytarenko Date: Wed, 23 Sep 2026 21:54:17 +0300 Subject: [PATCH 1/3] Add Find more experts for existing Expert Finder searches --- .../components/FindMoreExpertsModal.tsx | 129 ++++++++++++++++ .../components/SearchDetailContent.tsx | 145 ++++++++++++++---- .../new/components/ExpertFinderForm.tsx | 12 +- app/expert-finder/library/new/schema.ts | 15 +- hooks/useExpertFinder.ts | 54 +++++++ services/expertFinder.service.ts | 30 ++++ types/expertFinder.ts | 69 +++++++-- 7 files changed, 397 insertions(+), 57 deletions(-) create mode 100644 app/expert-finder/library/[searchId]/components/FindMoreExpertsModal.tsx diff --git a/app/expert-finder/library/[searchId]/components/FindMoreExpertsModal.tsx b/app/expert-finder/library/[searchId]/components/FindMoreExpertsModal.tsx new file mode 100644 index 000000000..508271b00 --- /dev/null +++ b/app/expert-finder/library/[searchId]/components/FindMoreExpertsModal.tsx @@ -0,0 +1,129 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { ChevronDown } from 'lucide-react'; +import { BaseModal } from '@/components/ui/BaseModal'; +import { Alert } from '@/components/ui/Alert'; +import { Button } from '@/components/ui/Button'; +import { Dropdown, DropdownItem } from '@/components/ui/form/Dropdown'; +import { Textarea } from '@/components/ui/form/Textarea'; +import { LoadingButton } from '@/components/ui/LoadingButton'; +import { cn } from '@/utils/styles'; +import { + EXPERT_COUNT_OPTIONS, + EXPERT_SEARCH_ADDITIONAL_CONTEXT_MAX_LENGTH, + type ExpertCountOption, + type FindMoreExpertsPayload, +} from '@/services/expertFinder.service'; + +export interface FindMoreExpertsModalProps { + isOpen: boolean; + onClose: () => void; + initialAdditionalContext: string; + isSubmitting: boolean; + error: string | null; + onSubmit: (payload: FindMoreExpertsPayload) => Promise; +} + +const INITIAL_EXPERT_COUNT: ExpertCountOption = 10; + +export function FindMoreExpertsModal({ + isOpen, + onClose, + initialAdditionalContext, + isSubmitting, + error, + onSubmit, +}: Readonly) { + const [expertCount, setExpertCount] = useState(INITIAL_EXPERT_COUNT); + const [additionalContext, setAdditionalContext] = useState(initialAdditionalContext); + const [countOpen, setCountOpen] = useState(false); + + useEffect(() => { + if (!isOpen) return; + setExpertCount(INITIAL_EXPERT_COUNT); + setAdditionalContext(initialAdditionalContext); + setCountOpen(false); + }, [isOpen, initialAdditionalContext]); + + const handleSubmit = async () => { + const payload: FindMoreExpertsPayload = { expert_count: expertCount }; + if (additionalContext !== initialAdditionalContext) { + payload.additional_context = additionalContext; + } + await onSubmit(payload); + }; + + return ( + +
+

+ Request additional experts for this search. New results are appended; existing experts + stay. +

+ + + {expertCount} + + + } + className="max-h-60 overflow-y-auto py-1" + onOpenChange={setCountOpen} + > +
+ {EXPERT_COUNT_OPTIONS.map((option) => ( + setExpertCount(option)} + className={expertCount === option ? 'bg-primary-50 text-primary-900' : ''} + > + {option} + + ))} +
+
+ +