jan/web/screens/HubScreen2/components/HeaderModal.tsx
2024-08-05 14:31:31 +07:00

151 lines
4.5 KiB
TypeScript

import { Fragment, useCallback, useEffect, useRef, useState } from 'react'
import Image from 'next/image'
import { Button, Select } from '@janhq/joi'
import { ChevronsLeftRight, Copy, ExternalLink } from 'lucide-react'
import { twMerge } from 'tailwind-merge'
import DropdownModal from './DropdownModal'
type Props = {
name: string
modelHandle?: string
availableModels: string[]
onActionClick: () => void
isLocalModel?: boolean
}
const HeaderModal: React.FC<Props> = ({
name,
modelHandle,
availableModels,
onActionClick,
isLocalModel = false,
}) => {
const [options, setOptions] = useState<{ name: string; value: string }[]>([])
const [selectedVariant, setSelectedVariant] = useState<string | undefined>()
const textRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const isFromCortexHub = modelHandle?.includes('cortexso') ?? false
if (!isLocalModel) {
setOptions(
availableModels.map((variant) => ({
name: variant,
value: variant,
}))
)
if (availableModels.length > 0) {
setSelectedVariant(availableModels[0])
}
return
}
if (isLocalModel && !isFromCortexHub) {
setOptions([
{
name: modelHandle ?? '',
value: modelHandle ?? '',
},
])
setSelectedVariant(modelHandle)
return
}
setOptions(
availableModels.map((variant) => ({
name: `${name}:${variant}`,
value: `${name}:${variant}`,
}))
)
if (availableModels.length > 0) {
setSelectedVariant(`${name}:${availableModels[0]}`)
}
}, [availableModels, name, modelHandle, isLocalModel])
const onCopyClicked = useCallback(() => {
navigator.clipboard.writeText(textRef.current?.innerText ?? '')
}, [])
const title = name.charAt(0).toUpperCase() + name.slice(1)
if (!selectedVariant) return null
return (
<div className="flex items-center">
<span className="text-xl font-semibold leading-8">{title}</span>
<DropdownModal
className="z-[500] min-w-[320px] rounded-lg border border-[hsla(var(--app-border))] bg-[hsla(var(--app-bg))] p-3 shadow-dropDown"
trigger={
<div
className={twMerge(
'ml-auto mr-3 flex h-8 cursor-pointer items-center gap-1.5 rounded-md border border-[hsla(var(--app-border))] px-4 py-2',
isLocalModel && 'mr-6'
)}
>
<Image
width={22.5}
height={16}
src="icons/ic_cortex.svg"
alt="Cortex icon"
/>
<span className="text-[16.2px] font-bold leading-[9px]">
Cortex
</span>
<ChevronsLeftRight
size={16}
className="text-[hsla(var(--text-primary))]"
/>
</div>
}
content={
<Fragment>
<Select
value={selectedVariant}
className="z-[999] h-8 w-full gap-1 px-2"
options={options}
onValueChange={(value) => setSelectedVariant(value)}
/>
<div className="mt-3 flex w-full items-center gap-1 font-medium text-[var(--text-primary)]">
<div
ref={textRef}
className="line-clamp-1 flex-1 whitespace-nowrap rounded-md border border-[hsla(var(--app-border))] bg-[hsla(var(--disabled-bg))] p-2 leading-[16.71px]"
>
cortex run {selectedVariant}
</div>
<button
onClick={onCopyClicked}
className="flex h-8 w-8 items-center justify-center rounded-md border border-[hsla(var(--app-border))] bg-[hsla(var())]"
>
<Copy size={16} />
</button>
</div>
<a
rel="noopener noreferrer"
className="mt-4 flex items-center gap-1 text-xs text-[hsla(var(--app-link))] no-underline"
href="https://cortex.so/docs/quickstart"
target="_blank_"
>
Cortex Quickstart Guide
<ExternalLink size={12} />
</a>
</Fragment>
}
/>
{isLocalModel ? null : (
<Button
data-testid="btn-setup"
theme="ghost"
onClick={onActionClick}
className="mr-6 bg-[hsla(var(--secondary-bg))] px-4 py-2"
>
<span className="text-sm font-semibold">Set Up</span>
</Button>
)}
</div>
)
}
export default HeaderModal