<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>GATEPAS Prompt Library Template</title>

    <script src="https://cdn.tailwindcss.com"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

    <script src="https://unpkg.com/lucide-react@0.292.0/dist/lucide-react.js"></script>

    <style>

        :root {

            --header-bg: #1e3a8a; /* dark blue */

            --header-text: #ffffff;

            --status-production: #dcfce7; /* green */

            --status-testing: #fef9c3;   /* yellow */

            --status-draft: #e0f2fe;     /* light blue */

            --status-deprecated: #e5e7eb;/* gray */

            --review-alert: #fecaca;    /* red */

        }

        .tab-active { 

            border-bottom: 2px solid var(--header-bg); 

            color: var(--header-bg);

            font-weight: 600;

        }

        #prompt-library-table th {

            background-color: var(--header-bg);

            color: var(--header-text);

            text-align: center;

            padding: 8px;

            border: 1px solid #ddd;

            position: sticky;

            top: 0;

            z-index: 10;

        }

        #prompt-library-table td {

            border: 1px solid #ddd;

            padding: 6px 8px;

            white-space: nowrap;

        }

        #prompt-library-table td.wrap {

            white-space: normal;

        }

        .status-Production { background-color: var(--status-production); }

        .status-Testing { background-color: var(--status-testing); }

        .status-Draft { background-color: var(--status-draft); }

        .status-Deprecated { background-color: var(--status-deprecated); }

        .review-needed { background-color: var(--review-alert); }

        .high-performer { color: #15803d; font-weight: bold; }

        .modal {

            transition: opacity 0.25s ease;

        }

    </style>

</head>

<body class="bg-gray-100 font-sans">

    <div class="container mx-auto p-4">

        <div class="bg-white rounded-lg shadow-lg p-6">

            <header class="flex justify-between items-center mb-4">

                <h1 class="text-2xl font-bold text-gray-800">GATEPAS Prompt Library</h1>

                <div class="flex items-center space-x-2">

                    <label for="file-upload" class="cursor-pointer bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition-colors text-sm font-semibold flex items-center">

                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" x2="12" y1="3" y2="15"/></svg>

                        Upload .xlsx

                    </label>

                    <input id="file-upload" type="file" class="hidden" accept=".xlsx, .xls">

                    <button id="download-btn" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700 transition-colors text-sm font-semibold flex items-center">

                         <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/></svg>

                        Download Template

                    </button>

                </div>

            </header>


            <!-- Tabs -->

            <div class="border-b border-gray-200">

                <nav class="-mb-px flex space-x-6" id="tabs">

                    <button data-tab="Prompt_Library" class="py-3 px-1 border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none tab-active">Prompt Library</button>

                    <button data-tab="Analytics" class="py-3 px-1 border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none">Analytics</button>

                    <button data-tab="Dropdown_Lists" class="py-3 px-1 border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none">Dropdown Lists</button>

                    <button data-tab="Archive" class="py-3 px-1 border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none">Archive</button>

                    <button data-tab="Instructions" class="py-3 px-1 border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none">Instructions</button>

                </nav>

            </div>


            <!-- Tab Content -->

            <div id="tab-content" class="mt-6">

                <!-- Prompt Library -->

                <div id="Prompt_Library" class="tab-pane">

                    <div class="flex justify-between items-center mb-4">

                        <div class="flex items-center space-x-3">

                             <button id="add-prompt-btn" class="bg-blue-800 text-white px-4 py-2 rounded-md hover:bg-blue-900 transition-colors text-sm font-semibold flex items-center">

                                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2"><line x1="12" x2="12" y1="5" y2="19"/><line x1="5" x2="19" y1="12" y2="12"/></svg>

                                Add New Prompt

                            </button>

                            <div>

                                <label for="filter-view" class="text-sm font-medium text-gray-700 mr-2">Filter Views:</label>

                                <select id="filter-view" class="rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">

                                    <option value="all">All Prompts</option>

                                    <option value="my_active">My Active Prompts</option>

                                    <option value="needs_review">Needs Review</option>

                                    <option value="top_performers">Top Performers</option>

                                </select>

                            </div>

                        </div>

                        <div class="relative">

                            <input type="text" id="search-input" placeholder="Search library..." class="pl-8 pr-4 py-2 border rounded-md w-64 focus:outline-none focus:ring-2 focus:ring-blue-500">

                             <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="absolute left-2.5 top-1/2 -translate-y-1/2 text-gray-400"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>

                        </div>

                    </div>

                    <div class="overflow-x-auto h-[60vh] relative">

                        <table id="prompt-library-table" class="w-full text-sm">

                            <thead>

                                <tr id="table-headers"></tr>

                            </thead>

                            <tbody id="table-body"></tbody>

                        </table>

                    </div>

                </div>


                <!-- Analytics -->

                <div id="Analytics" class="tab-pane hidden">

                    <h2 class="text-xl font-bold mb-4 text-gray-700">Prompt Library Analytics</h2>

                    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">

                        <div class="bg-gray-50 p-4 rounded-lg shadow">

                            <h3 class="font-semibold text-gray-600">Total Prompts</h3>

                            <p id="total-prompts" class="text-3xl font-bold text-blue-800">0</p>

                        </div>

                        <div class="bg-gray-50 p-4 rounded-lg shadow">

                            <h3 class="font-semibold text-gray-600">Production Ready</h3>

                            <p id="production-ready" class="text-3xl font-bold text-green-600">0</p>

                        </div>

                        <div class="bg-gray-50 p-4 rounded-lg shadow">

                            <h3 class="font-semibold text-gray-600">Avg. Success Rate</h3>

                            <p id="avg-success" class="text-3xl font-bold text-yellow-600">0%</p>

                        </div>

                         <div class="bg-gray-50 p-4 rounded-lg shadow">

                            <h3 class="font-semibold text-gray-600">Total Hours Saved</h3>

                            <p id="hours-saved" class="text-3xl font-bold text-indigo-600">0</p>

                        </div>

                    </div>

                     <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">

                        <div class="bg-white p-4 rounded-lg shadow">

                            <h3 class="font-semibold text-center mb-2">Prompts by Status</h3>

                            <canvas id="status-chart"></canvas>

                        </div>

                        <div class="bg-white p-4 rounded-lg shadow">

                            <h3 class="font-semibold text-center mb-2">Prompts by Practice Area</h3>

                            <canvas id="practice-area-chart"></canvas>

                        </div>

                        <div class="bg-white p-4 rounded-lg shadow">

                            <h3 class="font-semibold text-center mb-2">Prompts by Document Type</h3>

                            <canvas id="doc-type-chart"></canvas>

                        </div>

                    </div>

                </div>


                <!-- Dropdown Lists -->

                <div id="Dropdown_Lists" class="tab-pane hidden">

                    <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-6" id="dropdown-lists-container"></div>

                </div>


                <!-- Archive -->

                <div id="Archive" class="tab-pane hidden">

                    <p class="text-gray-600">Archived prompts will be stored here. This functionality can be expanded to move prompts from the main library to this sheet.</p>

                </div>

                

                <!-- Instructions -->

                <div id="Instructions" class="tab-pane hidden prose max-w-none">

                    <h2 class="font-bold text-lg">HOW TO USE THE GATEPAS PROMPT LIBRARY</h2>

                    <h3 class="font-semibold">1. FINDING PROMPTS:</h3>

                    <ul>

                        <li>Use the search bar at the top right of the library view.</li>

                        <li>Use the "Filter views" dropdown for pre-configured searches.</li>

                        <li>Sort by any column by clicking its header.</li>

                    </ul>

                    <h3 class="font-semibold">2. ADDING NEW PROMPTS:</h3>

                    <ul>

                        <li>Click the "Add New Prompt" button.</li>

                        <li>Fill in the required fields in the form that appears.</li>

                        <li>The Status will be set to "Draft" initially.</li>

                    </ul>

                    <h3 class="font-semibold">3. SCALE GUIDELINES (1-10):</h3>

                    <ul>

                        <li>5-6 is neutral/standard.</li>

                        <li>Higher numbers indicate more of that quality (e.g., 10 is max Urgency).</li>

                    </ul>

                     <h3 class="font-semibold">4. WORKFLOW:</h3>

                    <p>Draft → Testing (after ~3 uses) → Production → Archive</p>


                    <hr class="my-6">

                    <h2 class="font-bold text-lg">WHY A WEB APP (vs. Google Sheets)?</h2>

                     <h3 class="font-semibold">Collaboration Features</h3>

                    <ul>

                        <li><strong>Centralized Data:</strong> Everyone accesses the same, single source of truth.</li>

                        <li><strong>User Roles (Future):</strong> Permissions can be set for different user types.</li>

                    </ul>

                     <h3 class="font-semibold">Automation & Integration</h3>

                    <ul>

                        <li><strong>API Access:</strong> Can be integrated with other legal tech tools.</li>

                        <li><strong>Custom Logic:</strong> Features like automatic ID generation are built-in and reliable.</li>

                    </ul>

                </div>

            </div>

        </div>

    </div>

    

    <!-- Modal for Adding/Editing Prompts -->

    <div id="prompt-modal" class="modal fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full hidden">

        <div class="relative top-10 mx-auto p-5 border w-full max-w-4xl shadow-lg rounded-md bg-white">

            <div class="flex justify-between items-center pb-3">

                <p class="text-2xl font-bold" id="modal-title">Add New Prompt</p>

                <button id="close-modal-btn" class="cursor-pointer z-50">

                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>

                </button>

            </div>

            <form id="prompt-form" class="space-y-4 max-h-[75vh] overflow-y-auto pr-2">

                <!-- Form fields will be generated by JS -->

            </form>

            <div class="flex justify-end pt-4">

                <button id="save-prompt-btn" class="px-4 py-2 bg-blue-600 text-white text-base font-medium rounded-md w-full sm:w-auto hover:bg-blue-700">Save Prompt</button>

            </div>

        </div>

    </div>


<script>

document.addEventListener('DOMContentLoaded', () => {


    // --- DATA & STATE MANAGEMENT ---

    const headers = [

        'Prompt_ID', 'Version', 'Status', 'Prompt_Name', 'Practice_Area', 'Document_Type', 'Jurisdiction', 'Complexity',

        'Experience_Level', 'Formality', 'Assertiveness', 'Emotional_Temp', 'Urgency', 'Success_Probability',

        'Risk_Tolerance', 'Strategic_Importance', 'Audience_Sophistication', 'Audience_Patience', 'Audience_Predisposition',

        'Scope_Breadth', 'Scope_Depth', 'Full_Prompt', 'Guardrails', 'Required_Checkpoints', 'Known_Issues', 'Times_Used',

        'Success_Rate', 'Avg_Time_Saved', 'User_Rating', 'Author', 'Owner', 'Created_Date', 'Modified_Date',

        'Last_Tested', 'Next_Review', 'Notes'

    ];


    const dropdownData = {

        'Status': ['Draft', 'Testing', 'Production', 'Deprecated'],

        'Practice_Area': ['Criminal Defense', 'Civil Litigation', 'Corporate', 'Real Estate', 'Family Law', 'Immigration', 'Tax', 'Employment', 'IP'],

        'Document_Type': ['Motion', 'Letter', 'Contract', 'Discovery', 'Brief', 'Memo', 'Agreement', 'Pleading', 'Appeal'],

        'Complexity': ['Green', 'Yellow', 'Red'],

        'Jurisdiction': ['Federal', 'State', 'E.D. La.', 'M.D. La.', 'W.D. La.', 'La. State Court', 'Fifth Circuit']

    };


    let promptData = [

        { Prompt_ID: 'CIVI-MOTI-001', Version: 1.0, Status: 'Production', Prompt_Name: 'Initial Motion to Compel', Practice_Area: 'Civil Litigation', Document_Type: 'Motion', Jurisdiction: 'Federal', Complexity: 'Yellow', Experience_Level: 5, Formality: 8, Assertiveness: 7, Emotional_Temp: 4, Urgency: 6, Success_Probability: 7, Risk_Tolerance: 4, Strategic_Importance: 8, Audience_Sophistication: 9, Audience_Patience: 3, Audience_Predisposition: 2, Scope_Breadth: 6, Scope_Depth: 7, Full_Prompt: 'Draft a motion to compel discovery responses from Opposing Counsel in the matter of [Case Name], Case No. [Case #]. The motion should address the overdue responses for Interrogatories and Requests for Production served on [Date].', Guardrails: 'Adhere to local rules for formatting. Do not include sanctions request at this stage.', Required_Checkpoints: 'Verify service date of original discovery. Confirm meet-and-confer attempts.', Known_Issues: 'Opposing counsel is notoriously slow to respond.', Times_Used: 15, Success_Rate: 0.9, Avg_Time_Saved: 30, User_Rating: 4.5, Author: 'user@example.com', Owner: 'user@example.com', Created_Date: '2023-01-15', Modified_Date: '2023-10-20', Last_Tested: '2023-10-18', Next_Review: '2024-04-20', Notes: 'Highly effective for standard discovery disputes.' },

        { Prompt_ID: 'CORP-AGRE-002', Version: 0.5, Status: 'Draft', Prompt_Name: 'Standard NDA for Contractors', Practice_Area: 'Corporate', Document_Type: 'Agreement', Jurisdiction: 'State', Complexity: 'Green', Experience_Level: 3, Formality: 9, Assertiveness: 5, Emotional_Temp: 5, Urgency: 3, Success_Probability: 9, Risk_Tolerance: 2, Strategic_Importance: 5, Audience_Sophistication: 5, Audience_Patience: 7, Audience_Predisposition: 5, Scope_Breadth: 4, Scope_Depth: 4, Full_Prompt: 'Generate a standard, unilateral Non-Disclosure Agreement for an independent contractor providing services to our company. Include clauses for confidentiality, return of information, and term of agreement (2 years).', Guardrails: 'Use boilerplate language. No unusual clauses.', Required_Checkpoints: 'Define "Confidential Information" broadly.', Known_Issues: '', Times_Used: 0, Success_Rate: 0, Avg_Time_Saved: 15, User_Rating: 0, Author: 'admin@example.com', Owner: 'admin@example.com', Created_Date: '2023-11-01', Modified_Date: '2023-11-05', Last_Tested: '', Next_Review: '2024-05-01', Notes: 'Awaiting legal review.' },

        { Prompt_ID: 'CRIM-APPE-003', Version: 2.1, Status: 'Testing', Prompt_Name: 'Appellate Brief Opening Statement', Practice_Area: 'Criminal Defense', Document_Type: 'Appeal', Jurisdiction: 'Fifth Circuit', Complexity: 'Red', Experience_Level: 9, Formality: 10, Assertiveness: 9, Emotional_Temp: 6, Urgency: 8, Success_Probability: 4, Risk_Tolerance: 8, Strategic_Importance: 10, Audience_Sophistication: 10, Audience_Patience: 2, Audience_Predisposition: 1, Scope_Breadth: 8, Scope_Depth: 9, Full_Prompt: 'Craft the opening "Statement of the Case" for an appellate brief concerning the wrongful admission of evidence in [Case Name]. Focus on the violation of the Fourth Amendment.', Guardrails: 'Strictly adhere to Fifth Circuit formatting rules. Maintain a respectful but firm tone.', Required_Checkpoints: 'Cite the trial record accurately for every factual assertion.', Known_Issues: 'The panel is known to be hostile to this type of appeal.', Times_Used: 2, Success_Rate: 0.5, Avg_Time_Saved: 120, User_Rating: 4, Author: 'user@example.com', Owner: 'admin@example.com', Created_Date: '2022-05-30', Modified_Date: '2023-09-15', Last_Tested: '2023-09-14', Next_Review: '2023-12-15', Notes: 'Requires careful wording.' }

    ];


    let charts = {};

    let currentSort = { column: null, direction: 'asc' };

    

    // --- UI ELEMENTS ---

    const tabs = document.getElementById('tabs');

    const tabContent = document.getElementById('tab-content');

    const tableHeaders = document.getElementById('table-headers');

    const tableBody = document.getElementById('table-body');

    const modal = document.getElementById('prompt-modal');

    const promptForm = document.getElementById('prompt-form');


    // --- INITIALIZATION ---

    const init = () => {

        setupEventListeners();

        renderAll();

    };


    // --- EVENT LISTENERS ---

    const setupEventListeners = () => {

        tabs.addEventListener('click', handleTabClick);

        document.getElementById('add-prompt-btn').addEventListener('click', () => openModal());

        document.getElementById('close-modal-btn').addEventListener('click', closeModal);

        document.getElementById('save-prompt-btn').addEventListener('click', handleSavePrompt);

        document.getElementById('download-btn').addEventListener('click', handleDownload);

        document.getElementById('file-upload').addEventListener('change', handleUpload);

        document.getElementById('filter-view').addEventListener('change', renderPromptLibrary);

        document.getElementById('search-input').addEventListener('input', renderPromptLibrary);

    };


    // --- RENDER FUNCTIONS ---

    const renderAll = () => {

        renderHeaders();

        renderDropdownLists();

        renderPromptLibrary();

        renderAnalytics();

    };

    

    const renderHeaders = () => {

        tableHeaders.innerHTML = `<tr>${headers.map(h => `<th class="cursor-pointer" data-column="${h}">${h.replace(/_/g, ' ')}</th>`).join('')}</tr>`;

        tableHeaders.querySelectorAll('th').forEach(th => th.addEventListener('click', (e) => handleSort(e.currentTarget.dataset.column)));

    };


    const renderPromptLibrary = () => {

        const filteredData = getFilteredData();

        tableBody.innerHTML = filteredData.map(prompt => {

            const isReviewNeeded = prompt.Next_Review && new Date(prompt.Next_Review) <= new Date();

            const isHighPerformer = prompt.Times_Used >= 10;

            return `<tr class="hover:bg-gray-50">

                ${headers.map(header => {

                    let value = prompt[header] || '';

                    let className = '';

                    if (header === 'Status') className += ` status-${value}`;

                    if (header === 'Next_Review' && isReviewNeeded) className += ' review-needed';

                    if (header === 'Times_Used' && isHighPerformer) className += ' high-performer';

                    if (['Full_Prompt', 'Guardrails', 'Required_Checkpoints', 'Known_Issues', 'Notes'].includes(header)) {

                       className += ' wrap';

                    }


                    // Formatting

                    if (header === 'Success_Rate' && typeof value === 'number') value = `${(value * 100).toFixed(0)}%`;

                    if (header === 'Version' && typeof value === 'number') value = value.toFixed(1);

                    

                    return `<td class="${className}" title="${value}">${value}</td>`;

                }).join('')}

            </tr>`;

        }).join('');

    };

    

    const renderDropdownLists = () => {

        const container = document.getElementById('dropdown-lists-container');

        container.innerHTML = Object.entries(dropdownData).map(([title, items]) => `

            <div class="p-4 bg-gray-50 rounded-lg">

                <h3 class="font-semibold text-gray-800 border-b pb-2 mb-2">${title.replace(/_/g, ' ')}</h3>

                <ul class="space-y-1">${items.map(item => `<li class="text-sm text-gray-600">${item}</li>`).join('')}</ul>

            </div>

        `).join('');

    };


    const renderAnalytics = () => {

        const total = promptData.length;

        const production = promptData.filter(p => p.Status === 'Production').length;

        const avgSuccess = promptData.length > 0 ? promptData.reduce((acc, p) => acc + (p.Success_Rate || 0), 0) / total : 0;

        const hoursSaved = promptData.reduce((acc, p) => acc + (p.Avg_Time_Saved || 0), 0) / 60;


        document.getElementById('total-prompts').textContent = total;

        document.getElementById('production-ready').textContent = production;

        document.getElementById('avg-success').textContent = `${(avgSuccess * 100).toFixed(1)}%`;

        document.getElementById('hours-saved').textContent = hoursSaved.toFixed(1);

        

        createOrUpdateChart('status-chart', 'pie', getChartData('Status'));

        createOrUpdateChart('practice-area-chart', 'doughnut', getChartData('Practice_Area'));

        createOrUpdateChart('doc-type-chart', 'pie', getChartData('Document_Type'));

    };


    // --- CHARTING ---

    const getChartData = (field) => {

        const counts = promptData.reduce((acc, p) => {

            const key = p[field] || 'N/A';

            acc[key] = (acc[key] || 0) + 1;

            return acc;

        }, {});

        return {

            labels: Object.keys(counts),

            datasets: [{

                data: Object.values(counts),

                backgroundColor: ['#3b82f6', '#16a34a', '#f97316', '#6b7280', '#ef4444', '#8b5cf6', '#d946ef'],

            }]

        };

    };


    const createOrUpdateChart = (canvasId, type, data) => {

        const ctx = document.getElementById(canvasId).getContext('2d');

        if (charts[canvasId]) {

            charts[canvasId].data = data;

            charts[canvasId].update();

        } else {

            charts[canvasId] = new Chart(ctx, { type, data, options: { responsive: true, maintainAspectRatio: true } });

        }

    };

    

    // --- DATA HANDLING & FILTERING ---

    const getFilteredData = () => {

        let data = [...promptData];

        const filter = document.getElementById('filter-view').value;

        const search = document.getElementById('search-input').value.toLowerCase();

        const today = new Date().toISOString().split('T')[0];


        // Apply named filter views

        if (filter === 'my_active') {

            data = data.filter(p => (p.Status === 'Production' || p.Status === 'Testing') && p.Owner === 'user@example.com');

        } else if (filter === 'needs_review') {

            data = data.filter(p => p.Next_Review && p.Next_Review <= today);

        } else if (filter === 'top_performers') {

            data = data.filter(p => p.Success_Rate >= 0.85).sort((a, b) => (b.Times_Used || 0) - (a.Times_Used || 0));

        }


        // Apply search

        if (search) {

            data = data.filter(p => Object.values(p).some(val => String(val).toLowerCase().includes(search)));

        }


        // Apply sort

        if (currentSort.column) {

            data.sort((a, b) => {

                const valA = a[currentSort.column] || '';

                const valB = b[currentSort.column] || '';

                if (valA < valB) return currentSort.direction === 'asc' ? -1 : 1;

                if (valA > valB) return currentSort.direction === 'asc' ? 1 : -1;

                return 0;

            });

        }

        

        return data;

    };


    const handleSort = (column) => {

        if (currentSort.column === column) {

            currentSort.direction = currentSort.direction === 'asc' ? 'desc' : 'asc';

        } else {

            currentSort.column = column;

            currentSort.direction = 'asc';

        }

        renderPromptLibrary();

    };


    // --- MODAL & FORM HANDLING ---

    const openModal = (promptId = null) => {

        // For simplicity, this implementation only supports adding new prompts.

        // An edit functionality would find the prompt by ID and populate the form.

        document.getElementById('modal-title').textContent = 'Add New Prompt';

        promptForm.innerHTML = createFormFields();

        modal.classList.remove('hidden');

    };


    const closeModal = () => modal.classList.add('hidden');


    const createFormFields = (prompt = {}) => {

        return headers.map(h => {

            const value = prompt[h] || '';

            const label = h.replace(/_/g, ' ');


            if (dropdownData[h]) {

                return `<div><label class="block text-sm font-medium text-gray-700">${label}</label><select name="${h}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm">${dropdownData[h].map(opt => `<option value="${opt}" ${opt === value ? 'selected' : ''}>${opt}</option>`).join('')}</select></div>`;

            }

            if (h.includes('Date') || h.includes('Review') || h.includes('Tested')) {

                 return `<div><label class="block text-sm font-medium text-gray-700">${label}</label><input type="date" name="${h}" value="${value}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm"></div>`;

            }

            if (['Full_Prompt', 'Guardrails', 'Required_Checkpoints', 'Known_Issues', 'Notes'].includes(h)) {

                return `<div><label class="block text-sm font-medium text-gray-700">${label}</label><textarea name="${h}" rows="3" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm">${value}</textarea></div>`;

            }

             if (typeof value === 'number' || h.includes('Level') || h.includes('Rate') || h.includes('Saved')) {

                return `<div><label class="block text-sm font-medium text-gray-700">${label}</label><input type="number" name="${h}" value="${value}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm"></div>`;

            }

            return `<div><label class="block text-sm font-medium text-gray-700">${label}</label><input type="text" name="${h}" value="${value}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm" ${h === 'Prompt_ID' ? 'disabled' : ''}></div>`;


        }).join('');

    };


    const handleSavePrompt = () => {

        const formData = new FormData(promptForm);

        const newPrompt = {};

        

        for (let [key, value] of formData.entries()) {

            // Convert numbers back to number type

            if (!isNaN(value) && value !== '') {

                 const numHeaders = ['Version', 'Experience_Level', 'Formality', 'Assertiveness', 'Emotional_Temp', 'Urgency', 'Success_Probability', 'Risk_Tolerance', 'Strategic_Importance', 'Audience_Sophistication', 'Audience_Patience', 'Audience_Predisposition', 'Scope_Breadth', 'Scope_Depth', 'Times_Used', 'Success_Rate', 'Avg_Time_Saved', 'User_Rating'];

                if(numHeaders.includes(key)) value = parseFloat(value);

            }

            newPrompt[key] = value;

        }


        // App Script Emulation

        const practice = newPrompt.Practice_Area || 'GEN';

        const docType = newPrompt.Document_Type || 'DOC';

        const prefix = practice.substring(0,4).toUpperCase();

        const type = docType.substring(0,4).toUpperCase();

        const count = String(promptData.length + 1).padStart(3, '0');

        

        newPrompt.Prompt_ID = `${prefix}-${type}-${count}`;

        newPrompt.Version = 0.1;

        newPrompt.Status = 'Draft';

        const today = new Date().toISOString().split('T')[0];

        newPrompt.Created_Date = today;

        newPrompt.Modified_Date = today;

        newPrompt.Author = 'user@example.com'; // Hardcoded for demo

        newPrompt.Owner = 'user@example.com'; // Hardcoded for demo

        

        promptData.push(newPrompt);

        closeModal();

        renderAll();

    };


    // --- FILE I/O ---

    const handleDownload = () => {

        const wb = XLSX.utils.book_new();


        // 1. Prompt_Library Sheet

        const ws_library = XLSX.utils.json_to_sheet(promptData, { header: headers });

        XLSX.utils.book_append_sheet(wb, ws_library, 'Prompt_Library');


        // 2. Dropdown_Lists Sheet

        const dropdownArray = [];

        const maxLen = Math.max(...Object.values(dropdownData).map(arr => arr.length));

        const dropdownHeaders = Object.keys(dropdownData);

        dropdownArray.push(dropdownHeaders);

        for(let i=0; i < maxLen; i++) {

            const row = [];

            dropdownHeaders.forEach(h => row.push(dropdownData[h][i] || ''));

            dropdownArray.push(row);

        }

        const ws_dropdowns = XLSX.utils.aoa_to_sheet(dropdownArray);

        XLSX.utils.book_append_sheet(wb, ws_dropdowns, 'Dropdown_Lists');


        // 3. Analytics Sheet

        const analyticsData = [

            ['PROMPT LIBRARY ANALYTICS'],

            [],

            [`Total Prompts:`, {f: `COUNTA(Prompt_Library!C:C)-1`}],

            [`Production Ready:`, {f: `COUNTIF(Prompt_Library!C:C,"Production")`}],

            [`Avg Success Rate:`, {f: `AVERAGE(Prompt_Library!AA:AA)`, z: '0.0%'}],

            [`Total Hours Saved:`, {f: `SUM(Prompt_Library!AB:AB)/60`, z: '0.0'}],

        ];

        const ws_analytics = XLSX.utils.aoa_to_sheet(analyticsData);

        XLSX.utils.book_append_sheet(wb, ws_analytics, 'Analytics');


        // 4. Other Sheets

        const ws_archive = XLSX.utils.aoa_to_sheet([headers]);

        XLSX.utils.book_append_sheet(wb, ws_archive, 'Archive');


        const instructionsText = document.getElementById('Instructions').innerText;

        const ws_instructions = XLSX.utils.aoa_to_sheet([[instructionsText]]);

        XLSX.utils.book_append_sheet(wb, ws_instructions, 'Instructions');


        XLSX.writeFile(wb, "GATEPAS_Prompt_Library.xlsx");

    };


    const handleUpload = (event) => {

        const file = event.target.files[0];

        if (!file) return;


        const reader = new FileReader();

        reader.onload = (e) => {

            const data = new Uint8Array(e.target.result);

            const workbook = XLSX.read(data, {type: 'array', cellDates:true});

            const firstSheetName = workbook.SheetNames[0];

            const worksheet = workbook.Sheets[firstSheetName];

            const jsonData = XLSX.utils.sheet_to_json(worksheet);

            

            // Basic data validation

            if (jsonData.length > 0 && headers.every(h => Object.keys(jsonData[0]).includes(h))) {

                promptData = jsonData.map(row => {

                    // Ensure dates are formatted correctly

                    headers.forEach(h => {

                        if (h.includes('Date') || h.includes('Review') || h.includes('Tested')) {

                            if (row[h] instanceof Date) {

                                row[h] = row[h].toISOString().split('T')[0];

                            }

                        }

                    });

                    return row;

                });

                renderAll();

                alert('File uploaded and data loaded successfully!');

            } else {

                alert('Error: The uploaded file does not have the correct headers.');

            }

        };

        reader.readAsArrayBuffer(file);

    };


    // --- TABS ---

    const handleTabClick = (e) => {

        if (e.target.tagName !== 'BUTTON') return;

        

        document.querySelectorAll('#tabs button').forEach(b => b.classList.remove('tab-active'));

        e.target.classList.add('tab-active');


        document.querySelectorAll('.tab-pane').forEach(p => p.classList.add('hidden'));

        document.getElementById(e.target.dataset.tab).classList.remove('hidden');

    };


    // --- START THE APP ---

    init();

});

</script>

</body>

</html>