added firestore config

This commit is contained in:
2026-02-24 11:37:18 +05:30
parent aec080ba54
commit 190243081a
4 changed files with 229 additions and 2 deletions

View File

@@ -13,7 +13,9 @@ import {
signOut as firebaseSignOut,
type User,
} from 'firebase/auth'
import { auth, googleProvider } from '../lib/firebase'
import { auth, googleProvider, db } from '../lib/firebase'
import { doc, setDoc } from 'firebase/firestore'
import { COLLECTIONS } from '../lib/firestoreConfig'
type AuthContextValue = {
user: User | null
@@ -28,9 +30,28 @@ export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null)
const [loading, setLoading] = useState(true)
// Save user info to Firestore when they authenticate
async function saveUserToFirestore(authUser: User) {
try {
const userRef = doc(db, COLLECTIONS.USERS, authUser.uid)
await setDoc(userRef, {
id: authUser.uid,
email: authUser.email || '',
displayName: authUser.displayName || '',
photoURL: authUser.photoURL || '',
lastLoginAt: Date.now(),
}, { merge: true })
} catch (error) {
console.error('Error saving user to Firestore:', error)
}
}
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (u) => {
const unsubscribe = onAuthStateChanged(auth, async (u) => {
setUser(u)
if (u) {
await saveUserToFirestore(u)
}
setLoading(false)
})
return () => unsubscribe()

View File

@@ -1,5 +1,6 @@
import { initializeApp } from 'firebase/app'
import { getAuth, GoogleAuthProvider } from 'firebase/auth'
import { getFirestore, connectFirestoreEmulator } from 'firebase/firestore'
const firebaseConfig = {
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
@@ -12,5 +13,15 @@ const firebaseConfig = {
}
const app = initializeApp(firebaseConfig)
// Auth initialization
export const auth = getAuth(app)
export const googleProvider = new GoogleAuthProvider()
// Firestore initialization
export const db = getFirestore(app)
// Enable Firestore emulator in development (uncomment when testing locally)
// if (import.meta.env.DEV) {
// connectFirestoreEmulator(db, 'localhost', 8080)
// }

View File

@@ -0,0 +1,65 @@
/**
* Firestore Collections Configuration
* Define all collection names and common data structure interfaces here
*/
// Collection names
export const COLLECTIONS = {
USERS: 'users',
ENTRIES: 'entries',
SETTINGS: 'settings',
TAGS: 'tags',
} as const
// User document interface
export interface FirestoreUser {
id: string
email: string
displayName?: string
photoURL?: string
createdAt: number
updatedAt: number
theme?: 'light' | 'dark'
}
// Entry (Journal Entry) document interface
export interface JournalEntry {
id: string
userId: string
title: string
content: string
mood?: 'happy' | 'sad' | 'neutral' | 'anxious' | 'grateful'
tags?: string[]
isPublic?: boolean
createdAt: number
updatedAt: number
}
// Settings document interface
export interface UserSettings {
userId: string
notifications?: boolean
emailNotifications?: boolean
theme?: 'light' | 'dark' | 'system'
language?: string
updatedAt: number
}
// Tags document interface
export interface Tag {
id: string
userId: string
name: string
color?: string
createdAt: number
updatedAt: number
}
// Firestore emulator configuration
export function isEmulatorEnabled(): boolean {
return import.meta.env.VITE_FIREBASE_EMULATOR_ENABLED === 'true'
}
export function getEmulatorHost(): string {
return import.meta.env.VITE_FIRESTORE_EMULATOR_HOST || 'localhost:8080'
}

130
src/lib/firestoreService.ts Normal file
View File

@@ -0,0 +1,130 @@
import {
collection,
doc,
getDoc,
getDocs,
setDoc,
updateDoc,
deleteDoc,
query,
where,
orderBy,
WriteBatch,
writeBatch,
} from 'firebase/firestore'
import { db } from './firebase'
type FirestoreData = Record<string, any>
/**
* Generic function to add or update a document
*/
export async function setDocument<T extends FirestoreData>(
collectionName: string,
docId: string,
data: T,
merge = true
): Promise<void> {
try {
await setDoc(doc(db, collectionName, docId), data, { merge })
} catch (error) {
console.error(`Error setting document in ${collectionName}:`, error)
throw error
}
}
/**
* Generic function to get a single document
*/
export async function getDocument<T extends FirestoreData>(
collectionName: string,
docId: string
): Promise<T | null> {
try {
const docRef = doc(db, collectionName, docId)
const docSnapshot = await getDoc(docRef)
return (docSnapshot.exists() ? docSnapshot.data() : null) as T | null
} catch (error) {
console.error(`Error getting document from ${collectionName}:`, error)
throw error
}
}
/**
* Generic function to get all documents from a collection
*/
export async function getDocuments<T extends FirestoreData>(
collectionName: string
): Promise<T[]> {
try {
const querySnapshot = await getDocs(collection(db, collectionName))
return querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as T))
} catch (error) {
console.error(`Error getting documents from ${collectionName}:`, error)
throw error
}
}
/**
* Generic function to query documents with conditions
*/
export async function queryDocuments<T extends FirestoreData>(
collectionName: string,
constraints: any[]
): Promise<T[]> {
try {
const q = query(collection(db, collectionName), ...constraints)
const querySnapshot = await getDocs(q)
return querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as T))
} catch (error) {
console.error(`Error querying ${collectionName}:`, error)
throw error
}
}
/**
* Generic function to update a document
*/
export async function updateDocument<T extends Partial<FirestoreData>>(
collectionName: string,
docId: string,
data: T
): Promise<void> {
try {
await updateDoc(doc(db, collectionName, docId), data)
} catch (error) {
console.error(`Error updating document in ${collectionName}:`, error)
throw error
}
}
/**
* Generic function to delete a document
*/
export async function deleteDocument(
collectionName: string,
docId: string
): Promise<void> {
try {
await deleteDoc(doc(db, collectionName, docId))
} catch (error) {
console.error(`Error deleting document from ${collectionName}:`, error)
throw error
}
}
/**
* Batch write operations
*/
export function createWriteBatch(): WriteBatch {
return writeBatch(db)
}
export async function commitBatch(batch: WriteBatch): Promise<void> {
try {
await batch.commit()
} catch (error) {
console.error('Error committing batch write:', error)
throw error
}
}