From da4202bbdfb50eb963ffacf5f40e27b9657ae2bc Mon Sep 17 00:00:00 2001 From: mehanana Date: Sat, 25 Jul 2026 20:15:56 -0400 Subject: [PATCH 1/2] extracted Project, Expenditure, and User (and AuthUser) into their own types & created index.ts file so it can be uploaded from @/types --- apps/frontend/src/types/auth.ts | 5 +++++ apps/frontend/src/types/expenditure.ts | 10 ++++++++++ apps/frontend/src/types/index.ts | 4 ++++ apps/frontend/src/types/project.ts | 19 +++++++++++++++++++ apps/frontend/src/types/user.ts | 8 ++++++++ 5 files changed, 46 insertions(+) create mode 100644 apps/frontend/src/types/auth.ts create mode 100644 apps/frontend/src/types/expenditure.ts create mode 100644 apps/frontend/src/types/index.ts create mode 100644 apps/frontend/src/types/project.ts create mode 100644 apps/frontend/src/types/user.ts diff --git a/apps/frontend/src/types/auth.ts b/apps/frontend/src/types/auth.ts new file mode 100644 index 00000000..312d7a24 --- /dev/null +++ b/apps/frontend/src/types/auth.ts @@ -0,0 +1,5 @@ +export interface AuthUser { + sub: string; + email: string; + name?: string; +} \ No newline at end of file diff --git a/apps/frontend/src/types/expenditure.ts b/apps/frontend/src/types/expenditure.ts new file mode 100644 index 00000000..c0560780 --- /dev/null +++ b/apps/frontend/src/types/expenditure.ts @@ -0,0 +1,10 @@ +export interface Expenditure { + expenditure_id: number; + project_id: number; + entered_by: number | null; + amount: string; + category: string | null; + description: string | null; + spent_on: string; + created_at: string | null; + }; \ No newline at end of file diff --git a/apps/frontend/src/types/index.ts b/apps/frontend/src/types/index.ts new file mode 100644 index 00000000..231818ef --- /dev/null +++ b/apps/frontend/src/types/index.ts @@ -0,0 +1,4 @@ +export * from './project'; +export * from './expenditure'; +export * from './user'; +export * from './auth'; \ No newline at end of file diff --git a/apps/frontend/src/types/project.ts b/apps/frontend/src/types/project.ts new file mode 100644 index 00000000..f1af6a27 --- /dev/null +++ b/apps/frontend/src/types/project.ts @@ -0,0 +1,19 @@ +export interface Project { + project_id: number; + name: string; + description: string; + total_budget: string | null; + start_date: string | null; + end_date: string | null; + currency: string | null; + created_at: string | null; +}; + +export type ProjectRole = 'PI' | 'Accountant' | 'Staff' | 'Admin'; + +export interface Member { + user_id: number; + name: string; + email: string; + role: ProjectRole; +} \ No newline at end of file diff --git a/apps/frontend/src/types/user.ts b/apps/frontend/src/types/user.ts new file mode 100644 index 00000000..d3f23ad4 --- /dev/null +++ b/apps/frontend/src/types/user.ts @@ -0,0 +1,8 @@ +export interface User { + user_id: number; + name: string; + email: string; + is_admin: boolean; + created_at?: string; + profile_image?: string | null; +} \ No newline at end of file From 3c6580da6deedbe5e50f6bba975369062a37422c Mon Sep 17 00:00:00 2001 From: mehanana Date: Sat, 25 Jul 2026 20:16:17 -0400 Subject: [PATCH 2/2] uploaded Project, Expenditure, User from types directory --- apps/frontend/src/app/accounts/page.tsx | 9 +-------- .../src/app/components/AddExpenseModal.tsx | 9 ++------- .../src/app/components/ExpensesTable.tsx | 12 +---------- apps/frontend/src/app/expenses/page.tsx | 19 ++---------------- .../app/projects/[id]/ProjectDetailClient.tsx | 20 +------------------ apps/frontend/src/context/AuthContext.tsx | 13 ++++-------- 6 files changed, 11 insertions(+), 71 deletions(-) diff --git a/apps/frontend/src/app/accounts/page.tsx b/apps/frontend/src/app/accounts/page.tsx index 16e6ab87..1c5cd0f4 100644 --- a/apps/frontend/src/app/accounts/page.tsx +++ b/apps/frontend/src/app/accounts/page.tsx @@ -2,14 +2,7 @@ import React from 'react'; import StaffCard from '../components/StaffCard'; - -interface User { - user_id: number; - name: string; - email: string; - is_admin: boolean; - created_at?: string; -} +import { User } from '@/types'; const mockUsers: User[] = [ { user_id: 1, name: 'Mehana Nagarur', email: 'nagarur.m@northeastern.edu', is_admin: true }, diff --git a/apps/frontend/src/app/components/AddExpenseModal.tsx b/apps/frontend/src/app/components/AddExpenseModal.tsx index 87a1855c..ad95daaf 100644 --- a/apps/frontend/src/app/components/AddExpenseModal.tsx +++ b/apps/frontend/src/app/components/AddExpenseModal.tsx @@ -6,19 +6,14 @@ import DropdownSelector from './DropdownSelector'; import { apiFetch } from '@/lib/api'; import FileUpload from './FileUpload'; import { FiDollarSign } from 'react-icons/fi'; - -interface Project { - project_id: number; - name: string; -} - +import { Project } from '@/types'; interface AddExpenseModalProps { open: boolean; onClose: () => void; onSuccess: () => void; token: string; categories: string[]; - projects: Project[]; + projects: Pick[]; } export default function AddExpenseModal({ diff --git a/apps/frontend/src/app/components/ExpensesTable.tsx b/apps/frontend/src/app/components/ExpensesTable.tsx index 90c090c7..eaf134e7 100644 --- a/apps/frontend/src/app/components/ExpensesTable.tsx +++ b/apps/frontend/src/app/components/ExpensesTable.tsx @@ -1,17 +1,7 @@ import { Table, } from '@chakra-ui/react'; - - export type Expenditure = { - expenditure_id: number; - project_id: number; - entered_by: number | null; - amount: string; - category: string | null; - description: string | null; - spent_on: string; - created_at: string | null; - }; +import { Expenditure } from '@/types'; interface ExpensesTableProps { expenditures: Expenditure[]; diff --git a/apps/frontend/src/app/expenses/page.tsx b/apps/frontend/src/app/expenses/page.tsx index 67d6758c..50f95a6d 100644 --- a/apps/frontend/src/app/expenses/page.tsx +++ b/apps/frontend/src/app/expenses/page.tsx @@ -16,22 +16,7 @@ import { CiFilter } from 'react-icons/ci'; import { LuArrowDownUp } from 'react-icons/lu'; import { FaPlus } from 'react-icons/fa'; import ExpensesTable from '../components/ExpensesTable'; - -type Expenditure = { - expenditure_id: number; - project_id: number; - entered_by: number | null; - amount: string; - category: string | null; - description: string | null; - spent_on: string; - created_at: string | null; -}; - -type Project = { - project_id: number; - name: string; -}; +import { Expenditure, Project } from '@/types'; const MONTHS = [ 'January', 'February', 'March', 'April', 'May', 'June', @@ -59,7 +44,7 @@ export default function ExpensePage() { function ExpensePageContent() { // Data const [expenditures, setExpenditures] = useState([]); - const [projects, setProjects] = useState([]); + const [projects, setProjects] = useState[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); diff --git a/apps/frontend/src/app/projects/[id]/ProjectDetailClient.tsx b/apps/frontend/src/app/projects/[id]/ProjectDetailClient.tsx index 6d37af05..d3fea60d 100644 --- a/apps/frontend/src/app/projects/[id]/ProjectDetailClient.tsx +++ b/apps/frontend/src/app/projects/[id]/ProjectDetailClient.tsx @@ -6,26 +6,8 @@ import { RxCaretRight } from 'react-icons/rx'; import NavBar from '../../components/Navbar'; import ExpensesTable from '../../components/ExpensesTable'; import StaffCard from '../../components/StaffCard'; -import type { Expenditure } from '../../components/ExpensesTable'; import { apiFetch } from '@/lib/api'; - -type Project = { - project_id: number; - name: string; - description: string; - total_budget: string | null; - start_date: string | null; - end_date: string | null; - currency: string | null; - created_at: string | null; -}; - -type Member = { - user_id: number; - name: string; - email: string; - role: string; -}; +import { Project, Expenditure, Member } from '@/types'; const PREVIEW_EXPENSES = 8; const PREVIEW_STAFF = 4; diff --git a/apps/frontend/src/context/AuthContext.tsx b/apps/frontend/src/context/AuthContext.tsx index 166675f5..cd503d0e 100644 --- a/apps/frontend/src/context/AuthContext.tsx +++ b/apps/frontend/src/context/AuthContext.tsx @@ -2,17 +2,12 @@ import { createContext, useContext, useEffect, useState } from 'react'; import { apiFetch } from '@/lib/api'; +import { AuthUser } from '@/types'; // --------------------------------------------------------------------------- // Types // --------------------------------------------------------------------------- -interface User { - sub: string; - email: string; - name?: string; -} - interface AuthTokens { accessToken: string; idToken: string; @@ -20,7 +15,7 @@ interface AuthTokens { } interface AuthContextValue { - user: User | null; + user: AuthUser | null; isAuthenticated: boolean; isLoading: boolean; login: (email: string, password: string) => Promise; @@ -53,7 +48,7 @@ const STORAGE_KEYS = { REFRESH: 'branch_refresh_token', } as const; -function decodeIdToken(token: string): User | null { +function decodeIdToken(token: string): AuthUser | null { try { const payload = token.split('.')[1]; const padded = payload.replace(/-/g, '+').replace(/_/g, '/'); @@ -88,7 +83,7 @@ function clearTokens() { const AuthContext = createContext(null); export function AuthProvider({ children }: { children: React.ReactNode }) { - const [user, setUser] = useState(null); + const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); // Restore session from localStorage on mount