refactor: change layout profile and related products

This commit is contained in:
paolosantarsiero 2025-01-03 12:35:38 +01:00
parent 6775f7363b
commit 23f9f55fab
10 changed files with 114 additions and 26 deletions

View File

@ -9,8 +9,8 @@ export async function GET(req: NextRequest) {
if (!session?.user?.store_id) {
return NextResponse.json({ error: 'User not logged' }, { status: 401 });
}
const cart = await woocommerce.get('customers', { id: session?.user.store_id });
return NextResponse.json(cart, { status: 200 });
const customer = await woocommerce.get('customers', { id: session?.user.store_id });
return NextResponse.json(customer, { status: 200 });
} catch (error) {
return NextResponse.json({ error: JSON.stringify(error) }, { status: 500 });
}
@ -19,9 +19,9 @@ export async function GET(req: NextRequest) {
export async function POST(req: NextRequest) {
try {
const data = await req.json();
const cart = await woocommerce.post('customers', data);
return NextResponse.json(cart, { status: 200 });
const customer = await woocommerce.post('customers', data);
return NextResponse.json(customer, { status: 200 });
} catch (error) {
return NextResponse.json({ error: 'Failed to add item to cart' }, { status: 500 });
return NextResponse.json({ error: 'Failed to add item to customer' }, { status: 500 });
}
}

View File

@ -11,6 +11,7 @@ import { HIDDEN_PRODUCT_TAG } from 'lib/constants';
import { Image } from 'lib/woocomerce/models/base';
import { Product, ProductVariations } from 'lib/woocomerce/models/product';
import { woocommerce } from 'lib/woocomerce/woocommerce';
import Link from 'next/link';
import { Suspense } from 'react';
export async function generateMetadata(props: {
@ -51,6 +52,10 @@ export default async function ProductPage(props: { params: Promise<{ name: strin
if (!product) return notFound();
const relatedProducts = await Promise.all(
product.related_ids?.map(async (id) => woocommerce.get(`products/${id}`)) || []
);
const productJsonLd = {
'@context': 'https://schema.org',
'@type': 'Product',
@ -114,6 +119,31 @@ export default async function ProductPage(props: { params: Promise<{ name: strin
<AddToCart product={product} variations={variations} />
</div>
</div>
<div className="mt-8 py-4">
<h3 className="text-2xl font-bold">Related Products</h3>
<div className="mt-4 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
{relatedProducts.map((relatedProduct) => {
return (
<div
key={relatedProduct.id}
className="rounded-lg border border-neutral-200 bg-white dark:border-neutral-800 dark:bg-black"
>
<img
src={relatedProduct.images?.[0].src}
alt={relatedProduct.name}
className="h-48 w-full object-cover"
/>
<div className="p-4">
<Link href={`/product/${relatedProduct.slug}`}>
<h2 className="text-xl font-bold">{relatedProduct.name}</h2>
</Link>
<div dangerouslySetInnerHTML={{ __html: relatedProduct.short_description }} />
</div>
</div>
);
})}
</div>
</div>
</div>
</ProductProvider>
);

View File

@ -1,7 +0,0 @@
export default async function PersonalArea() {
return (
<section className="mt-4 grid max-w-screen-2xl gap-4 px-4 pb-4">
<h1 className="text-2xl font-bold">Personal Area</h1>
</section>
);
}

View File

@ -1,5 +1,6 @@
'use client';
import { CubeIcon, UserCircleIcon } from '@heroicons/react/24/outline';
import { Avatar } from '@nextui-org/react';
import LogoutButton from 'components/button/logout';
import { Customer } from 'lib/woocomerce/models/customer';
@ -39,15 +40,17 @@ export default function ProfileLayout({ children }: { children: React.ReactNode
<span className="text-lg font-bold">{customer.last_name}</span>
</div>
<div className="flex-start mt-3 flex">
<Link href={`/profile/area`}>
<button type="button" className="w-full rounded-md py-3">
<Link href={`/profile`} className="hover:text-indigo-500">
<button type="button" className="flex flex-row items-center rounded-md py-3">
<UserCircleIcon className="me-2 h-4" />
Personal area
</button>
</Link>
</div>
<div className="flex-start mt-3 flex">
<Link href={`/profile/orders`}>
<button type="button" className="w-full rounded-md py-3">
<Link href={`/profile/orders`} className="hover:text-indigo-500">
<button type="button" className="flex flex-row items-center rounded-md py-3">
<CubeIcon className="me-2 h-4" />
Orders
</button>
</Link>

View File

@ -1,7 +1,62 @@
export default async function ProfilePage() {
'use server';
import { authOptions } from 'lib/auth/config';
import { woocommerce } from 'lib/woocomerce/woocommerce';
import { getServerSession } from 'next-auth';
export default async function PersonalArea() {
const session = await getServerSession(authOptions);
if (!session?.user?.store_id) {
return { status: 401, body: { error: 'User not logged' } };
}
const customer = await woocommerce.get('customers', { id: session?.user.store_id });
return (
<section className="mt-4 grid max-w-screen-2xl gap-4 px-4 pb-4">
<h1 className="text-2xl font-bold">Personal Area</h1>
<div className="flex flex-col">
<label
htmlFor="name"
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
>
First Name
</label>
<input
type="text"
id="name"
name="name"
className="mt-1 block w-full rounded-md border-gray-300 py-3 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-lg"
value={customer.first_name}
disabled
/>
<label
htmlFor="last_name"
className="mt-2 block text-sm font-medium text-gray-700 dark:text-gray-300"
>
Last Name
</label>
<input
type="text"
id="last_name"
className="mt-1 block w-full rounded-md border-gray-300 py-3 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-lg"
value={customer.last_name}
disabled
/>
<label
htmlFor="email"
className="mt-2 block text-sm font-medium text-gray-700 dark:text-gray-300"
>
Email
</label>
<input
type="email"
id="email"
className="mt-1 block w-full rounded-md border-gray-300 py-3 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-lg"
value={customer.email}
disabled
/>
</div>
</section>
);
}

View File

@ -1,4 +1,5 @@
'use client';
import { ArrowRightEndOnRectangleIcon } from '@heroicons/react/24/outline';
import { signOut } from 'next-auth/react';
import { useRouter } from 'next/navigation';
@ -7,11 +8,12 @@ export default function LogoutButton() {
return (
<button
type="button"
className="rounded-md py-3"
className="flex flex-row items-center rounded-md py-3 hover:text-indigo-500"
onClick={() => {
signOut({ callbackUrl: '/' });
}}
>
<ArrowRightEndOnRectangleIcon className="me-2 h-4" />
Logout
</button>
);

View File

@ -4,6 +4,7 @@ import { PlusIcon } from '@heroicons/react/24/outline';
import clsx from 'clsx';
import { useProduct } from 'components/product/product-context';
import { Product, ProductVariations } from 'lib/woocomerce/models/product';
import { toast } from 'sonner';
import { useCart } from './cart-context';
function SubmitButton({ disabled = false }: { disabled: boolean }) {
@ -50,6 +51,7 @@ export function AddToCart({
})
).json();
setNewCart(cart);
toast('Item added to cart');
} catch (error) {
console.error(error);
}

View File

@ -89,7 +89,12 @@ export default function CartModal() {
key={i}
className="flex w-full flex-col border-b border-neutral-300 dark:border-neutral-700"
>
<CartItemView item={item} editable={true} closeCart={closeCart} />
<CartItemView
item={item}
editable={true}
deletable={true}
closeCart={closeCart}
/>
</li>
);
})}

View File

@ -1,5 +1,5 @@
import { storeApi } from 'lib/woocomerce/storeApi';
import { woocommerce } from 'lib/woocomerce/woocommerce';
import { wordpress } from 'lib/wordpress/wordpress';
import { NextAuthOptions, Session, User } from 'next-auth';
import { JWT } from 'next-auth/jwt';
import CredentialsProvider from 'next-auth/providers/credentials';
@ -20,11 +20,13 @@ export const authOptions = {
if (!credentials?.username || !credentials?.password) {
return null;
}
const user = await woocommerce.login(credentials.username, credentials.password);
const user = await wordpress.login(credentials.username, credentials.password);
// If no error and we have user data, return it
if (user) {
return user;
}
storeApi._seCartToken('');
storeApi._setAuthorizationToken('');
// Return null if user data could not be retrieved
return null;
}

View File

@ -30,7 +30,7 @@ export type WooRestApiParams = CouponsParams &
type WooCommerceResponse<
T extends WooRestApiEndpoint,
P extends Partial<WooRestApiParams> = {}
> = P['id'] extends number | string // Verifica se `id` è definito e di tipo string
> = P['id'] extends number | string
? T extends 'products'
? Product
: T extends 'customers'
@ -115,10 +115,6 @@ export default class WooCommerceRestApi<T extends WooRestApiOptions> {
this._opt.classVersion = '0.0.2';
}
login(username: string, password: string): Promise<any> {
return this._request('POST', 'token', { username, password }, {}, 'jwt-auth/v1');
}
/**
* Parse params to object.
*