Home Manual Reference Source

src/database/firebaseDBMethods.js

import { collection, getDocs, doc, getDoc, updateDoc, serverTimestamp, arrayUnion, setDoc } from 'firebase/firestore';
import { db } from './firebase';


/**
 *  A classe Storage e responsavel por gerenciar as operacoes de acesso, atualizacao e manipulacao de dados no 
 *  banco de dados Firebase Firestore. Ela abstrai a logica de interacao com o Firestore, proporcionando metodos 
 *  para realizar operacoes como obter todos os usuarios, criar novos usuarios, obter documentos especificos, 
 *  atualizar documentos, entre outros.
 */
export default class DBStorage {
    collection = collection(db, 'bankapp');
    allUsersDoc = doc(db, 'bankapp', 'allUsersDoc')
    myDoc;

    /**
     *  Inicializa instancias dos objetos Firestore necessarios para operacoes subsequentes
        Aceita um parametro opcional docName para especificar o nome do documento a ser manipulado
     * @param {string} docName 
     */
    constructor(docName) {
        this.myDoc = doc(db, 'bankapp', docName);
    }

    /**
     *  Um metodo generico para acessar o banco de dados, utilizado por outros metodos
        Aceita uma funcao func que representa a operacao a ser realizada
        Retorna os dados se isReturn for verdadeiro, caso contrario, retorna true se a operacao for bem-sucedida
     * @param {function} func 
     * @param {boolean} isReturn 
     * @returns Se a operacao teve sucesso
     */
    accessDatabase = async (func, isReturn = false) => {
        try {
            const docSnapshot = await func();
            if (isReturn) {
                if (docSnapshot.exists()) {
                    const dadosDoDocumento = docSnapshot.data();
                    let jsonD = JSON.stringify(dadosDoDocumento);
                    return JSON.parse(jsonD);
                } else {
                    console.log('Documento nao encontrado!');
                    return 404;
                }
            } else {
                console.log('Operacao efetuada com sucesso!');
                return true;
            }
        } catch (error) {
            console.log('Erro na acao: ', error);
            return false;
        }
    }

    /**
     *  Obtem todos os usuarios do documento especifico (allUsersDoc)
     * @returns Um objeto contendo os dados dos usuarios da base
     */
    async getAllUsers() {
        return await this.accessDatabase(async () => await getDoc(this.allUsersDoc), true);
    }

    /**
     * Adiciona um novo usuario ao array de usuarios no documento especifico (allUsersDoc)
     * @param {object} data 
     * @returns Se a operacao teve sucesso
     */
    async createNewUser(data) {
        const out = await this.accessDatabase(async () => {
            await updateDoc(this.allUsersDoc, {
                users: arrayUnion(data)
            });
        });
        return out;
    }

    /**
     * Cria um novo documento com nome especifico baseado no email do usuario.
     * @param {string} email 
     * @returns Se a operacao teve sucesso
     */
    async createNewUserDoc(email) {
        let newDoc = {
            userData: {
                email: email
            }
        };

        try {
            const novoDocRef = doc(db, 'bankapp', email);
            await setDoc(novoDocRef, { ...newDoc, createdAt: serverTimestamp() });
            console.log('Novo documento criado com nome especifico com sucesso!');
            return true;
        } catch (error) {
            console.log('Erro ao criar novo documento com nome especifico:', error);
            return false;
        }
    }

    /**
     * Obtem todos os documentos na colecao bankapp.
     * @returns Uma lista com os documentos
     */
    async getAllDocs() {
        try {
            const querySnapshot = await getDocs(this.collection);
            const nomesDosDocs = querySnapshot.docs.map((doc) => doc.id);
            return nomesDosDocs;
        } catch (error) {
            console.error('Erro ao obter nomes dos documentos:', error);
            return [];
        }
    }

    /**
     * Obtem todos os dados do documento especifico (myDoc)
     * @returns Os dados do documento
     */
    async getFullDoc() {
        return await this.accessDatabase(async () => await getDoc(this.myDoc), true);
    }

    /**
     * Atualiza o documento especifico (myDoc)
     * @param {object} data 
     * @returns Se a operacao teve sucesso
     */
    async updateDoc(data) {
        const out = await this.accessDatabase(async () => {
            await updateDoc(this.myDoc, { ...data, updatedAt: serverTimestamp() });
        });
        return out;
    }

    /**
     * Adiciona um investimento ao valor ja existente no banco
     * @param {object} data 
     * @returns Se a operacao teve sucesso
     */
    async appendToInvestments(data) {
        const out = await this.accessDatabase(async () => {
            await updateDoc(this.myDoc, {
                investments: arrayUnion(data)
            });
        });
        return out;
    }

    /**
     * Adiciona uma receita ao valor ja existente no banco
     * @param {object} data 
     * @returns Se a operacao teve sucesso
     */
    async appendToIncomes(data) {
        const out = await this.accessDatabase(async () => {
            await updateDoc(this.myDoc, {
                incomes: arrayUnion(data)
            });
        });
        return out;
    }

    /**
     * Adiciona um gasto/uma compra ao valor ja existente no banco
     * @param {object} data 
     * @returns Se a operacao teve sucesso
     */
    async appendToExpenses(data) {
        const out = await this.accessDatabase(async () => {
            await updateDoc(this.myDoc, {
                expenses: arrayUnion(data)
            });
        });
        return out;
    }

    /**
     * Deleta um documento especifico da colecao
     * @param {number} index
     * @returns Se a operacao teve sucesso
     */
    async deleteContent(index) {
        try {
            this.collection.doc(index).delete();
            return 'Dados deletados com sucesso!';
        } catch (e) {
            return 'Ocorreu um problema ao deletar os dados da nuvem!\n' + e;
        }
    }
}