// Notes/reports operations
let notesCollectionName = 'notes'; // Default, will be loaded from config
let jobsCollectionName = 'Job_Info'; // Default, will be loaded from config
/**
* Initialize configuration
*/
async function initNotesConfig() {
try {
if (typeof getNotesCollection !== 'undefined') {
notesCollectionName = await getNotesCollection();
}
if (typeof getJobsCollection !== 'undefined') {
jobsCollectionName = await getJobsCollection();
}
} catch (error) {
console.error('Error initializing notes config:', error);
// Use defaults if config fails to load
}
}
// Initialize config when script loads
if (typeof getNotesCollection !== 'undefined' || typeof getJobsCollection !== 'undefined') {
initNotesConfig();
}
// Get note editor instance from global scope or window
function getNoteEditor() {
return window.noteEditorInstance || noteEditorInstance || null;
}
/**
* Load notes for a specific job
*/
async function loadJobNotes() {
try {
const jobId = document.getElementById('jobId').value;
if (!jobId) {
document.getElementById('notesList').innerHTML = '
No job selected
';
return;
}
const job = await pb.collection(jobsCollectionName).getOne(jobId);
const noteRefs = job.Note_Ref || [];
if (noteRefs.length === 0) {
document.getElementById('notesList').innerHTML = 'No notes for this job
';
return;
}
// Fetch all notes
const notes = await Promise.all(
noteRefs.map(noteId =>
pb.collection(notesCollectionName).getOne(noteId).catch(() => null)
)
);
const validNotes = notes.filter(note => note !== null);
if (validNotes.length === 0) {
document.getElementById('notesList').innerHTML = 'No notes found
';
return;
}
displayNotes(validNotes, true);
} catch (error) {
console.error('Error loading job notes:', error);
document.getElementById('notesList').innerHTML = 'Error loading notes
';
}
}
/**
* Load all notes
*/
async function loadAllNotes() {
try {
const result = await pb.collection(notesCollectionName).getList(1, 100, {
sort: '-created',
expand: 'job'
});
if (result.items.length === 0) {
document.getElementById('loadingIndicator').classList.add('hidden');
document.getElementById('emptyState').classList.remove('hidden');
return;
}
document.getElementById('loadingIndicator').classList.add('hidden');
document.getElementById('emptyState').classList.add('hidden');
document.getElementById('reportsTableContainer').classList.remove('hidden');
displayNotesTable(result.items);
} catch (error) {
console.error('Error loading notes:', error);
document.getElementById('loadingIndicator').classList.add('hidden');
document.getElementById('emptyState').classList.remove('hidden');
}
}
/**
* Display notes in list format (for job modal)
*/
function displayNotes(notes, showDelete = false) {
const container = document.getElementById('notesList');
if (!notes || notes.length === 0) {
container.innerHTML = 'No notes
';
return;
}
container.innerHTML = notes.map(note => {
const date = note.created ? new Date(note.created).toLocaleString() : '-';
const content = note.content || '';
const sentiment = note.sentiment || '-';
return `
${showDelete ? `
` : ''}
${content}
`;
}).join('');
}
/**
* Display notes in table format (for notes page)
*/
function displayNotesTable(notes) {
const tbody = document.getElementById('notesTableBody');
tbody.innerHTML = notes.map(note => {
const date = note.created ? new Date(note.created).toLocaleString() : '-';
const content = note.content ? note.content.substring(0, 100) + '...' : '-';
const jobName = note.job ? (note.job.Job_Number || note.job.Job_Name || '-') : '-';
const sentiment = note.sentiment || '-';
return `
| ${jobName} |
${content} |
${sentiment} |
${date} |
|
`;
}).join('');
}
/**
* Load note for editing
*/
async function loadNoteForEdit(noteId) {
try {
const note = await pb.collection(notesCollectionName).getOne(noteId);
document.getElementById('noteId').value = note.id;
document.getElementById('noteSentiment').value = note.sentiment || '';
document.getElementById('noteDate').value = note.date ? new Date(note.date).toISOString().slice(0, 16) : '';
if (note.job) {
document.getElementById('noteJob').value = note.job;
}
// Set Quill editor content
const editor = getNoteEditor();
if (editor && note.content) {
editor.root.innerHTML = note.content;
}
// Load jobs for select if not already loaded
await loadJobsForSelect();
} catch (error) {
console.error('Error loading note:', error);
showMessage('Error loading note: ' + (error.message || 'Unknown error'), 'error');
}
}
/**
* Save note (create or update)
*/
async function saveNote() {
try {
const noteId = document.getElementById('noteId')?.value;
const jobId = document.getElementById('noteJob')?.value || document.getElementById('jobId')?.value;
const editor = getNoteEditor();
const content = document.getElementById('noteContent')?.value || editor?.root.innerHTML || '';
const sentiment = document.getElementById('noteSentiment')?.value || '';
const date = document.getElementById('noteDate')?.value || new Date().toISOString();
if (!jobId && !noteId) {
showMessage('Please select a job', 'error');
return;
}
const noteData = {
content: content,
sentiment: sentiment,
date: date
};
let savedNote;
if (noteId) {
// Update existing note
savedNote = await pb.collection(notesCollectionName).update(noteId, noteData);
showMessage('Note updated successfully', 'success');
} else {
// Create new note
savedNote = await pb.collection(notesCollectionName).create(noteData);
showMessage('Note created successfully', 'success');
// Link note to job
if (jobId) {
await linkNoteToJob(savedNote.id, jobId);
}
}
// Close modal and reload
if (document.getElementById('noteModal')) {
closeNoteModal();
loadAllNotes();
} else {
// In job modal
cancelAddNote();
loadJobNotes();
}
} catch (error) {
console.error('Error saving note:', error);
showMessage('Error saving note: ' + (error.message || 'Unknown error'), 'error');
}
}
/**
* Link note to job
*/
async function linkNoteToJob(noteId, jobId) {
try {
const job = await pb.collection(jobsCollectionName).getOne(jobId);
const noteRefs = job.Note_Ref || [];
if (!noteRefs.includes(noteId)) {
noteRefs.push(noteId);
await pb.collection(jobsCollectionName).update(jobId, {
Note_Ref: noteRefs
});
}
} catch (error) {
console.error('Error linking note to job:', error);
}
}
/**
* Delete note
*/
async function deleteNote(noteId) {
if (!confirm('Are you sure you want to delete this note?')) {
return;
}
try {
await pb.collection(notesCollectionName).delete(noteId);
showMessage('Note deleted successfully', 'success');
loadAllNotes();
} catch (error) {
console.error('Error deleting note:', error);
showMessage('Error deleting note: ' + (error.message || 'Unknown error'), 'error');
}
}
/**
* Delete note from job (unlink)
*/
async function deleteNoteFromJob(noteId) {
if (!confirm('Are you sure you want to delete this note?')) {
return;
}
try {
const jobId = document.getElementById('jobId').value;
if (jobId) {
const job = await pb.collection(jobsCollectionName).getOne(jobId);
const noteRefs = (job.Note_Ref || []).filter(id => id !== noteId);
await pb.collection(jobsCollectionName).update(jobId, {
Note_Ref: noteRefs
});
}
await pb.collection(notesCollectionName).delete(noteId);
showMessage('Note deleted successfully', 'success');
loadJobNotes();
} catch (error) {
console.error('Error deleting note:', error);
showMessage('Error deleting note: ' + (error.message || 'Unknown error'), 'error');
}
}
/**
* Show add note form (in job modal)
*/
function showAddNoteForm() {
document.getElementById('addNoteForm').classList.remove('hidden');
const editor = getNoteEditor();
if (editor) {
editor.setContents([]);
}
}
/**
* Cancel add note form
*/
function cancelAddNote() {
document.getElementById('addNoteForm').classList.add('hidden');
const editor = getNoteEditor();
if (editor) {
editor.setContents([]);
}
}