From 4776317beb944e088926b1744b9a51cda7dab427 Mon Sep 17 00:00:00 2001 From: khangluong2004 Date: Thu, 5 Sep 2024 20:55:17 +1000 Subject: [PATCH 01/15] Add schema and cleans up the old one --- src/components/Invoice.tsx | 12 +++--------- src/database/invoice.ts | 10 ++++++++++ 2 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 src/database/invoice.ts diff --git a/src/components/Invoice.tsx b/src/components/Invoice.tsx index 9def781..62160e1 100644 --- a/src/components/Invoice.tsx +++ b/src/components/Invoice.tsx @@ -18,6 +18,8 @@ import { Button } from "@mui/joy"; import { ToastContainer, toast } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; import "../App.css"; +import {InvoiceSchema} from "../database/invoice"; + const const_images = { logo: "/cissa.png", club: "/cissa-affiliated-club.jpg", @@ -384,15 +386,7 @@ const styles = StyleSheet.create({ }, }); -interface InvoiceProps { - invoice_id: string; - recipient: string; - recipient_abn: string; - recipient_address: string; - items: { - description: string; - amount: string; - }[]; +interface InvoiceProps extends InvoiceSchema{ total_amount: string; } export default function Invoice(props: InvoiceProps) { diff --git a/src/database/invoice.ts b/src/database/invoice.ts new file mode 100644 index 0000000..57aff75 --- /dev/null +++ b/src/database/invoice.ts @@ -0,0 +1,10 @@ +export interface InvoiceSchema { + invoice_id: string; + recipient: string; + recipient_abn: string; + recipient_address: string; + items: { + description: string; + amount: string; + }[]; +} \ No newline at end of file From 1b6a6977d0ac4fa8f8990018bae2bcd66ce2270f Mon Sep 17 00:00:00 2001 From: Troppydash Date: Fri, 6 Sep 2024 12:09:21 +1000 Subject: [PATCH 02/15] Added reimbursement timestamp --- src/components/ReimbursementCard.tsx | 2 +- src/database/analytics.ts | 16 +++++------ src/database/reimbursement.ts | 41 +++++++++++++++++++--------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/components/ReimbursementCard.tsx b/src/components/ReimbursementCard.tsx index 7b2a9ae..aca22c4 100644 --- a/src/components/ReimbursementCard.tsx +++ b/src/components/ReimbursementCard.tsx @@ -29,7 +29,7 @@ export default function ReimbursementCard( const time = useMemo(() => { - return reimbursement.purchaseDate.toLocaleString(undefined, { + return (reimbursement.purchaseDate as Date).toLocaleString(undefined, { weekday: 'short', year: 'numeric', month: 'long', diff --git a/src/database/analytics.ts b/src/database/analytics.ts index 3ed1765..3f62116 100644 --- a/src/database/analytics.ts +++ b/src/database/analytics.ts @@ -1,4 +1,4 @@ -import {DEPARTMENTS, getActiveReimbursement, ReimbursementRead} from "./reimbursement"; +import {DEPARTMENTS, getActiveReimbursement, snapShotToList} from "./reimbursement"; import {app} from "../config"; import { getFirestore, @@ -77,6 +77,7 @@ export async function activeReimbursementDepartmentStatistics(): Promise>(names: string[], columns: */ export async function getSpreadSheetExport(): Promise { /** - * Timestamp (nope), + * Timestamp, * Full name, * Bank account name * have you submitted your bank account before (nope) @@ -141,12 +142,8 @@ export async function getSpreadSheetExport(): Promise { const reimbursementQuery = query( collection(db, 'reimbursement') ); - const reimbursements = (await getDocs(reimbursementQuery)).docs.map(res => { - let data = res.data(); - data.docId = res.id; - data.purchaseDate = data.purchaseDate.toDate(); - return (data as ReimbursementRead); - }); + const docs = await getDocs(reimbursementQuery); + const reimbursements = await snapShotToList(docs) const users: Record = {}; const rows: SpreadSheetRow[] = []; @@ -156,6 +153,7 @@ export async function getSpreadSheetExport(): Promise { } const user = users[row.userid]; rows.push({ + timestamp: row.timestamp?.toLocaleDateString() ?? "", purchaseDate: row.purchaseDate.toLocaleDateString(), fullname: user.name, accountName: user.name, @@ -171,10 +169,12 @@ export async function getSpreadSheetExport(): Promise { } const columns: (keyof SpreadSheetRow)[] = [ + 'timestamp', 'purchaseDate', 'fullname', 'accountName', 'event', 'description', 'amount', 'receipt', 'additional', 'bsb', 'accountNumber', 'status' ]; const columnsNames: string[] = [ + 'Timestamp', 'Purchase Date', 'Full Name', 'Bank account name (the name that your account is under)', 'What event was with for?', 'Description of purchase', 'Purchase amount (AUD)', 'Receipt upload (please upload pdf)', 'Is there anything you would like to let me know?', 'BSB', 'Account No', 'initiated?' diff --git a/src/database/reimbursement.ts b/src/database/reimbursement.ts index f848226..9b0730b 100644 --- a/src/database/reimbursement.ts +++ b/src/database/reimbursement.ts @@ -1,7 +1,19 @@ import {app} from "../config"; -import {getFirestore, doc, setDoc, getDoc, getDocs, - collection, query, where, orderBy, updateDoc, - QuerySnapshot, DocumentData} from "firebase/firestore"; +import { + collection, + doc, + DocumentData, + getDoc, + getDocs, + getFirestore, + orderBy, + query, + QuerySnapshot, + serverTimestamp, + setDoc, + updateDoc, + where +} from "firebase/firestore"; import {createUser, User} from "../auth/types"; const db = getFirestore(app); @@ -13,6 +25,8 @@ export const DEPARTMENTS = ["IT", "Events", "Competition", "Education", "Industr // submission schema export interface Reimbursement { + // created at + timestamp?: Date; // foreign key for the account name, bsb, account number userid: string; // name of event @@ -58,23 +72,24 @@ export async function addReimbursement(submission: Reimbursement) { // store the document const ref = doc(collection(db, "reimbursement")); try { - await setDoc(ref, submission); + await setDoc(ref, { + ...submission, + timestamp: serverTimestamp() + }); } catch (e){ console.log((e as Error).message); throw new Error("Error while uploading the submission to DB"); } - } -function snapShotToList(snapshot: QuerySnapshot): ReimbursementRead[]{ - let result: ReimbursementRead[] = snapshot.docs.map(res => { +export function snapShotToList(snapshot: QuerySnapshot): ReimbursementRead[]{ + return snapshot.docs.map(res => { let data = res.data(); data.docId = res.id; data.purchaseDate = data.purchaseDate.toDate(); + data.timestamp = data.timestamp.toDate(); return (data as ReimbursementRead); - }) - - return result; + }); } // returns the list of all active reimbursements @@ -82,7 +97,7 @@ export async function getActiveReimbursement(): Promise { const q = query( collection(db, "reimbursement"), where("state", "==", "Active"), - orderBy("purchaseDate", "desc") + orderBy("timestamp", "desc") ); const snapshot = await getDocs(q); @@ -92,7 +107,7 @@ export async function getActiveReimbursement(): Promise { export async function getAllReimbursement(): Promise { const q = query( collection(db, "reimbursement"), - orderBy("purchaseDate", "desc") + orderBy("timestamp", "desc") ); const snapshot = await getDocs(q); @@ -105,7 +120,7 @@ export async function getMyReimbursement(user: User): Promise Date: Fri, 6 Sep 2024 12:40:58 +1000 Subject: [PATCH 03/15] Changed sitewise header --- src/components/Header.tsx | 70 +++++++++++++++++++++----------- src/components/header.module.css | 27 ++++++++++++ src/pages/Analytics/index.tsx | 11 +---- src/pages/Dashboard/index.tsx | 1 - src/routes/RouterProvider.tsx | 6 ++- 5 files changed, 78 insertions(+), 37 deletions(-) create mode 100644 src/components/header.module.css diff --git a/src/components/Header.tsx b/src/components/Header.tsx index ab85e86..1e1a72e 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,31 +1,53 @@ +import styles from './header.module.css'; +import Casino from "@mui/icons-material/Casino"; import * as React from "react"; -import type { User } from "../auth/types"; -import Card from "@mui/joy/Card"; -import Typography from "@mui/joy/Typography"; -import Avatar from "@mui/joy/Avatar"; -import Button from "@mui/joy/Button"; +import Typography from "@mui/material/Typography"; +import {Link} from 'react-router-dom'; +import {useContext, useMemo} from "react"; +import {UserContext} from "../stores/user"; +import {logoutSession} from "../auth/session"; + +export function Header() { + + const {user} = useContext(UserContext); + const isAuthed = useMemo(() => { + return user.id !== ""; + }, [user]); -type Props = { - user: User; - onLogout: () => void; - onAnalytics: () => void; -}; -export function Header({ user, onLogout, onAnalytics }: Props) { return ( - - - - Hello {user?.name}, Welcome to Pennywise! - +
+
+ +
+
+ + Pennywise + +
+
+
+ + + Dashboard + + + + + Analytics + + + { + isAuthed && ( + + + Log Out + + + ) + } -
- {user.isTreasurer && } -
- +
); } diff --git a/src/components/header.module.css b/src/components/header.module.css new file mode 100644 index 0000000..4b113e8 --- /dev/null +++ b/src/components/header.module.css @@ -0,0 +1,27 @@ +* { + box-sizing: border-box; +} + +.header { + display: flex; + width: 100vw; + background: #020a23; + padding: 1rem; + align-items: center; +} + +.header > * { + margin-left: 1rem; +} + +.spacer { + flex: 1; +} + +.links { + display: flex; +} + +.links > * { + margin-right: 1.5rem; +} \ No newline at end of file diff --git a/src/pages/Analytics/index.tsx b/src/pages/Analytics/index.tsx index 058b9bb..076343c 100644 --- a/src/pages/Analytics/index.tsx +++ b/src/pages/Analytics/index.tsx @@ -14,6 +14,7 @@ import Card from '@mui/material/Card'; import CardContent from "@mui/material/CardContent"; import Typography from "@mui/material/Typography"; import {PieChart} from "../../components/AnalyticChart"; +import {Header} from "../../components/Header"; /** @@ -88,16 +89,6 @@ export function Analytics() { }, [stats]); return
- - -
- Analytics - -
-
-
-
-