import {
createClient
} from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm';
// --- SUPABASE SETUP ---
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
document.addEventListener('DOMContentLoaded', () => {
// --- RENDER FUNCTIONS ---
const renderContractList = () => { /* ... */ };
const renderDetails = () => { /* ... */ };
const renderActiveTimers = () => { /* ... */ };
// --- EVENT HANDLERS ---
contractListEl.addEventListener('click', (e) => {
const link = e.target.closest('.contract-item');
const completeBtn = e.target.closest('.quick-complete-btn');
if (completeBtn) {
e.stopPropagation();
const contractId = parseInt(completeBtn.dataset.id);
const contract = contracts.find(c => c.id === contractId);
if (contract) {
updateContractStatus(contract.id, 'Completed');
}
} else if (link) {
e.preventDefault();
selectedContractId = parseInt(link.dataset.id);
renderContractList();
renderDetails();
}
});
detailsPanelEl.addEventListener('change', (e) => {
const el = e.target;
const action = el.dataset.action;
if (action === 'change-status') {
const contract = contracts.find(c => c.id === selectedContractId);
if (contract) {
updateContractStatus(contract.id, el.value);
}
}
});
detailsPanelEl.addEventListener('input', (e) => {
const el = e.target;
const action = el.dataset.action;
if (action === 'update-signature') {
const contract = contracts.find(c => c.id === selectedContractId);
if (contract) {
contract.signatures[el.dataset.type] = el.value;
updateContract(contract.id, {
signatures: contract.signatures
});
}
}
});
detailsPanelEl.addEventListener('click', (e) => {
const button = e.target.closest('.action-btn');
if (!button) return;
const action = button.dataset.action;
const contract = contracts.find(c => c.id === selectedContractId);
if (!contract) return;
switch (action) {
case 'delete':
document.getElementById('delete-modal-text').innerHTML = `Are you sure you want to delete contract ${contract.contract_id} for client ${contract.client}? This action cannot be undone.`;
deleteModalEl.classList.remove('hidden');
break;
case 'edit':
openAddModal(contract);
break;
case 'get-book-content':
const pages = generateBookPages(contract);
const container = document.getElementById('command-pages-container');
container.innerHTML = ''; // Clear previous content
pages.forEach((pageContent, index) => {
const pageId = `page-content-${index}`;
const pageHtml = `
`;
container.insertAdjacentHTML('beforeend', pageHtml);
});
commandModalEl.classList.remove('hidden');
break;
}
});
// --- MODAL & FORM HANDLING ---
const getNextContractId = async () => {
const prefix = "RM-";
let {
data,
error
} = await supabase.from('settings').select('value').eq('key', 'totalContractsCreated').maybeSingle();
if (error) {
console.error("Error fetching contract counter from settings:", error);
// Fallback if settings table is empty or has an issue
let {
data: maxIdData,
error: maxIdError
} = await supabase.from('contracts').select('contract_id').order('contract_id', {
ascending: false
}).limit(1).maybeSingle();
if (maxIdError) {
console.error("Error fetching max contract ID:", maxIdError);
return `${prefix}001`; // Ultimate fallback
}
const nextIdNumber = (maxIdData ? parseInt(maxIdData.contract_id.substring(3)) : 0) + 1;
return `${prefix}${nextIdNumber.toString().padStart(3, '0')}`;
}
const nextIdNumber = (data ? parseInt(data.value) : 0) + 1;
return `${prefix}${nextIdNumber.toString().padStart(3, '0')}`;
};
addContractForm.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const contractId = formData.get('contract_id');
const timeframe = formData.get('deliveryTimeframe');
const contractData = {
contract_id: contractId,
client: formData.get('client'),
service: {
name: formData.get('serviceName'),
details: formData.get('serviceDetails'),
itemQuantity: parseInt(formData.get('itemQuantity')) || 0
},
payment: {
amount: formData.get('paymentAmount'),
due: formData.get('paymentDue')
},
delivery: {
timeframe: timeframe,
method: formData.get('deliveryMethod')
},
terms: formData.get('terms').split('\n').filter(t => t.trim() !== ''),
due_date: parseTimeframeToDate(timeframe),
};
if (editMode) {
const contractToUpdate = contracts.find(c => c.contract_id === contractId);
if (contractToUpdate) {
await updateContract(contractToUpdate.id, contractData);
}
} else {
contractData.date = new Date().toISOString();
contractData.signatures = {
client: "",
provider: ""
};
contractData.status = isAdminLoggedIn ? 'Active' : 'Pending';
await addContract(contractData);
}
addModalEl.classList.add('hidden');
});
document.getElementById('confirm-delete-button').addEventListener('click', () => {
const contract = contracts.find(c => c.id === selectedContractId);
if (contract) deleteContract(contract.id);
selectedContractId = null;
deleteModalEl.classList.add('hidden');
});
// --- BOOK CONTENT GENERATION ---
const generateBookPages = (contract) => {
const pages = [];
pages.push(`&3&lService Contract&r\n${contract.contract_id}\n\n&8Client:&r\n&e${contract.client}&r\n&8Provider:&r\n&e${contract.signatures.provider || 'N/A'}&r\n\n&7Date: ${new Date(contract.date).toLocaleDateString()}`);
pages.push(`&3&lService&r\n&8---------------\n&l${contract.service.name}&r\n&7${contract.service.details}`);
pages.push(`&3&lPayment&r\nAmount: &e${contract.payment.amount}&r\nDue: ${contract.payment.due}\n\n&3&lDelivery&r\nTimeframe: ${contract.delivery.timeframe}\nMethod: ${contract.delivery.method}`);
let termsContent = "&3&lTerms&r\n&8---------------\n";
(contract.terms || []).forEach(term => {
termsContent += `&7• ${term}&r\n`;
});
pages.push(termsContent.trim());
pages.push(`&3&lSignatures&r\n&8---------------\nClient Signature:\n\n&e&l${contract.signatures.client || ' '}&r\n\n\nProvider Signature:\n\n&e&l${contract.signatures.provider || ' '}&r`);
return pages;
};
// --- SUPABASE FUNCTIONS ---
async function addContract(contractData) {
const {
error
} = await supabase.from('contracts').insert([contractData]);
if (error) {
showCustomAlert(`Error adding contract: ${error.message}`, 'Error');
console.error('Error adding contract:', error);
} else {
const newIdNumber = parseInt(contractData.contract_id.substring(3));
await supabase.from('settings').upsert({
key: 'totalContractsCreated',
value: newIdNumber
}, {
onConflict: 'key'
});
}
}
async function updateContract(id, updates) {
const {
error
} = await supabase.from('contracts').update(updates).eq('id', id);
if (error) console.error('Error updating contract:', error);
}
async function updateContractStatus(id, status) {
await updateContract(id, {
status
});
}
async function deleteContract(id) {
const {
error
} = await supabase.from('contracts').delete().eq('id', id);
if (error) console.error('Error deleting contract:', error);
}
// --- INITIALIZATION ---
const init = async () => {
// ... (Initial setup logic) ...
const [contractsRes, settingsRes, stockRes] = await Promise.all([
supabase.from('contracts').select('*'),
]);
if (contractsRes.error) {
showCustomAlert('Could not fetch contracts. Check database permissions (RLS) and network connection.', 'Fatal Error');
console.error('Error fetching contracts:', contractsRes.error);
} else {
contracts = contractsRes.data;
}
// real-time subscriptions
supabase.channel('public:contracts').on('postgres_changes', {
event: '*',
schema: 'public',
table: 'contracts'
}, async () => {
await fetchInitialData();
updateAndRender();
}).subscribe();
};
init();
});