// API Configuration const API_BASE_URL = '/api'; let userPersona = 'explorer'; // Default const chatMessages = document.getElementById('chat-messages'); const userInput = document.getElementById('user-input'); const sendBtn = document.getElementById('send-btn'); const onboardingOverlay = document.getElementById('onboarding-overlay'); const appContainer = document.querySelector('.app-container'); const switchBtn = document.getElementById('switch-btn'); const profileStatus = document.getElementById('profile-status'); const attachBtn = document.getElementById('attach-btn'); const fileUpload = document.getElementById('file-upload'); const personaTooltip = document.getElementById('persona-tooltip'); const infoTrigger = document.getElementById('info-trigger'); let isRequestInProgress = false; let currentDraftText = ""; let lastCustomFields = null; let lastFormValues = null; // Persona Capability Data const personaCapabilities = { lawyer: "Legal Professional Mode
Optimized for deep statutory analysis, procedural advice, and drafting formal legal documents with precise terminology.", student: "Academic Mode
Focuses on legal theory, landmark Supreme Court cases, and historical context of Indian laws.", citizen: "Empowerment Mode
Provides simple explanations of legal rights, RTI support, and step-by-step guidance for basic legal issues.", explorer: "Orientation Mode
General overview of the Indian judicial hierarchy, history, and fundamental legal concepts." }; function setLockdown(active) { isRequestInProgress = active; if (active) { document.body.classList.add('lockdown-active'); userInput.placeholder = "Judicial Lockdown: Analysis in progress..."; sendBtn.disabled = true; } else { document.body.classList.remove('lockdown-active'); userInput.placeholder = "Enter your legal query here..."; sendBtn.disabled = false; } } // Handle File Upload attachBtn.addEventListener('click', () => fileUpload.click()); fileUpload.addEventListener('change', async (e) => { const file = e.target.files[0]; if (!file) return; addMessage(`Uploading ${file.name}...`, 'user'); const formData = new FormData(); formData.append('file', file); try { const response = await fetch(`${API_BASE_URL}/upload`, { method: 'POST', body: formData }); const data = await response.json(); if (data.text) { userInput.value = `Audit this document: \n\n ${data.text.substring(0, 1000)}...`; addMessage(`Document ${file.name} processed. I have extracted the text. Click Execute to start the audit.`, 'system'); } } catch (err) { addMessage(`Error uploading file: ${err.message}`, 'system'); } }); document.querySelectorAll('.persona-btn').forEach(btn => { btn.addEventListener('click', () => { userPersona = btn.getAttribute('data-persona'); onboardingOverlay.classList.add('hidden'); appContainer.classList.remove('blur-background'); // Update top bar status profileStatus.innerText = userPersona.charAt(0).toUpperCase() + userPersona.slice(1) + " Dashboard"; // Apply Dynamic Theme document.documentElement.setAttribute('data-theme', userPersona); // Update Wisdom Tooltip personaTooltip.innerHTML = personaCapabilities[userPersona]; addMessage(`Welcome! You are now connected as a **${userPersona.toUpperCase()}**. How can I help you navigate the legal system today?`, 'system'); }); }); function highlightCitations(text) { // Regex to find common Indian legal citations (e.g., Section 302, Article 21, IPC 302) const citationRegex = /\b(Section|Article|Act|Clause)\s+\d+[A-Z]?\b|\b(IPC|BNS|CRPC|CPC|DPDPA)\s+\d+[A-Z]?\b/gi; return text.replace(citationRegex, (match) => { return `${match}`; }); } switchBtn.addEventListener('click', () => { onboardingOverlay.classList.remove('hidden'); appContainer.classList.add('blur-background'); }); // Motto Carousel Data const mottos = [ { text: "सत्यमेव जयते", lang: "Hindi" }, { text: "সত্যমেব জয়তে", lang: "Bengali" }, { text: "सत्यमेव जयते", lang: "Marathi" }, { text: "సత్యమేవ జయతే", lang: "Telugu" }, { text: "சத்யமேவ ஜெயதே", lang: "Tamil" }, { text: "સત્યમેવ જયતે", lang: "Gujarati" }, { text: "ستیہ میو جیتے", lang: "Urdu" }, { text: "ಸತ್ಯಮೇವ ಜಯತೇ", lang: "Kannada" }, { text: "ସତ୍ୟମେବ ଜୟତେ", lang: "Odia" }, { text: "സത്യമേവ ജയതേ", lang: "Malayalam" } ]; let currentMottoIndex = 0; const mottoText = document.getElementById('motto-text'); const mottoLang = document.getElementById('motto-lang'); function updateMotto() { mottoText.classList.add('fade-out'); mottoLang.classList.add('fade-out'); setTimeout(() => { currentMottoIndex = (currentMottoIndex + 1) % mottos.length; mottoText.innerText = mottos[currentMottoIndex].text; mottoLang.innerText = mottos[currentMottoIndex].lang; mottoText.classList.remove('fade-out'); mottoLang.classList.remove('fade-out'); }, 500); } setInterval(updateMotto, 4000); // Change every 4 seconds function addMessage(text, sender) { if (text.includes('===REQUEST_NOTICE_FORM===')) { try { const parts = text.split('===REQUEST_NOTICE_FORM==='); const jsonStr = parts[1].trim(); const customFields = JSON.parse(jsonStr); addNoticeForm(customFields); } catch (e) { console.error("Failed to parse custom fields from LLM", e); addNoticeForm(["Sender Details (Name, Address)", "Receiver Details (Name, Address)", "Grievance / Cause of Action", "Relief / Demand"]); } return; } const msgDiv = document.createElement('div'); msgDiv.className = `message ${sender}`; // Explicitly set classes // Highlight Citations let highlightedText = highlightCitations(text); // Add Spark Icon for System if (sender === 'system') { const spark = document.createElement('div'); spark.className = 'system-spark'; spark.innerHTML = '✨'; msgDiv.appendChild(spark); } const contentDiv = document.createElement('div'); contentDiv.className = 'message-content'; let renderText = highlightedText.replace('===DRAFT BEGIN===', '').replace('===DRAFT END===', ''); contentDiv.innerHTML = marked.parse(renderText); msgDiv.appendChild(contentDiv); // Action Button Detection (Proactive Agent Feature) if (sender === 'system') { const actionArea = document.createElement('div'); actionArea.classList.add('action-area'); let hasDraft = text.includes('===DRAFT BEGIN==='); if (hasDraft) { // Helper function to extract just the draft const extractDraft = (fullText) => { const startMarker = '===DRAFT BEGIN==='; const endMarker = '===DRAFT END==='; let startIndex = fullText.indexOf(startMarker); let endIndex = fullText.indexOf(endMarker); if (startIndex !== -1 && endIndex !== -1) { return fullText.substring(startIndex + startMarker.length, endIndex).trim(); } return fullText; // Fallback }; const draftText = extractDraft(text); currentDraftText = draftText; // Store globally for editing const copyBtn = createActionButton('copy', 'Copy Draft', () => { navigator.clipboard.writeText(draftText); alert('Draft copied to clipboard! (Satyameva Jayate)'); }); actionArea.appendChild(copyBtn); const docBtn = createActionButton('file-text', 'Download DOC', () => exportToDoc(draftText)); actionArea.appendChild(docBtn); const pdfBtn = createActionButton('download', 'Download PDF', () => exportToPdf(draftText)); actionArea.appendChild(pdfBtn); const editBtn = createActionButton('edit-3', 'Edit Draft', () => { if (lastCustomFields && lastFormValues) { addNoticeForm(lastCustomFields, lastFormValues); } else { addNoticeForm([], []); // Show form with just Additional Instructions } }); actionArea.appendChild(editBtn); } else { if (text.toLowerCase().includes('rti query') || text.toLowerCase().includes('rti act')) { const btn = createActionButton('scroll', 'Draft RTI Query', () => { userInput.value = "Draft an RTI query for this matter."; handleSendMessage(); }); actionArea.appendChild(btn); } if (text.toLowerCase().includes('legal notice')) { const btn = createActionButton('file-text', 'Prepare Legal Notice', () => { userInput.value = "Please draft a legal notice for this matter."; handleSendMessage(); }); actionArea.appendChild(btn); } } if (actionArea.children.length > 0) { msgDiv.appendChild(actionArea); } } const time = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); const timeSpan = document.createElement('span'); timeSpan.classList.add('message-time'); timeSpan.innerText = time; msgDiv.appendChild(timeSpan); chatMessages.appendChild(msgDiv); setTimeout(scrollToBottom, 50); // Small delay for smooth rendering lucide.createIcons(); } function scrollToBottom() { chatMessages.scrollTo({ top: chatMessages.scrollHeight, behavior: 'smooth' }); } function exportToDoc(text) { const header = "Legal Draft"; const footer = ""; const sourceHTML = header + marked.parse(text) + footer; const source = 'data:application/vnd.ms-word;charset=utf-8,' + encodeURIComponent(sourceHTML); const fileDownload = document.createElement("a"); document.body.appendChild(fileDownload); fileDownload.href = source; fileDownload.download = 'Nyaya_Legal_Draft.doc'; fileDownload.click(); document.body.removeChild(fileDownload); } function exportToPdf(text) { // Premium Print Mode for PDF const printWindow = window.open('', '_blank'); printWindow.document.write(` Nyaya Legal Draft
NYAYA AGENT
${marked.parse(text)} `); printWindow.document.close(); } function createActionButton(icon, label, callback) { const btn = document.createElement('button'); btn.classList.add('action-btn'); btn.innerHTML = ` ${label}`; btn.onclick = callback; return btn; } function addNoticeForm(customFields = ["Sender Details (Name, Address)", "Receiver Details (Name, Address)", "Grievance / Cause of Action", "Relief / Demand"], previousValues = null) { const msgDiv = document.createElement('div'); msgDiv.className = `message system`; // Generate unique ID suffix for this specific form instance const uniqueId = Date.now(); // Store globally for edit draft lastCustomFields = customFields; let inputsHtml = customFields.map((field, index) => { const isLongText = field.toLowerCase().includes('grievance') || field.toLowerCase().includes('relief') || field.toLowerCase().includes('grounds') || field.toLowerCase().includes('facts'); const isDate = field.toLowerCase().includes('date'); let value = previousValues && previousValues[index] ? previousValues[index] : ""; value = value.replace(/"/g, '"'); if (isLongText) { return ``; } else if (isDate) { const today = new Date().toISOString().split('T')[0]; return `
${field}
`; } else { return ``; } }).join(''); let additionalInstructionsHtml = previousValues ? `
Additional Instructions / Changes
` : ""; const formTitle = previousValues ? "Edit Draft" : "Prepare Draft"; const btnText = previousValues ? "Update Draft" : "Prepare Draft"; msgDiv.innerHTML = `

