| 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> |
| ); |
| }; |
|
|