|
<!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; |
|
} |
|
.shake { |
|
animation: shake 0.5s linear; |
|
} |
|
@keyframes shake { |
|
0%, 100% { transform: translateX(0); } |
|
20%, 60% { transform: translateX(-5px); } |
|
40%, 80% { transform: translateX(5px); } |
|
} |
|
</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 & User Feedback</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">Provide Suggestion</label> |
|
<textarea id="userSuggestion" rows="2" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Suggest improvements for generated questions..."></textarea> |
|
<button id="submitSuggestion" class="mt-2 px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700"> |
|
<i class="fas fa-lightbulb mr-2"></i> Submit Suggestion |
|
</button> |
|
</div> |
|
|
|
<div id="apiStatus" class="p-3 rounded-lg bg-blue-50 border border-blue-200 flex items-center"> |
|
<div class="w-3 h-3 rounded-full bg-blue-500 mr-2 animate-pulse"></div> |
|
<span class="text-sm text-blue-700">Connected to DeepSeek API</span> |
|
<i class="fas fa-check-circle ml-auto text-green-500"></i> |
|
</div> |
|
|
|
<div class="bg-blue-50 p-4 rounded-lg mt-4"> |
|
<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 through integrated API. 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 overflow-x-auto pb-2"> |
|
<button data-tab="all" class="tab-btn whitespace-nowrap pb-2 px-1 text-gray-600 hover:text-blue-600">All</button> |
|
<button data-tab="deposit" class="tab-btn whitespace-nowrap pb-2 px-1 text-gray-600 hover:text-blue-600">Deposit</button> |
|
<button data-tab="transfer" class="tab-btn whitespace-nowrap pb-2 px-1 text-gray-600 hover:text-blue-600">Transfer</button> |
|
<button data-tab="withdrawal" class="tab-btn whitespace-nowrap pb-2 px-1 text-gray-600 hover:text-blue-600">Withdrawal</button> |
|
<button data-tab="security" class="tab-btn whitespace-nowrap pb-2 px-1 text-gray-600 hover:text-blue-600">Security</button> |
|
<button data-tab="payment" class="tab-btn whitespace-nowrap pb-2 px-1 text-gray-600 hover:text-blue-600">Payment</button> |
|
<button data-tab="card" class="tab-btn whitespace-nowrap pb-2 px-1 text-gray-600 hover:text-blue-600">Card</button> |
|
<button data-tab="billing" class="tab-btn whitespace-nowrap pb-2 px-1 text-gray-600 hover:text-blue-600">Billing</button> |
|
<button data-tab="basic" class="tab-btn whitespace-nowrap pb-2 px-1 text-gray-600 hover:text-blue-600">Basic</button> |
|
<button data-tab="other" class="tab-btn whitespace-nowrap 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> |
|
|
|
|
|
<div id="suggestionModal" 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">Feedback Submitted</h3> |
|
<button id="closeSuggestionModal" class="text-gray-500 hover:text-gray-700"> |
|
<i class="fas fa-times"></i> |
|
</button> |
|
</div> |
|
<div class="flex items-center"> |
|
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mr-4"> |
|
<i class="fas fa-check text-green-500 text-xl"></i> |
|
</div> |
|
<div> |
|
<p class="text-gray-700">Thank you for your suggestion!</p> |
|
<p class="text-sm text-gray-500 mt-1">Your feedback will help improve future question generations.</p> |
|
</div> |
|
</div> |
|
<button id="okSuggestionBtn" class="w-full mt-6 bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg"> |
|
OK |
|
</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 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'); |
|
const uploadBtn = document.getElementById('uploadBtn'); |
|
const externalData = document.getElementById('externalData'); |
|
const fileName = document.getElementById('fileName'); |
|
const userSuggestion = document.getElementById('userSuggestion'); |
|
const submitSuggestion = document.getElementById('submitSuggestion'); |
|
const suggestionModal = document.getElementById('suggestionModal'); |
|
const closeSuggestionModal = document.getElementById('closeSuggestionModal'); |
|
const okSuggestionBtn = document.getElementById('okSuggestionBtn'); |
|
const apiStatus = document.getElementById('apiStatus'); |
|
|
|
|
|
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 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')); |
|
uploadBtn.addEventListener('click', () => externalData.click()); |
|
externalData.addEventListener('change', handleFileUpload); |
|
prevPage.addEventListener('click', () => navigatePage(-1)); |
|
nextPage.addEventListener('click', () => navigatePage(1)); |
|
submitSuggestion.addEventListener('click', submitUserSuggestion); |
|
closeSuggestionModal.addEventListener('click', () => suggestionModal.classList.add('hidden')); |
|
okSuggestionBtn.addEventListener('click', () => suggestionModal.classList.add('hidden')); |
|
|
|
|
|
difficultyBtns.forEach(btn => { |
|
btn.addEventListener('click', () => { |
|
difficultyBtns.forEach(b => { |
|
b.classList.remove('bg-blue-200'); |
|
b.classList.remove('ring-2', 'ring-blue-500'); |
|
}); |
|
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'); |
|
} |
|
|
|
|
|
if (selectedCategories.size === 0) { |
|
chip.classList.add('shake'); |
|
setTimeout(() => chip.classList.remove('shake'), 500); |
|
document.querySelectorAll('.category-chip').forEach(c => { |
|
c.classList.add('ring-2', 'ring-red-500'); |
|
}); |
|
} else { |
|
document.querySelectorAll('.category-chip').forEach(c => { |
|
c.classList.remove('ring-2', 'ring-red-500'); |
|
}); |
|
} |
|
}); |
|
}); |
|
|
|
|
|
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; |
|
} |
|
|
|
|
|
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}`; |
|
|
|
|
|
const categoriesList = Array.from(selectedCategories).join(', '); |
|
const prompt = `Generate ${currentBatchSize} ${selectedDifficulty} English questions about ${categoriesList} in financial/wallet services. ` + |
|
`Ensure questions are varied and avoid redundancy. ${customPrompt.value}`; |
|
|
|
|
|
const batchQuestions = await callDeepSeekApi(prompt, 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> |
|
`; |
|
} |
|
} |
|
|
|
|
|
async function callDeepSeekApi(prompt, count) { |
|
|
|
|
|
|
|
|
|
const delay = 500 + Math.random() * 1000; |
|
await new Promise(resolve => setTimeout(resolve, delay)); |
|
|
|
|
|
const categories = Array.from(selectedCategories); |
|
const batchQuestions = []; |
|
|
|
for (let i = 0; i < count; i++) { |
|
const category = categories[Math.floor(Math.random() * categories.length)]; |
|
const difficulty = selectedDifficulty === 'random' |
|
? ['simple', 'medium', 'complex'][Math.floor(Math.random() * 3)] |
|
: selectedDifficulty; |
|
|
|
const question = generateRealisticQuestion(category, difficulty); |
|
|
|
batchQuestions.push({ |
|
id: Date.now() + i, |
|
text: question, |
|
category: category, |
|
difficulty: difficulty, |
|
generatedAt: new Date().toISOString() |
|
}); |
|
} |
|
|
|
return batchQuestions; |
|
} |
|
|
|
function generateRealisticQuestion(category, difficulty) { |
|
|
|
const questions = { |
|
deposit: { |
|
simple: [ |
|
"How do I deposit money into my digital wallet?", |
|
"What payment methods can I use for deposits?", |
|
"Is there a minimum amount for deposits?" |
|
], |
|
medium: [ |
|
"Why is my deposit taking longer than usual to process?", |
|
"Can I deposit funds from an international bank account?", |
|
"What are the deposit limits for unverified accounts?" |
|
], |
|
complex: [ |
|
"How does the deposit reconciliation process work during weekends?", |
|
"What security protocols are in place for large deposit transactions?", |
|
"Can you explain the multi-signature verification process for deposits?" |
|
] |
|
}, |
|
transfer: { |
|
simple: [ |
|
"How do I send money to another user?", |
|
"What's the maximum amount I can transfer in one transaction?", |
|
"How long do transfers usually take?" |
|
], |
|
medium: [ |
|
"Why was my transfer returned by the recipient's bank?", |
|
"Can I schedule recurring transfers to family members?", |
|
"How do foreign currency transfers work?" |
|
], |
|
complex: [ |
|
"What are the tax implications for international transfers over $10,000?", |
|
"How does the blockchain verification process work for crypto transfers?", |
|
"Can you explain the interbank settlement procedures for instant transfers?" |
|
] |
|
}, |
|
withdrawal: { |
|
simple: [ |
|
"How do I withdraw money to my bank account?", |
|
"Are there any fees for withdrawals?", |
|
"How long does a withdrawal take to process?" |
|
], |
|
medium: [ |
|
"Why does my withdrawal request keep getting declined?", |
|
"Can I withdraw to a different bank than my deposit source?", |
|
"What are the tax reporting requirements for large withdrawals?" |
|
], |
|
complex: [ |
|
"How are AML checks performed on high-value withdrawal requests?", |
|
"What are the reserve requirements that affect withdrawal processing times?", |
|
"Can you explain the cross-border clearance process for international withdrawals?" |
|
] |
|
}, |
|
security: { |
|
simple: [ |
|
"How do I create a strong password for my account?", |
|
"What should I do if I lose my phone with my wallet app?", |
|
"How does two-factor authentication work?" |
|
], |
|
medium: [ |
|
"Why did I receive a security alert for a login attempt?", |
|
"Can I restrict transactions from certain locations?", |
|
"How are my biometric data stored and protected?" |
|
], |
|
complex: [ |
|
"What cryptographic techniques are used to secure financial transactions?", |
|
"How does the zero-knowledge proof verification process work?", |
|
"Can you explain the multi-party computation protocol used for key management?" |
|
] |
|
}, |
|
payment: { |
|
simple: [ |
|
"How do I pay a merchant using my digital wallet?", |
|
"Can I split a payment with friends?", |
|
"What's contactless payment and how does it work?" |
|
], |
|
medium: [ |
|
"Why was my payment to a merchant declined?", |
|
"Can I dispute a payment after it's completed?", |
|
"How do recurring subscription payments work?" |
|
], |
|
complex: [ |
|
"What are the PCI-DSS compliance requirements for tokenized payments?", |
|
"How does the merchant acquiring bank authorization process work?", |
|
"Can you explain the chargeback arbitration process?" |
|
] |
|
}, |
|
card: { |
|
simple: [ |
|
"How do I add a debit card to my wallet?", |
|
"Can I remove a saved card from my account?", |
|
"What should I do if my card is lost or stolen?" |
|
], |
|
medium: [ |
|
"Why is my card verification failing during checkout?", |
|
"Can I set spending limits for specific cards?", |
|
"How do virtual card numbers work?" |
|
], |
|
complex: [ |
|
"How are card details tokenized during online transactions?", |
|
"What are the EMV 3D Secure 2.0 authentication protocols?", |
|
"Can you explain the card network settlement reconciliation process?" |
|
] |
|
}, |
|
billing: { |
|
simple: [ |
|
"How do I view my transaction history?", |
|
"Can I download my monthly statements?", |
|
"Where can I see my current balance?" |
|
], |
|
medium: [ |
|
"Why is there a discrepancy in my transaction records?", |
|
"Can I generate customized reports for tax purposes?", |
|
"How do I categorize transactions for budgeting?" |
|
], |
|
complex: [ |
|
"What accounting standards are followed for transaction record-keeping?", |
|
"How does the GL reconciliation process work across multiple currencies?", |
|
"Can you explain the audit trail generation process?" |
|
] |
|
}, |
|
basic: { |
|
simple: [ |
|
"How do I create an account?", |
|
"What's the customer support phone number?", |
|
"Where can I find the app settings?" |
|
], |
|
medium: [ |
|
"Why can't I receive the verification SMS?", |
|
"Can I merge two accounts under one email?", |
|
"How do I update my personal information?" |
|
], |
|
complex: [ |
|
"What identity verification protocols are used during KYC onboarding?", |
|
"How does the real-time account monitoring system work?", |
|
"Can you explain the multi-jurisdictional compliance process?" |
|
] |
|
}, |
|
other: { |
|
simple: [ |
|
"What currencies does your service support?", |
|
"Can I use this service while traveling abroad?", |
|
"Where can I find your terms of service?" |
|
], |
|
medium: [ |
|
"Why can't I access certain features in my country?", |
|
"Can I give limited access to an accountant?", |
|
"How does interest accrual work on stored balances?" |
|
], |
|
complex: [ |
|
"What regulatory bodies oversee the financial services provided?", |
|
"How are exchange rates calculated for multi-currency transactions?", |
|
"Can you explain the liquidity provisions for fast settlements?" |
|
] |
|
} |
|
}; |
|
|
|
|
|
let possibleQuestions = questions[category][difficulty]; |
|
|
|
|
|
if (selectedDifficulty === 'random') { |
|
possibleQuestions = [ |
|
...questions[category].simple, |
|
...questions[category].medium, |
|
...questions[category].complex |
|
]; |
|
} |
|
|
|
|
|
return possibleQuestions[Math.floor(Math.random() * possibleQuestions.length)]; |
|
} |
|
|
|
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 data-id="${question.id}" class="edit-btn text-blue-500 hover:text-blue-700"><i class="fas fa-edit"></i></button> |
|
<button data-id="${question.id}" class="delete-btn text-red-500 hover:text-red-700"><i class="fas fa-trash-alt"></i></button> |
|
</div> |
|
</div> |
|
`; |
|
|
|
questionsContainer.appendChild(questionEl); |
|
}); |
|
|
|
|
|
document.querySelectorAll('.edit-btn').forEach(btn => { |
|
btn.addEventListener('click', (e) => editQuestion(e.target.closest('button').dataset.id)); |
|
}); |
|
|
|
document.querySelectorAll('.delete-btn').forEach(btn => { |
|
btn.addEventListener('click', (e) => deleteQuestion(e.target.closest('button').dataset.id)); |
|
}); |
|
|
|
pagination.classList.remove('hidden'); |
|
} |
|
|
|
function editQuestion(id) { |
|
const question = allQuestions.find(q => q.id.toString() === id); |
|
if (!question) return; |
|
|
|
const newText = prompt("Edit question:", question.text); |
|
if (newText && newText.trim() !== '') { |
|
question.text = newText.trim(); |
|
renderQuestions(); |
|
} |
|
} |
|
|
|
function deleteQuestion(id) { |
|
if (confirm("Are you sure you want to delete this question?")) { |
|
allQuestions = allQuestions.filter(q => q.id.toString() !== id); |
|
filterQuestions(); |
|
} |
|
} |
|
|
|
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'); |
|
} |
|
|
|
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); |
|
} |
|
|
|
function submitUserSuggestion() { |
|
const suggestion = userSuggestion.value.trim(); |
|
if (!suggestion) { |
|
userSuggestion.classList.add('ring-2', 'ring-red-500'); |
|
setTimeout(() => userSuggestion.classList.remove('ring-2', 'ring-red-500'), 1000); |
|
return; |
|
} |
|
|
|
|
|
console.log("User suggestion submitted:", suggestion); |
|
|
|
|
|
suggestionModal.classList.remove('hidden'); |
|
userSuggestion.value = ''; |
|
|
|
|
|
|
|
} |
|
</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> |