| 30 | const MAX_CHARS = 100 //TODO: move to const folder |
| 31 | |
| 32 | const AiPromptDialog: React.FC<AiDialogProps> = ({ |
| 33 | isOpen, |
| 34 | onClose, |
| 35 | onSubmit, |
| 36 | isLoading, |
| 37 | title, |
| 38 | placeholder, |
| 39 | }) => { |
| 40 | const { t } = useTranslation() |
| 41 | const [prompt, setPrompt] = useState<string>('') |
| 42 | const closeButtonRef = useRef<HTMLButtonElement>(null) |
| 43 | const { data } = useQuery<AIUsageQuota>({ |
| 44 | queryKey: ['usageQuota'], |
| 45 | queryFn: UsersService.getMyAiUsageQuota, |
| 46 | enabled: isOpen, |
| 47 | }) |
| 48 | const usageQuota: AIUsageQuota = data || { |
| 49 | max_usage_allowed: 0, |
| 50 | usage_count: 0, |
| 51 | reset_date: new Date().toLocaleDateString(), |
| 52 | } |
| 53 | |
| 54 | const handleSubmit = () => { |
| 55 | if (!prompt.trim() || isLoading) return |
| 56 | onSubmit(prompt) |
| 57 | setPrompt('') |
| 58 | } |
| 59 | |
| 60 | const handleOpenChange = (detail: OpenChangeDetails) => { |
| 61 | if (!detail.open) { |
| 62 | onClose() |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | const handleKeyDown = (event: { key: string; preventDefault: () => void }) => { |
| 67 | if (event.key === 'Enter' && !isLoading) { |
| 68 | event.preventDefault() |
| 69 | handleSubmit() |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | if (!isOpen && prompt !== '') { |
| 74 | setPrompt('') |
| 75 | } |
| 76 | |
| 77 | return ( |
| 78 | <DialogRoot |
| 79 | key="ai-dialog" |
| 80 | placement="center" |
| 81 | motionPreset="slide-in-bottom" |
| 82 | open={isOpen} |
| 83 | onOpenChange={handleOpenChange} |
| 84 | > |
| 85 | <DialogContent bg="bg.50"> |
| 86 | <DialogHeader> |
| 87 | <DialogTitle color="fg.DEFAULT">{title}</DialogTitle> |
| 88 | </DialogHeader> |
| 89 | <DialogBody> |