Skip to content
This repository was archived by the owner on Dec 30, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CRUD Database App

This code runs the CRUD Database application for volunteers to interact with, input, and update datbase information relating to the Parking Lot Map and Parking Reform Map.
This code runs the CRUD Database application for volunteers to interact with, input, and update database information relating to the Parking Lot Map and Parking Reform Map.

This project utilizes React, Typescript, and Parcel.

Expand Down
5 changes: 4 additions & 1 deletion crud-frontend/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
"sourceType": "module"
},
"plugins": ["@typescript-eslint", "react"],
"rules": {},
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "off"
},
"settings": {
"react": {
"version": "detect" // Automatically detect the React version
Expand Down
3 changes: 3 additions & 0 deletions crud-frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ yarn-error.log*
# Ignore cache files
/.changelog
/.cache

# Environment files
.env
9 changes: 6 additions & 3 deletions crud-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"description": "",
"main": "index.js",
"scripts": {
"start": "set PORT=3000 && parcel ./src/index.html",
"build": "rm -rf dist; parcel build --detailed-report",
"start": "parcel ./src/index.html --port 3000",
"build": "rm -rf dist; parcel build ./src/index.html",
"test": "echo \"Error: no test specified\" && exit 1",
"fmt": "prettier --write .",
"fix": "prettier --write .; eslint --fix .",
Expand All @@ -30,12 +30,15 @@
"@mui/icons-material": "^5.14.16",
"@mui/material": "^5.14.17",
"@react-oauth/google": "^0.11.1",
"@supabase/supabase-js": "^2.39.3",
"@types/react": "^18.2.33",
"@types/react-dom": "^18.2.14",
"axios": "^1.6.1",
"deasync": "^0.1.29",
"dotenv": "^16.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.18.0"
"react-router-dom": "^6.20.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.10.0",
Expand Down
22 changes: 13 additions & 9 deletions crud-frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import React, { lazy, Suspense, FC } from "react";
import { Route, Routes, BrowserRouter } from "react-router-dom";

const HomePage = lazy(() => import("./pages/home/home"));
import LoggedIn from "./pages/loggedIn/loggedIn";
import HomePage from "./pages/home/home"
import { AuthProvider } from "./contexts/AuthContext";

const AppRoutes: FC = () => {
return (
<BrowserRouter>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<HomePage />} />
</Routes>
</Suspense>
</BrowserRouter>
<AuthProvider>
<BrowserRouter>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/logged-in" element={<LoggedIn />} />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally the URL wouldn't change when you're logged in to a value like this. Was this for experimentation, or you intend to keep it?

</Routes>
</Suspense>
</BrowserRouter>
</AuthProvider>
);
};

Expand Down
76 changes: 76 additions & 0 deletions crud-frontend/src/components/login/login.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState, useEffect } from "react";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why call this login/login.tsx rather than login/index.tsx or simply login.tsx?

Also I believe the convention is to use capital letters for the file name, Login.tsx.

import axios from "axios";
import { createClient } from "@supabase/supabase-js";

const supabase = createClient(process.env.REACT_APP_SUPABASE_URL, process.env.REACT_APP_SUPABASE_PUBLIC_ANON_KEY, {
auth: {
Comment on lines +5 to +6

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add instructions to the README about what env vars are necessary, where to find them, and where to set them like an .env file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this seems to duplicate code from supabaseSetup.tsx?

autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: true
}
});

...
declare global {
interface Window {
handleSignInWithGoogle?: any;
}
}

function Login() {
const [session, setSession] = useState(null);
const [user, setUser] = useState(null);

useEffect(() => {
const script = document.createElement('script');

script.src = "https://accounts.google.com/gsi/client";
script.async = true;
script.defer = true;

document.body.appendChild(script);

return () => {
document.body.removeChild(script);
}
}, []);

window.handleSignInWithGoogle = async(response) => {
try {
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: 'http://localhost:3000/logged-in'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't redirect

},
})

} catch (error) {
console.log("Error:", error);
}
}

return (
<>
<div className="google-login-button">
<div id="g_id_onload"
data-client_id="757897629512-3ltcl0q206uancd3h7jbi63aaj3levud.apps.googleusercontent.com"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally client IDs are risky to leak in source code and should be set via env vars. What is this client ID corresponding to? Google API client ID?

data-context="signin"
data-ux_mode="popup"
data-callback="handleSignInWithGoogle"
data-auto_prompt="false">
</div>

<div className="g_id_signin"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="signin_with"
data-size="large"
data-logo_alignment="left">
</div>
</div>
</>
);
}

