mirror of
https://github.com/fergalmoran/supanextail.git
synced 2025-12-22 09:17:54 +00:00
WIP Custom auth handler / login
Forgot password is not working
This commit is contained in:
@@ -6,18 +6,18 @@ CONFIGURE THE AUTH COMPONENT LINE 30
|
|||||||
You can select your auth providers, or just keep the email/password. You can
|
You can select your auth providers, or just keep the email/password. You can
|
||||||
check the providers available here: https://supabase.io/docs/guides/auth
|
check the providers available here: https://supabase.io/docs/guides/auth
|
||||||
*/
|
*/
|
||||||
import { Auth } from "@supabase/ui";
|
|
||||||
|
import Login from "./UI/Login";
|
||||||
import { supabase } from "utils/supabaseClient";
|
import { supabase } from "utils/supabaseClient";
|
||||||
|
import { useAuth } from "utils/Authcontext";
|
||||||
|
|
||||||
const Container = (props) => {
|
const Container = (props) => {
|
||||||
const { user } = Auth.useUser();
|
const { user, signOut } = useAuth();
|
||||||
if (user)
|
if (user)
|
||||||
return (
|
return (
|
||||||
<div className='w-80 md:w-96 order-first lg:order-last'>
|
<div className='w-80 md:w-96 order-first lg:order-last'>
|
||||||
<p>Hello {user.email}! 👋 You are already logged in</p>
|
<p>Hello {user.email}! 👋 You are already logged in</p>
|
||||||
<button
|
<button className='btn btn-primary' onClick={() => signOut()}>
|
||||||
className='btn btn-primary'
|
|
||||||
onClick={() => props.supabaseClient.auth.signOut()}>
|
|
||||||
Sign out
|
Sign out
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -26,19 +26,16 @@ const Container = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const AuthComponent = () => {
|
const AuthComponent = () => {
|
||||||
|
const { signUp, signIn, signOut, resetPassword } = useAuth();
|
||||||
return (
|
return (
|
||||||
<Auth.UserContextProvider supabaseClient={supabase}>
|
<Container supabaseClient={supabase}>
|
||||||
<Container supabaseClient={supabase}>
|
<Login
|
||||||
<Auth
|
signUp={signUp}
|
||||||
supabaseClient={supabase}
|
signIn={signIn}
|
||||||
providers={["google"]}
|
signOut={signOut}
|
||||||
socialLayout='horizontal'
|
resetPassword={resetPassword}
|
||||||
socialButtonSize='xlarge'
|
/>
|
||||||
socialColors={true}
|
</Container>
|
||||||
className='p-5 bg-neutral-content rounded-md'
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
</Auth.UserContextProvider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,14 +12,36 @@ The images are in the public folder.
|
|||||||
|
|
||||||
import "react-toastify/dist/ReactToastify.css";
|
import "react-toastify/dist/ReactToastify.css";
|
||||||
|
|
||||||
import { Auth } from "@supabase/ui";
|
|
||||||
import Footer from "./Footer";
|
import Footer from "./Footer";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import Nav from "./Nav";
|
import Nav from "./Nav";
|
||||||
import { ToastContainer } from "react-toastify";
|
import { ToastContainer } from "react-toastify";
|
||||||
|
import { supabase } from "utils/supabaseClient";
|
||||||
|
import { useAuth } from "utils/Authcontext";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
const Layout = (props) => {
|
const Layout = (props) => {
|
||||||
const { user } = Auth.useUser();
|
const { user, signOut } = useAuth();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const { data: authListener } = supabase.auth.onAuthStateChange(
|
||||||
|
(event, session) => {
|
||||||
|
if ((event === "SIGNED_OUT") | (event === "SIGNED_IN")) {
|
||||||
|
fetch("/api/auth", {
|
||||||
|
method: "POST",
|
||||||
|
headers: new Headers({ "Content-Type": "application/json" }),
|
||||||
|
credentials: "same-origin",
|
||||||
|
body: JSON.stringify({ event, session }),
|
||||||
|
}).then((res) => res.json());
|
||||||
|
}
|
||||||
|
if (event === "USER_UPDATED") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return () => {
|
||||||
|
authListener.unsubscribe();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const toastStyle = {
|
const toastStyle = {
|
||||||
//Style your toast elements here
|
//Style your toast elements here
|
||||||
@@ -56,7 +78,7 @@ const Layout = (props) => {
|
|||||||
<meta name='theme-color' content='#ffffff' />
|
<meta name='theme-color' content='#ffffff' />
|
||||||
</Head>
|
</Head>
|
||||||
<div className='max-w-7xl flex flex-col min-h-screen mx-auto p-5'>
|
<div className='max-w-7xl flex flex-col min-h-screen mx-auto p-5'>
|
||||||
<Nav user={user} />
|
<Nav user={user} signOut={signOut} />
|
||||||
<main className='flex-1'>{props.children}</main>
|
<main className='flex-1'>{props.children}</main>
|
||||||
<ToastContainer
|
<ToastContainer
|
||||||
position='bottom-center'
|
position='bottom-center'
|
||||||
|
|||||||
@@ -6,30 +6,8 @@ import Image from "next/image";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Logo from "public/logo.svg";
|
import Logo from "public/logo.svg";
|
||||||
import { Menu } from "react-feather";
|
import { Menu } from "react-feather";
|
||||||
import { supabase } from "utils/supabaseClient";
|
|
||||||
import { useEffect } from "react";
|
|
||||||
|
|
||||||
const Nav = (props) => {
|
const Nav = (props) => {
|
||||||
useEffect(() => {
|
|
||||||
const { data: authListener } = supabase.auth.onAuthStateChange(
|
|
||||||
(event, session) => {
|
|
||||||
if ((event === "SIGNED_OUT") | (event === "SIGNED_IN")) {
|
|
||||||
fetch("/api/auth", {
|
|
||||||
method: "POST",
|
|
||||||
headers: new Headers({ "Content-Type": "application/json" }),
|
|
||||||
credentials: "same-origin",
|
|
||||||
body: JSON.stringify({ event, session }),
|
|
||||||
}).then((res) => res.json());
|
|
||||||
}
|
|
||||||
if (event === "USER_UPDATED") {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return () => {
|
|
||||||
authListener.unsubscribe();
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
//Modify you menu directly here
|
//Modify you menu directly here
|
||||||
const NavMenu = (
|
const NavMenu = (
|
||||||
<div className='flex flex-col lg:flex-row lg:space-x-10 lg:m-auto font-body text-sm'>
|
<div className='flex flex-col lg:flex-row lg:space-x-10 lg:m-auto font-body text-sm'>
|
||||||
@@ -50,7 +28,7 @@ const Nav = (props) => {
|
|||||||
{props.user ? (
|
{props.user ? (
|
||||||
<button
|
<button
|
||||||
className='btn btn-ghost btn-sm'
|
className='btn btn-ghost btn-sm'
|
||||||
onClick={() => supabase.auth.signOut()}>
|
onClick={() => props.signOut()}>
|
||||||
Logout
|
Logout
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ https://dashboard.stripe.com/test/settings/billing/portal
|
|||||||
import { getSub, supabase } from "utils/supabaseClient";
|
import { getSub, supabase } from "utils/supabaseClient";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
import { Auth } from "@supabase/ui";
|
|
||||||
import { Prices } from "utils/priceList";
|
import { Prices } from "utils/priceList";
|
||||||
import { Switch } from "@headlessui/react";
|
import { Switch } from "@headlessui/react";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import router from "next/router";
|
import router from "next/router";
|
||||||
|
import { useAuth } from "utils/Authcontext";
|
||||||
|
|
||||||
const Pricing = () => {
|
const Pricing = () => {
|
||||||
const [enabled, setEnabled] = useState(false);
|
const [enabled, setEnabled] = useState(false);
|
||||||
const { user, session } = Auth.useUser();
|
const { user } = useAuth();
|
||||||
const [customerId, setCustomerId] = useState(null);
|
const [customerId, setCustomerId] = useState(null);
|
||||||
const [sub, setSub] = useState(false);
|
const [sub, setSub] = useState(false);
|
||||||
const flat = false; // Switch between subscription system or flat prices
|
const flat = false; // Switch between subscription system or flat prices
|
||||||
@@ -143,19 +143,23 @@ const Pricing = () => {
|
|||||||
<button
|
<button
|
||||||
className='btn btn-primary w-full'
|
className='btn btn-primary w-full'
|
||||||
onClick={
|
onClick={
|
||||||
sub
|
user
|
||||||
? () => {
|
? sub
|
||||||
portal();
|
? () => {
|
||||||
|
portal();
|
||||||
|
}
|
||||||
|
: (e) =>
|
||||||
|
handleSubmit(
|
||||||
|
e,
|
||||||
|
enabled
|
||||||
|
? Prices.personal.annually.id
|
||||||
|
: Prices.personal.monthly.id
|
||||||
|
)
|
||||||
|
: () => {
|
||||||
|
router.push("/auth");
|
||||||
}
|
}
|
||||||
: (e) =>
|
|
||||||
handleSubmit(
|
|
||||||
e,
|
|
||||||
enabled
|
|
||||||
? Prices.personal.annually.id
|
|
||||||
: Prices.personal.monthly.id
|
|
||||||
)
|
|
||||||
}>
|
}>
|
||||||
{sub ? "Upgrade" : "Buy Now"}
|
{user ? (sub ? "Upgrade" : "Buy Now") : "Register"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -192,19 +196,23 @@ const Pricing = () => {
|
|||||||
<button
|
<button
|
||||||
className='btn btn-primary w-full'
|
className='btn btn-primary w-full'
|
||||||
onClick={
|
onClick={
|
||||||
sub
|
user
|
||||||
? () => {
|
? sub
|
||||||
portal();
|
? () => {
|
||||||
|
portal();
|
||||||
|
}
|
||||||
|
: (e) =>
|
||||||
|
handleSubmit(
|
||||||
|
e,
|
||||||
|
enabled
|
||||||
|
? Prices.team.annually.id
|
||||||
|
: Prices.team.monthly.id
|
||||||
|
)
|
||||||
|
: () => {
|
||||||
|
router.push("/auth");
|
||||||
}
|
}
|
||||||
: (e) =>
|
|
||||||
handleSubmit(
|
|
||||||
e,
|
|
||||||
enabled
|
|
||||||
? Prices.team.annually.id
|
|
||||||
: Prices.team.monthly.id
|
|
||||||
)
|
|
||||||
}>
|
}>
|
||||||
{sub ? "Upgrade" : "Buy Now"}
|
{user ? (sub ? "Upgrade" : "Buy Now") : "Register"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -240,17 +248,23 @@ const Pricing = () => {
|
|||||||
<button
|
<button
|
||||||
className='btn btn-primary w-full'
|
className='btn btn-primary w-full'
|
||||||
onClick={
|
onClick={
|
||||||
sub
|
user
|
||||||
? () => {
|
? sub
|
||||||
portal();
|
? () => {
|
||||||
|
portal();
|
||||||
|
}
|
||||||
|
: (e) =>
|
||||||
|
handleSubmit(
|
||||||
|
e,
|
||||||
|
enabled
|
||||||
|
? Prices.pro.annually.id
|
||||||
|
: Prices.pro.monthly.id
|
||||||
|
)
|
||||||
|
: () => {
|
||||||
|
router.push("/auth");
|
||||||
}
|
}
|
||||||
: (e) =>
|
|
||||||
handleSubmit(
|
|
||||||
e,
|
|
||||||
enabled ? Prices.pro.annually.id : Prices.pro.monthly.id
|
|
||||||
)
|
|
||||||
}>
|
}>
|
||||||
{sub ? "Upgrade" : "Buy Now"}
|
{user ? (sub ? "Upgrade" : "Buy Now") : "Register"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
133
components/UI/Login.js
Normal file
133
components/UI/Login.js
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
import { IoLogoGoogle } from "react-icons/io";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
const Login = (props) => {
|
||||||
|
const [email, setEmail] = useState("");
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
const [forgot, setForgot] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='p-10 bg-base-100 md:flex-1 rounded-md text-base-content shadow-md'>
|
||||||
|
{!forgot && (
|
||||||
|
<>
|
||||||
|
<h3 className='my-4 text-2xl font-semibold'>Account Login</h3>
|
||||||
|
<form action='#' className='flex flex-col space-y-5'>
|
||||||
|
<div className='flex flex-col space-y-1'>
|
||||||
|
<label
|
||||||
|
htmlFor='email'
|
||||||
|
className='text-sm font-semibold text-gray-500'>
|
||||||
|
Email address
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type='email'
|
||||||
|
id='email'
|
||||||
|
autoFocus
|
||||||
|
className='input input-primary input-bordered input-sm'
|
||||||
|
value={email}
|
||||||
|
onChange={(event) => {
|
||||||
|
setEmail(event.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col space-y-1'>
|
||||||
|
<div className='flex items-center justify-between'>
|
||||||
|
<label
|
||||||
|
htmlFor='password'
|
||||||
|
className='text-sm font-semibold text-gray-500'>
|
||||||
|
Password
|
||||||
|
</label>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setForgot(true);
|
||||||
|
}}
|
||||||
|
className='text-sm text-blue-600 hover:underline focus:text-blue-800'>
|
||||||
|
Forgot Password?
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type='password'
|
||||||
|
id='password'
|
||||||
|
className='input input-primary input-bordered input-sm'
|
||||||
|
value={password}
|
||||||
|
onChange={(event) => {
|
||||||
|
setPassword(event.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className='btn btn-primary w-full'
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
props.signIn({ email: email, password: password });
|
||||||
|
}}>
|
||||||
|
Log in
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col space-y-5'>
|
||||||
|
<span className='flex items-center justify-center space-x-2'>
|
||||||
|
<span className='h-px bg-gray-400 w-14'></span>
|
||||||
|
<span className='font-normal text-gray-500'>or login with</span>
|
||||||
|
<span className='h-px bg-gray-400 w-14'></span>
|
||||||
|
</span>
|
||||||
|
<div className='flex flex-col space-y-4'>
|
||||||
|
<button
|
||||||
|
href='#'
|
||||||
|
className='flex items-center justify-center px-4 py-2 space-x-2 transition-colors duration-300 border border-gray-800 rounded-md group hover:bg-gray-800 focus:outline-none '
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
props.signIn({ provider: "google" });
|
||||||
|
}}>
|
||||||
|
<div className='text-base-content group-hover:text-white'>
|
||||||
|
<IoLogoGoogle />
|
||||||
|
</div>
|
||||||
|
<span className='text-sm font-medium text-gray-800 group-hover:text-white'>
|
||||||
|
Gmail
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{forgot && (
|
||||||
|
<>
|
||||||
|
<h3 className='my-4 text-2xl font-semibold'>Password recovery</h3>
|
||||||
|
<form action='#' className='flex flex-col space-y-5'>
|
||||||
|
<div className='flex flex-col space-y-1'>
|
||||||
|
<label
|
||||||
|
htmlFor='email'
|
||||||
|
className='text-sm font-semibold text-gray-500'>
|
||||||
|
Email address
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type='email'
|
||||||
|
id='email'
|
||||||
|
autoFocus
|
||||||
|
className='input input-primary input-bordered input-sm'
|
||||||
|
value={email}
|
||||||
|
onChange={(event) => {
|
||||||
|
setEmail(event.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className='btn btn-primary w-full'
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
props.resetPassword(email);
|
||||||
|
}}>
|
||||||
|
Recover my password
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Login;
|
||||||
911
package-lock.json
generated
911
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,6 @@
|
|||||||
"micro": "^9.3.4",
|
"micro": "^9.3.4",
|
||||||
"next": "latest",
|
"next": "latest",
|
||||||
"next-seo": "^4.24.0",
|
"next-seo": "^4.24.0",
|
||||||
"octokit": "^1.1.0",
|
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-feather": "^2.0.9",
|
"react-feather": "^2.0.9",
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import "./global.css";
|
import "./global.css";
|
||||||
|
|
||||||
import { Auth } from "@supabase/ui";
|
import { AuthProvider } from "utils/Authcontext";
|
||||||
import { DefaultSeo } from "next-seo";
|
import { DefaultSeo } from "next-seo";
|
||||||
import { supabase } from "utils/supabaseClient";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Next-seo is integrated by default, if you want more information and how to
|
Next-seo is integrated by default, if you want more information and how to
|
||||||
@@ -12,7 +11,7 @@ setup more elements, visit their Github page https://github.com/garmeeh/next-seo
|
|||||||
function MyApp({ Component, pageProps }) {
|
function MyApp({ Component, pageProps }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Auth.UserContextProvider supabaseClient={supabase}>
|
<AuthProvider>
|
||||||
<DefaultSeo
|
<DefaultSeo
|
||||||
openGraph={{
|
openGraph={{
|
||||||
type: "website",
|
type: "website",
|
||||||
@@ -26,7 +25,7 @@ function MyApp({ Component, pageProps }) {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</Auth.UserContextProvider>
|
</AuthProvider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* NOTE: this file is only needed if you're doing SSR (getServerSideProps)!
|
* NOTE: this file is only needed if you're doing SSR (getServerSideProps)!
|
||||||
* With SupaNexTail, we use SSR with the Dashboard page (pages/dashboard.js)
|
* With SupaNexTail, we use SSR with the Dashboard page (pages/dashboard.js)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { supabase } from 'utils/supabaseClient'
|
import { supabase } from "utils/supabaseClient";
|
||||||
|
|
||||||
export default function handler(req, res) {
|
export default function handler(req, res) {
|
||||||
supabase.auth.api.setAuthCookie(req, res)
|
supabase.auth.api.setAuthCookie(req, res);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,24 +4,12 @@ You have 2 components, the "AuthComponent" that handle the logic,
|
|||||||
and the "AuthText" that will show the description on the left of the screen
|
and the "AuthText" that will show the description on the left of the screen
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Auth } from "@supabase/ui";
|
import AuthComponent from "components/Auth";
|
||||||
import AuthComponent from "../components/Auth";
|
|
||||||
import AuthText from "components/AuthText";
|
import AuthText from "components/AuthText";
|
||||||
import Layout from "components/Layout";
|
import Layout from "components/Layout";
|
||||||
import { NextSeo } from "next-seo";
|
import { NextSeo } from "next-seo";
|
||||||
import { useEffect } from "react";
|
|
||||||
import { useRouter } from "next/router";
|
|
||||||
|
|
||||||
const AuthPage = () => {
|
const AuthPage = () => {
|
||||||
const { user, session } = Auth.useUser();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// If a user is already logged in, return to the homepage
|
|
||||||
if (user) {
|
|
||||||
router.push("/");
|
|
||||||
}
|
|
||||||
}, [user]);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NextSeo
|
<NextSeo
|
||||||
@@ -32,7 +20,9 @@ const AuthPage = () => {
|
|||||||
<Layout>
|
<Layout>
|
||||||
<div className='flex flex-wrap justify-evenly w-full'>
|
<div className='flex flex-wrap justify-evenly w-full'>
|
||||||
<AuthText />
|
<AuthText />
|
||||||
<div>{!session && <AuthComponent />}</div>
|
<div>
|
||||||
|
<AuthComponent />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
</>
|
</>
|
||||||
|
|||||||
33
utils/AuthContext.js
Normal file
33
utils/AuthContext.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import React, { createContext, useContext, useState } from "react";
|
||||||
|
|
||||||
|
import { supabase } from "utils/supabaseClient";
|
||||||
|
|
||||||
|
// create a context for authentication
|
||||||
|
const AuthContext = createContext();
|
||||||
|
|
||||||
|
export const AuthProvider = ({ children }) => {
|
||||||
|
// create state values for user data and loading
|
||||||
|
const [user, setUser] = useState();
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
|
// create signUp, signIn, signOut functions
|
||||||
|
const value = {
|
||||||
|
signUp: (data) => supabase.auth.signUp(data),
|
||||||
|
signIn: (data) => supabase.auth.signIn(data),
|
||||||
|
signOut: () => supabase.auth.signOut(),
|
||||||
|
resetPassword: (data) => supabase.auth.api.resetPasswordForEmail(data),
|
||||||
|
user,
|
||||||
|
};
|
||||||
|
|
||||||
|
// use a provider to pass down the value
|
||||||
|
return (
|
||||||
|
<AuthContext.Provider value={value}>
|
||||||
|
{!loading && children}
|
||||||
|
</AuthContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// export the useAuth hook
|
||||||
|
export const useAuth = () => {
|
||||||
|
return useContext(AuthContext);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user