added firestore config
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
// }
|
||||
|
||||
65
src/lib/firestoreConfig.ts
Normal file
65
src/lib/firestoreConfig.ts
Normal 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
130
src/lib/firestoreService.ts
Normal 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user