Spaces:
Paused
Paused
| import { FC, KeyboardEvent, useEffect, useRef, useState } from 'react'; | |
| import { Prompt } from '@/types/prompt'; | |
| interface Props { | |
| prompt: Prompt; | |
| variables: string[]; | |
| onSubmit: (updatedVariables: string[]) => void; | |
| onClose: () => void; | |
| } | |
| export const VariableModal: FC<Props> = ({ | |
| prompt, | |
| variables, | |
| onSubmit, | |
| onClose, | |
| }) => { | |
| const [updatedVariables, setUpdatedVariables] = useState< | |
| { key: string; value: string }[] | |
| >( | |
| variables | |
| .map((variable) => ({ key: variable, value: '' })) | |
| .filter( | |
| (item, index, array) => | |
| array.findIndex((t) => t.key === item.key) === index, | |
| ), | |
| ); | |
| const modalRef = useRef<HTMLDivElement>(null); | |
| const nameInputRef = useRef<HTMLTextAreaElement>(null); | |
| const handleChange = (index: number, value: string) => { | |
| setUpdatedVariables((prev) => { | |
| const updated = [...prev]; | |
| updated[index].value = value; | |
| return updated; | |
| }); | |
| }; | |
| const handleSubmit = () => { | |
| if (updatedVariables.some((variable) => variable.value === '')) { | |
| alert('Please fill out all variables'); | |
| return; | |
| } | |
| onSubmit(updatedVariables.map((variable) => variable.value)); | |
| onClose(); | |
| }; | |
| const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => { | |
| if (e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| handleSubmit(); | |
| } else if (e.key === 'Escape') { | |
| onClose(); | |
| } | |
| }; | |
| useEffect(() => { | |
| const handleOutsideClick = (e: MouseEvent) => { | |
| if (modalRef.current && !modalRef.current.contains(e.target as Node)) { | |
| onClose(); | |
| } | |
| }; | |
| window.addEventListener('click', handleOutsideClick); | |
| return () => { | |
| window.removeEventListener('click', handleOutsideClick); | |
| }; | |
| }, [onClose]); | |
| useEffect(() => { | |
| if (nameInputRef.current) { | |
| nameInputRef.current.focus(); | |
| } | |
| }, []); | |
| return ( | |
| <div | |
| className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50" | |
| onKeyDown={handleKeyDown} | |
| > | |
| <div | |
| ref={modalRef} | |
| className="dark:border-netural-400 inline-block max-h-[400px] transform overflow-y-auto rounded-lg border border-gray-300 bg-white px-4 pt-5 pb-4 text-left align-bottom shadow-xl transition-all dark:bg-[#202123] sm:my-8 sm:max-h-[600px] sm:w-full sm:max-w-lg sm:p-6 sm:align-middle" | |
| role="dialog" | |
| > | |
| <div className="mb-4 text-xl font-bold text-black dark:text-neutral-200"> | |
| {prompt.name} | |
| </div> | |
| <div className="mb-4 text-sm italic text-black dark:text-neutral-200"> | |
| {prompt.description} | |
| </div> | |
| {updatedVariables.map((variable, index) => ( | |
| <div className="mb-4" key={index}> | |
| <div className="mb-2 text-sm font-bold text-neutral-200"> | |
| {variable.key} | |
| </div> | |
| <textarea | |
| ref={index === 0 ? nameInputRef : undefined} | |
| className="mt-1 w-full rounded-lg border border-neutral-500 px-4 py-2 text-neutral-900 shadow focus:outline-none dark:border-neutral-800 dark:border-opacity-50 dark:bg-[#40414F] dark:text-neutral-100" | |
| style={{ resize: 'none' }} | |
| placeholder={`Enter a value for ${variable.key}...`} | |
| value={variable.value} | |
| onChange={(e) => handleChange(index, e.target.value)} | |
| rows={3} | |
| /> | |
| </div> | |
| ))} | |
| <button | |
| className="mt-6 w-full rounded-lg border border-neutral-500 px-4 py-2 text-neutral-900 shadow hover:bg-neutral-100 focus:outline-none dark:border-neutral-800 dark:border-opacity-50 dark:bg-white dark:text-black dark:hover:bg-neutral-300" | |
| onClick={handleSubmit} | |
| > | |
| Submit | |
| </button> | |
| </div> | |
| </div> | |
| ); | |
| }; | |