From c0e73e54b17719868b6c4a51112b7f4be2a99f40 Mon Sep 17 00:00:00 2001 From: Robert Lucas <100799838+Robert-M-Lucas@users.noreply.github.com> Date: Thu, 25 Apr 2024 12:11:20 +0100 Subject: [PATCH 1/3] Renamed firestore.ts to transaction.ts --- src/main.tsx | 2 +- src/pages/test firestore/TestFirestore.tsx | 2 +- src/utils/{firestore.test.ts => transaction.test.ts} | 4 ++-- src/utils/{firestore.ts => transaction.ts} | 0 src/utils/transaction_utils.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename src/utils/{firestore.test.ts => transaction.test.ts} (99%) rename src/utils/{firestore.ts => transaction.ts} (100%) diff --git a/src/main.tsx b/src/main.tsx index a1fb6fd..084976b 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,7 +1,7 @@ import React from 'react' import ReactDOM from 'react-dom/client' import './utils/firebase.ts' -import './utils/firestore.ts' +import './utils/transaction.ts' import {RouterProvider} from "react-router-dom"; import {router} from "./router.tsx"; diff --git a/src/pages/test firestore/TestFirestore.tsx b/src/pages/test firestore/TestFirestore.tsx index ba10d12..a92d27f 100644 --- a/src/pages/test firestore/TestFirestore.tsx +++ b/src/pages/test firestore/TestFirestore.tsx @@ -7,7 +7,7 @@ import { overwriteTransaction, Transaction, writeNewTransaction -} from "../../utils/firestore.ts"; +} from "../../utils/transaction.ts"; import {faker, fakerEN_GB} from "@faker-js/faker"; import {getCurrentBalance} from "../../utils/transaction_utils.ts"; import {signInWithGoogle} from "../../utils/authentication.ts"; diff --git a/src/utils/firestore.test.ts b/src/utils/transaction.test.ts similarity index 99% rename from src/utils/firestore.test.ts rename to src/utils/transaction.test.ts index f05741c..28b8bbb 100644 --- a/src/utils/firestore.test.ts +++ b/src/utils/transaction.test.ts @@ -6,7 +6,7 @@ import { Transaction, writeNewTransaction, writeNewTransactionsBatched -} from "./firestore.ts"; +} from "./transaction.ts"; import {faker, fakerEN_GB} from "@faker-js/faker"; import _ from "lodash"; import { describe, expect, test } from "vitest"; @@ -27,7 +27,7 @@ function fakeTransaction(uid: string, name?: string): Transaction { ); } -describe("Firestore Tests", () => { +describe("Firestore Transaction Tests", () => { test("Write/Read Test", async () => { const user = { uid: "sample_uid" } diff --git a/src/utils/firestore.ts b/src/utils/transaction.ts similarity index 100% rename from src/utils/firestore.ts rename to src/utils/transaction.ts diff --git a/src/utils/transaction_utils.ts b/src/utils/transaction_utils.ts index 2882890..53dd236 100644 --- a/src/utils/transaction_utils.ts +++ b/src/utils/transaction_utils.ts @@ -1,5 +1,5 @@ import {User} from "firebase/auth"; -import {getTransactions, getTransactionsFilterOrderBy, Transaction} from "./firestore.ts"; +import {getTransactions, getTransactionsFilterOrderBy, Transaction} from "./transaction.ts"; import {limit, startAfter, where} from "firebase/firestore"; export async function getCurrentBalance(user: User): Promise { From 1d92705a2d18c15c5a51d7ef7f5a3d886d390d72 Mon Sep 17 00:00:00 2001 From: Robert Lucas <100799838+Robert-M-Lucas@users.noreply.github.com> Date: Thu, 25 Apr 2024 12:11:38 +0100 Subject: [PATCH 2/3] Created basic UserPrefs implementation --- src/utils/user_prefs.test.ts | 32 ++++++++++++++++++++++++++ src/utils/user_prefs.ts | 44 ++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/utils/user_prefs.test.ts create mode 100644 src/utils/user_prefs.ts diff --git a/src/utils/user_prefs.test.ts b/src/utils/user_prefs.test.ts new file mode 100644 index 0000000..6ab94d1 --- /dev/null +++ b/src/utils/user_prefs.test.ts @@ -0,0 +1,32 @@ +import {describe, expect, test} from "vitest"; +import {faker} from "@faker-js/faker"; +import {UserPrefs, getUserPrefs, setUserPrefs} from "./user_prefs.ts"; +import _ from "lodash"; + + +describe("Firestore UserPrefs Tests", () => { + test("Read/Write/Default Value Test", async () => { + const user = { uid: faker.string.alphanumeric(20) } + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + const prefs = await getUserPrefs(user); + + expect(_.isEqual(prefs, UserPrefs.default()), "Non-existent UserPrefs should return default").toBeTruthy(); + + prefs.goal = 213; + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + await setUserPrefs(user, prefs); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + const read_prefs = await getUserPrefs(user); + + console.log(prefs); + console.log(read_prefs); + + expect(_.isEqual(read_prefs, prefs), "UserPref changes to be read").toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/src/utils/user_prefs.ts b/src/utils/user_prefs.ts new file mode 100644 index 0000000..c2da073 --- /dev/null +++ b/src/utils/user_prefs.ts @@ -0,0 +1,44 @@ +import {collection, doc, DocumentSnapshot, getDoc, setDoc, SnapshotOptions} from "firebase/firestore"; +import {User} from "firebase/auth"; +import {db} from "./firebase.ts"; + + +export class UserPrefs { + public goal: number; + + constructor(goal: number) { + this.goal = goal; + } + + static default(): UserPrefs { + return new UserPrefs(100); + } + + // Utility method for creating `Transactions` + static fromFirestore(snapshot: DocumentSnapshot, options: SnapshotOptions): UserPrefs { + const data = snapshot.data(options); + if (!data) { + throw Error("No data returned for snapshot!"); + } + const u = new UserPrefs(data.goal); + return u; + } + + toSendObject(): object { + const {...transObject} = this; + return transObject; + } +} + +export async function getUserPrefs(user: User): Promise { + const docRef = doc(collection(db, "UserPrefs"), user.uid); + + return await getDoc(docRef).then((ds) => + UserPrefs.fromFirestore(ds, {}) + ).catch(() => UserPrefs.default()); +} + +export async function setUserPrefs(user: User, prefs: UserPrefs): Promise { + const docRef = doc(collection(db, "UserPrefs"), user.uid); + await setDoc(docRef, prefs.toSendObject()); +} From 47c0405012e2110c3f05a648bb20a2b1d51fbaeb Mon Sep 17 00:00:00 2001 From: Robert Lucas <100799838+Robert-M-Lucas@users.noreply.github.com> Date: Thu, 25 Apr 2024 12:23:41 +0100 Subject: [PATCH 3/3] Added a test page for UserPrefs --- src/pages/test firestore/TestFirestore.tsx | 64 ++++++++++++++++------ src/utils/user_prefs.ts | 3 +- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/pages/test firestore/TestFirestore.tsx b/src/pages/test firestore/TestFirestore.tsx index a92d27f..434b0f4 100644 --- a/src/pages/test firestore/TestFirestore.tsx +++ b/src/pages/test firestore/TestFirestore.tsx @@ -13,6 +13,8 @@ import {getCurrentBalance} from "../../utils/transaction_utils.ts"; import {signInWithGoogle} from "../../utils/authentication.ts"; import {Header} from "../../components/Header.tsx"; import { orderBy } from "firebase/firestore"; +import {User} from "firebase/auth"; +import {getUserPrefs, setUserPrefs, UserPrefs} from "../../utils/user_prefs.ts"; function writeSampleData() { if (auth.currentUser === null) { @@ -43,6 +45,8 @@ export function TestFirestorePage() { const [transactions, setTransactions] = useState([]); const [balance, setBalance] = useState(0); const [update ,setUpdate] = useState(0); + const [user, setUser] = useState(undefined); + const [userPrefs, _setUserPrefs] = useState(null); if (!authResolved) { auth.authStateReady().then(() => setAuthResolved(true)); @@ -56,6 +60,11 @@ export function TestFirestorePage() { } if (auth.currentUser === null) { + auth.onAuthStateChanged((new_user: User | null) => { + if (new_user !== null && new_user.uid !== user) { + setUser(new_user.uid) + } + }); return <>
@@ -71,6 +80,7 @@ export function TestFirestorePage() { getTransactionsFilterOrderBy(auth.currentUser, orderBy("dateTime", "desc")).then((t) => setTransactions(t)); getCurrentBalance(auth.currentUser).then((b) => setBalance(b)); + getUserPrefs(auth.currentUser).then((up) => _setUserPrefs(up)); return ( <> @@ -81,30 +91,48 @@ export function TestFirestorePage() { Sign in with Google - + :

Loading

+ } + +

+ Transactions +

+

+ Balance: {balance} +

+ -

- Balance: {balance} -

-

- Transactions:
-

{ transactions.map((t) =>
-

{new Date(t.dateTime).toISOString()}

-