diff --git a/task_yell/.gitignore b/task_yell/.gitignore index fd3dbb5..f696615 100644 --- a/task_yell/.gitignore +++ b/task_yell/.gitignore @@ -34,3 +34,5 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +certificates \ No newline at end of file diff --git a/task_yell/package.json b/task_yell/package.json index 0843702..66c9299 100644 --- a/task_yell/package.json +++ b/task_yell/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "dev": "next dev", + "dev-https": "next dev --experimental-https", "build": "next build", "start": "next start", "lint": "next lint" diff --git a/task_yell/src/components/sign-in-button.tsx b/task_yell/src/components/sign-in-button.tsx new file mode 100644 index 0000000..ae274a7 --- /dev/null +++ b/task_yell/src/components/sign-in-button.tsx @@ -0,0 +1,69 @@ +"use client"; + +import { onAuthStateChanged } from "@/firebase/auth"; +import { auth } from "@/firebase/client-app"; +import { GoogleAuthProvider, signInWithPopup, type User } from "firebase/auth"; +import { useRouter } from "next/navigation"; +import { useCallback, useEffect, useState } from "react"; + +function useUserSession() { + // The initialUser comes from the server via a server component + const [user, setUser] = useState(); + const router = useRouter(); + + // Register the service worker that sends auth state back to server + // The service worker is built with npm run build-service-worker + // useEffect(() => { + // if ("serviceWorker" in navigator) { + // const serializedFirebaseConfig = encodeURIComponent(JSON.stringify(firebaseConfig)); + // const serviceWorkerUrl = `/auth-service-worker.js?firebaseConfig=${serializedFirebaseConfig}` + + // navigator.serviceWorker + // .register(serviceWorkerUrl) + // .then((registration) => console.log("scope is: ", registration.scope)); + // } + // }, []); + + useEffect(() => { + const unsubscribe = onAuthStateChanged((authUser) => { + setUser(authUser) + }) + + return () => unsubscribe() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + onAuthStateChanged((authUser) => { + if (user === undefined) return + + // refresh when user changed to ease testing + if (user?.email !== authUser?.email) { + router.refresh() + } + }) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [user, router.refresh]) + + return user; +} + +export function SignInButton() { + const user = useUserSession(); + const handleSignIn = useCallback(async () => { + const provider = new GoogleAuthProvider(); + await signInWithPopup(auth, provider); + }, []); + const handleSignOut = useCallback(async () => { + console.log("signing out") + await auth.signOut(); + }, []); + + return !user ? + () : ( + ) +} \ No newline at end of file diff --git a/task_yell/src/firebase/auth.ts b/task_yell/src/firebase/auth.ts new file mode 100644 index 0000000..e767709 --- /dev/null +++ b/task_yell/src/firebase/auth.ts @@ -0,0 +1,31 @@ +import { + GoogleAuthProvider, + signInWithPopup, + onAuthStateChanged as _onAuthStateChanged, +} from "firebase/auth"; + +import { auth } from "@/firebase/client-app"; + +export type NextOrObserveUser = Parameters[1]; + +export function onAuthStateChanged(cb: NextOrObserveUser) { + return _onAuthStateChanged(auth, cb); +} + +export async function signInWithGoogle() { + const provider = new GoogleAuthProvider(); + + try { + await signInWithPopup(auth, provider); + } catch (error) { + console.error("Error signing in with Google", error); + } +} + +export async function signOut() { + try { + return auth.signOut(); + } catch (error) { + console.error("Error signing out with Google", error); + } +} \ No newline at end of file