Skip to content

Commit

Permalink
handle auth on client side only. added logout
Browse files Browse the repository at this point in the history
  • Loading branch information
khanghy2130 committed Jan 16, 2024
1 parent a71f5eb commit f86c681
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 177 deletions.
Binary file removed app/assets/oauth_providers/facebook-icon.png
Binary file not shown.
22 changes: 21 additions & 1 deletion app/components/SidePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
import { Link } from '@remix-run/react';

import { useTheme } from '~/utils/Navbar/ThemeProvider';

import type { ContextProps } from '../utils/types/ContextProps.type';


type Props = {
sidePanelIsShown: boolean;
setSidePanelIsShown: React.Dispatch<React.SetStateAction<boolean>>;
user: ContextProps["user"];
supabase: ContextProps["supabase"]
};

export default function SidePanel(
{sidePanelIsShown, setSidePanelIsShown}
{sidePanelIsShown, setSidePanelIsShown, user, supabase}
: Props){
const [theme, setTheme] = useTheme();
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
};

const logout = async () => {
const {error} = await supabase.auth.signOut();
if (error) alert("Error while logging out.");
}

return <div
className={(sidePanelIsShown ? "right-0" : "-right-96") +
` fixed h-screen transition-[right] ease-in-out duration-500
Expand All @@ -21,5 +33,13 @@ export default function SidePanel(
<button className='btn'
onClick={()=>setSidePanelIsShown(false)}>CLOSE</button>
<button className='btn' onClick={toggleTheme}>Theme: {theme}</button>

{user? <div className='flex flex-col mt-12'>
<p>Logged in as {user.email}</p>
<button className='btn' onClick={logout}>Log out</button>
</div> : <Link to="/login">
<button className='btn'>Login</button>
</Link>}

</div>
}
24 changes: 24 additions & 0 deletions app/components/SpinnerSVG.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

type Props = {
size: number;
};

export default function SidePanel({size} : Props){
return <svg className={`h-${size} w-${size}`} viewBox="0 0 24 24">
<rect width="6" height="14" x="1" y="4" fill="currentColor">
<animate id="svgSpinnersBarsScaleFade0" fill="freeze" attributeName="y" begin="0;svgSpinnersBarsScaleFade1.end-0.25s" dur="0.75s" values="1;5"/>
<animate fill="freeze" attributeName="height" begin="0;svgSpinnersBarsScaleFade1.end-0.25s" dur="0.75s" values="22;14"/>
<animate fill="freeze" attributeName="opacity" begin="0;svgSpinnersBarsScaleFade1.end-0.25s" dur="0.75s" values="1;.2"/>
</rect>
<rect width="6" height="14" x="9" y="4" fill="currentColor" opacity=".4">
<animate fill="freeze" attributeName="y" begin="svgSpinnersBarsScaleFade0.begin+0.15s" dur="0.75s" values="1;5"/>
<animate fill="freeze" attributeName="height" begin="svgSpinnersBarsScaleFade0.begin+0.15s" dur="0.75s" values="22;14"/>
<animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsScaleFade0.begin+0.15s" dur="0.75s" values="1;.2"/>
</rect>
<rect width="6" height="14" x="17" y="4" fill="currentColor" opacity=".3">
<animate id="svgSpinnersBarsScaleFade1" fill="freeze" attributeName="y" begin="svgSpinnersBarsScaleFade0.begin+0.3s" dur="0.75s" values="1;5"/>
<animate fill="freeze" attributeName="height" begin="svgSpinnersBarsScaleFade0.begin+0.3s" dur="0.75s" values="22;14"/>
<animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsScaleFade0.begin+0.3s" dur="0.75s" values="1;.2"/>
</rect>
</svg>;
}
167 changes: 89 additions & 78 deletions app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@

import type { LinksFunction, LoaderFunction } from "@remix-run/node";
import type { Database } from '../database.types'
import type { User } from "@supabase/supabase-js";
import { Database } from "database.types";

import { json } from "@remix-run/node";
import {
Links,
Meta,
Outlet,
Scripts,
useLoaderData,
useRevalidator
Links,
Meta,
Outlet,
Scripts,
useLoaderData,
useRevalidator
} from "@remix-run/react";
import { useState, useEffect } from "react";
import { createBrowserClient } from '@supabase/ssr'
Expand All @@ -25,91 +26,101 @@ import Navbar from "./components/Navbar";
import SidePanel from "./components/SidePanel";




export const links: LinksFunction = () => [
{ rel: "stylesheet", href: stylesheet },
{ rel: "stylesheet", href: stylesheet },
];

export type LoaderData = {
theme: ThemeType | null;
env: { [key: string]: string }
theme: ThemeType | null;
env: { [key: string]: string }
};

export const loader: LoaderFunction = async ({ request }) => {
const themeSession = await getThemeSession(request);
const themeSession = await getThemeSession(request);

const data: LoaderData = {
theme: themeSession.getTheme(),
env: {
SUPABASE_URL: process.env.SUPABASE_URL!,
SUPABASE_ANON_KEY: process.env.SUPABASE_ANON_KEY!,
}
};
const data: LoaderData = {
theme: themeSession.getTheme(),
env: {
SUPABASE_URL: process.env.SUPABASE_URL!,
SUPABASE_ANON_KEY: process.env.SUPABASE_ANON_KEY!,
}
};

return json(data)
return json(data)
}


function App() {
const { env } = useLoaderData<LoaderFunction>()
const [supabase] = useState(() =>
createBrowserClient<Database>(env.SUPABASE_URL, env.SUPABASE_ANON_KEY)
)

// recalls loaders when authentication state changes
const revalidator = useRevalidator()
useEffect(() => {
const {
data: { subscription }
} = supabase.auth.onAuthStateChange((event, session) => {
revalidator.revalidate()
})

return () => {
subscription.unsubscribe()
}
}, [supabase /*, revalidator*/ ])


const [theme] = useTheme();
const [sidePanelIsShown, setSidePanelIsShown] = useState<boolean>(false);


// hide for specific routes
const location = useLocation();
const routesToHideNavigation = ['/login', '/signup']; ///// add homepage
const shouldHideNavigation = routesToHideNavigation.includes(location.pathname);



return (
<html lang="en" className={theme ?? ""}>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
{shouldHideNavigation ? null : <>
<Navbar setSidePanelIsShown={setSidePanelIsShown}/>
<SidePanel sidePanelIsShown={sidePanelIsShown} setSidePanelIsShown={setSidePanelIsShown} />
</>}

{/* space for navbar above main page content */}
<div className="pt-24">
<Outlet context={{ supabase }} />
</div>
<Scripts />
</body>
</html>
);
const { env } = useLoaderData<LoaderFunction>()
const [supabase] = useState(() =>
createBrowserClient<Database>(env.SUPABASE_URL, env.SUPABASE_ANON_KEY)
)
const [user, setUser] = useState<undefined | User>(undefined);

// recalls loaders when authentication state changes
const revalidator = useRevalidator();
useEffect(() => {
const {
data: { subscription }
} = supabase.auth.onAuthStateChange((event, session) => {
revalidator.revalidate();
if (event === "SIGNED_IN") {
setUser(session?.user);
} else if (event === "SIGNED_OUT"){
setUser(undefined);
}
})

return () => {
subscription.unsubscribe()
}
}, [supabase /*, revalidator*/])


const [theme] = useTheme();
const [sidePanelIsShown, setSidePanelIsShown] = useState<boolean>(false);


// hide for specific routes
const location = useLocation();
const routesToHideNavigation = ['/login', '/signup']; ///// add homepage
const shouldHideNavigation = routesToHideNavigation.includes(location.pathname);



return (
<html lang="en" className={theme ?? ""}>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
{shouldHideNavigation ? null : <>
<Navbar setSidePanelIsShown={setSidePanelIsShown} />
<SidePanel user={user} supabase={supabase}
sidePanelIsShown={sidePanelIsShown}
setSidePanelIsShown={setSidePanelIsShown} />
</>}

{/* space for navbar above main page content */}
<div className="pt-24">
<Outlet context={{ supabase, user }} />
</div>
<Scripts />
</body>
</html>
);
}

export default function AppWithProviders() {
const data = useLoaderData<LoaderData>();
return (
<ThemeProvider specifiedTheme={data.theme}>
<App />
</ThemeProvider>
);
const data = useLoaderData<LoaderData>();
return (
<ThemeProvider specifiedTheme={data.theme}>
<App />
</ThemeProvider>
);
}
Loading

0 comments on commit f86c681

Please sign in to comment.