cleanup
This commit is contained in:
14
.env.example
14
.env.example
@@ -1,14 +0,0 @@
|
||||
# Firebase – copy to .env and fill with your Firebase project config
|
||||
# Get these from Firebase Console → Project settings → General → Your apps
|
||||
|
||||
VITE_FIREBASE_API_KEY=
|
||||
VITE_FIREBASE_AUTH_DOMAIN=
|
||||
VITE_FIREBASE_DATABASE_URL=
|
||||
VITE_FIREBASE_PROJECT_ID=
|
||||
VITE_FIREBASE_STORAGE_BUCKET=
|
||||
VITE_FIREBASE_MESSAGING_SENDER_ID=
|
||||
VITE_FIREBASE_APP_ID=
|
||||
# Optional: Firestore Emulator (for local development)
|
||||
# Uncomment and set these if running Firebase emulator locally
|
||||
# VITE_FIRESTORE_EMULATOR_HOST=localhost:8080
|
||||
# VITE_FIREBASE_EMULATOR_ENABLED=true
|
||||
8
.github/copilot-instructions.md
vendored
8
.github/copilot-instructions.md
vendored
@@ -58,7 +58,8 @@ src/ # Frontend
|
||||
components/ # BottomNav, LoginCard, GoogleSignInButton, ProtectedRoute
|
||||
contexts/ # AuthContext (Firebase Google Auth)
|
||||
lib/
|
||||
firebase.ts # Firebase auth config (Firestore removed)
|
||||
firebase.ts # Firebase auth config (Google sign-in only)
|
||||
api.ts # API client for backend calls
|
||||
|
||||
backend/ # FastAPI backend (Port 8001)
|
||||
main.py # FastAPI app, CORS, routes, lifespan
|
||||
@@ -90,9 +91,8 @@ backend/ # FastAPI backend (Port 8001)
|
||||
✅ Pydantic models for User, JournalEntry, UserSettings
|
||||
✅ Route structure: `/api/users/*` and `/api/entries/*`
|
||||
✅ CORS enabled for frontend (localhost:8000)
|
||||
✅ Firestore database files removed (`firestoreService.ts`, `firestoreConfig.ts`)
|
||||
✅ Firebase authentication kept (Google sign-in only)
|
||||
|
||||
✅ Firebase Google Auth kept (Firestore completely removed)
|
||||
✅ MongoDB as single source of truth
|
||||
### API Ready
|
||||
|
||||
- User registration, profile updates, deletion
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
# MongoDB & FastAPI Backend Setup - Quick Start
|
||||
|
||||
## What's Been Set Up
|
||||
|
||||
✅ **Backend directory structure** (`/backend`)
|
||||
✅ **FastAPI application** (main.py with routes, CORS, lifecycle)
|
||||
✅ **MongoDB connection** (config.py, db.py)
|
||||
✅ **Pydantic models** (User, JournalEntry, UserSettings)
|
||||
✅ **API routes** (users.py, entries.py)
|
||||
✅ **Environment configuration** (.env.example)
|
||||
✅ **Documentation** (README.md, MONGODB_SETUP.md)
|
||||
✅ **Firebase auth preserved** (Google sign-in, no Firestore)
|
||||
|
||||
---
|
||||
|
||||
## How to Start MongoDB
|
||||
|
||||
### 1. Install MongoDB (if not already installed)
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
brew tap mongodb/brew
|
||||
brew install mongodb-community
|
||||
|
||||
# Linux (Ubuntu)
|
||||
curl -fsSL https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add -
|
||||
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse" \
|
||||
| sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y mongodb-org
|
||||
|
||||
# Windows: Download from https://www.mongodb.com/try/download/community
|
||||
```
|
||||
|
||||
### 2. Start MongoDB Service
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
brew services start mongodb-community
|
||||
|
||||
# Linux
|
||||
sudo systemctl start mongod
|
||||
|
||||
# Windows
|
||||
net start MongoDB
|
||||
|
||||
# Verify it's running
|
||||
mongosh # Should connect successfully
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How to Start FastAPI Backend
|
||||
|
||||
### 1. Navigate to backend directory
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
```
|
||||
|
||||
### 2. Create Python virtual environment
|
||||
|
||||
```bash
|
||||
python3 -m venv venv
|
||||
|
||||
# Activate it
|
||||
source venv/bin/activate # macOS/Linux
|
||||
# or
|
||||
venv\Scripts\activate # Windows
|
||||
```
|
||||
|
||||
### 3. Install dependencies
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 4. Configure environment (optional)
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env if you need to change defaults
|
||||
```
|
||||
|
||||
### 5. Start the API server
|
||||
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
You should see:
|
||||
|
||||
```
|
||||
✓ Connected to MongoDB: grateful_journal
|
||||
INFO: Uvicorn running on http://0.0.0.0:8001
|
||||
```
|
||||
|
||||
### 6. Access API Documentation
|
||||
|
||||
Open in browser:
|
||||
|
||||
- **Interactive API Docs**: http://localhost:8001/docs
|
||||
- **Alternative Docs**: http://localhost:8001/redoc
|
||||
- **Health Check**: http://localhost:8001/health
|
||||
|
||||
---
|
||||
|
||||
## Complete Startup (All Services)
|
||||
|
||||
### Terminal 1: Start MongoDB
|
||||
|
||||
```bash
|
||||
brew services start mongodb-community
|
||||
mongosh # Verify connection
|
||||
```
|
||||
|
||||
### Terminal 2: Start Frontend
|
||||
|
||||
```bash
|
||||
npm run dev -- --port 8000
|
||||
```
|
||||
|
||||
### Terminal 3: Start Backend
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
source venv/bin/activate
|
||||
python main.py
|
||||
```
|
||||
|
||||
Now you have:
|
||||
|
||||
- **Frontend**: http://localhost:8000
|
||||
- **Backend**: http://localhost:8001
|
||||
- **MongoDB**: localhost:27017
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints Ready to Use
|
||||
|
||||
### User Management
|
||||
|
||||
- `POST /api/users/register` — Register user after Firebase auth
|
||||
- `GET /api/users/by-email/{email}` — Fetch user profile
|
||||
- `PUT /api/users/update/{user_id}` — Update profile
|
||||
- `DELETE /api/users/{user_id}` — Delete account & data
|
||||
|
||||
### Journal Entries
|
||||
|
||||
- `POST /api/entries/{user_id}` — Create entry
|
||||
- `GET /api/entries/{user_id}` — List entries (paginated)
|
||||
- `GET /api/entries/{user_id}/{entry_id}` — Get entry
|
||||
- `PUT /api/entries/{user_id}/{entry_id}` — Update entry
|
||||
- `DELETE /api/entries/{user_id}/{entry_id}` — Delete entry
|
||||
- `GET /api/entries/{user_id}/date/{YYYY-MM-DD}` — Entries by date
|
||||
|
||||
---
|
||||
|
||||
## Authentication Flow
|
||||
|
||||
1. **Frontend**: User clicks "Sign in with Google"
|
||||
2. **Firebase**: Returns auth token + user info (email, displayName, photoURL)
|
||||
3. **Frontend**: Calls `POST /api/users/register` with user data
|
||||
4. **Backend**: Stores user in MongoDB, returns user ID
|
||||
5. **Frontend**: Uses user ID for all subsequent API calls
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
grateful-journal/
|
||||
├── backend/ # NEW: FastAPI backend
|
||||
│ ├── main.py # FastAPI app
|
||||
│ ├── config.py # Settings
|
||||
│ ├── db.py # MongoDB connection
|
||||
│ ├── models.py # Pydantic models
|
||||
│ ├── requirements.txt # Python dependencies
|
||||
│ ├── .env.example # Environment template
|
||||
│ ├── README.md # Backend docs
|
||||
│ └── routers/ # API routes
|
||||
│ ├── users.py
|
||||
│ └── entries.py
|
||||
├── src/ # Frontend (existing)
|
||||
│ └── lib/
|
||||
│ └── firebase.ts # Auth only (Firestore removed)
|
||||
├── docs/
|
||||
│ ├── FIRESTORE_SETUP.md # (old, keep for reference)
|
||||
│ └── MONGODB_SETUP.md # NEW: MongoDB setup guide
|
||||
└── project-context.md # Updated with backend info
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Removed Files (Firestore)
|
||||
|
||||
- ❌ `src/lib/firestoreService.ts` (removed — use MongoDB API instead)
|
||||
- ❌ `src/lib/firestoreConfig.ts` (removed — use MongoDB API instead)
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Start MongoDB** (see above)
|
||||
2. **Start FastAPI** (see above)
|
||||
3. **Connect Frontend to Backend**
|
||||
- Update `src/contexts/AuthContext.tsx` to call `/api/users/register`
|
||||
- Create hooks to fetch/save entries from `/api/entries/*`
|
||||
- Pass Firebase user ID to all API calls
|
||||
|
||||
4. **Test in API Docs** (http://localhost:8001/docs)
|
||||
- Try creating a user
|
||||
- Try creating an entry
|
||||
- Try fetching entries
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**"MongoDB connection refused"**
|
||||
|
||||
- Is the service running? `brew services list` (macOS) or `systemctl status mongod` (Linux)
|
||||
- Check port 27017 is free: `lsof -i :27017`
|
||||
|
||||
**"ModuleNotFoundError: pymongo"**
|
||||
|
||||
- Is venv activated? Run `. venv/bin/activate` again
|
||||
- Did you run `pip install -r requirements.txt`?
|
||||
|
||||
**"CORS error in browser console"**
|
||||
|
||||
- Backend running on 8001? Check `http://localhost:8001/docs`
|
||||
- Frontend URL in `.env`? Should be `http://localhost:8000`
|
||||
|
||||
---
|
||||
|
||||
For detailed setup instructions, see:
|
||||
|
||||
- [MONGODB_SETUP.md](./docs/MONGODB_SETUP.md) — Full MongoDB installation & configuration
|
||||
- [backend/README.md](./backend/README.md) — Backend architecture & endpoints
|
||||
- [project-context.md](./project-context.md) — Implementation rules & conventions
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
from pydantic_settings import BaseSettings
|
||||
from pydantic_settings import BaseSettings # type: ignore
|
||||
from functools import lru_cache
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field # type: ignore
|
||||
from datetime import datetime
|
||||
from typing import Optional, List
|
||||
from enum import Enum
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
296
docs/FIRESTORE_SETUP.md
Normal file
296
docs/FIRESTORE_SETUP.md
Normal file
@@ -0,0 +1,296 @@
|
||||
# Firebase Firestore Setup Guide
|
||||
|
||||
This document explains how to set up and use Firebase Firestore in the grateful-journal project.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Firebase project created at [console.firebase.google.com](https://console.firebase.google.com)
|
||||
- Node.js and npm installed
|
||||
|
||||
## Installation
|
||||
|
||||
Firebase is already installed in this project. To verify, check the `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"firebase": "^12.9.0",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### 1. Set Environment Variables
|
||||
|
||||
Copy the existing `.env.example` to `.env`:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
### 2. Add Firebase Project Credentials
|
||||
|
||||
1. Go to [Firebase Console](https://console.firebase.google.com)
|
||||
2. Select your project
|
||||
3. Go to **Project Settings** (gear icon)
|
||||
4. Under "Your apps", find your web app
|
||||
5. Copy the Firebase config object
|
||||
6. Fill in the following variables in `.env`:
|
||||
|
||||
```env
|
||||
VITE_FIREBASE_API_KEY=your-api-key
|
||||
VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
|
||||
VITE_FIREBASE_DATABASE_URL=https://your-project.firebaseio.com
|
||||
VITE_FIREBASE_PROJECT_ID=your-project-id
|
||||
VITE_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
|
||||
VITE_FIREBASE_MESSAGING_SENDER_ID=your-sender-id
|
||||
VITE_FIREBASE_APP_ID=your-app-id
|
||||
```
|
||||
|
||||
### 3. Enable Firestore in Firebase Console
|
||||
|
||||
1. In Firebase Console, go to **Firestore Database**
|
||||
2. Click **Create Database**
|
||||
3. Choose **Start in test mode** (for development) or set up security rules
|
||||
4. Select your region
|
||||
5. Click **Create**
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/lib/
|
||||
├── firebase.ts # Main Firebase initialization
|
||||
├── firestoreService.ts # Generic Firestore CRUD operations
|
||||
└── firestoreConfig.ts # Collection names and data interfaces
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Import the Firestore instance
|
||||
|
||||
```typescript
|
||||
import { db } from "@/lib/firebase";
|
||||
```
|
||||
|
||||
### Use the Firestore service
|
||||
|
||||
The `firestoreService.ts` file provides generic CRUD operations:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
setDocument,
|
||||
getDocument,
|
||||
getDocuments,
|
||||
queryDocuments,
|
||||
updateDocument,
|
||||
deleteDocument,
|
||||
} from '@/lib/firestoreService'
|
||||
import { COLLECTIONS, JournalEntry } from '@/lib/firestoreConfig'
|
||||
|
||||
// Create or update a journal entry
|
||||
await setDocument(COLLECTIONS.ENTRIES, entryId, {
|
||||
title: 'Today's thoughts',
|
||||
content: 'I am grateful for...',
|
||||
mood: 'grateful',
|
||||
userId: userId,
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
})
|
||||
|
||||
// Get a single entry
|
||||
const entry = await getDocument<JournalEntry>(COLLECTIONS.ENTRIES, entryId)
|
||||
|
||||
// Get all entries
|
||||
const entries = await getDocuments<JournalEntry>(COLLECTIONS.ENTRIES)
|
||||
|
||||
// Query entries with conditions
|
||||
import { where, orderBy } from 'firebase/firestore'
|
||||
|
||||
const userEntries = await queryDocuments<JournalEntry>(COLLECTIONS.ENTRIES, [
|
||||
where('userId', '==', userId),
|
||||
orderBy('createdAt', 'desc'),
|
||||
])
|
||||
|
||||
// Update an entry
|
||||
await updateDocument(COLLECTIONS.ENTRIES, entryId, {
|
||||
updatedAt: Date.now(),
|
||||
})
|
||||
|
||||
// Delete an entry
|
||||
await deleteDocument(COLLECTIONS.ENTRIES, entryId)
|
||||
```
|
||||
|
||||
### Batch Operations
|
||||
|
||||
```typescript
|
||||
import { createWriteBatch, commitBatch } from "@/lib/firestoreService";
|
||||
|
||||
const batch = createWriteBatch();
|
||||
|
||||
// Add operations to batch
|
||||
batch.set(doc(db, COLLECTIONS.ENTRIES, entryId1), entryData1);
|
||||
batch.update(doc(db, COLLECTIONS.ENTRIES, entryId2), { mood: "happy" });
|
||||
batch.delete(doc(db, COLLECTIONS.ENTRIES, entryId3));
|
||||
|
||||
// Commit all at once
|
||||
await commitBatch(batch);
|
||||
```
|
||||
|
||||
## Firestore Collections Schema
|
||||
|
||||
### users
|
||||
|
||||
Document ID: User's auth UID
|
||||
|
||||
```typescript
|
||||
{
|
||||
email: string
|
||||
displayName?: string
|
||||
photoURL?: string
|
||||
createdAt: number (timestamp)
|
||||
updatedAt: number (timestamp)
|
||||
theme?: 'light' | 'dark'
|
||||
}
|
||||
```
|
||||
|
||||
### entries
|
||||
|
||||
Document ID: Auto-generated or custom ID
|
||||
|
||||
```typescript
|
||||
{
|
||||
userId: string (reference to user)
|
||||
title: string
|
||||
content: string
|
||||
mood?: 'happy' | 'sad' | 'neutral' | 'anxious' | 'grateful'
|
||||
tags?: string[]
|
||||
isPublic?: boolean
|
||||
createdAt: number (timestamp)
|
||||
updatedAt: number (timestamp)
|
||||
}
|
||||
```
|
||||
|
||||
### settings
|
||||
|
||||
Document ID: User's auth UID
|
||||
|
||||
```typescript
|
||||
{
|
||||
userId: string
|
||||
notifications?: boolean
|
||||
emailNotifications?: boolean
|
||||
theme?: 'light' | 'dark' | 'system'
|
||||
language?: string
|
||||
updatedAt: number (timestamp)
|
||||
}
|
||||
```
|
||||
|
||||
### tags
|
||||
|
||||
Document ID: Auto-generated or custom ID
|
||||
|
||||
```typescript
|
||||
{
|
||||
userId: string
|
||||
name: string
|
||||
color?: string
|
||||
createdAt: number (timestamp)
|
||||
updatedAt: number (timestamp)
|
||||
}
|
||||
```
|
||||
|
||||
## Security Rules (Production)
|
||||
|
||||
For production, update Firestore security rules in the Firebase Console:
|
||||
|
||||
```firestore-rules
|
||||
rules_version = '2';
|
||||
service cloud.firestore {
|
||||
match /databases/{database}/documents {
|
||||
// Users can only read/write their own user document
|
||||
match /users/{userId} {
|
||||
allow read, write: if request.auth.uid == userId;
|
||||
}
|
||||
|
||||
// Users can only read/write their own entries
|
||||
match /entries/{document=**} {
|
||||
allow read, write: if request.auth.uid == resource.data.userId;
|
||||
allow create: if request.auth.uid == request.resource.data.userId;
|
||||
}
|
||||
|
||||
// Users can only read/write their own settings
|
||||
match /settings/{userId} {
|
||||
allow read, write: if request.auth.uid == userId;
|
||||
}
|
||||
|
||||
// Users can only read/write their own tags
|
||||
match /tags/{document=**} {
|
||||
allow read, write: if request.auth.uid == resource.data.userId;
|
||||
allow create: if request.auth.uid == request.resource.data.userId;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Local Emulator (Optional)
|
||||
|
||||
To test locally without hitting your Firebase backend:
|
||||
|
||||
### 1. Install Firebase CLI
|
||||
|
||||
```bash
|
||||
npm install -g firebase-tools
|
||||
```
|
||||
|
||||
### 2. Initialize Firebase Emulator
|
||||
|
||||
```bash
|
||||
firebase init emulators
|
||||
```
|
||||
|
||||
Select Firestore and Authentication emulators.
|
||||
|
||||
### 3. Start the Emulator
|
||||
|
||||
```bash
|
||||
firebase emulators:start
|
||||
```
|
||||
|
||||
### 4. Enable Emulator in Your App (Optional)
|
||||
|
||||
Update `.env`:
|
||||
|
||||
```env
|
||||
VITE_FIREBASE_EMULATOR_ENABLED=true
|
||||
VITE_FIRESTORE_EMULATOR_HOST=localhost:8080
|
||||
```
|
||||
|
||||
The emulator connection is already commented in `src/lib/firebase.ts` - uncomment it when needed.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Permission Denied Error
|
||||
|
||||
- Check your Firestore security rules in Firebase Console
|
||||
- Ensure your `.env` variables are correct
|
||||
- Make sure you're authenticated before writing to Firestore
|
||||
|
||||
### Document Not Found
|
||||
|
||||
- Verify the collection name and document ID
|
||||
- Check if the document exists in Firestore Console
|
||||
- Ensure the user has read permissions
|
||||
|
||||
### Emulator Not Connecting
|
||||
|
||||
- Ensure Firebase emulator is running: `firebase emulators:start`
|
||||
- Check that the emulator host matches your `.env` configuration
|
||||
- Verify port 8080 is available
|
||||
|
||||
## Resources
|
||||
|
||||
- [Firebase Firestore Documentation](https://firebase.google.com/docs/firestore)
|
||||
- [Firestore Best Practices](https://firebase.google.com/docs/firestore/best-practices)
|
||||
- [Firebase Security Rules](https://firebase.google.com/docs/firestore/security/start)
|
||||
@@ -62,7 +62,8 @@ src/ # Frontend
|
||||
components/ # BottomNav, LoginCard, GoogleSignInButton, ProtectedRoute
|
||||
contexts/ # AuthContext (Firebase Google Auth)
|
||||
lib/
|
||||
firebase.ts # Firebase auth config (Firestore removed)
|
||||
firebase.ts # Firebase auth config (Google sign-in only)
|
||||
api.ts # API client for backend calls
|
||||
|
||||
backend/ # FastAPI backend (Port 8001)
|
||||
main.py # FastAPI app, CORS, routes, lifespan
|
||||
@@ -96,9 +97,8 @@ _Last updated: 2026-03-04_
|
||||
✅ Pydantic models for User, JournalEntry, UserSettings
|
||||
✅ Route structure: `/api/users/*` and `/api/entries/*`
|
||||
✅ CORS enabled for frontend (localhost:8000)
|
||||
✅ Firestore database files removed (`firestoreService.ts`, `firestoreConfig.ts`)
|
||||
✅ Firebase authentication kept (Google sign-in only)
|
||||
|
||||
✅ Firebase Google Auth kept (Firestore completely removed)
|
||||
✅ MongoDB as single source of truth
|
||||
### API Ready
|
||||
|
||||
- User registration, profile updates, deletion
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/**
|
||||
* 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'
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
45
start-dev.sh
45
start-dev.sh
@@ -1,45 +0,0 @@
|
||||
#!/bin/bash
|
||||
# grateful-journal startup script
|
||||
|
||||
echo "🚀 Starting Grateful Journal (Development)"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Check if MongoDB is running
|
||||
echo "Checking MongoDB..."
|
||||
if mongosh --eval "db.adminCommand('ping')" &>/dev/null; then
|
||||
echo "✅ MongoDB is running"
|
||||
else
|
||||
echo "❌ MongoDB not running. Start it with:"
|
||||
echo " brew services start mongodb-community (macOS)"
|
||||
echo " sudo systemctl start mongod (Linux)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Starting Frontend..."
|
||||
cd "$(dirname "$0")"
|
||||
npm run dev -- --port 8000 &
|
||||
FRONTEND_PID=$!
|
||||
echo "✅ Frontend: http://localhost:8000 (PID: $FRONTEND_PID)"
|
||||
|
||||
echo ""
|
||||
echo "Starting Backend..."
|
||||
cd backend
|
||||
source venv/bin/activate 2>/dev/null || . venv/Scripts/activate 2>/dev/null
|
||||
python main.py &
|
||||
BACKEND_PID=$!
|
||||
echo "✅ Backend: http://localhost:8001 (PID: $BACKEND_PID)"
|
||||
echo " API Docs: http://localhost:8001/docs"
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Services running:"
|
||||
echo " • Frontend (React): 8000"
|
||||
echo " • Backend (FastAPI): 8001"
|
||||
echo " • MongoDB: 27017"
|
||||
echo ""
|
||||
echo "Press Ctrl+C to stop all services"
|
||||
echo "=========================================="
|
||||
|
||||
wait
|
||||
Reference in New Issue
Block a user