ProspectIQ / static /js /components /modals.js
praneelchettys's picture
Replace main with mobile-friendly ProspectIQ codebase
5bcd5ab
Raw
History Blame Contribute Delete
11 kB
function showContactDetails(contactId) {
openContactDetailsModal(contactId);
}
// ── OPEN CONTACT DETAILS MODAL/DRAWER ──
function openContactDetailsModal(contactId, isEditMode = false) {
const c = mockContacts.find(x => x.id === contactId);
if (!c) {
alert("Contact not found.");
return;
}
let backdrop = document.getElementById('contact-details-backdrop');
if (!backdrop) {
backdrop = document.createElement('div');
backdrop.id = 'contact-details-backdrop';
backdrop.className = 'sidepanel-backdrop';
document.body.appendChild(backdrop);
}
let sidepanel = document.getElementById('contact-details-drawer');
if (!sidepanel) {
sidepanel = document.createElement('div');
sidepanel.id = 'contact-details-drawer';
sidepanel.className = 'sidepanel';
document.body.appendChild(sidepanel);
}
if (isEditMode) {
const companyOptions = mockCompanies.map(comp => `<option value="${comp.id}" ${comp.id === c.company_id ? 'selected' : ''}>${escapeHtml(comp.name)}</option>`).join('');
sidepanel.innerHTML = `
<div class="sidepanel-header">
<h3 class="sidepanel-title">Edit Contact</h3>
</div>
<form id="contact-edit-form" class="h-100 d-flex flex-column m-0">
<div class="sidepanel-body">
<div class="mb-3">
<label class="form-label-sm fw-semibold">Company *</label>
<select class="form-select form-select-sm shadow-none" name="company_id" required>
${companyOptions}
</select>
</div>
<div class="row g-2">
<div class="col-6 mb-3">
<label class="form-label-sm fw-semibold">First Name *</label>
<input type="text" class="form-control form-control-sm shadow-none" name="first_name" value="${escapeHtml(c.first_name)}" required>
</div>
<div class="col-6 mb-3">
<label class="form-label-sm fw-semibold">Last Name *</label>
<input type="text" class="form-control form-control-sm shadow-none" name="last_name" value="${escapeHtml(c.last_name)}" required>
</div>
</div>
<div class="mb-3">
<label class="form-label-sm fw-semibold">Title / Position</label>
<input type="text" class="form-control form-control-sm shadow-none" name="title" value="${escapeHtml(c.title || '')}" placeholder="e.g. Purchasing Manager">
</div>
<div class="mb-3">
<label class="form-label-sm fw-semibold">Email</label>
<input type="email" class="form-control form-control-sm shadow-none" name="email" value="${escapeHtml(c.email || '')}" placeholder="e.g. john.doe@company.com">
</div>
<div class="mb-3">
<label class="form-label-sm fw-semibold">Phone</label>
<input type="text" class="form-control form-control-sm shadow-none" name="phone" value="${escapeHtml(c.phone || '')}" placeholder="e.g. +1 555-123-4567">
</div>
<div class="mb-3">
<label class="form-label-sm fw-semibold">LinkedIn Profile URL</label>
<input type="url" class="form-control form-control-sm shadow-none" name="linkedin" value="${escapeHtml(c.linkedin || '')}" placeholder="e.g. https://linkedin.com/in/username">
</div>
<div class="form-check mb-3">
<input class="form-check-input shadow-none" type="checkbox" name="is_primary" id="contact-edit-is-primary" ${c.is_primary ? 'checked' : ''}>
<label class="form-check-label small text-muted" for="contact-edit-is-primary" style="cursor: pointer;">
Mark as Primary Contact for this company
</label>
</div>
</div>
<div class="sidepanel-footer">
<button type="button" class="btn btn-outline-secondary btn-cancel-custom btn-sm" id="contact-edit-cancel-btn">Cancel</button>
<button type="submit" class="btn btn-dark-custom btn-sm">Save Changes</button>
</div>
</form>
`;
} else {
sidepanel.innerHTML = `
<div class="sidepanel-header">
<h3 class="sidepanel-title">Contact Profile</h3>
<div>
<button class="btn btn-outline-secondary btn-sm d-flex align-items-center gap-2" id="contact-details-edit-btn">
<i class="bi bi-pencil"></i> <span>Edit</span>
</button>
</div>
</div>
<div class="sidepanel-body">
<div class="d-flex align-items-center gap-3 mb-4">
<div class="bg-dark text-white rounded-circle d-flex align-items-center justify-content-center fw-bold" style="width: 56px; height: 56px; font-size: 1.35rem;">
${escapeHtml(c.first_name[0] || '')}${escapeHtml(c.last_name[0] || '')}
</div>
<div>
<h4 class="m-0 fw-bold">${escapeHtml(c.first_name)} ${escapeHtml(c.last_name)}</h4>
<p class="text-muted m-0 small">${escapeHtml(c.title || 'No Title')}</p>
</div>
</div>
<div class="sidepanel-section-title">Professional Identity</div>
<div class="mb-3">
<span class="field-label d-block text-uppercase text-muted fw-bold" style="font-size: 0.72rem;">Associated Company</span>
<strong class="text-dark small">${escapeHtml(c.company || 'No Company')}</strong>
</div>
<div class="mb-3">
<span class="field-label d-block text-uppercase text-muted fw-bold" style="font-size: 0.72rem;">Role / Title</span>
<span class="text-dark small">${escapeHtml(c.title) || '<span class="text-muted small">No Data</span>'}</span>
</div>
<div class="mb-3">
<span class="field-label d-block text-uppercase text-muted fw-bold" style="font-size: 0.72rem;">Contact Role Status</span>
${c.is_primary ? `<span class="badge bg-dark text-white small">Primary Contact</span>` : `<span class="badge bg-light text-dark border small">Standard Contact</span>`}
</div>
<div class="sidepanel-section-title">Contact Details</div>
<div class="mb-3">
<span class="field-label d-block text-uppercase text-muted fw-bold" style="font-size: 0.72rem;">Email</span>
${c.email ? `<a href="mailto:${escapeHtml(c.email)}" class="text-dark text-decoration-underline small">${escapeHtml(c.email)}</a>` : '<span class="text-muted small">No Data</span>'}
</div>
<div class="mb-3">
<span class="field-label d-block text-uppercase text-muted fw-bold" style="font-size: 0.72rem;">Phone</span>
<span class="text-dark small">${escapeHtml(c.phone) || '<span class="text-muted small">No Data</span>'}</span>
</div>
<div class="mb-3">
<span class="field-label d-block text-uppercase text-muted fw-bold" style="font-size: 0.72rem;">LinkedIn</span>
${c.linkedin ? `<a href="${escapeHtml(c.linkedin)}" target="_blank" class="text-dark text-decoration-underline small"><i class="bi bi-linkedin me-1 text-muted"></i>${escapeHtml(c.linkedin)}</a>` : '<span class="text-muted small">No Data</span>'}
</div>
</div>
<div class="sidepanel-footer">
<button type="button" class="btn btn-dark-custom btn-sm" id="contact-details-ok-btn">Close</button>
</div>
`;
}
const closeBtn = document.getElementById('contact-details-close-btn');
const closeDrawer = () => {
sidepanel.classList.remove('show');
backdrop.classList.remove('show');
};
if (closeBtn) {
closeBtn.addEventListener('click', closeDrawer);
}
backdrop.onclick = closeDrawer;
if (isEditMode) {
const cancelBtn = document.getElementById('contact-edit-cancel-btn');
const form = document.getElementById('contact-edit-form');
if (cancelBtn) {
cancelBtn.addEventListener('click', () => {
openContactDetailsModal(contactId, false);
});
}
if (form) {
form.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(form);
const payload = {};
formData.forEach((val, key) => {
payload[key] = val;
});
payload.company_id = parseInt(payload.company_id, 10);
payload.is_primary = document.getElementById('contact-edit-is-primary').checked ? 1 : 0;
try {
const response = await fetch(`/api/contacts/${contactId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const result = await response.json();
if (response.ok && result.success) {
closeDrawer();
await loadDataFromDb();
handleNavigation();
} else {
alert("Error: " + (result.error || "Could not save contact."));
}
} catch (err) {
console.error("Error updating contact:", err);
alert("Error sending update request to backend.");
}
});
}
} else {
const editBtn = document.getElementById('contact-details-edit-btn');
const okBtn = document.getElementById('contact-details-ok-btn');
if (editBtn) {
editBtn.addEventListener('click', () => {
openContactDetailsModal(contactId, true);
});
}
if (okBtn) {
okBtn.addEventListener('click', closeDrawer);
}
}
setTimeout(() => {
sidepanel.classList.add('show');
backdrop.classList.add('show');
}, 10);
}
// ── OPEN AGENT SPACE DRAWER/SIDEPANEL ──