mirror of
https://github.com/vercel/commerce.git
synced 2025-07-26 03:31:23 +00:00
auth proccess
This commit is contained in:
50
app/account/component/AccountBook.tsx
Normal file
50
app/account/component/AccountBook.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import AddressCard from '@/components/AddressCard';
|
||||
import { Button } from '@/components/Button';
|
||||
import { Text } from '@/components/Text';
|
||||
import { Customer, MailingAddress } from '@/lib/shopify/types';
|
||||
import { convertObjectToQueryString } from '@/lib/utils';
|
||||
|
||||
export default function AccountBook({
|
||||
customer,
|
||||
addresses,
|
||||
}: {
|
||||
customer: Customer;
|
||||
addresses: MailingAddress[];
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<div className="grid w-full gap-4 p-4 py-6 md:gap-8 md:p-8 lg:p-12">
|
||||
<h3 className="font-bold text-lead">Address Book</h3>
|
||||
<div>
|
||||
{!addresses?.length && (
|
||||
<Text className="mb-1" width="narrow" as="p" size="copy">
|
||||
You haven't saved any addresses yet.
|
||||
</Text>
|
||||
)}
|
||||
<div className="w-48">
|
||||
<a
|
||||
href={`account?${convertObjectToQueryString({
|
||||
modal: 'address-add',
|
||||
})}`}
|
||||
className="inline-block rounded font-medium text-center py-3 px-6 border border-primary/10 bg-contrast text-primary mt-2 text-sm w-full mb-6"
|
||||
>
|
||||
Add an Address
|
||||
</a>
|
||||
</div>
|
||||
{Boolean(addresses?.length) && (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
||||
{customer.defaultAddress && (
|
||||
<AddressCard address={customer.defaultAddress} defaultAddress />
|
||||
)}
|
||||
{addresses
|
||||
.filter(address => address.id !== customer.defaultAddress?.id)
|
||||
.map(address => (
|
||||
<AddressCard key={address.id} address={address} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
11
app/account/component/AuthLayout.tsx
Normal file
11
app/account/component/AuthLayout.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
export default function AuthLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex justify-center my-24 px-4">
|
||||
<div className="max-w-md w-full">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
22
app/account/component/FormButton.tsx
Normal file
22
app/account/component/FormButton.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
'use client';
|
||||
import cn from 'clsx';
|
||||
export default function FormButton({
|
||||
variant = 'primary'
|
||||
}: {
|
||||
btnText: string;
|
||||
state?: string;
|
||||
variant?: 'primary' | 'outline';
|
||||
}) {
|
||||
const buttonClasses = cn({
|
||||
'bg-primary text-contrast rounded py-2 px-4 focus:shadow-outline block w-full':
|
||||
variant === 'primary',
|
||||
'text-left text-primary/50 ml-6 text-sm': variant === 'outline'
|
||||
});
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<button className={buttonClasses} type="submit">
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
45
app/account/component/FormFooter.tsx
Normal file
45
app/account/component/FormFooter.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
interface IFormFooter {
|
||||
page: 'login' | 'register' | 'recover';
|
||||
}
|
||||
|
||||
export default function FormFooter({ page }: IFormFooter) {
|
||||
const data = {
|
||||
login: {
|
||||
linkText: 'Create an account',
|
||||
phrase: 'New to Hydrogen?',
|
||||
href: '/account/register',
|
||||
},
|
||||
register: {
|
||||
linkText: 'Sign In',
|
||||
phrase: 'Already have an account?',
|
||||
href: '/account/login',
|
||||
},
|
||||
recover: {
|
||||
linkText: 'Login',
|
||||
phrase: 'Return to',
|
||||
href: '/account/login',
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between gap-5 mt-8 border-t border-gray-300">
|
||||
<p className="align-baseline text-sm mt-6">
|
||||
{data[page].phrase}
|
||||
|
||||
<Link className="inline underline" href={data[page].href}>
|
||||
{data[page].linkText}
|
||||
</Link>
|
||||
</p>
|
||||
{page === 'login' && (
|
||||
<Link
|
||||
className="mt-6 inline-block align-baseline text-sm text-primary/50x"
|
||||
href="/account/recover"
|
||||
>
|
||||
Forgot Password
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
3
app/account/component/FormHeader.tsx
Normal file
3
app/account/component/FormHeader.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function FormHeader({ title }: { title: string }) {
|
||||
return <h1 className="text-4xl">{title}</h1>;
|
||||
}
|
14
app/account/component/OrderHistory.tsx
Normal file
14
app/account/component/OrderHistory.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import EmptyOrders from '@/components/EmptyOrder';
|
||||
import Orders from '@/components/Orders';
|
||||
import { Order } from '@/lib/shopify/types';
|
||||
|
||||
export default function OrderHistory({ orders }: { orders: Order[] }) {
|
||||
return (
|
||||
<div className="mt-6">
|
||||
<div className="grid w-full gap-4 p-4 py-6 md:gap-8 md:p-8 lg:p-12">
|
||||
<h2 className="font-bold text-lead">Order History</h2>
|
||||
{orders?.length ? <Orders orders={orders} /> : <EmptyOrders />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
23
app/account/component/SignOutSection.tsx
Normal file
23
app/account/component/SignOutSection.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { cookies } from 'next/headers';
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
export default function SignOutSection() {
|
||||
const signOut = async () => {
|
||||
'use server';
|
||||
cookies().set({
|
||||
name: 'customerAccessToken',
|
||||
value: '',
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
expires: new Date(Date.now()),
|
||||
});
|
||||
redirect('/account/login');
|
||||
};
|
||||
return (
|
||||
<form action={signOut} noValidate>
|
||||
<button type="submit" className="text-primary/50">
|
||||
Sign out
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user