export default Login;
66 changes: 66 additions & 0 deletions crud-frontend/src/contexts/AuthContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { createContext, useState, useEffect, useContext, ReactNode } from "react";
import { createClient, Session, AuthChangeEvent } from "@supabase/supabase-js";

const supabase = createClient(process.env.REACT_APP_SUPABASE_URL, process.env.REACT_APP_SUPABASE_PUBLIC_ANON_KEY, {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is duplicated

auth: {
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: true
}
});

interface AuthContextProps {
session: Session | null;
user: any;
}
const AuthContext = createContext<AuthContextProps>({session: null, user: null});

export const useAuth = () => useContext(AuthContext)

export const AuthProvider: React.FC<{ children: ReactNode }> = ({children}) => {
const [session, setSession] = useState<Session | null>(null);
const [user, setUser] = useState<any>(null);

useEffect(() => {
const sessionListener = supabase.auth.onAuthStateChange((event: AuthChangeEvent, session: Session | null) => {
setSession(session);
setUser(session?.user ?? null);
});

const fetchSession = async() => {
try {
const { data, error } = await supabase.auth.getSession();

if(error) {
// Handle error if any
console.error("Error fetching session: ", error)
} else if (data && data.session) {
// session exists
setSession(data.session);
setUser(data.session.user ?? null);
} else {
// no session exists, set seesion state to null
setSession(null);
setUser(null);
}
} catch (error) {
console.error("Unexpected error fetching session: ", error)
}
};

fetchSession();

return () => {
if(sessionListener.data.subscription) {
sessionListener.data.subscription.unsubscribe();
}
};
}, []);

return (
<AuthContext.Provider value={{ session, user }}>
{children}
</AuthContext.Provider>
);
};
1 change: 1 addition & 0 deletions crud-frontend/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
<body>
<div id="app"></div>
<script type="module" src="index.tsx"></script>
<script src="https://accounts.google.com/gsi/client" async></script>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You auto-inject this via the JS code. What approach did you intend to do?

</body>
</html>
2 changes: 2 additions & 0 deletions crud-frontend/src/pages/home/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import PRN_LOGO from "../../../public/imgs/PRN_logo.png";
import "./home.scss";
import Login from "./../../components/login/login";

export default function HomePage() {
return (
Expand All @@ -33,6 +34,7 @@ export default function HomePage() {
<Typography component="h1" variant="h5">
Sign in
</Typography>
<Login />
</Box>
</Grid>
</Grid>
Expand Down
34 changes: 34 additions & 0 deletions crud-frontend/src/pages/loggedIn/loggedIn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from "react";
import { useAuth } from "../../contexts/AuthContext";
import { supabase } from "../../setup/supabaseSetup";
import { useNavigate } from "react-router-dom";


export default function LoggedIn() {
const {session, user} = useAuth();

const navigate = useNavigate();

const signOut = async() => {
try {
const { error } = await supabase.auth.signOut();
if(error) {
console.error("Error signing out: ", error.message)
} else {
console.log("User signed out successfully");
navigate("/");
}
} catch (error) {
console.error("Error while signing out: ", error)
}
}

return (
<div>
{session ? <h1>User is logged in</h1> : <h1>User is not logged in</h1>}
{user ? <h2>User {user.email} is logged in</h2> : <h2>User has no name</h2>}
<button onClick={signOut}>Sign Out</button>
</div>
)
}

2 changes: 0 additions & 2 deletions crud-frontend/src/pages/rootpage/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ interface RootpageProps {
const Rootpage: FC<RootpageProps> = ({ children, header }) => {
return (
<>
{/* Have a header here */}
{children}
{/* Have a footer here */}
</>
);
};
Expand Down
10 changes: 10 additions & 0 deletions crud-frontend/src/setup/supabaseSetup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createClient } from '@supabase/supabase-js';

const supabaseUrl = process.env.REACT_APP_SUPABASE_URL;
const supabaseKey = process.env.REACT_APP_SUPABASE_PUBLIC_ANON_KEY;

if (!supabaseUrl || !supabaseKey) {
throw new Error("Supabase URL or Supabase Key is missing. Make sure to set them in your environment variables.");
}

export const supabase = createClient(supabaseUrl, supabaseKey);
15 changes: 4 additions & 11 deletions crud-frontend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,14 @@
"compilerOptions": {
/* Language and Environment */
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,

/* Modules */
"module": "commonjs" /* Specify what module code is generated. */,

"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,

/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,

/* Completeness */
"skipLibCheck": true /* Skip type checking all .d.ts files. */,

"moduleResolution": "node",
"lib": ["DOM", "ESNext"],
"jsx": "react-jsx"
"jsx": "react-jsx",
"noUnusedLocals": false,
"allowSyntheticDefaultImports": true,
"module": "esnext"
}
}