smart-dictionary-v1 / index.html
alterzick's picture
Add 3 files
38e9357 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Online Dictionary App</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>
<link href="https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.css" rel="stylesheet" type="text/css" />
<script src="https://kit.fontawesome.com/1f7e5e05ce.js" crossorigin="anonymous"></script>
</head>
<body class="bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen">
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="text-center mb-10">
<h1 class="text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600 mb-2">
<i class="fas fa-book mr-3"></i>Smart Dictionary
</h1>
<p class="text-gray-600">Create, manage and share your personal dictionary with ease</p>
</header>
<!-- Main Tabs -->
<div class="tabs tabs-lifted w-full max-w-6xl mx-auto mb-6">
<a class="tab tab-lg" id="input-tab">📝 Input</a>
<a class="tab tab-lg" id="search-tab">🔍 Search</a>
<a class="tab tab-lg" id="records-tab">📊 Records</a>
<a class="tab tab-lg" id="import-tab">📂 Import/Export</a>
</div>
<!-- Input Tab Content -->
<div id="input-content" class="tab-content bg-white rounded-xl shadow-xl p-8 mb-8 transition-all duration-300">
<h2 class="text-2xl font-semibold mb-6 text-gray-800 flex items-center">
<i class="fas fa-plus-circle mr-3 text-green-500"></i>Add New Dictionary Entry
</h2>
<form id="dictionary-form" class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Word</span>
<span class="label-text-alt text-red-500">*</span>
</label>
<input type="text" id="word" placeholder="Enter word" class="input input-bordered w-full" required />
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Part of Speech</span>
</label>
<select id="part-of-speech" class="select select-bordered w-full">
<option value="">Select...</option>
<option value="noun">Noun</option>
<option value="verb">Verb</option>
<option value="adjective">Adjective</option>
<option value="adverb">Adverb</option>
<option value="pronoun">Pronoun</option>
<option value="preposition">Preposition</option>
<option value="conjunction">Conjunction</option>
<option value="interjection">Interjection</option>
</select>
</div>
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Definition</span>
<span class="label-text-alt text-red-500">*</span>
</label>
<textarea id="definition" placeholder="Enter definition" class="textarea textarea-bordered h-24" required></textarea>
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Example</span>
</label>
<textarea id="example" placeholder="Enter example usage" class="textarea textarea-bordered h-24"></textarea>
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Synonyms</span>
</label>
<input type="text" id="synonyms" placeholder="Comma separated synonyms" class="input input-bordered w-full" />
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Category/Tags</span>
</label>
<input type="text" id="tags" placeholder="Comma separated tags (e.g. tech, medical, slang)" class="input input-bordered w-full" />
</div>
<div class="flex flex-wrap gap-4 pt-4">
<button type="submit" class="btn btn-primary btn-lg flex-1 md:flex-none">
<i class="fas fa-save mr-2"></i>Save Entry
</button>
<button type="button" id="clear-form" class="btn btn-outline btn-lg flex-1 md:flex-none">
<i class="fas fa-times mr-2"></i>Clear
</button>
</div>
</form>
</div>
<!-- Search Tab Content -->
<div id="search-content" class="tab-content bg-white rounded-xl shadow-xl p-8 mb-8 hidden transition-all duration-300">
<h2 class="text-2xl font-semibold mb-6 text-gray-800 flex items-center">
<i class="fas fa-search mr-3 text-blue-500"></i>Search Dictionary
</h2>
<div class="form-control mb-6">
<label class="label">
<span class="label-text font-medium">Search Term</span>
</label>
<div class="relative">
<input type="text" id="search-input" placeholder="Search for words, definitions, tags..." class="input input-bordered w-full pr-12" />
<button id="search-btn" class="btn btn-square btn-ghost absolute right-1 top-1">
<i class="fas fa-search"></i>
</button>
</div>
</div>
<div class="form-control mb-6">
<label class="label cursor-pointer">
<span class="label-text">Search in definitions as well</span>
<input type="checkbox" id="search-in-definitions" class="checkbox checkbox-primary" checked />
</label>
</div>
<div id="search-results" class="mt-6 space-y-4"></div>
</div>
<!-- Records Tab Content -->
<div id="records-content" class="tab-content bg-white rounded-xl shadow-xl p-8 mb-8 hidden transition-all duration-300">
<h2 class="text-2xl font-semibold mb-6 text-gray-800 flex items-center">
<i class="fas fa-database mr-3 text-purple-500"></i>All Dictionary Entries
<span id="record-count" class="badge badge-primary ml-3"></span>
</h2>
<div class="overflow-x-auto">
<table id="records-table" class="table table-zebra w-full">
<thead>
<tr>
<th>Word</th>
<th>Part of Speech</th>
<th>Definition</th>
<th>Actions</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<!-- Import/Export Tab Content -->
<div id="import-content" class="tab-content bg-white rounded-xl shadow-xl p-8 hidden transition-all duration-300">
<h2 class="text-2xl font-semibold mb-6 text-gray-800 flex items-center">
<i class="fas fa-file-import mr-3 text-orange-500"></i>Import/Export Data
</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- Import Section -->
<div class="p-6 border-2 border-dashed border-blue-300 rounded-xl bg-blue-50">
<h3 class="text-xl font-semibold mb-4 text-blue-700 flex items-center">
<i class="fas fa-upload mr-3"></i>Import Data
</h3>
<p class="text-gray-700 mb-4">Import your dictionary data from Excel (XLS/XLSX) file.</p>
<div class="form-control">
<label class="label">
<span class="label-text">Upload Excel File</span>
</label>
<input type="file" id="import-file" accept=".xlsx, .xls" class="file-input file-input-bordered w-full" />
</div>
<button id="import-btn" class="btn btn-primary mt-4 w-full">
<i class="fas fa-download mr-2"></i>Import Data
</button>
<div class="mt-4 text-sm text-gray-600">
<p><strong>File format requirements:</strong></p>
<ul class="list-disc list-inside mt-1">
<li>Must be in XLS or XLSX format</li>
<li>First row should contain headers: Word, PartOfSpeech, Definition, Example, Synonyms, Tags</li>
<li>All fields except "Example", "Synonyms", and "Tags" are required</li>
</ul>
</div>
</div>
<!-- Export Section -->
<div class="p-6 border-2 border-dashed border-green-300 rounded-xl bg-green-50">
<h3 class="text-xl font-semibold mb-4 text-green-700 flex items-center">
<i class="fas fa-download mr-3"></i>Export Data
</h3>
<p class="text-gray-700 mb-4">Export your dictionary data to Excel for backup or sharing.</p>
<button id="export-btn" class="btn btn-success w-full text-lg py-4">
<i class="fas fa-file-excel mr-2"></i>Export to Excel
</button>
<div class="mt-4 text-sm text-gray-600">
<p><strong>Export options:</strong></p>
<ul class="list-disc list-inside mt-1">
<li>Exports all dictionary entries</li>
<li>Creates an XLSX file compatible with Excel and Google Sheets</li>
<li>Includes all data fields</li>
</ul>
</div>
</div>
</div>
<div class="mt-8 p-4 bg-yellow-50 border-l-4 border-yellow-400 rounded">
<p class="text-sm text-yellow-800 flex items-start">
<i class="fas fa-exclamation-triangle mr-2 mt-1"></i>
<strong>Warning:</strong> Importing a new file will overwrite any existing entries with the same words. Please backup your data before importing.
</p>
</div>
</div>
<!-- Toast Notification -->
<div id="toast" class="toast toast-top toast-end hidden">
<div id="toast-content" class="alert alert-success">
<span id="toast-message"></span>
</div>
</div>
<!-- Edit Modal -->
<input type="checkbox" id="edit-modal" class="modal-toggle" />
<div class="modal modal-bottom sm:modal-middle">
<div class="modal-box">
<h3 id="edit-modal-title" class="font-bold text-lg mb-4">Edit Entry</h3>
<form id="edit-form" class="space-y-4">
<input type="hidden" id="edit-id" />
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Word</span>
</label>
<input type="text" id="edit-word" class="input input-bordered w-full" required />
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Part of Speech</span>
</label>
<select id="edit-part-of-speech" class="select select-bordered w-full">
<option value="">Select...</option>
<option value="noun">Noun</option>
<option value="verb">Verb</option>
<option value="adjective">Adjective</option>
<option value="adverb">Adverb</option>
<option value="pronoun">Pronoun</option>
<option value="preposition">Preposition</option>
<option value="conjunction">Conjunction</option>
<option value="interjection">Interjection</option>
</select>
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Definition</span>
</label>
<textarea id="edit-definition" class="textarea textarea-bordered h-24" required></textarea>
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Example</span>
</label>
<textarea id="edit-example" class="textarea textarea-bordered h-24"></textarea>
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Synonyms</span>
</label>
<input type="text" id="edit-synonyms" class="input input-bordered w-full" />
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Tags</span>
</label>
<input type="text" id="edit-tags" class="input input-bordered w-full" />
</div>
<div class="modal-action">
<button type="submit" class="btn btn-primary">Save Changes</button>
<label for="edit-modal" class="btn">Cancel</label>
</div>
</form>
</div>
</div>
<!-- Delete Confirmation Modal -->
<input type="checkbox" id="delete-modal" class="modal-toggle" />
<div class="modal">
<div class="modal-box">
<h3 id="delete-modal-title" class="font-bold text-lg">Delete Confirmation</h3>
<p id="delete-modal-body" class="py-4">Are you sure you want to delete this entry? This action cannot be undone.</p>
<div class="modal-action">
<button id="confirm-delete" class="btn btn-error">Yes, Delete</button>
<label for="delete-modal" class="btn">Cancel</label>
</div>
</div>
</div>
</div>
<script>
// Dictionary App Main Logic
document.addEventListener('DOMContentLoaded', function() {
// Initialize local storage if not exists
if (!localStorage.getItem('dictionaryEntries')) {
localStorage.setItem('dictionaryEntries', JSON.stringify([]));
}
// Tab functionality
const tabs = document.querySelectorAll('.tab');
const tabContents = document.querySelectorAll('.tab-content');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
// Remove active class from all tabs and contents
tabs.forEach(t => t.classList.remove('tab-active'));
tabContents.forEach(content => content.classList.add('hidden'));
// Add active class to clicked tab and corresponding content
tab.classList.add('tab-active');
const tabId = tab.id.replace('-tab', '-content');
document.getElementById(tabId).classList.remove('hidden');
// Special handling for records tab - refresh table when shown
if (tabId === 'records-content') {
displayAllRecords();
}
});
});
// Show input tab by default
document.getElementById('input-tab').click();
// Dictionary data functions
function getEntries() {
return JSON.parse(localStorage.getItem('dictionaryEntries')) || [];
}
function saveEntries(entries) {
localStorage.setItem('dictionaryEntries', JSON.stringify(entries));
}
function addEntry(entry) {
const entries = getEntries();
// Check if word already exists and update if it does
const existingIndex = entries.findIndex(e => e.word.toLowerCase() === entry.word.toLowerCase());
if (existingIndex > -1) {
entries[existingIndex] = { ...entries[existingIndex], ...entry };
} else {
entry.id = Date.now(); // Simple ID generation
entries.push(entry);
}
saveEntries(entries);
}
function updateEntry(id, updatedEntry) {
const entries = getEntries();
const index = entries.findIndex(e => e.id == id);
if (index > -1) {
entries[index] = { ...entries[index], ...updatedEntry };
saveEntries(entries);
}
}
function deleteEntry(id) {
let entries = getEntries();
entries = entries.filter(e => e.id != id);
saveEntries(entries);
}
function searchEntries(term, searchInDefinitions = true) {
const entries = getEntries();
const searchTerm = term.toLowerCase();
return entries.filter(entry => {
if (entry.word.toLowerCase().includes(searchTerm)) {
return true;
}
if (searchInDefinitions && entry.definition.toLowerCase().includes(searchTerm)) {
return true;
}
if (entry.synonyms && entry.synonyms.toLowerCase().includes(searchTerm)) {
return true;
}
if (entry.tags && entry.tags.toLowerCase().includes(searchTerm)) {
return true;
}
return false;
});
}
// Form submission
const dictionaryForm = document.getElementById('dictionary-form');
dictionaryForm.addEventListener('submit', function(e) {
e.preventDefault();
const entry = {
word: document.getElementById('word').value.trim(),
partOfSpeech: document.getElementById('part-of-speech').value,
definition: document.getElementById('definition').value.trim(),
example: document.getElementById('example').value.trim(),
synonyms: document.getElementById('synonyms').value.trim(),
tags: document.getElementById('tags').value.trim()
};
// Validation
if (!entry.word) {
showNotification('Word is required', 'error');
return;
}
if (!entry.definition) {
showNotification('Definition is required', 'error');
return;
}
addEntry(entry);
showNotification('Entry added successfully!', 'success');
// Reset form
dictionaryForm.reset();
});
// Clear form
document.getElementById('clear-form').addEventListener('click', function() {
dictionaryForm.reset();
});
// Search functionality
const searchBtn = document.getElementById('search-btn');
const searchInput = document.getElementById('search-input');
const searchInDefinitions = document.getElementById('search-in-definitions');
const searchResults = document.getElementById('search-results');
function performSearch() {
const term = searchInput.value.trim();
if (!term) {
searchResults.innerHTML = '<div class="alert alert-info">Enter a search term above.</div>';
return;
}
const results = searchEntries(term, searchInDefinitions.checked);
if (results.length === 0) {
searchResults.innerHTML = '<div class="alert alert-warning">No entries found matching your search.</div>';
return;
}
searchResults.innerHTML = `
<div class="alert alert-info mb-4">
Found ${results.length} result${results.length !== 1 ? 's' : ''} for "${term}"
</div>
${results.map(renderEntryCard).join('')}
`;
// Add event listeners to edit and delete buttons
document.querySelectorAll('.edit-btn').forEach(btn => {
btn.addEventListener('click', handleEditClick);
});
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', handleDeleteClick);
});
}
searchBtn.addEventListener('click', performSearch);
searchInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
performSearch();
}
});
searchInDefinitions.addEventListener('change', performSearch);
// Display all records
function displayAllRecords() {
const entries = getEntries();
const tableBody = document.querySelector('#records-table tbody');
const recordCount = document.getElementById('record-count');
if (entries.length === 0) {
tableBody.innerHTML = `
<tr>
<td colspan="4" class="text-center py-8 text-gray-500">
<i class="fas fa-inbox text-4xl mb-2 opacity-50"></i>
<div>No entries yet. Start by adding your first word!</div>
</td>
</tr>
`;
recordCount.textContent = '0 entries';
return;
}
tableBody.innerHTML = entries.map(entry => {
return `
<tr>
<td class="font-medium">${entry.word}</td>
<td>${entry.partOfSpeech || '-'}</td>
<td>${truncateText(entry.definition, 80)}</td>
<td>
<div class="join join-vertical md:join-horizontal">
<button class="btn btn-xs btn-outline join-item edit-btn" data-id="${entry.id}">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-xs btn-outline join-item delete-btn" data-id="${entry.id}">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
`;
}).join('');
recordCount.textContent = `${entries.length} entries`;
// Add event listeners to edit and delete buttons
document.querySelectorAll('.edit-btn').forEach(btn => {
btn.addEventListener('click', handleEditClick);
});
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', handleDeleteClick);
});
}
// Edit entry
let currentEditId = null;
function handleEditClick(e) {
currentEditId = e.target.closest('.edit-btn').dataset.id;
const entries = getEntries();
const entry = entries.find(e => e.id == currentEditId);
// Fill the form
document.getElementById('edit-id').value = entry.id;
document.getElementById('edit-word').value = entry.word;
document.getElementById('edit-part-of-speech').value = entry.partOfSpeech || '';
document.getElementById('edit-definition').value = entry.definition;
document.getElementById('edit-example').value = entry.example || '';
document.getElementById('edit-synonyms').value = entry.synonyms || '';
document.getElementById('edit-tags').value = entry.tags || '';
// Show modal
document.getElementById('edit-modal').checked = true;
}
document.getElementById('edit-form').addEventListener('submit', function(e) {
e.preventDefault();
const updatedEntry = {
word: document.getElementById('edit-word').value.trim(),
partOfSpeech: document.getElementById('edit-part-of-speech').value,
definition: document.getElementById('edit-definition').value.trim(),
example: document.getElementById('edit-example').value.trim(),
synonyms: document.getElementById('edit-synonyms').value.trim(),
tags: document.getElementById('edit-tags').value.trim()
};
// Validation
if (!updatedEntry.word) {
showNotification('Word is required', 'error');
return;
}
if (!updatedEntry.definition) {
showNotification('Definition is required', 'error');
return;
}
updateEntry(currentEditId, updatedEntry);
showNotification('Entry updated successfully!', 'success');
// Close modal
document.getElementById('edit-modal').checked = false;
// Refresh views if needed
if (!document.getElementById('search-content').classList.contains('hidden')) {
performSearch();
}
if (!document.getElementById('records-content').classList.contains('hidden')) {
displayAllRecords();
}
});
// Delete entry
let currentDeleteId = null;
function handleDeleteClick(e) {
currentDeleteId = e.target.closest('.delete-btn').dataset.id;
// Update modal content
const entries = getEntries();
const entry = entries.find(e => e.id == currentDeleteId);
document.getElementById('delete-modal-body').textContent =
`Are you sure you want to delete "${entry.word}"? This action cannot be undone.`;
// Show modal
document.getElementById('delete-modal').checked = true;
}
document.getElementById('confirm-delete').addEventListener('click', function() {
deleteEntry(currentDeleteId);
showNotification('Entry deleted successfully!', 'success');
// Close modal
document.getElementById('delete-modal').checked = false;
// Refresh views if needed
if (!document.getElementById('search-content').classList.contains('hidden')) {
performSearch();
}
if (!document.getElementById('records-content').classList.contains('hidden')) {
displayAllRecords();
}
});
// Import/Export functionality
document.getElementById('import-btn').addEventListener('click', function() {
const fileInput = document.getElementById('import-file');
const file = fileInput.files[0];
if (!file) {
showNotification('Please select a file to import', 'error');
return;
}
const reader = new FileReader();
reader.onload = function(e) {
try {
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, { type: 'array' });
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
const jsonData = XLSX.utils.sheet_to_json(firstSheet);
// Validate data structure
const requiredFields = ['Word', 'Definition'];
const missingFields = requiredFields.filter(field => !jsonData[0] || !jsonData[0].hasOwnProperty(field));
if (missingFields.length > 0) {
showNotification(`Required column(s) missing: ${missingFields.join(', ')}`, 'error');
return;
}
// Process data
const entries = getEntries();
let importedCount = 0;
jsonData.forEach(row => {
// Skip empty rows
if (!row.Word || !row.Definition) return;
const entry = {
word: row.Word.trim(),
partOfSpeech: row.PartOfSpeech || '',
definition: row.Definition.trim(),
example: row.Example || '',
synonyms: row.Synonyms || '',
tags: row.Tags || '',
id: Date.now() + Math.floor(Math.random() * 1000) // Generate unique ID
};
// Check if word already exists and update if needed
const existingIndex = entries.findIndex(e => e.word.toLowerCase() === entry.word.toLowerCase());
if (existingIndex > -1) {
entries[existingIndex] = { ...entries[existingIndex], ...entry };
} else {
entries.push(entry);
}
importedCount++;
});
saveEntries(entries);
showNotification(`Successfully imported ${importedCount} entries!`, 'success');
// Clear file input
fileInput.value = '';
// Refresh views
if (!document.getElementById('records-content').classList.contains('hidden')) {
displayAllRecords();
}
} catch (error) {
console.error(error);
showNotification('Error processing file. Please check the format and try again.', 'error');
}
};
reader.readAsArrayBuffer(file);
});
document.getElementById('export-btn').addEventListener('click', function() {
const entries = getEntries();
if (entries.length === 0) {
showNotification('No data to export', 'warning');
return;
}
// Transform data for export
const exportData = entries.map(entry => ({
'Word': entry.word,
'PartOfSpeech': entry.partOfSpeech || '',
'Definition': entry.definition,
'Example': entry.example || '',
'Synonyms': entry.synonyms || '',
'Tags': entry.tags || ''
}));
// Create worksheet
const worksheet = XLSX.utils.json_to_sheet(exportData);
// Create workbook
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Dictionary');
// Generate file
XLSX.writeFile(workbook, `dictionary_export_${new Date().toISOString().split('T')[0]}.xlsx`);
showNotification('Data exported successfully!', 'success');
});
// Helper functions
function renderEntryCard(entry) {
return `
<div class="card bg-base-100 shadow-md border border-gray-100 mb-4">
<div class="card-body p-6">
<h3 class="card-title text-xl">
${entry.word}
${entry.partOfSpeech ? `<span class="badge badge-outline text-sm">${entry.partOfSpeech}</span>` : ''}
</h3>
<div class="mt-2">
<p><strong>Definition:</strong> ${entry.definition}</p>
${entry.example ? `<p class="mt-2"><strong>Example:</strong> ${entry.example}</p>` : ''}
${entry.synonyms ? `<p class="mt-2"><strong>Synonyms:</strong> ${entry.synonyms}</p>` : ''}
${entry.tags ? `<p class="mt-2"><strong>Tags:</strong> ${entry.tags.split(',').map(tag => `<span class="badge badge-ghost">${tag.trim()}</span>`).join(' ')}</p>` : ''}
</div>
<div class="card-actions justify-end mt-4">
<button class="btn btn-outline btn-sm edit-btn" data-id="${entry.id}">
<i class="fas fa-edit mr-1"></i>Edit
</button>
<button class="btn btn-outline btn-error btn-sm delete-btn" data-id="${entry.id}">
<i class="fas fa-trash mr-1"></i>Delete
</button>
</div>
</div>
</div>
`;
}
function truncateText(text, maxLength) {
if (text.length <= maxLength) {
return text;
}
return text.substring(0, maxLength) + '...';
}
function showNotification(message, type = 'success') {
const toast = document.getElementById('toast');
const toastContent = document.getElementById('toast-content');
const toastMessage = document.getElementById('toast-message');
// Set message and style
toastMessage.textContent = message;
// Remove previous classes
toastContent.className = 'alert';
// Add appropriate class based on type
if (type === 'error') {
toastContent.classList.add('alert-error');
} else if (type === 'warning') {
toastContent.classList.add('alert-warning');
} else {
toastContent.classList.add('alert-success');
}
// Show toast
toast.classList.remove('hidden');
// Hide after 3 seconds
setTimeout(() => {
toast.classList.add('hidden');
}, 3000);
}
// Initialize the app
displayAllRecords();
});
</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-qwensite.hf.space/logo.svg" alt="qwensite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-qwensite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >QwenSite</a> - 🧬 <a href="https://enzostvs-qwensite.hf.space?remix=alterzick/smart-dictionary-v1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>