PISAN
สร้างหน้าแดชบอร์ดอินเตอร์แอคทิฟสามารถเพิ่มลบแก้ไขข้อมูลได้บันทึกข้อมูลได้เชื่อมต่อกับฟิลด์บนส่วนพรีวิวโอัพเดทดูผลลัพธ์ได้ทันที ใช้การจัดการข้อมูลมาตรฐานโปรดักชั่น
9a9a400
verified
| ; | |
| // 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); | |
| }); | |
| } |