and firebase-database.js before this script.");
document.getElementById('profilesGrid').innerHTML = '
Firebase SDK not loaded.
';
return;
}
// Realtime DB ref (Profiles/)
const dbRef = firebase.database().ref('Profiles');
// DOM refs
const profilesGrid = document.getElementById('profilesGrid');
const modal = document.getElementById('modal');
const profileForm = document.getElementById('profileForm');
const profileIdInput = document.getElementById('profileId');
const addBtn = document.getElementById('addBtn');
const refreshBtn = document.getElementById('refreshBtn');
const cancelBtn = document.getElementById('cancelBtn');
const saveBtn = document.getElementById('saveBtn');
const genderFilter = document.getElementById('genderFilter');
const minAge = document.getElementById('minAge');
const maxAge = document.getElementById('maxAge');
const religionFilter = document.getElementById('religionFilter');
const nameFilter = document.getElementById('nameFilter');
const globalSearch = document.getElementById('globalSearch');
const sortBy = document.getElementById('sortBy');
const applyFilters = document.getElementById('applyFilters');
const clearFilters = document.getElementById('clearFilters');
// Local cache of profiles (array of { id, ...data })
let allProfiles = [];
// Modal helpers
function openModal(){ modal.classList.add('open'); const nm = document.getElementById('name'); if(nm) nm.focus(); }
function closeModal(){ modal.classList.remove('open'); }
cancelBtn && cancelBtn.addEventListener('click', (e)=>{ e.preventDefault(); closeModal(); });
// Add button -> open for create
addBtn && addBtn.addEventListener('click', ()=> {
profileForm.reset();
profileIdInput.value = '';
const titleEl = modal.querySelector('#modalTitle');
if(titleEl) titleEl.textContent = 'Add Profile';
// enable form fields & show save
Array.from(profileForm.elements).forEach(el => el.disabled = false);
if(saveBtn) saveBtn.style.display = '';
openModal();
});
// Submit (create or update)
profileForm && profileForm.addEventListener('submit', function(e){
e.preventDefault();
const id = profileIdInput.value;
const payload = {
name: (document.getElementById('name').value || '').trim(),
gender: (document.getElementById('gender').value || '').trim(),
age: Number(document.getElementById('age').value) || null,
religion: (document.getElementById('religion').value || '').trim(),
location: (document.getElementById('location').value || '').trim(),
profession: (document.getElementById('profession').value || '').trim(),
bio: (document.getElementById('bio').value || '').trim(),
photo: (document.getElementById('photo').value || '').trim(),
createdAt: Date.now()
};
if(id){
// update
dbRef.child(id).update(payload)
.then(()=> { showToast('Profile updated'); closeModal(); })
.catch(err => alert('Update error: '+err.message));
} else {
// create
dbRef.push(payload)
.then(()=> { showToast('Profile added'); closeModal(); })
.catch(err => alert('Save error: '+err.message));
}
});
// Live listener -> populate allProfiles
dbRef.on('value', snap => {
const val = snap.val() || {};
allProfiles = Object.keys(val).map(k => ({ id: k, ...val[k] }));
// sort by createdAt desc default
allProfiles.sort((a,b)=> (b.createdAt||0) - (a.createdAt||0));
applyAndRender();
}, err => {
console.error('DB listen error', err);
profilesGrid.innerHTML = `
Error loading profiles.
`;
});
// Render helpers
function initials(name){
if(!name) return '?';
const parts = name.trim().split(' ').filter(Boolean);
return (parts[0]?.[0]||'') + (parts[1]?.[0]||'');
}
function escapeHtml(s){
if(s == null) return '';
return String(s).replace(/&/g,'&').replace(//g,'>');
}
function renderProfiles(list){
profilesGrid.innerHTML = '';
if(!list || list.length === 0){
profilesGrid.innerHTML = '
No profiles found.
';
return;
}
list.forEach(p => {
const card = document.createElement('div');
card.className = 'card';
const photoHtml = p.photo ? `
` : `
${escapeHtml(initials(p.name).toUpperCase())}
`;
card.innerHTML = `
${photoHtml}
${escapeHtml(p.name || '-')}
Age ${p.age||'-'}
${escapeHtml(p.profession||'—')} • ${escapeHtml(p.location||'—')}
${escapeHtml(p.religion||'—')}
${escapeHtml(p.gender || '')}
View
Edit
Delete
`;
profilesGrid.appendChild(card);
});
// attach events
profilesGrid.querySelectorAll('button.small').forEach(btn => {
btn.addEventListener('click', (e)=>{
const id = btn.dataset.id;
const action = btn.dataset.action;
if(action === 'view') viewProfile(id);
if(action === 'edit') editProfile(id);
if(action === 'delete') deleteProfile(id);
});
});
}
// View profile (readonly modal)
function viewProfile(id){
const p = allProfiles.find(x=>x.id===id);
if(!p) return alert('Profile not found');
fillFormFromProfile(p);
const titleEl = modal.querySelector('#modalTitle');
if(titleEl) titleEl.textContent = 'View Profile';
// disable inputs, hide save
Array.from(profileForm.elements).forEach(el => el.disabled = true);
if(saveBtn) saveBtn.style.display = 'none';
openModal();
}
// Edit profile (open modal with data)
function editProfile(id){
const p = allProfiles.find(x=>x.id===id);
if(!p) return alert('Profile not found');
fillFormFromProfile(p);
const titleEl = modal.querySelector('#modalTitle');
if(titleEl) titleEl.textContent = 'Edit Profile';
Array.from(profileForm.elements).forEach(el => el.disabled = false);
if(saveBtn) saveBtn.style.display = '';
openModal();
}
// Delete profile
function deleteProfile(id){
if(!confirm('Delete this profile?')) return;
dbRef.child(id).remove().then(()=> showToast('Profile deleted')).catch(err=> alert('Delete failed: '+err.message));
}
// Fill HTML form from profile object
function fillFormFromProfile(p){
profileIdInput.value = p.id || '';
document.getElementById('name').value = p.name || '';
document.getElementById('gender').value = p.gender || 'bride';
document.getElementById('age').value = p.age || '';
document.getElementById('religion').value = p.religion || '';
document.getElementById('location').value = p.location || '';
document.getElementById('profession').value = p.profession || '';
document.getElementById('bio').value = p.bio || '';
document.getElementById('photo').value = p.photo || '';
}
// Filters & Sorting
function applyAndRender(){
let list = [...allProfiles];
// gender
const g = genderFilter?.value || 'all';
if(g !== 'all') list = list.filter(p => (p.gender||'') === g);
// ages
const min = parseInt(minAge?.value) || null;
const max = parseInt(maxAge?.value) || null;
if(min !== null) list = list.filter(p => (p.age || 0) >= min);
if(max !== null) list = list.filter(p => (p.age || 0) <= max);
// religion filter
const r = (religionFilter?.value || '').trim().toLowerCase();
if(r) list = list.filter(p => ((p.religion||'').toLowerCase().includes(r)));
// nameFilter
const nameQ = (nameFilter?.value || '').trim().toLowerCase();
if(nameQ) list = list.filter(p => (p.name||'').toLowerCase().includes(nameQ));
// globalSearch
const q = (globalSearch?.value || '').trim().toLowerCase();
if(q) list = list.filter(p => {
return (p.name||'').toLowerCase().includes(q) ||
(p.bio||'').toLowerCase().includes(q) ||
(p.profession||'').toLowerCase().includes(q) ||
(p.location||'').toLowerCase().includes(q);
});
// sort
const s = sortBy?.value || 'newest';
if(s === 'ageAsc') list.sort((a,b)=> (a.age||0) - (b.age||0));
else if(s === 'ageDesc') list.sort((a,b)=> (b.age||0) - (a.age||0));
else list.sort((a,b)=> (b.createdAt||0) - (a.createdAt||0));
renderProfiles(list);
}
// Filters UI hooks
applyFilters?.addEventListener('click', applyAndRender);
clearFilters?.addEventListener('click', ()=>{
genderFilter.value = 'all'; minAge.value = ''; maxAge.value = ''; religionFilter.value=''; nameFilter.value=''; globalSearch.value=''; sortBy.value='newest';
applyAndRender();
});
sortBy?.addEventListener('change', applyAndRender);
globalSearch?.addEventListener('input', ()=> setTimeout(applyAndRender, 150));
nameFilter?.addEventListener('input', ()=> setTimeout(applyAndRender, 150));
// Refresh button simply reapplies local filters (data is live)
refreshBtn?.addEventListener('click', ()=> {
applyAndRender();
showToast('Refreshed local view');
});
// Small toast
function showToast(msg){
const t = document.createElement('div');
t.textContent = msg;
t.style.position='fixed'; t.style.right='20px'; t.style.bottom='20px';
t.style.padding='10px 14px'; t.style.background='rgba(0,0,0,0.7)'; t.style.color='white'; t.style.borderRadius='8px';
document.body.appendChild(t);
setTimeout(()=> t.remove(), 2400);
}
// Expose view/edit/delete to global (not strictly needed but ok)
window.viewProfile = viewProfile;
window.editProfile = editProfile;
window.deleteProfile = deleteProfile;
// close modal if backdrop clicked
modal && modal.addEventListener('click', (e)=> { if(e.target === modal) closeModal(); });
// initial apply (if allProfiles already filled)
applyAndRender();
})();