mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-16 15:59:40 +02:00
293 lines
7.4 KiB
TypeScript
293 lines
7.4 KiB
TypeScript
import {
|
|
collection,
|
|
query,
|
|
where,
|
|
getDocs,
|
|
addDoc,
|
|
updateDoc,
|
|
deleteDoc,
|
|
doc,
|
|
getDoc,
|
|
orderBy,
|
|
limit,
|
|
writeBatch,
|
|
} from 'firebase/firestore';
|
|
import { db, auth } from '../firebaseConfig';
|
|
import { Deck } from '../types/models';
|
|
import type { Slide } from '../types/models';
|
|
|
|
// Decks
|
|
export const getUserDecks = async (userId: string): Promise<Deck[]> => {
|
|
console.log('[Firestore] Getting all decks for user:', userId);
|
|
|
|
try {
|
|
const decksRef = collection(db, 'decks');
|
|
const q = query(decksRef, where('userId', '==', userId), orderBy('createdAt', 'desc'));
|
|
|
|
const querySnapshot = await getDocs(q);
|
|
const decks = querySnapshot.docs.map((doc) => {
|
|
const data = doc.data();
|
|
return {
|
|
id: doc.id,
|
|
...data,
|
|
createdAt: data.createdAt?.toDate() || new Date(),
|
|
updatedAt: data.updatedAt?.toDate() || new Date(),
|
|
} as Deck;
|
|
});
|
|
|
|
console.log('[Firestore] Retrieved decks:', decks.length);
|
|
return decks;
|
|
} catch (error) {
|
|
console.error('[Firestore] Error getting decks:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
export const createDeck = async (deckData: Partial<Deck>): Promise<Deck> => {
|
|
console.log('[Firestore] Creating new deck:', deckData);
|
|
|
|
try {
|
|
if (!auth.currentUser) {
|
|
throw new Error('No authenticated user');
|
|
}
|
|
|
|
const now = new Date();
|
|
const newDeck = {
|
|
...deckData,
|
|
userId: auth.currentUser.uid,
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
sharing: {
|
|
isPublic: false,
|
|
collaborators: {},
|
|
},
|
|
};
|
|
|
|
const docRef = await addDoc(collection(db, 'decks'), newDeck);
|
|
|
|
return {
|
|
id: docRef.id,
|
|
...newDeck,
|
|
} as Deck;
|
|
} catch (error) {
|
|
console.error('[Firestore] Error creating deck:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
export const getDeck = async (deckId: string): Promise<Deck> => {
|
|
console.log('[Firestore] Getting deck:', deckId);
|
|
|
|
try {
|
|
const deckRef = doc(db, 'decks', deckId);
|
|
const deckDoc = await getDoc(deckRef);
|
|
|
|
if (!deckDoc.exists()) {
|
|
throw new Error('Deck not found');
|
|
}
|
|
|
|
const data = deckDoc.data();
|
|
return {
|
|
id: deckDoc.id,
|
|
...data,
|
|
createdAt: data.createdAt?.toDate() || new Date(),
|
|
updatedAt: data.updatedAt?.toDate() || new Date(),
|
|
} as Deck;
|
|
} catch (error) {
|
|
console.error('[Firestore] Error getting deck:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
export const deleteDeck = async (deckId: string): Promise<void> => {
|
|
try {
|
|
console.log('[Firestore] Deleting deck:', deckId);
|
|
const deckRef = doc(db, 'decks', deckId);
|
|
await deleteDoc(deckRef);
|
|
console.log('[Firestore] Deck deleted successfully');
|
|
} catch (error) {
|
|
console.error('[Firestore] Error deleting deck:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
// Slides
|
|
export const getDeckSlides = async (deckId: string): Promise<Slide[]> => {
|
|
console.log('[Firestore] Getting slides for deck:', deckId);
|
|
|
|
try {
|
|
const slidesRef = collection(db, 'decks', deckId, 'slides');
|
|
const q = query(slidesRef, orderBy('order', 'asc'));
|
|
const querySnapshot = await getDocs(q);
|
|
|
|
const slides = querySnapshot.docs.map((doc) => ({
|
|
id: doc.id,
|
|
...doc.data(),
|
|
createdAt: doc.data().createdAt?.toDate() || new Date(),
|
|
updatedAt: doc.data().updatedAt?.toDate() || new Date(),
|
|
})) as Slide[];
|
|
|
|
console.log('[Firestore] Retrieved slides:', slides.length);
|
|
return slides;
|
|
} catch (error) {
|
|
console.error('[Firestore] Error getting slides:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
export const createSlide = async (slideData: Partial<Slide>): Promise<Slide> => {
|
|
console.log('[Firestore] Creating new slide:', slideData);
|
|
|
|
if (!slideData.deckId) {
|
|
throw new Error('deckId is required to create a slide');
|
|
}
|
|
|
|
try {
|
|
const slidesRef = collection(db, 'decks', slideData.deckId, 'slides');
|
|
const now = new Date();
|
|
|
|
// Get the current highest order
|
|
const q = query(slidesRef, orderBy('order', 'desc'), limit(1));
|
|
const querySnapshot = await getDocs(q);
|
|
const highestOrder = querySnapshot.empty ? 0 : querySnapshot.docs[0].data().order;
|
|
|
|
const newSlide = {
|
|
...slideData,
|
|
order: highestOrder + 1,
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
};
|
|
|
|
const docRef = await addDoc(slidesRef, newSlide);
|
|
return {
|
|
id: docRef.id,
|
|
...newSlide,
|
|
} as Slide;
|
|
} catch (error) {
|
|
console.error('[Firestore] Error creating slide:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
export const updateSlide = async (slideId: string, slideData: Partial<Slide>): Promise<void> => {
|
|
console.log('[Firestore] Updating slide:', slideId, slideData);
|
|
|
|
if (!slideData.deckId) {
|
|
throw new Error('deckId is required to update a slide');
|
|
}
|
|
|
|
try {
|
|
const slideRef = doc(db, 'decks', slideData.deckId, 'slides', slideId);
|
|
await updateDoc(slideRef, {
|
|
...slideData,
|
|
updatedAt: new Date(),
|
|
});
|
|
} catch (error) {
|
|
console.error('[Firestore] Error updating slide:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
export const deleteSlide = async (slideId: string, deckId: string): Promise<void> => {
|
|
console.log('[Firestore] Deleting slide:', slideId);
|
|
|
|
try {
|
|
const slideRef = doc(db, 'decks', deckId, 'slides', slideId);
|
|
await deleteDoc(slideRef);
|
|
} catch (error) {
|
|
console.error('[Firestore] Error deleting slide:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
export const reorderSlide = async (
|
|
slideId: string,
|
|
newOrder: number,
|
|
deckId: string
|
|
): Promise<void> => {
|
|
console.log('[Firestore] Reordering slide:', slideId, 'to order:', newOrder);
|
|
|
|
try {
|
|
const slidesRef = collection(db, 'decks', deckId, 'slides');
|
|
const batch = writeBatch(db);
|
|
const now = new Date();
|
|
|
|
// Get all slides in the deck
|
|
const q = query(slidesRef, orderBy('order', 'asc'));
|
|
const querySnapshot = await getDocs(q);
|
|
const slides = querySnapshot.docs;
|
|
|
|
// Find the current slide and its order
|
|
const currentSlide = slides.find((doc) => doc.id === slideId);
|
|
if (!currentSlide) {
|
|
throw new Error('Slide not found');
|
|
}
|
|
const currentOrder = currentSlide.data().order;
|
|
|
|
// Update orders
|
|
slides.forEach((doc) => {
|
|
const slideOrder = doc.data().order;
|
|
if (doc.id === slideId) {
|
|
// Update the target slide
|
|
batch.update(doc.ref, {
|
|
order: newOrder,
|
|
updatedAt: now,
|
|
});
|
|
} else if (newOrder > currentOrder && slideOrder > currentOrder && slideOrder <= newOrder) {
|
|
// Move slides up
|
|
batch.update(doc.ref, {
|
|
order: slideOrder - 1,
|
|
updatedAt: now,
|
|
});
|
|
} else if (newOrder < currentOrder && slideOrder >= newOrder && slideOrder < currentOrder) {
|
|
// Move slides down
|
|
batch.update(doc.ref, {
|
|
order: slideOrder + 1,
|
|
updatedAt: now,
|
|
});
|
|
}
|
|
});
|
|
|
|
await batch.commit();
|
|
console.log('[Firestore] Reorder operation completed successfully');
|
|
} catch (error) {
|
|
console.error('[Firestore] Error reordering slide:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
export const migrateDecksToNewSchema = async (userId: string) => {
|
|
console.log('[Firestore] Migrating decks to new schema for user:', userId);
|
|
|
|
try {
|
|
const decksRef = collection(db, 'decks');
|
|
const q = query(decksRef, where('userId', '==', userId));
|
|
|
|
const querySnapshot = await getDocs(q);
|
|
const batch = writeBatch(db);
|
|
let updateCount = 0;
|
|
|
|
querySnapshot.docs.forEach((docSnapshot) => {
|
|
const deckData = docSnapshot.data();
|
|
if (!deckData.sharing) {
|
|
batch.update(docSnapshot.ref, {
|
|
sharing: {
|
|
isPublic: false,
|
|
collaborators: {},
|
|
},
|
|
});
|
|
updateCount++;
|
|
}
|
|
});
|
|
|
|
if (updateCount > 0) {
|
|
await batch.commit();
|
|
console.log(`[Firestore] Successfully migrated ${updateCount} decks`);
|
|
} else {
|
|
console.log('[Firestore] No decks needed migration');
|
|
}
|
|
} catch (error) {
|
|
console.error('[Firestore] Error migrating decks:', error);
|
|
throw error;
|
|
}
|
|
};
|