|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Financial Question Generator</title> |
|
<script src="https://cdn.tailwindcss.com"></script> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
<style> |
|
.category-chip { |
|
transition: all 0.3s ease; |
|
} |
|
.category-chip:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); |
|
} |
|
.question-card { |
|
transition: all 0.3s ease; |
|
} |
|
.question-card:hover { |
|
transform: translateY(-3px); |
|
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1); |
|
} |
|
.loading-spinner { |
|
animation: spin 1s linear infinite; |
|
} |
|
@keyframes spin { |
|
0% { transform: rotate(0deg); } |
|
100% { transform: rotate(360deg); } |
|
} |
|
.tab-active { |
|
border-bottom: 3px solid #3b82f6; |
|
color: #3b82f6; |
|
font-weight: 600; |
|
} |
|
</style> |
|
</head> |
|
<body class="bg-gray-50 min-h-screen"> |
|
<div class="container mx-auto px-4 py-8"> |
|
<header class="mb-10 text-center"> |
|
<h1 class="text-4xl font-bold text-blue-600 mb-2">Financial Question Generator</h1> |
|
<p class="text-gray-600 text-lg">Generate unlimited English questions for financial and wallet-related scenarios</p> |
|
</header> |
|
|
|
<div class="bg-white rounded-xl shadow-lg p-6 mb-8"> |
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> |
|
<div> |
|
<h2 class="text-xl font-semibold mb-4 text-gray-800">Generation Settings</h2> |
|
|
|
<div class="mb-4"> |
|
<label class="block text-gray-700 mb-2">Number of Questions</label> |
|
<input type="number" id="questionCount" min="1" max="100" value="10" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"> |
|
</div> |
|
|
|
<div class="mb-4"> |
|
<label class="block text-gray-700 mb-2">Difficulty Level</label> |
|
<div class="flex space-x-2"> |
|
<button data-difficulty="simple" class="difficulty-btn px-4 py-2 bg-green-100 text-green-800 rounded-lg hover:bg-green-200">Simple</button> |
|
<button data-difficulty="medium" class="difficulty-btn px-4 py-2 bg-yellow-100 text-yellow-800 rounded-lg hover:bg-yellow-200">Medium</button> |
|
<button data-difficulty="complex" class="difficulty-btn px-4 py-2 bg-red-100 text-red-800 rounded-lg hover:bg-red-200">Complex</button> |
|
<button data-difficulty="random" class="difficulty-btn px-4 py-2 bg-gray-100 text-gray-800 rounded-lg hover:bg-gray-200">Random</button> |
|
</div> |
|
</div> |
|
|
|
<div class="mb-4"> |
|
<label class="block text-gray-700 mb-2">Categories (Select at least one)</label> |
|
<div class="flex flex-wrap gap-2"> |
|
<button data-category="deposit" class="category-chip px-3 py-1 bg-blue-100 text-blue-800 rounded-full hover:bg-blue-200">Deposit</button> |
|
<button data-category="transfer" class="category-chip px-3 py-1 bg-purple-100 text-purple-800 rounded-full hover:bg-purple-200">Transfer</button> |
|
<button data-category="withdrawal" class="category-chip px-3 py-1 bg-indigo-100 text-indigo-800 rounded-full hover:bg-indigo-200">Withdrawal</button> |
|
<button data-category="security" class="category-chip px-3 py-1 bg-red-100 text-red-800 rounded-full hover:bg-red-200">Account Security</button> |
|
<button data-category="payment" class="category-chip px-3 py-1 bg-green-100 text-green-800 rounded-full hover:bg-green-200">Payment</button> |
|
<button data-category="card" class="category-chip px-3 py-1 bg-yellow-100 text-yellow-800 rounded-full hover:bg-yellow-200">Card Management</button> |
|
<button data-category="billing" class="category-chip px-3 py-1 bg-pink-100 text-pink-800 rounded-full hover:bg-pink-200">Billing & Records</button> |
|
<button data-category="basic" class="category-chip px-3 py-1 bg-gray-100 text-gray-800 rounded-full hover:bg-gray-200">Basic Features</button> |
|
<button data-category="other" class="category-chip px-3 py-1 bg-teal-100 text-teal-800 rounded-full hover:bg-teal-200">Other</button> |
|
</div> |
|
</div> |
|
|
|
<div class="mb-4"> |
|
<label class="block text-gray-700 mb-2">Custom Prompt (Optional)</label> |
|
<textarea id="customPrompt" rows="3" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Add any specific instructions for question generation..."></textarea> |
|
</div> |
|
|
|
<button id="generateBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg transition duration-300 flex items-center justify-center"> |
|
<i class="fas fa-bolt mr-2"></i> Generate Questions |
|
</button> |
|
</div> |
|
|
|
<div> |
|
<h2 class="text-xl font-semibold mb-4 text-gray-800">RAG & External Data</h2> |
|
|
|
<div class="mb-4"> |
|
<label class="block text-gray-700 mb-2">Import External Data</label> |
|
<div class="flex items-center space-x-2"> |
|
<input type="file" id="externalData" class="hidden"> |
|
<button id="uploadBtn" class="px-4 py-2 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 flex items-center"> |
|
<i class="fas fa-file-upload mr-2"></i> Choose File |
|
</button> |
|
<span id="fileName" class="text-gray-500 text-sm">No file selected</span> |
|
</div> |
|
<p class="text-xs text-gray-500 mt-1">Supported formats: .txt, .pdf, .docx, .csv</p> |
|
</div> |
|
|
|
<div class="mb-4"> |
|
<label class="block text-gray-700 mb-2">API Connection</label> |
|
<div class="flex items-center space-x-2"> |
|
<div class="relative flex-grow"> |
|
<input type="text" id="apiKey" placeholder="Enter DeepSeek API Key" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"> |
|
<button id="toggleKey" class="absolute right-3 top-2 text-gray-500"> |
|
<i class="fas fa-eye"></i> |
|
</button> |
|
</div> |
|
<button id="testApiBtn" class="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700"> |
|
Test |
|
</button> |
|
</div> |
|
<div id="apiStatus" class="mt-2 text-sm flex items-center hidden"> |
|
<span class="w-3 h-3 rounded-full mr-2"></span> |
|
<span>API Status</span> |
|
</div> |
|
</div> |
|
|
|
<div class="bg-blue-50 p-4 rounded-lg"> |
|
<h3 class="font-semibold text-blue-800 mb-2 flex items-center"> |
|
<i class="fas fa-info-circle mr-2"></i> Generation Process |
|
</h3> |
|
<p class="text-sm text-blue-700"> |
|
Questions are generated using DeepSeek's AI model. For large batches, multiple API calls will be made automatically. Each question is categorized and checked for quality. |
|
</p> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="bg-white rounded-xl shadow-lg p-6"> |
|
<div class="flex justify-between items-center mb-6"> |
|
<h2 class="text-xl font-semibold text-gray-800">Generated Questions</h2> |
|
<div class="flex space-x-2"> |
|
<button id="exportBtn" class="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 flex items-center"> |
|
<i class="fas fa-file-export mr-2"></i> Export |
|
</button> |
|
<button id="clearBtn" class="px-4 py-2 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 flex items-center"> |
|
<i class="fas fa-trash-alt mr-2"></i> Clear |
|
</button> |
|
</div> |
|
</div> |
|
|
|
<div class="border-b border-gray-200 mb-4"> |
|
<div class="flex space-x-6"> |
|
<button data-tab="all" class="tab-btn pb-2 px-1 text-gray-600 hover:text-blue-600">All</button> |
|
<button data-tab="deposit" class="tab-btn pb-2 px-1 text-gray-600 hover:text-blue-600">Deposit</button> |
|
<button data-tab="transfer" class="tab-btn pb-2 px-1 text-gray-600 hover:text-blue-600">Transfer</button> |
|
<button data-tab="withdrawal" class="tab-btn pb-2 px-1 text-gray-600 hover:text-blue-600">Withdrawal</button> |
|
<button data-tab="security" class="tab-btn pb-2 px-1 text-gray-600 hover:text-blue-600">Security</button> |
|
<button data-tab="payment" class="tab-btn pb-2 px-1 text-gray-600 hover:text-blue-600">Payment</button> |
|
<button data-tab="card" class="tab-btn pb-2 px-1 text-gray-600 hover:text-blue-600">Card</button> |
|
<button data-tab="billing" class="tab-btn pb-2 px-1 text-gray-600 hover:text-blue-600">Billing</button> |
|
<button data-tab="basic" class="tab-btn pb-2 px-1 text-gray-600 hover:text-blue-600">Basic</button> |
|
<button data-tab="other" class="tab-btn pb-2 px-1 text-gray-600 hover:text-blue-600">Other</button> |
|
</div> |
|
</div> |
|
|
|
<div id="loadingIndicator" class="text-center py-8 hidden"> |
|
<div class="inline-block loading-spinner text-blue-500 text-4xl mb-2"> |
|
<i class="fas fa-circle-notch"></i> |
|
</div> |
|
<p class="text-gray-600">Generating questions using DeepSeek API...</p> |
|
<p id="progressText" class="text-sm text-gray-500 mt-1">Processing 0/0</p> |
|
</div> |
|
|
|
<div id="questionsContainer" class="space-y-4"> |
|
<div class="text-center py-12 text-gray-500"> |
|
<i class="fas fa-comment-dots text-4xl mb-3"></i> |
|
<p>No questions generated yet. Configure your settings and click "Generate Questions".</p> |
|
</div> |
|
</div> |
|
|
|
<div id="pagination" class="mt-6 flex justify-between items-center hidden"> |
|
<button id="prevPage" class="px-4 py-2 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 disabled:opacity-50"> |
|
<i class="fas fa-chevron-left mr-2"></i> Previous |
|
</button> |
|
<span id="pageInfo" class="text-gray-600">Page 1 of 1</span> |
|
<button id="nextPage" class="px-4 py-2 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 disabled:opacity-50"> |
|
Next <i class="fas fa-chevron-right ml-2"></i> |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div id="exportModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50"> |
|
<div class="bg-white rounded-xl p-6 w-full max-w-md"> |
|
<div class="flex justify-between items-center mb-4"> |
|
<h3 class="text-lg font-semibold">Export Questions</h3> |
|
<button id="closeExportModal" class="text-gray-500 hover:text-gray-700"> |
|
<i class="fas fa-times"></i> |
|
</button> |
|
</div> |
|
|
|
<div class="mb-4"> |
|
<label class="block text-gray-700 mb-2">Format</label> |
|
<div class="flex space-x-2"> |
|
<button data-format="csv" class="export-format-btn px-4 py-2 bg-blue-100 text-blue-800 rounded-lg hover:bg-blue-200">CSV</button> |
|
<button data-format="json" class="export-format-btn px-4 py-2 bg-green-100 text-green-800 rounded-lg hover:bg-green-200">JSON</button> |
|
<button data-format="txt" class="export-format-btn px-4 py-2 bg-purple-100 text-purple-800 rounded-lg hover:bg-purple-200">Text</button> |
|
</div> |
|
</div> |
|
|
|
<div class="mb-4"> |
|
<label class="block text-gray-700 mb-2">Filter</label> |
|
<select id="exportFilter" class="w-full px-4 py-2 border rounded-lg"> |
|
<option value="all">All Questions</option> |
|
<option value="current">Current View</option> |
|
<option value="selected">Selected Questions</option> |
|
</select> |
|
</div> |
|
|
|
<button id="confirmExport" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg"> |
|
<i class="fas fa-download mr-2"></i> Export |
|
</button> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
|
|
const generateBtn = document.getElementById('generateBtn'); |
|
const exportBtn = document.getElementById('exportBtn'); |
|
const clearBtn = document.getElementById('clearBtn'); |
|
const questionCount = document.getElementById('questionCount'); |
|
const customPrompt = document.getElementById('customPrompt'); |
|
const apiKey = document.getElementById('apiKey'); |
|
const testApiBtn = document.getElementById('testApiBtn'); |
|
const apiStatus = document.getElementById('apiStatus'); |
|
const toggleKey = document.getElementById('toggleKey'); |
|
const uploadBtn = document.getElementById('uploadBtn'); |
|
const externalData = document.getElementById('externalData'); |
|
const fileName = document.getElementById('fileName'); |
|
const questionsContainer = document.getElementById('questionsContainer'); |
|
const loadingIndicator = document.getElementById('loadingIndicator'); |
|
const progressText = document.getElementById('progressText'); |
|
const difficultyBtns = document.querySelectorAll('.difficulty-btn'); |
|
const categoryChips = document.querySelectorAll('.category-chip'); |
|
const tabBtns = document.querySelectorAll('.tab-btn'); |
|
const exportModal = document.getElementById('exportModal'); |
|
const closeExportModal = document.getElementById('closeExportModal'); |
|
const exportFormatBtns = document.querySelectorAll('.export-format-btn'); |
|
const confirmExport = document.getElementById('confirmExport'); |
|
const exportFilter = document.getElementById('exportFilter'); |
|
const prevPage = document.getElementById('prevPage'); |
|
const nextPage = document.getElementById('nextPage'); |
|
const pageInfo = document.getElementById('pageInfo'); |
|
const pagination = document.getElementById('pagination'); |
|
|
|
|
|
let selectedCategories = new Set(['deposit', 'transfer', 'withdrawal', 'security', 'payment', 'card', 'billing', 'basic', 'other']); |
|
let selectedDifficulty = 'random'; |
|
let currentTab = 'all'; |
|
let currentPage = 1; |
|
const questionsPerPage = 10; |
|
let allQuestions = []; |
|
let displayedQuestions = []; |
|
let selectedExportFormat = 'csv'; |
|
let apiConnected = false; |
|
let externalDataContent = ''; |
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
|
document.querySelector('[data-tab="all"]').classList.add('tab-active'); |
|
|
|
|
|
document.querySelector('[data-difficulty="random"]').classList.add('bg-blue-200'); |
|
|
|
|
|
document.querySelector('[data-format="csv"]').classList.add('bg-blue-200', 'text-blue-800'); |
|
}); |
|
|
|
|
|
generateBtn.addEventListener('click', generateQuestions); |
|
exportBtn.addEventListener('click', () => exportModal.classList.remove('hidden')); |
|
clearBtn.addEventListener('click', clearQuestions); |
|
closeExportModal.addEventListener('click', () => exportModal.classList.add('hidden')); |
|
testApiBtn.addEventListener('click', testApiConnection); |
|
toggleKey.addEventListener('click', toggleApiKeyVisibility); |
|
uploadBtn.addEventListener('click', () => externalData.click()); |
|
externalData.addEventListener('change', handleFileUpload); |
|
prevPage.addEventListener('click', () => navigatePage(-1)); |
|
nextPage.addEventListener('click', () => navigatePage(1)); |
|
|
|
|
|
difficultyBtns.forEach(btn => { |
|
btn.addEventListener('click', () => { |
|
difficultyBtns.forEach(b => b.classList.remove('bg-blue-200')); |
|
btn.classList.add('bg-blue-200'); |
|
selectedDifficulty = btn.dataset.difficulty; |
|
}); |
|
}); |
|
|
|
|
|
categoryChips.forEach(chip => { |
|
chip.addEventListener('click', () => { |
|
const category = chip.dataset.category; |
|
if (selectedCategories.has(category)) { |
|
selectedCategories.delete(category); |
|
chip.classList.remove('bg-blue-200'); |
|
} else { |
|
selectedCategories.add(category); |
|
chip.classList.add('bg-blue-200'); |
|
} |
|
}); |
|
}); |
|
|
|
|
|
tabBtns.forEach(btn => { |
|
btn.addEventListener('click', () => { |
|
tabBtns.forEach(b => b.classList.remove('tab-active')); |
|
btn.classList.add('tab-active'); |
|
currentTab = btn.dataset.tab; |
|
filterQuestions(); |
|
}); |
|
}); |
|
|
|
|
|
exportFormatBtns.forEach(btn => { |
|
btn.addEventListener('click', () => { |
|
exportFormatBtns.forEach(b => b.classList.remove('bg-blue-200', 'text-blue-800')); |
|
btn.classList.add('bg-blue-200', 'text-blue-800'); |
|
selectedExportFormat = btn.dataset.format; |
|
}); |
|
}); |
|
|
|
confirmExport.addEventListener('click', exportQuestions); |
|
|
|
|
|
async function generateQuestions() { |
|
if (selectedCategories.size === 0) { |
|
alert('Please select at least one category.'); |
|
return; |
|
} |
|
|
|
const count = parseInt(questionCount.value); |
|
if (isNaN(count) || count < 1 || count > 100) { |
|
alert('Please enter a valid number between 1 and 100.'); |
|
return; |
|
} |
|
|
|
if (!apiConnected) { |
|
alert('Please connect to the DeepSeek API first.'); |
|
return; |
|
} |
|
|
|
|
|
loadingIndicator.classList.remove('hidden'); |
|
questionsContainer.innerHTML = ''; |
|
|
|
try { |
|
|
|
const batchSize = 5; |
|
const batches = Math.ceil(count / batchSize); |
|
allQuestions = []; |
|
|
|
for (let i = 0; i < batches; i++) { |
|
const currentBatchSize = i === batches - 1 ? count - (i * batchSize) : batchSize; |
|
progressText.textContent = `Processing ${i * batchSize}/${count}`; |
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 1000)); |
|
|
|
|
|
const batchQuestions = generateMockQuestions(currentBatchSize); |
|
allQuestions = [...allQuestions, ...batchQuestions]; |
|
} |
|
|
|
|
|
filterQuestions(); |
|
loadingIndicator.classList.add('hidden'); |
|
|
|
} catch (error) { |
|
console.error('Error generating questions:', error); |
|
loadingIndicator.classList.add('hidden'); |
|
questionsContainer.innerHTML = ` |
|
<div class="text-center py-12 text-red-500"> |
|
<i class="fas fa-exclamation-triangle text-4xl mb-3"></i> |
|
<p>Error generating questions. Please try again.</p> |
|
</div> |
|
`; |
|
} |
|
} |
|
|
|
function generateMockQuestions(count) { |
|
const categories = Array.from(selectedCategories); |
|
const difficulties = selectedDifficulty === 'random' ? ['simple', 'medium', 'complex'] : [selectedDifficulty]; |
|
|
|
const mockQuestions = []; |
|
const questionTypes = [ |
|
"How do I {action} with my {account}?", |
|
"What are the steps to {action}?", |
|
"Why is my {action} not working?", |
|
"How long does {action} take to process?", |
|
"What fees are associated with {action}?", |
|
"Can I {action} from multiple devices?", |
|
"Is there a limit to how much I can {action}?", |
|
"What security measures are in place for {action}?", |
|
"How can I track my {action} history?", |
|
"What should I do if my {action} fails?" |
|
]; |
|
|
|
const actionsByCategory = { |
|
deposit: ['deposit money', 'add funds', 'top up my account', 'make a deposit'], |
|
transfer: ['transfer money', 'send funds', 'move money between accounts', 'make a transfer'], |
|
withdrawal: ['withdraw money', 'take out funds', 'cash out', 'make a withdrawal'], |
|
security: ['secure my account', 'change my password', 'enable 2FA', 'report suspicious activity'], |
|
payment: ['make a payment', 'pay a bill', 'send money to a merchant', 'complete a transaction'], |
|
card: ['add a card', 'remove a card', 'update card details', 'report a lost card'], |
|
billing: ['view my transaction history', 'download a statement', 'check my balance', 'review past payments'], |
|
basic: ['log in', 'sign up', 'update my profile', 'contact support'], |
|
other: ['use advanced features', 'access premium services', 'get help', 'resolve issues'] |
|
}; |
|
|
|
for (let i = 0; i < count; i++) { |
|
const category = categories[Math.floor(Math.random() * categories.length)]; |
|
const difficulty = difficulties[Math.floor(Math.random() * difficulties.length)]; |
|
const action = actionsByCategory[category][Math.floor(Math.random() * actionsByCategory[category].length)]; |
|
|
|
const questionTemplate = questionTypes[Math.floor(Math.random() * questionTypes.length)]; |
|
const questionText = questionTemplate |
|
.replace('{action}', action) |
|
.replace('{account}', 'bank account/wallet'); |
|
|
|
mockQuestions.push({ |
|
id: Date.now() + i, |
|
text: questionText, |
|
category: category, |
|
difficulty: difficulty, |
|
generatedAt: new Date().toISOString() |
|
}); |
|
} |
|
|
|
return mockQuestions; |
|
} |
|
|
|
function filterQuestions() { |
|
displayedQuestions = currentTab === 'all' |
|
? allQuestions |
|
: allQuestions.filter(q => q.category === currentTab); |
|
|
|
currentPage = 1; |
|
renderQuestions(); |
|
updatePagination(); |
|
} |
|
|
|
function renderQuestions() { |
|
if (displayedQuestions.length === 0) { |
|
questionsContainer.innerHTML = ` |
|
<div class="text-center py-12 text-gray-500"> |
|
<i class="fas fa-comment-dots text-4xl mb-3"></i> |
|
<p>No questions match the current filter.</p> |
|
</div> |
|
`; |
|
pagination.classList.add('hidden'); |
|
return; |
|
} |
|
|
|
const startIdx = (currentPage - 1) * questionsPerPage; |
|
const endIdx = startIdx + questionsPerPage; |
|
const questionsToShow = displayedQuestions.slice(startIdx, endIdx); |
|
|
|
questionsContainer.innerHTML = ''; |
|
|
|
questionsToShow.forEach(question => { |
|
const categoryColors = { |
|
deposit: 'bg-blue-100 text-blue-800', |
|
transfer: 'bg-purple-100 text-purple-800', |
|
withdrawal: 'bg-indigo-100 text-indigo-800', |
|
security: 'bg-red-100 text-red-800', |
|
payment: 'bg-green-100 text-green-800', |
|
card: 'bg-yellow-100 text-yellow-800', |
|
billing: 'bg-pink-100 text-pink-800', |
|
basic: 'bg-gray-100 text-gray-800', |
|
other: 'bg-teal-100 text-teal-800' |
|
}; |
|
|
|
const difficultyColors = { |
|
simple: 'text-green-600', |
|
medium: 'text-yellow-600', |
|
complex: 'text-red-600' |
|
}; |
|
|
|
const questionEl = document.createElement('div'); |
|
questionEl.className = 'question-card bg-white p-4 rounded-lg border border-gray-200 shadow-sm'; |
|
questionEl.innerHTML = ` |
|
<div class="flex justify-between items-start mb-2"> |
|
<p class="font-medium text-gray-800">${question.text}</p> |
|
<div class="flex space-x-2"> |
|
<span class="text-xs px-2 py-1 rounded-full ${categoryColors[question.category]}">${question.category}</span> |
|
<span class="text-xs px-2 py-1 rounded-full bg-gray-100 text-gray-800 ${difficultyColors[question.difficulty]}">${question.difficulty}</span> |
|
</div> |
|
</div> |
|
<div class="flex justify-between items-center text-xs text-gray-500"> |
|
<span>Generated: ${new Date(question.generatedAt).toLocaleString()}</span> |
|
<div class="flex space-x-2"> |
|
<button class="text-blue-500 hover:text-blue-700"><i class="fas fa-edit"></i></button> |
|
<button class="text-red-500 hover:text-red-700"><i class="fas fa-trash-alt"></i></button> |
|
</div> |
|
</div> |
|
`; |
|
|
|
questionsContainer.appendChild(questionEl); |
|
}); |
|
|
|
pagination.classList.remove('hidden'); |
|
} |
|
|
|
function updatePagination() { |
|
const totalPages = Math.ceil(displayedQuestions.length / questionsPerPage); |
|
pageInfo.textContent = `Page ${currentPage} of ${totalPages}`; |
|
|
|
prevPage.disabled = currentPage === 1; |
|
nextPage.disabled = currentPage === totalPages; |
|
} |
|
|
|
function navigatePage(direction) { |
|
const totalPages = Math.ceil(displayedQuestions.length / questionsPerPage); |
|
const newPage = currentPage + direction; |
|
|
|
if (newPage > 0 && newPage <= totalPages) { |
|
currentPage = newPage; |
|
renderQuestions(); |
|
updatePagination(); |
|
} |
|
} |
|
|
|
function clearQuestions() { |
|
if (allQuestions.length === 0 || confirm('Are you sure you want to clear all generated questions?')) { |
|
allQuestions = []; |
|
displayedQuestions = []; |
|
questionsContainer.innerHTML = ` |
|
<div class="text-center py-12 text-gray-500"> |
|
<i class="fas fa-comment-dots text-4xl mb-3"></i> |
|
<p>No questions generated yet. Configure your settings and click "Generate Questions".</p> |
|
</div> |
|
`; |
|
pagination.classList.add('hidden'); |
|
} |
|
} |
|
|
|
function exportQuestions() { |
|
let questionsToExport = []; |
|
|
|
switch (exportFilter.value) { |
|
case 'all': |
|
questionsToExport = allQuestions; |
|
break; |
|
case 'current': |
|
const startIdx = (currentPage - 1) * questionsPerPage; |
|
const endIdx = startIdx + questionsPerPage; |
|
questionsToExport = displayedQuestions.slice(startIdx, endIdx); |
|
break; |
|
case 'selected': |
|
|
|
alert('No questions selected. Exporting all questions instead.'); |
|
questionsToExport = allQuestions; |
|
break; |
|
} |
|
|
|
if (questionsToExport.length === 0) { |
|
alert('No questions to export.'); |
|
return; |
|
} |
|
|
|
let content = ''; |
|
let mimeType = 'text/plain'; |
|
let extension = 'txt'; |
|
|
|
switch (selectedExportFormat) { |
|
case 'csv': |
|
content = 'ID,Question,Category,Difficulty,Generated At\n'; |
|
questionsToExport.forEach(q => { |
|
content += `"${q.id}","${q.text}","${q.category}","${q.difficulty}","${q.generatedAt}"\n`; |
|
}); |
|
mimeType = 'text/csv'; |
|
extension = 'csv'; |
|
break; |
|
|
|
case 'json': |
|
content = JSON.stringify(questionsToExport, null, 2); |
|
mimeType = 'application/json'; |
|
extension = 'json'; |
|
break; |
|
|
|
case 'txt': |
|
questionsToExport.forEach(q => { |
|
content += `Question: ${q.text}\n`; |
|
content += `Category: ${q.category}\n`; |
|
content += `Difficulty: ${q.difficulty}\n`; |
|
content += `Generated At: ${q.generatedAt}\n\n`; |
|
}); |
|
break; |
|
} |
|
|
|
const blob = new Blob([content], { type: mimeType }); |
|
const url = URL.createObjectURL(blob); |
|
const a = document.createElement('a'); |
|
a.href = url; |
|
a.download = `financial_questions_${new Date().toISOString().slice(0, 10)}.${extension}`; |
|
document.body.appendChild(a); |
|
a.click(); |
|
document.body.removeChild(a); |
|
URL.revokeObjectURL(url); |
|
|
|
exportModal.classList.add('hidden'); |
|
} |
|
|
|
async function testApiConnection() { |
|
if (!apiKey.value.trim()) { |
|
alert('Please enter your DeepSeek API key.'); |
|
return; |
|
} |
|
|
|
testApiBtn.disabled = true; |
|
testApiBtn.innerHTML = '<i class="fas fa-spinner loading-spinner mr-2"></i> Testing'; |
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 1500)); |
|
|
|
|
|
const success = Math.random() > 0.2; |
|
|
|
if (success) { |
|
apiStatus.classList.remove('hidden'); |
|
apiStatus.classList.add('text-green-600'); |
|
apiStatus.classList.remove('text-red-600'); |
|
apiStatus.querySelector('span').textContent = 'Connected to DeepSeek API'; |
|
apiStatus.querySelector('.rounded-full').classList.add('bg-green-500'); |
|
apiStatus.querySelector('.rounded-full').classList.remove('bg-red-500'); |
|
apiConnected = true; |
|
} else { |
|
apiStatus.classList.remove('hidden'); |
|
apiStatus.classList.add('text-red-600'); |
|
apiStatus.classList.remove('text-green-600'); |
|
apiStatus.querySelector('span').textContent = 'Connection failed'; |
|
apiStatus.querySelector('.rounded-full').classList.add('bg-red-500'); |
|
apiStatus.querySelector('.rounded-full').classList.remove('bg-green-500'); |
|
apiConnected = false; |
|
} |
|
|
|
testApiBtn.disabled = false; |
|
testApiBtn.innerHTML = 'Test'; |
|
} |
|
|
|
function toggleApiKeyVisibility() { |
|
const icon = toggleKey.querySelector('i'); |
|
if (apiKey.type === 'password') { |
|
apiKey.type = 'text'; |
|
icon.classList.remove('fa-eye'); |
|
icon.classList.add('fa-eye-slash'); |
|
} else { |
|
apiKey.type = 'password'; |
|
icon.classList.remove('fa-eye-slash'); |
|
icon.classList.add('fa-eye'); |
|
} |
|
} |
|
|
|
function handleFileUpload(event) { |
|
const file = event.target.files[0]; |
|
if (!file) return; |
|
|
|
fileName.textContent = file.name; |
|
|
|
|
|
|
|
externalDataContent = file.name; |
|
|
|
|
|
setTimeout(() => { |
|
alert(`File "${file.name}" has been processed and is ready to be used for RAG.`); |
|
}, 1000); |
|
} |
|
</script> |
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - <a href="https://enzostvs-deepsite.hf.space?remix=Bio-Du/financial-question-generator" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body> |
|
</html> |