| import { useState } from 'react'; |
| import type { HarnessAgent } from '../../types'; |
|
|
| interface DelegateTaskModalProps { |
| agents: HarnessAgent[]; |
| onClose: () => void; |
| onDelegate: (agentId: string, title: string, description: string) => void; |
| } |
|
|
| export default function DelegateTaskModal({ |
| agents, |
| onClose, |
| onDelegate, |
| }: DelegateTaskModalProps) { |
| const [agentId, setAgentId] = useState(agents[0]?.id ?? ''); |
| const [title, setTitle] = useState(''); |
| const [description, setDescription] = useState(''); |
|
|
| const handleSubmit = (e: React.FormEvent) => { |
| e.preventDefault(); |
| if (!title.trim()) return; |
| onDelegate(agentId, title.trim(), description.trim()); |
| }; |
|
|
| return ( |
| <div className="fixed inset-0 z-50 flex items-center justify-center"> |
| <div |
| className="absolute inset-0 bg-ink-black/20 z-0" |
| onClick={onClose} |
| onKeyDown={(e) => { if (e.key === 'Escape') onClose(); }} |
| role="button" |
| tabIndex={-1} |
| aria-label="Close modal" |
| /> |
| <div className="relative z-10 bg-paper-white border border-border-default w-full max-w-lg mx-4 rounded-xl shadow-lg overflow-hidden"> |
| <div className="px-6 py-4 border-b border-border-default"> |
| <h3 className="text-base font-bold text-ink-black"> |
| μμ΄μ νΈμ νμ€ν¬ μμ |
| </h3> |
| </div> |
| |
| <form onSubmit={handleSubmit} className="p-6 space-y-5"> |
| <div> |
| <label |
| htmlFor="agent-select" |
| className="block text-xs font-semibold text-ink-dark mb-1.5" |
| > |
| λμ μμ΄μ νΈ |
| </label> |
| <select |
| id="agent-select" |
| value={agentId} |
| onChange={(e) => setAgentId(e.target.value)} |
| className="w-full border border-border-default bg-paper-white px-3 py-2 text-sm text-ink-black focus:outline-none focus:border-accent-teal" |
| > |
| {agents.map((a) => ( |
| <option key={a.id} value={a.id}> |
| {a.name} |
| </option> |
| ))} |
| </select> |
| </div> |
| |
| <div> |
| <label |
| htmlFor="task-title" |
| className="block text-xs font-semibold text-ink-dark mb-1.5" |
| > |
| νμ€ν¬ μ λͺ© |
| </label> |
| <input |
| id="task-title" |
| type="text" |
| value={title} |
| onChange={(e) => setTitle(e.target.value)} |
| placeholder="μ: (μ£Ό)κ·Έλ¦°μλμ§ 2026-Q2 λ°μ΄ν° κ²μ¦" |
| className="w-full border border-border-default bg-paper-white px-3 py-2 text-sm text-ink-black placeholder:text-ink-light focus:outline-none focus:border-accent-teal" |
| /> |
| </div> |
| |
| <div> |
| <label |
| htmlFor="task-desc" |
| className="block text-xs font-semibold text-ink-dark mb-1.5" |
| > |
| μμΈ μ€λͺ
(μ ν) |
| </label> |
| <textarea |
| id="task-desc" |
| value={description} |
| onChange={(e) => setDescription(e.target.value)} |
| rows={3} |
| placeholder="μμ΄μ νΈμκ² μ λ¬ν μΆκ° μ§μΉ¨μ μ
λ ₯νμΈμ." |
| className="w-full border border-border-default bg-paper-white px-3 py-2 text-sm text-ink-black placeholder:text-ink-light focus:outline-none focus:border-accent-teal resize-none" |
| /> |
| </div> |
| |
| <div className="flex justify-end gap-3 pt-2"> |
| <button |
| type="button" |
| onClick={onClose} |
| className="px-4 py-2 text-sm text-ink-medium border border-border-default rounded-md hover:border-border-strong transition-colors" |
| > |
| μ·¨μ |
| </button> |
| <button |
| type="submit" |
| disabled={!title.trim()} |
| className="px-4 py-2 text-sm font-semibold text-white bg-accent-teal hover:bg-accent-teal/90 rounded-md disabled:opacity-40 disabled:cursor-not-allowed transition-colors" |
| > |
| μμνκΈ° |
| </button> |
| </div> |
| </form> |
| </div> |
| </div> |
| ); |
| } |
|
|