${formTitle}

Please provide the details below.

`; chatMessages.appendChild(msgDiv); setTimeout(() => { const btn = document.getElementById(`generate-notice-btn-${uniqueId}`); if(btn) { btn.onclick = () => { let promptParts = []; let currentValues = []; customFields.forEach((field, index) => { const el = document.getElementById(`notice-field-${index}-${uniqueId}`); if (el && el.value.trim()) { promptParts.push(`**${field}:** ${el.value.trim()}`); } currentValues.push(el.value.trim()); }); // Save values globally for next edit lastFormValues = currentValues; const additionalEl = document.getElementById(`notice-additional-instructions-${uniqueId}`); if (additionalEl && additionalEl.value.trim()) { promptParts.push(`**Additional Instructions / Changes:** ${additionalEl.value.trim()}`); } btn.disabled = true; btn.innerHTML = ` Drafting...`; let combinedPrompt = "Please prepare the formal legal draft using the following details:\\n\\n" + promptParts.join('\\n\\n'); if (previousValues && currentDraftText) { combinedPrompt += "\\n\\n===EXISTING DRAFT TO MODIFY===\\n" + currentDraftText + "\\n===END EXISTING DRAFT===\\n\\nPlease apply the requested changes/details to the existing draft and return the FULL updated draft."; } userInput.value = combinedPrompt; handleSendMessage(); }; } lucide.createIcons(); }); setTimeout(() => { chatMessages.scrollTo({ top: chatMessages.scrollHeight, behavior: 'smooth' }); }, 50); lucide.createIcons(); } async function handleSendMessage() { if (isRequestInProgress) return; const text = userInput.value.trim(); if (!text) return; setLockdown(true); // Add user message to UI addMessage(text, 'user'); userInput.value = ''; // Show animated loading indicator const loadingId = 'loading-' + Date.now(); const loadingDiv = document.createElement('div'); loadingDiv.id = loadingId; loadingDiv.classList.add('message', 'system', 'glass', 'legal-loader'); loadingDiv.innerHTML = `
Order in the Court... Analyzing
`; chatMessages.appendChild(loadingDiv); lucide.createIcons(); scrollToBottom(); try { const apiPayload = { message: text, persona: userPersona }; // Silently inject the draft text if the user is editing it if (text.includes("Please modify the draft") && currentDraftText) { apiPayload.message = text + `\n\n===CURRENT DRAFT===\n${currentDraftText}`; } const response = await fetch(`${API_BASE_URL}/chat`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(apiPayload) }); const data = await response.json(); // Remove loading indicator document.getElementById(loadingId).remove(); if (data.response) { addMessage(data.response, 'system'); } else if (data.detail) { addMessage(`Error: ${data.detail}`, 'system'); } } catch (error) { if (document.getElementById(loadingId)) document.getElementById(loadingId).remove(); addMessage(`Connection Error: Could not reach the Judicial Network. Ensure the server is running.`, 'system'); console.error('API Error:', error); } finally { setLockdown(false); } } sendBtn.addEventListener('click', handleSendMessage); userInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { handleSendMessage(); } }); addMessage("Greetings. I am **Nyaya Agent**. I am ready to assist with your legal research, drafting, or compliance queries.", "system"); // Sidebar Navigation const toolExamples = { search: "Search for landmark cases. e.g., 'Find Supreme Court judgments on Right to Privacy (Justice K.S. Puttaswamy case)'", notice: "Prepare a formal notice. e.g., 'Help me draft a legal notice for non-payment of rent by a tenant.'", rti: "Draft an RTI application. e.g., 'Draft an RTI to find out the status of road repairs in Ward 12.'", compliance: "Upload a legal document using the paperclip icon (📎) below for the app to analyze. e.g., 'Audit this privacy policy for compliance with DPDPA 2023.'", bridge: "Translate old criminal laws (IPC, CrPC) to the newly enacted Bharatiya Nyaya Sanhita (BNS). e.g., 'What is the new BNS law for cheating (formerly IPC 420)?'" }; document.querySelectorAll('.nav-item').forEach(item => { item.addEventListener('click', () => { if (isRequestInProgress) { alert('Judicial Lockdown Active: Please wait for the current analysis to complete.'); return; } document.querySelectorAll('.nav-item').forEach(btn => btn.classList.remove('active')); item.classList.add('active'); const tool = item.getAttribute('data-tool'); // Toggle attachment button visibility const attachBtn = document.getElementById('attach-btn'); if (attachBtn) { attachBtn.style.display = (tool === 'compliance') ? 'flex' : 'none'; } if (tool !== 'chat') { const example = toolExamples[tool]; const moduleName = tool === 'bridge' ? 'Law BRIDGE' : tool.toUpperCase(); addMessage(`Switched to **${moduleName}** module.\n\n**Example:** ${example}`, 'system'); } }); });