add useAuth context

This commit is contained in:
tedraykov
2024-06-21 11:50:58 +03:00
parent cc9def4035
commit 19065c1d82
12 changed files with 181 additions and 109 deletions

View File

@@ -1,5 +1,3 @@
//See https://react.dev/reference/react-dom/hooks/useFormState
//https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#forms
'use server';
import { redirect } from 'next/navigation';
@@ -18,10 +16,8 @@ export async function doLogin(_: any) {
const clientId = CUSTOMER_API_CLIENT_ID;
const origin = ORIGIN_URL;
const loginUrl = new URL(`${customerAccountApiUrl}/auth/oauth/authorize`);
//console.log ("previous", prevState)
try {
//await addToCart(cartId, [{ merchandiseId: selectedVariantId, quantity: 1 }]);
loginUrl.searchParams.set('client_id', clientId);
loginUrl.searchParams.append('response_type', 'code');
loginUrl.searchParams.append('redirect_uri', `${origin}/authorize`);
@@ -30,34 +26,33 @@ export async function doLogin(_: any) {
'openid email https://api.customers.com/auth/customer.graphql'
);
const verifier = await generateCodeVerifier();
//const newVerifier = verifier.replace("+", '_').replace("-",'_').replace("/",'_').trim()
const challenge = await generateCodeChallenge(verifier);
cookies().set('shop_verifier', verifier as string, {
// @ts-ignore
//expires: auth?.expires, //not necessary here
});
cookies().set('shop_verifier', verifier as string, {});
const state = await generateRandomString();
const nonce = await generateRandomString();
cookies().set('shop_state', state as string, {
// @ts-ignore
//expires: auth?.expires, //not necessary here
});
cookies().set('shop_nonce', nonce as string, {
// @ts-ignore
//expires: auth?.expires, //not necessary here
});
cookies().set('shop_state', state as string, {});
cookies().set('shop_nonce', nonce as string, {});
loginUrl.searchParams.append('state', state);
loginUrl.searchParams.append('nonce', nonce);
loginUrl.searchParams.append('code_challenge', challenge);
loginUrl.searchParams.append('code_challenge_method', 'S256');
//console.log ("loginURL", loginUrl)
//throw new Error ("Error") //this is how you throw an error, if you want to. Then the catch will execute
} catch (e) {
console.log('Error', e);
//you can throw error here or return - return goes back to form b/c of state, throw will throw the error boundary
//throw new Error ("Error")
return 'Error logging in. Please try again';
}
redirect(`${loginUrl}`); // Navigate to the new post page
}
export async function isLoggedIn() {
const customerToken = cookies().get('shop_customer_token')?.value;
const refreshToken = cookies().get('shop_refresh_token')?.value;
if (!customerToken && !refreshToken) {
return false;
} else {
return true;
}
}

View File

@@ -6,9 +6,6 @@ export default async function Login() {
const customerToken = cookies().get('shop_customer_token')?.value;
const refreshToken = cookies().get('shop_refresh_token')?.value;
let isLoggedIn;
//obviously just checking for the cookies without verifying the cookie itself is not ideal. However, the cookie is validated on the
//account page, so a "fake" cookie does nothing, except show the UI and then it would be deleted when clicking on account
//so for now, just checking the cookie for the UI is sufficient. Alternatively, we can do a query here, or a custom JWT
if (!customerToken && !refreshToken) {
isLoggedIn = false;
} else {

View File

@@ -1,6 +1,5 @@
'use client';
import { Popover, PopoverButton, PopoverPanel, Transition } from '@headlessui/react';
import { CloseButton, Popover, PopoverButton, PopoverPanel, Transition } from '@headlessui/react';
import { ArrowRightIcon } from '@heroicons/react/16/solid';
import { Menu } from 'lib/shopify/types';
import { Fragment } from 'react';
@@ -8,6 +7,8 @@ import OpenProfile from './open-profile';
import { useFormState, useFormStatus } from 'react-dom';
import { doLogin } from 'components/auth/actions';
import { Button } from 'components/button';
import useAuth from 'hooks/use-auth';
import Link from 'next/link';
type ProfilePopoverProps = {
menu: Menu[];
@@ -34,7 +35,8 @@ function SubmitButton(props: any) {
);
}
const ProfilePopover = ({ menu }: ProfilePopoverProps) => {
const [message, formAction] = useFormState(doLogin, null);
const [message] = useFormState(doLogin, null);
const { isAuthenticated, loading } = useAuth();
return (
<Popover className="relative">
@@ -53,22 +55,29 @@ const ProfilePopover = ({ menu }: ProfilePopoverProps) => {
<PopoverPanel className="absolute -right-10 z-50 mt-2 w-72 max-w-lg px-4 sm:px-0 lg:right-0">
<div className="flex flex-col gap-2 overflow-hidden rounded-md bg-white px-4 py-3 text-black shadow-xl ring-1 ring-black/5">
<span className="text-sm font-medium">My Account</span>
<form action={formAction}>
<SubmitButton message={message} />
<p aria-live="polite" className="sr-only" role="status">
{message}
</p>
</form>
{!isAuthenticated && !loading && <SubmitButton message={message} />}
{menu.length ? (
<ul className="mt-2 flex w-full flex-col divide-y text-sm">
<ul className="flex w-full flex-col divide-y text-sm">
{isAuthenticated && (
<li className="cursor-pointer py-2 hover:underline">
<CloseButton
as={Link}
className="flex w-full flex-row items-center justify-between"
href="/account"
>
My Orders <ArrowRightIcon className="h-3" />
</CloseButton>
</li>
)}
{menu.map((menuItem) => (
<li className="cursor-pointer py-2 hover:underline" key={menuItem.title}>
<a
<CloseButton
as={Link}
className="flex w-full flex-row items-center justify-between"
href={menuItem.path}
>
{menuItem.title} <ArrowRightIcon className="h-3" />
</a>
</CloseButton>
</li>
))}
</ul>