mirror of
https://git.coastit.co.za/caitlin/CRM_ENVR.git
synced 2026-07-12 12:07:06 +02:00
Merge origin/main into main
This commit is contained in:
@@ -48,7 +48,12 @@ interface AIChatProps {
|
||||
}
|
||||
|
||||
|
||||
export const AIChat = forwardRef<{ fillInput: (text: string) => void }, AIChatProps>(({ onMessageSent }, ref) => {
|
||||
export interface AIChatHandle {
|
||||
fillInput: (text: string) => void
|
||||
addAssistantMessage: (content: string) => void
|
||||
}
|
||||
|
||||
export const AIChat = forwardRef<AIChatHandle, AIChatProps>(({ onMessageSent }, ref) => {
|
||||
const [messages, setMessages] = useState<ChatMessage[]>([])
|
||||
const [input, setInput] = useState("")
|
||||
const [loading, setLoading] = useState(false)
|
||||
@@ -66,6 +71,17 @@ export const AIChat = forwardRef<{ fillInput: (text: string) => void }, AIChatPr
|
||||
setInput(text)
|
||||
setTimeout(() => textareaRef.current?.focus(), 50)
|
||||
},
|
||||
addAssistantMessage(content: string) {
|
||||
setMessages((prev) => {
|
||||
if (!prev.some((m) => m.role === "user")) {
|
||||
return [
|
||||
{ role: "user", content: "Search Facebook" },
|
||||
{ role: "assistant", content },
|
||||
]
|
||||
}
|
||||
return [...prev, { role: "assistant", content }]
|
||||
})
|
||||
},
|
||||
}), [])
|
||||
|
||||
const handleGifSelect = useCallback((gif: { url: string; previewUrl: string; title: string }) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import { useState, useEffect } from "react"
|
||||
import { Briefcase, ChevronDown, Loader2 } from "lucide-react"
|
||||
import { Briefcase, ChevronDown, Loader2, Search } from "lucide-react"
|
||||
|
||||
interface Job {
|
||||
job_title: string
|
||||
@@ -12,9 +12,11 @@ interface Job {
|
||||
|
||||
interface JobSelectorProps {
|
||||
onSelect: (job: Job | null) => void
|
||||
onSearch?: (job: Job) => void
|
||||
searching?: boolean
|
||||
}
|
||||
|
||||
export function JobSelector({ onSelect }: JobSelectorProps) {
|
||||
export function JobSelector({ onSelect, onSearch, searching }: JobSelectorProps) {
|
||||
const [jobs, setJobs] = useState<Job[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [open, setOpen] = useState(false)
|
||||
@@ -41,7 +43,7 @@ export function JobSelector({ onSelect }: JobSelectorProps) {
|
||||
onClick={() => setOpen(!open)}
|
||||
className="w-full flex items-center gap-2.5 bg-card/50 border border-border hover:border-primary/20 rounded-xl px-4 py-3 text-sm text-muted-foreground hover:text-foreground transition-all duration-200"
|
||||
>
|
||||
<Briefcase className="h-4 w-4 text-primary flex-none" />
|
||||
<Briefcase className="h-4 w-4 text-[#f97316] flex-none" />
|
||||
<span className="flex-1 text-left truncate">
|
||||
{selected ? selected.job_title : loading ? "Loading jobs..." : "Select a job category"}
|
||||
</span>
|
||||
@@ -69,6 +71,17 @@ export function JobSelector({ onSelect }: JobSelectorProps) {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{selected && onSearch && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onSearch(selected)}
|
||||
disabled={searching}
|
||||
className="w-full flex items-center justify-center gap-2 mt-3 bg-gradient-to-r from-[#f97316] to-[#ea580c] hover:from-[#ea580c] hover:to-[#dc2626] disabled:opacity-50 disabled:cursor-not-allowed text-white text-sm font-semibold rounded-xl px-4 py-3 transition-all duration-200 shadow-lg shadow-[#f97316]/20"
|
||||
>
|
||||
{searching ? <Loader2 className="h-4 w-4 animate-spin" /> : <Search className="h-4 w-4" />}
|
||||
{searching ? "Searching..." : "Search Facebook"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user