doegoth / dashboard.js
PISAN
สร้างหน้าแดชบอร์ดอินเตอร์แอคทิฟสามารถเพิ่มลบแก้ไขข้อมูลได้บันทึกข้อมูลได้เชื่อมต่อกับฟิลด์บนส่วนพรีวิวโอัพเดทดูผลลัพธ์ได้ทันที ใช้การจัดการข้อมูลมาตรฐานโปรดักชั่น
9a9a400 verified
'use strict';
// Connect to existing DB from script.js
const DB_NAME = 'PDFWizardDB';
const STORE = 'docs';
let db;
// Field mapping (matches preview fields)
const fieldMap = {
'1': 'field-1', // Name
'2': 'field-2', // Position
'3': 'field-3', // Department
'4': 'field-4', // Photo URL
'5': 'field-5', // Start Date
'6': 'field-6', // End Date
'7': 'field-7', // Company
'8': 'field-8', // City
'9': 'field-9', // Postal Code
'10': 'field-10', // Country
'11': 'field-11', // Reference No.
'12': 'field-12' // Document No.
};
document.addEventListener('DOMContentLoaded', async () => {
try {
await initDB();
setupEventListeners();
loadRecords();
} catch (e) {
console.error('Dashboard init error:', e);
}
});
function initDB() {
return new Promise((resolve, reject) => {
const req = indexedDB.open(DB_NAME, 1);
req.onupgradeneeded = (e) => {
const db = e.target.result;
if (!db.objectStoreNames.contains(STORE)) {
db.createObjectStore(STORE, { keyPath: 'id' });
}
};
req.onsuccess = () => {
db = req.result;
resolve();
};
req.onerror = () => reject(req.error);
});
}
function setupEventListeners() {
// Add Record Button
document.getElementById('btn-add-record').addEventListener('click', () => {
document.getElementById('record-form').reset();
document.getElementById('record-id').value = '';
document.getElementById('modal-title').textContent = 'Add New Record';
document.getElementById('record-modal').classList.remove('hidden');
});
// Modal Buttons
document.getElementById('btn-cancel').addEventListener('click', () => {
document.getElementById('record-modal').classList.add('hidden');
});
document.getElementById('btn-save').addEventListener('click', saveRecord);
// Close Modal
document.querySelectorAll('.close-modal').forEach(btn => {
btn.addEventListener('click', () => {
document.getElementById('record-modal').classList.add('hidden');
});
});
}
async function loadRecords() {
try {
const records = await getAllRecords();
renderRecords(records);
} catch (e) {
console.error('Error loading records:', e);
}
}
function getAllRecords() {
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE, 'readonly');
const store = tx.objectStore(STORE);
const req = store.getAll();
req.onsuccess = () => resolve(req.result || []);
req.onerror = () => reject(req.error);
});
}
function renderRecords(records) {
const tbody = document.getElementById('data-table-body');
tbody.innerHTML = '';
if (records.length === 0) {
tbody.innerHTML = `
<tr>
<td colspan="5" class="px-6 py-4 text-center text-slate-500">
No records found. Click "Add Record" to create one.
</td>
</tr>
`;
return;
}
records.forEach(record => {
const tr = document.createElement('tr');
tr.className = 'hover:bg-slate-50 dark:hover:bg-slate-700/50';
tr.innerHTML = `
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-slate-900 dark:text-slate-200">
${record.id.substring(0, 6)}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-slate-500 dark:text-slate-400">
${record.data['1'] || 'N/A'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-slate-500 dark:text-slate-400">
${record.data['2'] || 'N/A'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-slate-500 dark:text-slate-400">
${record.data['7'] || 'N/A'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button class="btn-edit text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3" data-id="${record.id}">
<i data-feather="edit-2" class="w-4 h-4"></i>
</button>
<button class="btn-delete text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300" data-id="${record.id}">
<i data-feather="trash-2" class="w-4 h-4"></i>
</button>
</td>
`;
tbody.appendChild(tr);
});
// Add event listeners to action buttons
document.querySelectorAll('.btn-edit').forEach(btn => {
btn.addEventListener('click', (e) => editRecord(e.target.closest('button').dataset.id));
});
document.querySelectorAll('.btn-delete').forEach(btn => {
btn.addEventListener('click', (e) => deleteRecord(e.target.closest('button').dataset.id));
});
feather.replace();
}
async function editRecord(id) {
try {
const record = await getRecord(id);
if (!record) return;
document.getElementById('modal-title').textContent = 'Edit Record';
document.getElementById('record-id').value = record.id;
// Populate form fields
Object.keys(fieldMap).forEach(key => {
const fieldId = fieldMap[key];
const field = document.getElementById(fieldId);
if (field) field.value = record.data[key] || '';
});
document.getElementById('record-modal').classList.remove('hidden');
} catch (e) {
console.error('Error editing record:', e);
}
}
function getRecord(id) {
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE, 'readonly');
const store = tx.objectStore(STORE);
const req = store.get(id);
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
}
async function saveRecord() {
const form = document.getElementById('record-form');
if (!form.checkValidity()) {
form.reportValidity();
return;
}
const id = document.getElementById('record-id').value || Date.now().toString();
const record = {
id,
date: new Date().toISOString(),
data: {}
};
// Collect data from form
Object.keys(fieldMap).forEach(key => {
const fieldId = fieldMap[key];
const field = document.getElementById(fieldId);
if (field) record.data[key] = field.value;
});
try {
await saveRecordToDB(record);
document.getElementById('record-modal').classList.add('hidden');
loadRecords();
// Update preview if on main page
if (window.opener) {
window.opener.postMessage({ type: 'DATA_UPDATED', data: record.data }, '*');
}
} catch (e) {
console.error('Error saving record:', e);
}
}
function saveRecordToDB(record) {
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE, 'readwrite');
const store = tx.objectStore(STORE);
const req = store.put(record);
req.onsuccess = () => resolve();
req.onerror = () => reject(req.error);
});
}
async function deleteRecord(id) {
if (!confirm('Are you sure you want to delete this record?')) return;
try {
await deleteRecordFromDB(id);
loadRecords();
} catch (e) {
console.error('Error deleting record:', e);
}
}
function deleteRecordFromDB(id) {
return new Promise((resolve, reject) => {
const tx = db.transaction(STORE, 'readwrite');
const store = tx.objectStore(STORE);
const req = store.delete(id);
req.onsuccess = () => resolve();
req.onerror = () => reject(req.error);
});
}