From 392b9b32b7a50090c6dcaa77be1064b3f77df918 Mon Sep 17 00:00:00 2001 From: Gabriela Guedes Date: Sun, 27 Nov 2022 14:27:52 -0300 Subject: [PATCH 1/3] Add database watching method for checkin and bookings Signed-off-by: Gabriela Guedes --- src/contexts/BookingContext.tsx | 13 +++++-------- src/contexts/CheckinContext.tsx | 9 +++------ src/repositories/database.ts | 20 +++++++++++++++++--- src/services/bookingService.ts | 13 +++++++++++++ src/services/checkinService.ts | 13 +++++++++++++ 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/contexts/BookingContext.tsx b/src/contexts/BookingContext.tsx index 26ecd22..085f04b 100644 --- a/src/contexts/BookingContext.tsx +++ b/src/contexts/BookingContext.tsx @@ -1,5 +1,5 @@ import { createContext, ReactNode, useContext, useEffect, useState } from 'react' -import { Booking } from '_/models/booking' +import { Booking } from '_/models' import { IBookingService } from '_/services' import { useAuth } from './AuthContext' @@ -24,19 +24,16 @@ export function BookingContextProvider({ children, bookingService }: Props){ useEffect(() => { if(!isAuthenticated) return - getAllBookings() + bookingService.watchBookings(setBookings) + + return () => bookingService.unwatchBookings() }, [isAuthenticated]) const createBooking = async (booking: Booking) => { setIsCreatingBooking(true) await bookingService.createBooking(booking) setIsCreatingBooking(false) - } - - const getAllBookings = async () => { - const bookings = await bookingService.listBookings() - setBookings(bookings || []) - } + } return( diff --git a/src/contexts/CheckinContext.tsx b/src/contexts/CheckinContext.tsx index 006c747..1158d54 100644 --- a/src/contexts/CheckinContext.tsx +++ b/src/contexts/CheckinContext.tsx @@ -24,7 +24,9 @@ export function CheckinContextProvider({ children, checkinService }: Props){ useEffect(() => { if(!isAuthenticated) return - getAllCheckins() + checkinService.watchCheckins(setCheckins) + + return () => checkinService.unwatchCheckins() }, [isAuthenticated]) const createCheckin = async (checkin: Checkin) => { @@ -33,11 +35,6 @@ export function CheckinContextProvider({ children, checkinService }: Props){ setIsCreatingCheckin(false) } - const getAllCheckins = async () => { - const checkinsResponse = await checkinService.listCheckins() - setCheckins(checkinsResponse || []) - } - return( {children} diff --git a/src/repositories/database.ts b/src/repositories/database.ts index 198fc4f..cbfac6f 100644 --- a/src/repositories/database.ts +++ b/src/repositories/database.ts @@ -1,17 +1,32 @@ -import { getFirestore, setDoc, doc, Firestore, collection, query, getDocs, QueryConstraint, where, Query, DocumentData } from 'firebase/firestore'; +import { getFirestore, setDoc, doc, Firestore, collection, query, getDocs, where, Query, DocumentData, onSnapshot, QuerySnapshot, Unsubscribe, DocumentSnapshot } from 'firebase/firestore'; export interface DatabaseRepository { getAll(): Promise create(data: any): Promise findBy(field: string, value: string): Promise + watch(callback: (data: any) => void): void + unsubscribe(): void } export class FirebaseDatabaseRepository implements DatabaseRepository { private readonly firestore: Firestore = getFirestore() + private unsub: Unsubscribe | null = null constructor( private readonly collection: string){} + async watch(callback: (data: any) => void){ + this.unsub = onSnapshot(collection(this.firestore, this.collection), async (snap) => { + const data: any[] = snap.docs.map(doc => doc.data()) + callback(data) + }) + } + + async unsubscribe(){ + if(this.unsub === null) return + this.unsub() + } + async getAll(): Promise { const docsRef = query(collection(this.firestore, this.collection)); return await this.parseQueryResult(docsRef) @@ -28,9 +43,8 @@ export class FirebaseDatabaseRepository implements DatabaseRepository { return await this.parseQueryResult(docsRef) } - async parseQueryResult(query: Query){ + async parseQueryResult(query: Query):Promise{ const docsSnap = await getDocs(query) - const result: T[] = [] docsSnap.forEach(snap => { diff --git a/src/services/bookingService.ts b/src/services/bookingService.ts index 4ba3091..263895e 100644 --- a/src/services/bookingService.ts +++ b/src/services/bookingService.ts @@ -5,6 +5,8 @@ import { DatabaseRepository } from "_/repositories" export interface IBookingService { createBooking(booking: Booking): Promise listBookings(): Promise + watchBookings(callback: (data: any) => void): void + unwatchBookings(): void } export class BookingService implements IBookingService { @@ -31,4 +33,15 @@ export class BookingService implements IBookingService { this.alertHelper.alertError("Não foi possível recuperar as reservas.") } } + + watchBookings(callback: (data: Booking[]) => void){ + this.bookingDatabaseRepository.watch((data: any) => { + const bookings: Booking[] = data.map((item: any) => mapResponseToBooking(item)) + callback(bookings) + }) + } + + unwatchBookings(){ + this.bookingDatabaseRepository.unsubscribe() + } } \ No newline at end of file diff --git a/src/services/checkinService.ts b/src/services/checkinService.ts index c6bc03a..500aeb8 100644 --- a/src/services/checkinService.ts +++ b/src/services/checkinService.ts @@ -5,6 +5,8 @@ import { DatabaseRepository } from "_/repositories" export interface ICheckinService { createCheckin(checkin: Checkin): Promise listCheckins(): Promise + watchCheckins(callback: (data: Checkin[]) => void): void + unwatchCheckins(): void } export class CheckinService implements ICheckinService { @@ -31,4 +33,15 @@ export class CheckinService implements ICheckinService { this.alertHelper.alertError("Não foi possível recuperar os checkins.") } } + + watchCheckins(callback: (data: Checkin[]) => void){ + this.checkinDatabaseRepository.watch((data: any) => { + const checkins: Checkin[] = data.map((item: any) => mapResponseToCheckin(item)) + callback(checkins) + }) + } + + unwatchCheckins(){ + this.checkinDatabaseRepository.unsubscribe() + } } \ No newline at end of file From 5568b7a4797f04f34bf47ef477ef9aa9a5089973 Mon Sep 17 00:00:00 2001 From: Gabriela Guedes Date: Sun, 27 Nov 2022 14:37:10 -0300 Subject: [PATCH 2/3] Remove old unused function --- src/services/authService.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/services/authService.ts b/src/services/authService.ts index c79f0b1..359d556 100644 --- a/src/services/authService.ts +++ b/src/services/authService.ts @@ -45,12 +45,6 @@ export class AuthService implements IAuthService { return this.userService.createUser(responseUser) } - async createUserOnFirstLogin(data: any): Promise { - const responseUser = mapAuthResponseToUser(data) - this.userService.createUser(responseUser) - return responseUser - } - async checkAuthenticated() { return new Promise(resolve => { onAuthStateChanged(this.auth, (user) => { From 4aac1ecdd3ecb567c3c5163e0bc682d5aed9de8a Mon Sep 17 00:00:00 2001 From: Gabriela Guedes Date: Wed, 30 Nov 2022 23:31:17 -0300 Subject: [PATCH 3/3] Refactor: Use generic type instead of any --- src/repositories/database.ts | 11 +++++------ src/services/bookingService.ts | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/repositories/database.ts b/src/repositories/database.ts index cbfac6f..6139994 100644 --- a/src/repositories/database.ts +++ b/src/repositories/database.ts @@ -1,11 +1,11 @@ import { getFirestore, setDoc, doc, Firestore, collection, query, getDocs, where, Query, DocumentData, onSnapshot, QuerySnapshot, Unsubscribe, DocumentSnapshot } from 'firebase/firestore'; - +type VoidCallback = (data: T[]) => void export interface DatabaseRepository { getAll(): Promise create(data: any): Promise findBy(field: string, value: string): Promise - watch(callback: (data: any) => void): void + watch(callback: VoidCallback): Promise unsubscribe(): void } @@ -15,16 +15,15 @@ export class FirebaseDatabaseRepository implements DatabaseRepository { constructor( private readonly collection: string){} - async watch(callback: (data: any) => void){ + async watch(callback: VoidCallback){ this.unsub = onSnapshot(collection(this.firestore, this.collection), async (snap) => { - const data: any[] = snap.docs.map(doc => doc.data()) + const data: T[] = snap.docs.map(doc => doc.data() as T) callback(data) }) } async unsubscribe(){ - if(this.unsub === null) return - this.unsub() + this.unsub?.() } async getAll(): Promise { diff --git a/src/services/bookingService.ts b/src/services/bookingService.ts index 263895e..3d417cc 100644 --- a/src/services/bookingService.ts +++ b/src/services/bookingService.ts @@ -35,7 +35,7 @@ export class BookingService implements IBookingService { } watchBookings(callback: (data: Booking[]) => void){ - this.bookingDatabaseRepository.watch((data: any) => { + this.bookingDatabaseRepository.watch((data) => { const bookings: Booking[] = data.map((item: any) => mapResponseToBooking(item)) callback(bookings) })