in progress: establishing auth context in new client side app

This commit is contained in:
Mikayla Dobson
2022-10-03 11:58:31 -05:00
parent 89806f8713
commit ab475001e7
8 changed files with 1017 additions and 34 deletions

848
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,8 +9,11 @@
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
"@supabase/supabase-js": "^1.35.7",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-router-dom": "^6.3.0",
"sass": "^1.52.1"
},
"devDependencies": {
"@types/react": "^18.0.17",

View File

@@ -1,33 +1,18 @@
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import Home from './components/Home/Home'
import Register from './components/User/Register'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<div className="App">
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" className="logo" alt="Vite logo" />
</a>
<a href="https://reactjs.org" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
<BrowserRouter>
<div className="App">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/register" element={<Register />} />
</Routes>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</div>
</BrowserRouter>
)
}

View File

@@ -0,0 +1,9 @@
export default function Home() {
return (
<div>
<h1>Vite + React + Supabase</h1>
<p>Check out the user stuff below:</p>
<a href="/register">User stuff</a>
</div>
)
}

View File

@@ -0,0 +1,40 @@
import { useState } from "react";
import { createClient } from "@supabase/supabase-js";
import { useAuth } from "../../supabase/SupabaseContext";
const url = import.meta.env.VITE_SUPABASE_URL;
const key = import.meta.env.VITE_SUPABASE_KEY;
interface FormInput {
email: string
password: string
}
export default function Register() {
const [input, setInput] = useState<FormInput>({email: "", password: ""});
const { handleRegister, setUserData, setUserSession } = useAuth();
const handleClick = () => {
const { email, password } = input;
if (email && password) handleRegister(email, password, { setUserData, setUserSession });
}
return (
<section>
<h1>Register</h1>
<form>
<div>
<label>Email:</label>
<input required type="text" onChange={(e) => setInput({...input, email: e.target.value})} />
</div>
<div>
<label>Password:</label>
<input required type="text" onChange={(e) => setInput({...input, password: e.target.value})} />
</div>
</form>
<button onClick={handleClick}>Register</button>
</section>
)
}

View File

@@ -0,0 +1,57 @@
import { FunctionComponent, ReactPortal, createContext, useState, useContext, Dispatch, SetStateAction } from "react";
import { handleRegister, handleEmailLogin } from "./authHelpers";
import { createClient, SupabaseClient } from "@supabase/supabase-js";
const supabase = createClient(import.meta.env.VITE_SUPABASE_URL, import.meta.env.VITE_SUPABASE_KEY);
interface SupabaseContextData {
supabase: SupabaseClient
userSession?: any
setUserSession?: Dispatch<SetStateAction<any>>
userData?: any
setUserData?: Dispatch<SetStateAction<any>>
handleRegister: (email: string, password: string, authData: ReactAuthData) => Promise<AuthData>
handleEmailLogin: (email: string, password: string, authData: ReactAuthData) => Promise<AuthData>
}
interface AuthData {
user?: any
session?: any
error?: any
}
export interface ReactAuthData {
userSession: any
setUserSession: Dispatch<SetStateAction<any>>
userData: any
setUserData: Dispatch<SetStateAction<any>>
}
const initialState: SupabaseContextData = {
supabase: supabase,
userSession: undefined,
userData: undefined,
handleRegister: handleRegister,
handleEmailLogin: handleEmailLogin
}
const SupabaseContext = createContext<SupabaseContextData>(initialState);
export const SupabaseProvider: FunctionComponent<ReactPortal> = ({ children }) => {
const [userData, setUserData] = useState<any>();
const [userSession, setUserSession] = useState<any>();
const store = {
supabase, userData, setUserData, userSession, setUserSession, handleRegister, handleEmailLogin
}
return (
<SupabaseContext.Provider value={store}>
{ children }
</SupabaseContext.Provider>
)
}
export const useAuth = () => {
return useContext(SupabaseContext);
}

View File

@@ -0,0 +1 @@
export default {}

View File

@@ -0,0 +1,54 @@
import { SupabaseClient } from "@supabase/supabase-js";
import { ReactAuthData, useAuth } from "./SupabaseContext";
export const handleRegister = async (email: string, password: string, authData: ReactAuthData) => {
const { setUserData } = authData;
const { supabase } = useAuth();
const { user, session, error } = await supabase.auth.signUp({ email, password });
if (error) throw error;
if (user) setUserData(user);
return { user, session, error }
// SEE USER RETURN TYPE BELOW
/**
* object {
* app_metadata: {
* provider: string
* providers: string[]
* }
* aud: string
* confirmation_sent_at: string
* created_at: string
* email: string
* id: string
* identities: Identity[] // to define below
* phone: string?
* role: string
* updated_at: string
* user_metadata: object?
* }
*
* Identity = {
* created_at,
* id,
* identity_data: { sub: string },
* last_sign_in_at: string
* provider: email
* updated_at: string
* user_id: string
* }
*/
}
export const handleEmailLogin = async (email: string, password: string, authData: ReactAuthData) => {
const { setUserData, setUserSession } = authData;
const { supabase } = useAuth();
const { user, session, error } = await supabase.auth.signIn({ email, password });
if (error) throw error;
if (user) setUserData(user);
if (session) setUserSession(session);
return { user, session, error };
}