288 lines
8.1 KiB
TypeScript
288 lines
8.1 KiB
TypeScript
import {
|
|
collection,
|
|
doc,
|
|
getDoc,
|
|
getDocs,
|
|
setDoc,
|
|
updateDoc,
|
|
query,
|
|
where,
|
|
orderBy,
|
|
Timestamp,
|
|
addDoc,
|
|
deleteDoc,
|
|
} from 'firebase/firestore';
|
|
import { db } from './firebase';
|
|
import type {
|
|
User,
|
|
AgentSettings,
|
|
CallTask,
|
|
CallAttempt,
|
|
CallRecord,
|
|
CreditTransaction,
|
|
NotificationSettings,
|
|
BookedAppointment,
|
|
DefaultLimits,
|
|
Purchase,
|
|
} from './types';
|
|
|
|
// Users
|
|
export const getUser = async (uid: string): Promise<User | null> => {
|
|
const docRef = doc(db, 'users', uid);
|
|
const docSnap = await getDoc(docRef);
|
|
return docSnap.exists() ? (docSnap.data() as User) : null;
|
|
};
|
|
|
|
export const updateUserCredits = async (uid: string, newBalance: number) => {
|
|
const docRef = doc(db, 'users', uid);
|
|
await updateDoc(docRef, {
|
|
creditBalance: newBalance,
|
|
updatedAt: Timestamp.now(),
|
|
});
|
|
};
|
|
|
|
export const updateUserOnboardingCompleted = async (uid: string, completed: boolean) => {
|
|
const docRef = doc(db, 'users', uid);
|
|
await updateDoc(docRef, {
|
|
onboardingCompleted: completed,
|
|
updatedAt: Timestamp.now(),
|
|
});
|
|
};
|
|
|
|
// Agent Settings
|
|
export const getAgentSettings = async (userId: string): Promise<AgentSettings | null> => {
|
|
const docRef = doc(db, 'agentSettings', userId);
|
|
const docSnap = await getDoc(docRef);
|
|
if (docSnap.exists()) {
|
|
return docSnap.data() as AgentSettings;
|
|
}
|
|
// Create default if not exists
|
|
const defaults: AgentSettings = {
|
|
userId,
|
|
agentName: 'HolaCompi',
|
|
appLanguage: 'English',
|
|
primaryCallLanguage: 'English',
|
|
secondaryCallLanguages: [],
|
|
tone: 'Friendly',
|
|
agentInstructions: 'You are HolaCompi, a helpful Spanish friend who makes phone calls on behalf of users.',
|
|
createdAt: Timestamp.now(),
|
|
updatedAt: Timestamp.now(),
|
|
};
|
|
await setDoc(docRef, defaults);
|
|
return defaults;
|
|
};
|
|
|
|
export const updateAgentSettings = async (userId: string, updates: Partial<AgentSettings>) => {
|
|
const docRef = doc(db, 'agentSettings', userId);
|
|
await updateDoc(docRef, {
|
|
...updates,
|
|
updatedAt: Timestamp.now(),
|
|
});
|
|
};
|
|
|
|
// Call Tasks
|
|
export const createCallTask = async (task: Omit<CallTask, 'id'>): Promise<string> => {
|
|
const docRef = await addDoc(collection(db, 'callTasks'), task);
|
|
return docRef.id;
|
|
};
|
|
|
|
export const getCallTasks = async (userId: string): Promise<CallTask[]> => {
|
|
const q = query(
|
|
collection(db, 'callTasks'),
|
|
where('userId', '==', userId),
|
|
orderBy('scheduledAt', 'desc')
|
|
);
|
|
const snapshot = await getDocs(q);
|
|
return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as CallTask));
|
|
};
|
|
|
|
export const getCallTask = async (taskId: string): Promise<CallTask | null> => {
|
|
const docRef = doc(db, 'callTasks', taskId);
|
|
const docSnap = await getDoc(docRef);
|
|
return docSnap.exists() ? ({ id: docSnap.id, ...docSnap.data() } as CallTask) : null;
|
|
};
|
|
|
|
export const updateCallTask = async (taskId: string, updates: Partial<CallTask>) => {
|
|
const docRef = doc(db, 'callTasks', taskId);
|
|
await updateDoc(docRef, {
|
|
...updates,
|
|
updatedAt: Timestamp.now(),
|
|
});
|
|
};
|
|
|
|
export const deleteCallTask = async (taskId: string) => {
|
|
await deleteDoc(doc(db, 'callTasks', taskId));
|
|
};
|
|
|
|
// Call Attempts
|
|
export const createCallAttempt = async (
|
|
taskId: string,
|
|
attempt: Omit<CallAttempt, 'id'>
|
|
): Promise<string> => {
|
|
const docRef = await addDoc(
|
|
collection(db, 'callTasks', taskId, 'attempts'),
|
|
attempt
|
|
);
|
|
return docRef.id;
|
|
};
|
|
|
|
export const getCallAttempts = async (taskId: string): Promise<CallAttempt[]> => {
|
|
const q = query(
|
|
collection(db, 'callTasks', taskId, 'attempts'),
|
|
orderBy('startTime', 'desc')
|
|
);
|
|
const snapshot = await getDocs(q);
|
|
return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as CallAttempt));
|
|
};
|
|
|
|
export const updateCallAttempt = async (
|
|
taskId: string,
|
|
attemptId: string,
|
|
updates: Partial<CallAttempt>
|
|
) => {
|
|
const docRef = doc(db, 'callTasks', taskId, 'attempts', attemptId);
|
|
await updateDoc(docRef, updates);
|
|
};
|
|
|
|
// Calls
|
|
export const createCallRecord = async (
|
|
record: Omit<CallRecord, 'id' | 'createdAt' | 'updatedAt'>
|
|
): Promise<string> => {
|
|
const docRef = await addDoc(collection(db, 'calls'), {
|
|
...record,
|
|
createdAt: Timestamp.now(),
|
|
updatedAt: Timestamp.now(),
|
|
});
|
|
return docRef.id;
|
|
};
|
|
|
|
export const updateCallRecord = async (
|
|
callId: string,
|
|
updates: Partial<CallRecord>
|
|
) => {
|
|
const docRef = doc(db, 'calls', callId);
|
|
await updateDoc(docRef, { ...updates, updatedAt: Timestamp.now() });
|
|
};
|
|
|
|
export const getCallByVapiCallId = async (vapiCallId: string): Promise<CallRecord | null> => {
|
|
const q = query(collection(db, 'calls'), where('vapiCallId', '==', vapiCallId));
|
|
const snapshot = await getDocs(q);
|
|
if (snapshot.empty) return null;
|
|
const docSnap = snapshot.docs[0];
|
|
return { id: docSnap.id, ...(docSnap.data() as CallRecord) };
|
|
};
|
|
|
|
// Credit Transactions
|
|
export const createCreditTransaction = async (
|
|
transaction: Omit<CreditTransaction, 'id'>
|
|
): Promise<string> => {
|
|
const docRef = await addDoc(collection(db, 'creditLedger'), transaction);
|
|
return docRef.id;
|
|
};
|
|
|
|
export const getCreditTransactions = async (userId: string): Promise<CreditTransaction[]> => {
|
|
const q = query(
|
|
collection(db, 'creditLedger'),
|
|
where('userId', '==', userId),
|
|
orderBy('createdAt', 'desc')
|
|
);
|
|
const snapshot = await getDocs(q);
|
|
return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as CreditTransaction));
|
|
};
|
|
|
|
// Purchases
|
|
export const createPurchase = async (purchase: Omit<Purchase, 'id'>): Promise<string> => {
|
|
const docRef = await addDoc(collection(db, 'purchases'), purchase);
|
|
return docRef.id;
|
|
};
|
|
|
|
export const getPurchasesByUser = async (userId: string): Promise<Purchase[]> => {
|
|
const q = query(
|
|
collection(db, 'purchases'),
|
|
where('userId', '==', userId),
|
|
orderBy('createdAt', 'desc')
|
|
);
|
|
const snapshot = await getDocs(q);
|
|
return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as Purchase));
|
|
};
|
|
|
|
// Notification Settings
|
|
export const getNotificationSettings = async (userId: string): Promise<NotificationSettings> => {
|
|
const docRef = doc(db, 'notificationSettings', userId);
|
|
const docSnap = await getDoc(docRef);
|
|
if (docSnap.exists()) {
|
|
return docSnap.data() as NotificationSettings;
|
|
}
|
|
const defaults: NotificationSettings = {
|
|
userId,
|
|
notifyOnSuccess: true,
|
|
notifyOnFailure: true,
|
|
emailSummary: false,
|
|
autoAddToCalendar: false,
|
|
googleCalendarConnected: false,
|
|
iCloudCalendarConnected: false,
|
|
createdAt: Timestamp.now(),
|
|
updatedAt: Timestamp.now(),
|
|
};
|
|
await setDoc(docRef, defaults);
|
|
return defaults;
|
|
};
|
|
|
|
export const updateNotificationSettings = async (
|
|
userId: string,
|
|
updates: Partial<NotificationSettings>
|
|
) => {
|
|
const docRef = doc(db, 'notificationSettings', userId);
|
|
await updateDoc(docRef, {
|
|
...updates,
|
|
updatedAt: Timestamp.now(),
|
|
});
|
|
};
|
|
|
|
// Booked Appointments
|
|
export const createBookedAppointment = async (
|
|
appointment: Omit<BookedAppointment, 'id'>
|
|
): Promise<string> => {
|
|
const docRef = await addDoc(collection(db, 'bookedAppointments'), appointment);
|
|
return docRef.id;
|
|
};
|
|
|
|
export const getBookedAppointments = async (userId: string): Promise<BookedAppointment[]> => {
|
|
const q = query(
|
|
collection(db, 'bookedAppointments'),
|
|
where('userId', '==', userId),
|
|
orderBy('dateTime', 'asc')
|
|
);
|
|
const snapshot = await getDocs(q);
|
|
return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as BookedAppointment));
|
|
};
|
|
|
|
// Default Limits
|
|
export const getDefaultLimits = async (userId: string): Promise<DefaultLimits> => {
|
|
const docRef = doc(db, 'defaultLimits', userId);
|
|
const docSnap = await getDoc(docRef);
|
|
if (docSnap.exists()) {
|
|
return docSnap.data() as DefaultLimits;
|
|
}
|
|
const defaults: DefaultLimits = {
|
|
userId,
|
|
defaultMaxMinutes: 10,
|
|
defaultMaxCredits: 10,
|
|
allowAutoExtension: false,
|
|
maxExtraMinutes: 0,
|
|
defaultMaxRecalls: 2,
|
|
minDelayBetweenRecalls: 15,
|
|
updatedAt: Timestamp.now(),
|
|
};
|
|
await setDoc(docRef, defaults);
|
|
return defaults;
|
|
};
|
|
|
|
export const updateDefaultLimits = async (userId: string, updates: Partial<DefaultLimits>) => {
|
|
const docRef = doc(db, 'defaultLimits', userId);
|
|
await updateDoc(docRef, {
|
|
...updates,
|
|
updatedAt: Timestamp.now(),
|
|
});
|
|
};
|