mirror of
https://github.com/vercel/commerce.git
synced 2025-06-27 17:01:21 +00:00
fix: reuse cart token
This commit is contained in:
parent
150d361791
commit
b250d83534
@ -1,21 +1,38 @@
|
|||||||
import { authOptions } from 'lib/auth/config';
|
import { getStoreApiFromRequest } from 'lib/woocomerce/storeApi';
|
||||||
import { storeApi } from 'lib/woocomerce/storeApi';
|
|
||||||
import { getServerSession } from 'next-auth';
|
|
||||||
import { NextRequest, NextResponse } from 'next/server';
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
export async function GET(req: NextRequest) {
|
export async function GET(req: NextRequest) {
|
||||||
try {
|
try {
|
||||||
const session = await getServerSession(authOptions);
|
const storeApi = await getStoreApiFromRequest(req);
|
||||||
storeApi._setAuthorizationToken(session?.user?.token ?? '');
|
const { cart, cartToken: updatedToken } = await storeApi.getCart();
|
||||||
const cart = await storeApi.getCart();
|
|
||||||
return NextResponse.json(cart, { status: 200 });
|
const response = NextResponse.json(cart);
|
||||||
} catch (error) {
|
|
||||||
return NextResponse.json({ error: 'Failed to fetch cart', message: error }, { status: 500 });
|
if (updatedToken) {
|
||||||
|
response.cookies.set('cart-token', updatedToken, {
|
||||||
|
httpOnly: true,
|
||||||
|
sameSite: 'lax',
|
||||||
|
path: '/', //
|
||||||
|
maxAge: 60 * 60 * 46 // 46 ore
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error.message.includes('jwt_auth_invalid_token')) {
|
||||||
|
console.error('Token expired, please reauthenticate.');
|
||||||
|
return NextResponse.json({ error: 'Token expired, please reauthenticate.' }, { status: 401 });
|
||||||
|
}
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Failed to fetch cart', message: error.message },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function POST(req: NextRequest) {
|
export async function POST(req: NextRequest) {
|
||||||
try {
|
try {
|
||||||
|
const storeApi = await getStoreApiFromRequest(req);
|
||||||
const { id, quantity, variation } = await req.json();
|
const { id, quantity, variation } = await req.json();
|
||||||
const cart = await storeApi.addToCart({ id, quantity, variation });
|
const cart = await storeApi.addToCart({ id, quantity, variation });
|
||||||
return NextResponse.json(cart, { status: 200 });
|
return NextResponse.json(cart, { status: 200 });
|
||||||
@ -29,6 +46,7 @@ export async function POST(req: NextRequest) {
|
|||||||
|
|
||||||
export async function PUT(req: NextRequest) {
|
export async function PUT(req: NextRequest) {
|
||||||
try {
|
try {
|
||||||
|
const storeApi = await getStoreApiFromRequest(req);
|
||||||
const { key, quantity } = await req.json();
|
const { key, quantity } = await req.json();
|
||||||
if (quantity > 0) {
|
if (quantity > 0) {
|
||||||
const cart = await storeApi.updateItem({ key, quantity });
|
const cart = await storeApi.updateItem({ key, quantity });
|
||||||
@ -47,6 +65,7 @@ export async function PUT(req: NextRequest) {
|
|||||||
|
|
||||||
export async function DELETE(req: NextRequest) {
|
export async function DELETE(req: NextRequest) {
|
||||||
try {
|
try {
|
||||||
|
const storeApi = await getStoreApiFromRequest(req);
|
||||||
const { key } = await req.json();
|
const { key } = await req.json();
|
||||||
const cart = await storeApi.removeFromCart({ key });
|
const cart = await storeApi.removeFromCart({ key });
|
||||||
return NextResponse.json(cart, { status: 200 });
|
return NextResponse.json(cart, { status: 200 });
|
||||||
|
31
app/api/customer/order/route.ts
Normal file
31
app/api/customer/order/route.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { authOptions } from 'lib/auth/config';
|
||||||
|
import { getStoreApiFromRequest, OrderPayload } from 'lib/woocomerce/storeApi';
|
||||||
|
import { getServerSession } from 'next-auth';
|
||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
|
export async function POST(req: NextRequest) {
|
||||||
|
try {
|
||||||
|
const session = await getServerSession(authOptions);
|
||||||
|
if (!session?.user?.customer_id) {
|
||||||
|
return NextResponse.json({ error: 'User not logged' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const storeApi = await getStoreApiFromRequest(req);
|
||||||
|
|
||||||
|
const { billing_address, shipping_address, customer_note, payment_method, payment_data } =
|
||||||
|
await req.json();
|
||||||
|
const order: OrderPayload = {
|
||||||
|
shipping_address,
|
||||||
|
billing_address: billing_address || shipping_address,
|
||||||
|
customer_note,
|
||||||
|
payment_method: payment_method || 'bacs', // Ensure payment method is used
|
||||||
|
payment_data: payment_data || [] // Ensure payment data is used
|
||||||
|
};
|
||||||
|
console.log('Creating order', order);
|
||||||
|
const result = await storeApi.createOrder(order);
|
||||||
|
return NextResponse.json(result, { status: 200 });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error creating order', error);
|
||||||
|
return NextResponse.json({ error: JSON.stringify(error) }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
@ -20,9 +20,8 @@ const shippingSchema = z.object({
|
|||||||
address_1: z.string().min(3),
|
address_1: z.string().min(3),
|
||||||
address_2: z.string().optional(),
|
address_2: z.string().optional(),
|
||||||
city: z.string().min(3),
|
city: z.string().min(3),
|
||||||
state: z.string().max(2).min(2),
|
|
||||||
postcode: z.string().min(3),
|
postcode: z.string().min(3),
|
||||||
country: z.string().min(3),
|
country: z.string().min(2).max(2),
|
||||||
company: z.string().optional()
|
company: z.string().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9,6 +9,18 @@ export default function CheckoutReview() {
|
|||||||
const { cart } = useCart();
|
const { cart } = useCart();
|
||||||
const { checkout } = useCheckout();
|
const { checkout } = useCheckout();
|
||||||
|
|
||||||
|
const handleCreateOrder = async () => {
|
||||||
|
const order = await fetch('/api/customer/order', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
billing_address: checkout?.billing,
|
||||||
|
shipping_address: checkout?.shipping,
|
||||||
|
payment_method: checkout?.payment_method
|
||||||
|
})
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error('Error creating order', err);
|
||||||
|
});
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<section className="mt-4 grid w-full gap-4 px-4 pb-4">
|
<section className="mt-4 grid w-full gap-4 px-4 pb-4">
|
||||||
<h1 className="text-2xl font-bold">Riassunto</h1>
|
<h1 className="text-2xl font-bold">Riassunto</h1>
|
||||||
@ -41,8 +53,13 @@ export default function CheckoutReview() {
|
|||||||
<span className="mt-4 text-lg font-bold">Metodo di pagamento</span>
|
<span className="mt-4 text-lg font-bold">Metodo di pagamento</span>
|
||||||
<span>{checkout?.payment_method}</span>
|
<span>{checkout?.payment_method}</span>
|
||||||
|
|
||||||
<Button title="Vai al pagamento" color="primary" className="text-white">
|
<Button
|
||||||
Vai al pagamento
|
title="Vai al pagamento"
|
||||||
|
color="primary"
|
||||||
|
className="text-white"
|
||||||
|
onPress={handleCreateOrder}
|
||||||
|
>
|
||||||
|
Crea ordine
|
||||||
</Button>
|
</Button>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
@ -6,7 +6,8 @@ export default async function ProductPage(props: { params: Promise<{ slug: strin
|
|||||||
const slug = (await props.params).slug;
|
const slug = (await props.params).slug;
|
||||||
const category = (await woocommerce.get('products/categories', { slug }))?.[0];
|
const category = (await woocommerce.get('products/categories', { slug }))?.[0];
|
||||||
const products: Product[] = await woocommerce.get('products', {
|
const products: Product[] = await woocommerce.get('products', {
|
||||||
category: category.id.toString()
|
category: category.id.toString(),
|
||||||
|
author: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -103,7 +103,7 @@ export default async function ProductPage(props: { params: Promise<{ name: strin
|
|||||||
<div className="mx-auto max-w-screen-2xl px-4">
|
<div className="mx-auto max-w-screen-2xl px-4">
|
||||||
<div className="grid items-start gap-8 rounded-lg border border-neutral-200 bg-white p-4 dark:border-neutral-800 dark:bg-black md:flex-col-reverse lg:grid-cols-2 lg:flex-row lg:flex-col">
|
<div className="grid items-start gap-8 rounded-lg border border-neutral-200 bg-white p-4 dark:border-neutral-800 dark:bg-black md:flex-col-reverse lg:grid-cols-2 lg:flex-row lg:flex-col">
|
||||||
<h1 className="mb-2 text-5xl font-medium md:hidden lg:hidden">{product.name}</h1>
|
<h1 className="mb-2 text-5xl font-medium md:hidden lg:hidden">{product.name}</h1>
|
||||||
<div className="lg:sticky top-4 w-full self-start">
|
<div className="top-4 w-full self-start lg:sticky">
|
||||||
<Suspense
|
<Suspense
|
||||||
fallback={
|
fallback={
|
||||||
<div className="relative aspect-square h-full max-h-[550px] w-full overflow-hidden" />
|
<div className="relative aspect-square h-full max-h-[550px] w-full overflow-hidden" />
|
||||||
|
@ -20,7 +20,8 @@ export default async function SearchPage(props: {
|
|||||||
orderby: sortKey,
|
orderby: sortKey,
|
||||||
order,
|
order,
|
||||||
min_price: minPrice ?? '0',
|
min_price: minPrice ?? '0',
|
||||||
max_price: maxPrice ?? '1000'
|
max_price: maxPrice ?? '1000',
|
||||||
|
author: 1
|
||||||
});
|
});
|
||||||
const resultsText = products.length > 1 ? 'results' : 'result';
|
const resultsText = products.length > 1 ? 'results' : 'result';
|
||||||
|
|
||||||
|
@ -4,8 +4,7 @@ import Link from 'next/link';
|
|||||||
import { GridTileImage } from './grid/tile';
|
import { GridTileImage } from './grid/tile';
|
||||||
|
|
||||||
export async function Carousel() {
|
export async function Carousel() {
|
||||||
// Collections that start with `hidden-*` are hidden from the search page.
|
const products: Product[] = await woocommerce.get('products', { author: 1 });
|
||||||
const products: Product[] = await woocommerce.get('products');
|
|
||||||
|
|
||||||
if (!products?.length) return null;
|
if (!products?.length) return null;
|
||||||
|
|
||||||
|
@ -5,24 +5,22 @@ import { Cart } from 'lib/woocomerce/models/cart';
|
|||||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||||
|
|
||||||
type CartContextType = {
|
type CartContextType = {
|
||||||
cart: Cart | undefined;
|
cart?: Cart;
|
||||||
setNewCart: (cart: Cart) => void;
|
setNewCart: (cart: Cart) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CartContext = createContext<CartContextType | undefined>(undefined);
|
const CartContext = createContext<CartContextType | undefined>(undefined);
|
||||||
|
|
||||||
export function CartProvider({ children }: { children: React.ReactNode }) {
|
export function CartProvider({ children }: { children: React.ReactNode }) {
|
||||||
const [cart, setCart] = useState<Cart | undefined>(undefined);
|
const [cart, setCart] = useState<Cart>();
|
||||||
const setNewCart = (cart: Cart) => {
|
|
||||||
setCart(cart);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchCart = async () => {
|
const fetchCart = async () => {
|
||||||
try {
|
try {
|
||||||
const cart = await (await fetch('/api/cart')).json();
|
const res = await fetch('/api/cart');
|
||||||
setNewCart(cart);
|
const cart = await res.json();
|
||||||
|
setCart(cart);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error('Error fetching cart', err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,21 +30,14 @@ export function CartProvider({ children }: { children: React.ReactNode }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<NextUIProvider>
|
<NextUIProvider>
|
||||||
<CartContext.Provider
|
<CartContext.Provider value={{ cart, setNewCart: setCart }}>{children}</CartContext.Provider>
|
||||||
value={{
|
|
||||||
cart,
|
|
||||||
setNewCart
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</CartContext.Provider>
|
|
||||||
</NextUIProvider>
|
</NextUIProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useCart() {
|
export function useCart() {
|
||||||
const context = useContext(CartContext);
|
const context = useContext(CartContext);
|
||||||
if (context === undefined) {
|
if (!context) {
|
||||||
throw new Error('useCart must be used within a CartProvider');
|
throw new Error('useCart must be used within a CartProvider');
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
|
@ -32,7 +32,7 @@ export default function ShippingForm({
|
|||||||
<div className={clsx('flex flex-col', className)}>
|
<div className={clsx('flex flex-col', className)}>
|
||||||
{title && <h2 className="mt-2 text-2xl font-bold">{title}</h2>}
|
{title && <h2 className="mt-2 text-2xl font-bold">{title}</h2>}
|
||||||
{Object.entries(checkout?.shipping || {})
|
{Object.entries(checkout?.shipping || {})
|
||||||
.filter(([key]) => key !== 'country')
|
.filter(([key]) => key !== 'country' && key !== 'state')
|
||||||
.map(([key, value], index) => (
|
.map(([key, value], index) => (
|
||||||
<div className={index !== 0 ? 'mt-4' : ''} key={key}>
|
<div className={index !== 0 ? 'mt-4' : ''} key={key}>
|
||||||
<Input
|
<Input
|
||||||
@ -74,7 +74,7 @@ export default function ShippingForm({
|
|||||||
>
|
>
|
||||||
{countries.map((item) => (
|
{countries.map((item) => (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
key={item.name}
|
key={item.code}
|
||||||
startContent={
|
startContent={
|
||||||
<Avatar alt={item.name + '-img'} className="h-6 w-6" src={item.icon} />
|
<Avatar alt={item.name + '-img'} className="h-6 w-6" src={item.icon} />
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { storeApi } from 'lib/woocomerce/storeApi';
|
|
||||||
import { wordpress } from 'lib/wordpress/wordpress';
|
import { wordpress } from 'lib/wordpress/wordpress';
|
||||||
import { NextAuthOptions, Session, User } from 'next-auth';
|
import { NextAuthOptions, Session, User } from 'next-auth';
|
||||||
import { JWT } from 'next-auth/jwt';
|
import { JWT } from 'next-auth/jwt';
|
||||||
@ -25,8 +24,7 @@ export const authOptions = {
|
|||||||
if (user) {
|
if (user) {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
storeApi._seCartToken('');
|
|
||||||
storeApi._setAuthorizationToken('');
|
|
||||||
// Return null if user data could not be retrieved
|
// Return null if user data could not be retrieved
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -45,14 +43,5 @@ export const authOptions = {
|
|||||||
session.user = token.user;
|
session.user = token.user;
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
events: {
|
|
||||||
async signIn() {
|
|
||||||
storeApi._seCartToken('');
|
|
||||||
},
|
|
||||||
async signOut() {
|
|
||||||
storeApi._seCartToken('');
|
|
||||||
storeApi._setAuthorizationToken('');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} satisfies NextAuthOptions;
|
} satisfies NextAuthOptions;
|
||||||
|
@ -11,10 +11,11 @@ export const createUrl = (pathname: string, params: URLSearchParams | ReadonlyUR
|
|||||||
export const ensureStartsWith = (stringToCheck: string, startsWith: string) =>
|
export const ensureStartsWith = (stringToCheck: string, startsWith: string) =>
|
||||||
stringToCheck.startsWith(startsWith) ? stringToCheck : `${startsWith}${stringToCheck}`;
|
stringToCheck.startsWith(startsWith) ? stringToCheck : `${startsWith}${stringToCheck}`;
|
||||||
|
|
||||||
export const getCountries = (): { name: string; icon: string }[] =>
|
export const getCountries = (): { name: string; icon: string; code: string }[] =>
|
||||||
(countries as { country: string; flag_base64: string }[]).map(({ country, flag_base64 }) => ({
|
(countries as { name: string; emoji: string; code: string }[]).map(({ name, emoji, code }) => ({
|
||||||
name: country,
|
name,
|
||||||
icon: flag_base64
|
icon: emoji,
|
||||||
|
code
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const isStrinInteger = (value: string) => {
|
export const isStrinInteger = (value: string) => {
|
||||||
|
@ -72,7 +72,7 @@ export type OrderItem = {
|
|||||||
|
|
||||||
export interface OrderNotes {
|
export interface OrderNotes {
|
||||||
id: number;
|
id: number;
|
||||||
author: string;
|
author: string | number;
|
||||||
date_created: Date;
|
date_created: Date;
|
||||||
date_created_gmt: Date;
|
date_created_gmt: Date;
|
||||||
note: string;
|
note: string;
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
import axios, { AxiosInstance, RawAxiosRequestHeaders } from 'axios';
|
import axios, { RawAxiosRequestHeaders } from 'axios';
|
||||||
|
import { getToken } from 'next-auth/jwt';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
import { NextRequest } from 'next/server';
|
||||||
import { Billing } from './models/billing';
|
import { Billing } from './models/billing';
|
||||||
import { Cart } from './models/cart';
|
import { Cart } from './models/cart';
|
||||||
import { Order } from './models/orders';
|
import { Order } from './models/orders';
|
||||||
import { Shipping } from './models/shipping';
|
import { Shipping } from './models/shipping';
|
||||||
|
|
||||||
/**
|
|
||||||
* WooCommerce Store API Client for server-side requests.
|
|
||||||
* To use this in the client-side, you need to create a new route of api endpoint in your Next.js app.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export type OrderPayload = {
|
export type OrderPayload = {
|
||||||
billing_address: Billing;
|
billing_address: Billing;
|
||||||
shipping_address: Shipping;
|
shipping_address: Shipping;
|
||||||
@ -22,78 +20,98 @@ export type PaymentMethodData = {
|
|||||||
value: string;
|
value: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WooCommerceStoreApiClient {
|
function createStoreApiClient({
|
||||||
private client: AxiosInstance;
|
baseURL = process.env.WOOCOMMERCE_STORE_API_URL ?? 'http://localhost/wp-json/wc/store/v1',
|
||||||
|
authToken,
|
||||||
|
cartToken
|
||||||
|
}: {
|
||||||
|
baseURL?: string;
|
||||||
|
authToken?: string;
|
||||||
|
cartToken?: string;
|
||||||
|
}) {
|
||||||
|
const headers: RawAxiosRequestHeaders = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Accept: '*/*',
|
||||||
|
...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),
|
||||||
|
...(cartToken ? { 'cart-token': cartToken } : {})
|
||||||
|
};
|
||||||
|
|
||||||
constructor(baseURL: string) {
|
const client = axios.create({ baseURL, headers });
|
||||||
const headers: RawAxiosRequestHeaders = {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
Accept: '*/*'
|
|
||||||
};
|
|
||||||
|
|
||||||
this.client = axios.create({
|
async function _request(method: 'get' | 'post' | 'put' | 'delete', url: string, data?: any) {
|
||||||
baseURL,
|
try {
|
||||||
headers
|
console.debug('Request', method, url, data, headers);
|
||||||
});
|
const response = await axios({
|
||||||
}
|
method,
|
||||||
|
url: baseURL + url,
|
||||||
_setAuthorizationToken(token: string) {
|
data,
|
||||||
if (token) {
|
headers
|
||||||
this.client.defaults.headers['Authorization'] = `Bearer ${token}`;
|
});
|
||||||
} else {
|
return response;
|
||||||
this._deleteAuthorizationToken();
|
} catch (error: any) {
|
||||||
|
if (error.response) {
|
||||||
|
console.error('Error response:', error.response.data);
|
||||||
|
if (error.response.data.code === 'jwt_auth_invalid_token') {
|
||||||
|
console.debug('Token expired, regenerating...');
|
||||||
|
const newAuthToken = await regenerateAuthToken();
|
||||||
|
headers.Authorization = `Bearer ${newAuthToken}`;
|
||||||
|
return _request(method, url, data);
|
||||||
|
}
|
||||||
|
throw new Error(
|
||||||
|
`Request failed with status ${error.response.status}: ${error.response.data.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_deleteAuthorizationToken() {
|
async function regenerateAuthToken(): Promise<string> {
|
||||||
this.client.defaults.headers['Authorization'] = '';
|
console.debug('Regenerating auth token...');
|
||||||
|
const res = await axios.post(`${baseURL}/auth/refresh`, {}, { headers });
|
||||||
|
return res.data.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
_seCartToken(cartToken: string) {
|
return {
|
||||||
this.client.defaults.headers['cart-token'] = cartToken;
|
async getCart(
|
||||||
}
|
params?: Record<string, string | number>
|
||||||
|
): Promise<{ cart: Cart; cartToken?: string }> {
|
||||||
|
const res = await _request('get', '/cart', { params });
|
||||||
|
return { cart: res.data, cartToken: res.headers['cart-token'] };
|
||||||
|
},
|
||||||
|
|
||||||
async getCart(params?: Record<string, string | number>): Promise<Cart> {
|
async addToCart(payload: {
|
||||||
return this.client.get<Cart>('/cart', { params }).then(async (response) => {
|
id: string | number;
|
||||||
this._seCartToken(response.headers['cart-token']);
|
quantity: number;
|
||||||
|
variation: { attribute: string; value: string }[];
|
||||||
return response.data;
|
}): Promise<Cart> {
|
||||||
});
|
const res = await _request('post', '/cart/add-item', payload);
|
||||||
}
|
return res.data;
|
||||||
|
},
|
||||||
async addToCart(payload: {
|
async updateItem(payload: { key: string | number; quantity: number }): Promise<Cart> {
|
||||||
id: string | number;
|
const res = await _request('post', '/cart/update-item', payload);
|
||||||
quantity: number;
|
return res.data;
|
||||||
variation: { attribute: string; value: string }[];
|
},
|
||||||
}): Promise<Cart> {
|
async removeFromCart(payload: { key: string | number }): Promise<Cart> {
|
||||||
return this.client.post<Cart>('/cart/add-item', payload).then((response) => response.data);
|
const res = await _request('post', `/cart/remove-item?key=${payload.key}`);
|
||||||
}
|
return res.data;
|
||||||
|
},
|
||||||
async updateItem(payload: { key: string | number; quantity: number }): Promise<Cart> {
|
createOrder(order: OrderPayload): Promise<Order> {
|
||||||
return this.client.post<Cart>('/cart/update-item', payload).then((response) => response.data);
|
return _request('post', '/checkout', order).then((res) => res.data);
|
||||||
}
|
},
|
||||||
|
async getOrders(): Promise<Order[]> {
|
||||||
async removeFromCart(payload: { key: string | number }): Promise<Cart> {
|
const res = await _request('get', '/checkout');
|
||||||
return this.client
|
return res.data;
|
||||||
.post<Cart>(`/cart/remove-item?key=${payload.key}`)
|
},
|
||||||
.then((response) => response.data);
|
async getOrder(id: string | number): Promise<Order> {
|
||||||
}
|
const res = await _request('get', `/checkout/${id}`);
|
||||||
|
return res.data;
|
||||||
async createOrder(order: OrderPayload): Promise<Order> {
|
}
|
||||||
return this.client.post('/checkout', order).then((response) => response.data);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
async getOrders(params?: Record<string, string | number>): Promise<Order[]> {
|
|
||||||
return this.client.get<Order[]>('/checkout', { params }).then((response) => response.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getOrder(id: string | number): Promise<Order> {
|
|
||||||
return this.client.get<Order>(`/checkout/${id}`).then((response) => response.data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example usage.
|
export async function getStoreApiFromRequest(req?: NextRequest) {
|
||||||
const baseURL =
|
const cartToken = (await cookies()).get('cart-token')?.value;
|
||||||
process.env.WOOCOMMERCE_STORE_API_URL ?? 'http://wordpress.localhost/wp-json/wc/store/v1';
|
const authToken = req ? (await getToken({ req }))?.user?.token : undefined;
|
||||||
|
|
||||||
export const storeApi = new WooCommerceStoreApiClient(baseURL);
|
return createStoreApiClient({ cartToken, authToken });
|
||||||
|
}
|
||||||
|
@ -13,7 +13,6 @@ const nextConfig: NextConfig = {
|
|||||||
formats: ['image/avif', 'image/webp'],
|
formats: ['image/avif', 'image/webp'],
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
protocol: 'https',
|
|
||||||
hostname: '**'
|
hostname: '**'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
1992
types/countries.json
1992
types/countries.json
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user