Files
whsfund/src/donors.js
2026-03-11 21:18:58 -04:00

123 lines
3.1 KiB
JavaScript

import {
collection,
query,
orderBy,
onSnapshot,
addDoc,
getDocs,
doc,
updateDoc,
deleteDoc,
writeBatch,
serverTimestamp,
Timestamp,
} from 'firebase/firestore';
import { db } from './firebase.js';
const donorsRef = collection(db, 'donors');
let unsubscribe = null;
export function subscribeToDonors(callback) {
const q = query(donorsRef, orderBy('date', 'desc'));
unsubscribe = onSnapshot(
q,
(snapshot) => {
const donors = [];
snapshot.forEach((doc) => {
donors.push({ id: doc.id, ...doc.data() });
});
callback(donors);
},
(error) => {
console.error('Error fetching donors:', error);
callback([]);
}
);
return unsubscribe;
}
export async function addDonor({ name, amount, classYear, message, anonymous }) {
return addDoc(donorsRef, {
name: anonymous ? 'Anonymous' : name,
amount: Number(amount),
classYear: classYear || '',
message: message || '',
anonymous: !!anonymous,
date: serverTimestamp(),
});
}
export function calculateTotal(donors) {
return donors.reduce((sum, d) => sum + (d.amount || 0), 0);
}
// ===== Admin Operations =====
export async function getDonors() {
const q = query(donorsRef, orderBy('date', 'desc'));
const snapshot = await getDocs(q);
const donors = [];
snapshot.forEach((d) => donors.push({ id: d.id, ...d.data() }));
return donors;
}
export async function addDonorWithDate({ name, amount, classYear, message, anonymous, date }) {
const dateValue = date ? Timestamp.fromDate(new Date(date)) : serverTimestamp();
return addDoc(donorsRef, {
name: anonymous ? 'Anonymous' : name,
amount: Number(amount),
classYear: classYear || '',
message: message || '',
anonymous: !!anonymous,
date: dateValue,
});
}
export async function updateDonor(id, fields) {
return updateDoc(doc(db, 'donors', id), fields);
}
export async function deleteDonor(id) {
return deleteDoc(doc(db, 'donors', id));
}
export async function addDonorsBatch(donorsArray) {
const chunks = [];
for (let i = 0; i < donorsArray.length; i += 500) {
chunks.push(donorsArray.slice(i, i + 500));
}
let imported = 0;
for (const chunk of chunks) {
const batch = writeBatch(db);
for (const d of chunk) {
const ref = doc(collection(db, 'donors'));
const dateValue = d.date ? Timestamp.fromDate(new Date(d.date)) : serverTimestamp();
batch.set(ref, {
name: d.anonymous ? 'Anonymous' : (d.name || 'Anonymous'),
amount: Number(d.amount) || 0,
classYear: d.classYear || '',
message: d.message || '',
anonymous: !!d.anonymous,
date: dateValue,
});
}
await batch.commit();
imported += chunk.length;
}
return imported;
}
export function sortDonors(donors, sortBy) {
const sorted = [...donors];
if (sortBy === 'amount') {
sorted.sort((a, b) => (b.amount || 0) - (a.amount || 0));
} else {
sorted.sort((a, b) => {
const dateA = a.date?.toMillis?.() || 0;
const dateB = b.date?.toMillis?.() || 0;
return dateB - dateA;
});
}
return sorted;
}