/ app / src / components / InputField.tsx
InputField.tsx
  1  import React, { useState, useEffect, KeyboardEvent } from 'react';
  2  import { useApp } from '../contexts/AppContext';
  3  import { mockAgents } from '../data/mockData';
  4  import './InputField.css';
  5  
  6  const FlameAnimation: React.FC = () => {
  7    const [flames, setFlames] = useState('🔥🔥🔥🔥');
  8  
  9    useEffect(() => {
 10      const interval = setInterval(() => {
 11        const count = 2 + Math.floor(Math.random() * 7);
 12        setFlames('🔥'.repeat(count));
 13      }, 100);
 14  
 15      return () => clearInterval(interval);
 16    }, []);
 17  
 18    return <div className="flame-row">{flames}</div>;
 19  };
 20  
 21  interface AutocompleteProps {
 22    query: string;
 23    onSelect: (agent: string) => void;
 24  }
 25  
 26  const AgentAutocomplete: React.FC<AutocompleteProps> = ({ query, onSelect }) => {
 27    const prefix = query.toLowerCase();
 28    const matches = mockAgents.filter(agent =>
 29      prefix === '' || agent.name.toLowerCase().startsWith(prefix)
 30    ).slice(0, 5);
 31  
 32    if (matches.length === 0) return null;
 33  
 34    return (
 35      <div className="autocomplete-dropdown">
 36        {matches.map(agent => (
 37          <div
 38            key={agent.id}
 39            className="autocomplete-item"
 40            onClick={() => onSelect(agent.name)}
 41          >
 42            <span className="autocomplete-icon">{agent.icon}</span>
 43            <span className="autocomplete-name">{agent.name}</span>
 44            <span className="autocomplete-level" style={{ color: agent.color }}>
 45              [{agent.level}]
 46            </span>
 47          </div>
 48        ))}
 49      </div>
 50    );
 51  };
 52  
 53  export const InputField: React.FC = () => {
 54    const { addMessage, setLoading, loading } = useApp();
 55    const [input, setInput] = useState('');
 56    const [showAutocomplete, setShowAutocomplete] = useState(false);
 57    const [autocompleteQuery, setAutocompleteQuery] = useState('');
 58  
 59    useEffect(() => {
 60      // Check for @ mention
 61      const words = input.split(' ');
 62      const lastWord = words[words.length - 1];
 63  
 64      if (lastWord.startsWith('@')) {
 65        const query = lastWord.substring(1);
 66        setAutocompleteQuery(query);
 67        setShowAutocomplete(true);
 68      } else {
 69        setShowAutocomplete(false);
 70      }
 71    }, [input]);
 72  
 73    const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
 74      if (e.key === 'Enter' && !e.shiftKey) {
 75        e.preventDefault();
 76        handleSend();
 77      }
 78  
 79      if (e.key === 'Tab' && showAutocomplete) {
 80        e.preventDefault();
 81        const words = input.split(' ');
 82        const lastWord = words[words.length - 1];
 83  
 84        if (lastWord.startsWith('@')) {
 85          const query = lastWord.substring(1).toLowerCase();
 86          const match = mockAgents.find(agent =>
 87            query === '' || agent.name.toLowerCase().startsWith(query)
 88          );
 89  
 90          if (match) {
 91            words[words.length - 1] = `@${match.name}`;
 92            setInput(words.join(' ') + ' ');
 93            setShowAutocomplete(false);
 94          }
 95        }
 96      }
 97    };
 98  
 99    const handleSend = () => {
100      if (input.trim() === '' || loading) return;
101  
102      // Add user message
103      addMessage({
104        role: 'user',
105        content: input,
106        timestamp: new Date()
107      });
108  
109      // Simulate AI response
110      setLoading(true);
111      setTimeout(() => {
112        addMessage({
113          role: 'assistant',
114          content: `I've received your message: "${input}". This is a placeholder response from the Kamaji system. In a full implementation, this would be connected to an actual LLM provider.`,
115          agentName: 'Kamaji',
116          timestamp: new Date()
117        });
118        setLoading(false);
119      }, 1500);
120  
121      setInput('');
122      setShowAutocomplete(false);
123    };
124  
125    const handleAutocompleteSelect = (agentName: string) => {
126      const words = input.split(' ');
127      words[words.length - 1] = `@${agentName}`;
128      setInput(words.join(' ') + ' ');
129      setShowAutocomplete(false);
130    };
131  
132    return (
133      <div className="input-field-container">
134        {showAutocomplete && (
135          <AgentAutocomplete
136            query={autocompleteQuery}
137            onSelect={handleAutocompleteSelect}
138          />
139        )}
140  
141        <div className="input-field">
142          <span className="input-flame">🔥</span>
143          <textarea
144            value={input}
145            onChange={(e) => setInput(e.target.value)}
146            onKeyDown={handleKeyDown}
147            placeholder="Speak to the furnace spirit... (type @ for agents)"
148            className="input-textarea"
149            disabled={loading}
150            rows={1}
151          />
152        </div>
153  
154        <FlameAnimation />
155      </div>
156    );
157  };