Spaces:
Running
Running
| import { useState } from 'react' | |
| import { Lock, Unlock, FileText, Image, Music, Video, Loader2 } from 'lucide-react' | |
| const fileIcons = { | |
| text: FileText, | |
| image: Image, | |
| audio: Music, | |
| video: Video | |
| } | |
| export default function SecureProcessor({ selectedAgent }) { | |
| const [inputData, setInputData] = useState('') | |
| const [file, setFile] = useState(null) | |
| const [processing, setProcessing] = useState(false) | |
| const [result, setResult] = useState(null) | |
| const [operation, setOperation] = useState('analyze') | |
| const handleProcess = async () => { | |
| if (!selectedAgent || (!inputData && !file)) { | |
| alert('Please select an agent and provide input data') | |
| return | |
| } | |
| setProcessing(true) | |
| try { | |
| const formData = new FormData() | |
| const data = file || { content: inputData, timestamp: new Date().toISOString() } | |
| const response = await fetch('/api/secure-process', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| data, | |
| operation, | |
| agentId: selectedAgent.id | |
| }) | |
| }) | |
| const result = await response.json() | |
| if (result.success) { | |
| setResult(result) | |
| } else { | |
| throw new Error(result.message) | |
| } | |
| } catch (error) { | |
| console.error('Processing failed:', error) | |
| alert('Secure processing failed. Check console for details.') | |
| } finally { | |
| setProcessing(false) | |
| } | |
| } | |
| const handleFileUpload = (e) => { | |
| const uploadedFile = e.target.files[0] | |
| if (uploadedFile) { | |
| setFile({ | |
| name: uploadedFile.name, | |
| type: uploadedFile.type, | |
| size: uploadedFile.size, | |
| lastModified: new Date(uploadedFile.lastModified).toISOString() | |
| }) | |
| } | |
| } | |
| const Icon = fileIcons[selectedAgent?.type?.split(' ')[0].toLowerCase()] || Lock | |
| return ( | |
| <div className="card"> | |
| <h2 className="text-2xl font-bold mb-6 flex items-center"> | |
| <Lock className="mr-2 h-6 w-6 text-primary-500" /> | |
| Secure Processing | |
| </h2> | |
| {selectedAgent && ( | |
| <div className="mb-6 p-4 bg-primary-50 dark:bg-primary-900/20 rounded-lg"> | |
| <p className="text-sm text-primary-700 dark:text-primary-300"> | |
| Selected Agent: <span className="font-semibold">{selectedAgent.name}</span> | |
| </p> | |
| </div> | |
| )} | |
| <div className="space-y-6"> | |
| <div> | |
| <label className="block text-sm font-medium mb-2">Operation Type</label> | |
| <select | |
| value={operation} | |
| onChange={(e) => setOperation(e.target.value)} | |
| className="input-field" | |
| > | |
| <option value="analyze">Analyze</option> | |
| <option value="encrypt">Encrypt</option> | |
| <option value="sanitize">Sanitize</option> | |
| <option value="process">Process</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label className="block text-sm font-medium mb-2">Input Text</label> | |
| <textarea | |
| value={inputData} | |
| onChange={(e) => setInputData(e.target.value)} | |
| placeholder="Enter text to process securely..." | |
| className="input-field min-h-[120px]" | |
| rows={4} | |
| /> | |
| </div> | |
| <div> | |
| <label className="block text-sm font-medium mb-2">Or Upload File</label> | |
| <div className="border-2 border-dashed border-dark-300 dark:border-dark-600 rounded-lg p-6 text-center hover:border-primary-500 transition-colors duration-200"> | |
| <input | |
| type="file" | |
| onChange={handleFileUpload} | |
| className="hidden" | |
| id="file-upload" | |
| accept="image/*,audio/*,video/*,text/*,.pdf,.doc,.docx" | |
| /> | |
| <label htmlFor="file-upload" className="cursor-pointer"> | |
| <Icon className="h-8 w-8 mx-auto mb-2 text-dark-400 dark:text-dark-500" /> | |
| <p className="text-sm text-dark-600 dark:text-dark-400"> | |
| {file ? file.name : 'Click to upload or drag and drop'} | |
| </p> | |
| <p className="text-xs text-dark-500 dark:text-dark-500 mt-1"> | |
| Supports images, audio, video, and documents | |
| </p> | |
| </label> | |
| </div> | |
| </div> | |
| <button | |
| onClick={handleProcess} | |
| disabled={processing || !selectedAgent} | |
| className="btn-primary w-full flex items-center justify-center space-x-2 disabled:opacity-50 disabled:cursor-not-allowed" | |
| > | |
| {processing ? ( | |
| <> | |
| <Loader2 className="h-4 w-4 animate-spin" /> | |
| <span>Processing...</span> | |
| </> | |
| ) : ( | |
| <> | |
| <Lock className="h-4 w-4" /> | |
| <span>Process Securely</span> | |
| </> | |
| )} | |
| </button> | |
| {result && ( | |
| <div className="mt-6 p-4 bg-dark-50 dark:bg-dark-800 rounded-lg border border-dark-200 dark:border-dark-700"> | |
| <h3 className="font-semibold mb-3 flex items-center"> | |
| <Unlock className="h-4 w-4 mr-2 text-green-500" /> | |
| Processing Result | |
| </h3> | |
| <div className="space-y-2 text-sm"> | |
| <div className="flex justify-between"> | |
| <span className="text-dark-600 dark:text-dark-400">Status:</span> | |
| <span className="font-medium text-green-600 dark:text-green-400">Success</span> | |
| </div> | |
| <div className="flex justify-between"> | |
| <span className="text-dark-600 dark:text-dark-400">Security Hash:</span> | |
| <span className="font-mono text-xs">{result.security.hash.slice(0, 16)}...</span> | |
| </div> | |
| <div className="flex justify-between"> | |
| <span className="text-dark-600 dark:text-dark-400">Encryption:</span> | |
| <span className="font-medium">{result.security.encryption}</span> | |
| </div> | |
| {result.data.analysis && ( | |
| <div className="mt-3 p-3 bg-white dark:bg-dark-900 rounded border border-dark-200 dark:border-dark-700"> | |
| <p className="font-medium mb-1">Analysis:</p> | |
| <p className="text-xs">Sentiment: {result.data.analysis.sentiment}</p> | |
| <p className="text-xs">Confidence: {result.data.analysis.confidence}%</p> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ) | |
| } |