diff --git a/frontend/src/contexts/AuthContext.jsx b/frontend/src/contexts/AuthContext.jsx index 0413bd3..81169ef 100644 --- a/frontend/src/contexts/AuthContext.jsx +++ b/frontend/src/contexts/AuthContext.jsx @@ -1,140 +1,52 @@ -/** - * AuthContext - Firebase Authentication State Management - * - * Provides authentication state, tier info, and methods throughout the app - */ +import { createContext, useReducer, useContext } from "react"; +import shopReducer, { initialState } from "./shopReducer"; -import { createContext, useContext, useEffect, useState, useCallback } from "react"; -import { - createUserWithEmailAndPassword, - signInWithEmailAndPassword, - signOut, - onAuthStateChanged, -} from "firebase/auth"; -import { auth } from "../firebase/config"; -import { getAccount } from "../api/account"; +const AuthContext = createContext(initialState); -const AuthContext = createContext(); +export const AuthProvider = ({ children }) => { + const [state, dispatch] = useReducer(shopReducer, initialState); -const DEFAULT_TIER_LIMITS = { - max_addresses: 1, - max_alert_types: 1, - allowed_channels: ["email"], + const addAuthUser = (args) => { + const updatedUser = state.user.concat(product); + updatePrice(updatedCart); + dispatch({ + type: "ADD_AUTH_USER", + payload: { + args: updatedCart + } + }); + }; + + const logoutAuthUser = (args) => { + const updatedUser = state.user.filter( + (currentUser) => currentUser.name !== args.name + ); + updateUser(updatedCart); + + dispatch({ + type: "REMOVE_AUTH_USER", + payload: { + args: updatedCart + } + }); + }; + + + const value = { + user: state.name, + user: state.tier + }; + return {children}; }; -/** - * Hook to access auth context - * @returns {Object} Auth context value - */ -export function useAuth() { - const context = useContext(AuthContext); - if (!context) { - throw new Error("useAuth must be used within AuthProvider"); - } - return context; -} +const useAuthContext = () => { + const context = useContext(ShopContext); -/** - * AuthProvider - Wraps app and provides auth state + tier info - */ -export function AuthProvider({ children }) { - const [currentUser, setCurrentUser] = useState(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); + if (context === undefined) { + throw new Error("authUser must be used within AuthContext"); + } - const [userTier, setUserTier] = useState("free"); - const [tierLimits, setTierLimits] = useState(DEFAULT_TIER_LIMITS); - const [addressCount, setAddressCount] = useState(0); - const [subscriptionStatus, setSubscriptionStatus] = useState("none"); + return context; +}; - const refreshAccount = useCallback(async () => { - try { - const data = await getAccount(); - setUserTier(data.subscription_tier || "free"); - setTierLimits(data.tier_limits || DEFAULT_TIER_LIMITS); - setAddressCount(data.address_count || 0); - setSubscriptionStatus(data.subscription_status || "none"); - } catch { - // account fetch can fail during onboarding before subscription is active - } - }, []); - - async function signup(email, password) { - try { - setError(null); - const result = await createUserWithEmailAndPassword( - auth, - email, - password, - ); - return result.user; - } catch (err) { - setError(err.message); - throw err; - } - } - - async function login(email, password) { - try { - setError(null); - const result = await signInWithEmailAndPassword( - auth, - email, - password, - ); - return result.user; - } catch (err) { - setError(err.message); - throw err; - } - } - - async function logout() { - try { - setError(null); - setUserTier("free"); - setTierLimits(DEFAULT_TIER_LIMITS); - setAddressCount(0); - setSubscriptionStatus("none"); - await signOut(auth); - } catch (err) { - setError(err.message); - throw err; - } - } - - useEffect(() => { - const unsubscribe = onAuthStateChanged(auth, (user) => { - setCurrentUser(user); - setLoading(false); - if (user) { - refreshAccount(); - } - }); - return unsubscribe; - }, [refreshAccount]); - - const isSubscribed = - subscriptionStatus === "active" || subscriptionStatus === "trialing"; - - const value = { - currentUser, - signup, - login, - logout, - error, - loading, - userTier, - tierLimits, - addressCount, - subscriptionStatus, - isSubscribed, - refreshAccount, - }; - - return ( - - {!loading && children} - - ); -} +export default useAuthContext; diff --git a/frontend/src/contexts/UserPropertiesContext.jsx b/frontend/src/contexts/UserPropertiesContext.jsx deleted file mode 100644 index e2bd3e5..0000000 --- a/frontend/src/contexts/UserPropertiesContext.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import { createContext, useContext, useReducer, useEffect } from "react"; -import { - userPropertiesReducer, - initialState, - ACTION_TYPES, -} from "./userPropertiesReducer"; - -const STORAGE_KEY = "kp_onboard_user"; - -function hydrateState() { - try { - const raw = sessionStorage.getItem(STORAGE_KEY); - if (raw) return { ...initialState, ...JSON.parse(raw) }; - } catch { - /* corrupt data — fall through */ - } - return initialState; -} - -const UserPropertiesContext = createContext(initialState); - -export function useUserProperties() { - const ctx = useContext(UserPropertiesContext); - if (!ctx) { - throw new Error( - "useUserProperties must be used within UserPropertiesProvider", - ); - } - return ctx; -} - -export function UserPropertiesProvider({ children }) { - const [state, dispatch] = useReducer(userPropertiesReducer, null, hydrateState); - - useEffect(() => { - if (state.email || state.password) { - sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state)); - } else { - sessionStorage.removeItem(STORAGE_KEY); - } - }, [state]); - - return ( - - {children} - - ); -} diff --git a/frontend/src/contexts/userPropertiesReducer.js b/frontend/src/contexts/userPropertiesReducer.js deleted file mode 100644 index c693ccb..0000000 --- a/frontend/src/contexts/userPropertiesReducer.js +++ /dev/null @@ -1,20 +0,0 @@ -export const initialState = { - email: "", - password: "", -}; - -export const ACTION_TYPES = { - SET_USER_PROPERTIES: "SET_USER_PROPERTIES", - CLEAR_USER_PROPERTIES: "CLEAR_USER_PROPERTIES", -}; - -export function userPropertiesReducer(state, action) { - switch (action.type) { - case ACTION_TYPES.SET_USER_PROPERTIES: - return { ...state, ...action.payload }; - case ACTION_TYPES.CLEAR_USER_PROPERTIES: - return { ...initialState }; - default: - return state; - } -} diff --git a/frontend/src/reducers/authReducer.jsx b/frontend/src/reducers/authReducer.jsx new file mode 100644 index 0000000..d227086 --- /dev/null +++ b/frontend/src/reducers/authReducer.jsx @@ -0,0 +1,25 @@ +import { useReducer } from "react" + +const UserAuthContext = createContext(); + +export const initialState = { + authUser: null, + AuthTier: null +}; + +const authReducer = (state, action) => { + const { type, payload = "FREE_TIER" } = action + + switch (type) { + case "ADD_AUTH_USER": + console.log("ADD_AUTH_USER", payload); + return { + ...state, + auth: payload + }; + default: + throw new Error(`No case for type ${type} found.`); + } +} + +export default shopReducer \ No newline at end of file