${p.status}
`;
patentList.appendChild(li);
});
}
function renderPatentDropdown() {
relatedPatentSelect.innerHTML = '';
state.patents.forEach(p => {
relatedPatentSelect.innerHTML += ``;
});
}
// --- EVENT HANDLERS & LOGIC ---
function switchTab(tabName) {
state.currentTab = tabName;
Object.values(tabs).forEach(t => t.classList.remove('active'));
Object.values(contents).forEach(c => c.classList.add('hidden'));
tabs[tabName].classList.add('active');
contents[tabName].classList.remove('hidden');
updateNavButtons();
}
function updateNavButtons() {
navButtons.prev.disabled = state.currentTab === 'dashboard';
navButtons.next.disabled = state.currentTab === 'management';
}
patentForm.addEventListener('submit', (e) => {
e.preventDefault();
const data = {
id: state.editingPatentId ? state.editingPatentId : Date.now(),
appNo: document.getElementById('app-no').value,
title: document.getElementById('title').value,
jurisdiction: document.getElementById('jurisdiction').value,
status: document.getElementById('status').value,
};
if (state.editingPatentId) {
const index = state.patents.findIndex(p => p.id === state.editingPatentId);
state.patents[index] = data;
} else {
state.patents.push(data);
}
resetPatentForm();
renderAll();
});
deadlineForm.addEventListener('submit', (e) => {
e.preventDefault();
const data = {
id: Date.now(),
patentId: parseInt(document.getElementById('related-patent').value),
description: document.getElementById('deadline-description').value,
dueDate: document.getElementById('deadline-date').value,
};
state.deadlines.push(data);
deadlineForm.reset();
renderAll();
});
patentList.addEventListener('click', (e) => {
const id = parseInt(e.target.dataset.id);
if (e.target.classList.contains('edit-patent-btn')) {
const p = state.patents.find(p => p.id === id);
document.getElementById('patent-id').value = p.id;
document.getElementById('app-no').value = p.appNo;
document.getElementById('title').value = p.title;
document.getElementById('jurisdiction').value = p.jurisdiction;
document.getElementById('status').value = p.status;
state.editingPatentId = id;
patentFormTitle.textContent = 'Edit Patent';
cancelPatentEditBtn.classList.remove('hidden');
} else if (e.target.classList.contains('delete-patent-btn')) {
if (confirm('Delete this patent? All related deadlines will also be removed.')) {
state.patents = state.patents.filter(p => p.id !== id);
state.deadlines = state.deadlines.filter(d => d.patentId !== id);
renderAll();
}
}
});
function resetPatentForm() {
patentForm.reset();
state.editingPatentId = null;
patentFormTitle.textContent = 'Add New Patent';
cancelPatentEditBtn.classList.add('hidden');
}
cancelPatentEditBtn.addEventListener('click', resetPatentForm);
downloadPdfBtn.addEventListener('click', () => {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(20);
doc.text("International Patent Compliance Report", 14, 22);
doc.setFontSize(11);
doc.setTextColor(100);
doc.text(`Report Generated: ${new Date().toLocaleDateString()}`, 14, 30);
const head = [['Due Date', 'Patent / App No.', 'Jurisdiction', 'Action Required']];
const body = state.deadlines
.sort((a, b) => new Date(a.dueDate) - new Date(b.dueDate))
.map(deadline => {
const patent = state.patents.find(p => p.id === deadline.patentId);
return [deadline.dueDate, patent ? patent.appNo : 'N/A', patent ? patent.jurisdiction : 'N/A', deadline.description];
});
doc.autoTable({
startY: 35,
head: head,
body: body,
theme: 'striped',
headStyles: { fillColor: [14, 116, 144] }, // cyan-700
});
doc.save('Patent_Compliance_Report.pdf');
});
// --- ATTACH EVENT LISTENERS ---
tabs.dashboard.addEventListener('click', () => switchTab('dashboard'));
tabs.management.addEventListener('click', () => switchTab('management'));
navButtons.next.addEventListener('click', () => switchTab('management'));
navButtons.prev.addEventListener('click', () => switchTab('dashboard'));
// --- INITIALIZATION ---
loadInitialData();
renderAll();
updateNavButtons();
});
