mirror of
https://github.com/vercel/commerce.git
synced 2025-06-28 09:21:22 +00:00
fix: build
This commit is contained in:
parent
1b2211ddea
commit
aac4af90ae
5
app/[...not_found]/page.tsx
Normal file
5
app/[...not_found]/page.tsx
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { notFound } from 'next/navigation';
|
||||||
|
|
||||||
|
export default function NotFoundCatchAll() {
|
||||||
|
notFound();
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { authOptions } from "lib/auth/config";
|
import { authOptions } from 'lib/auth/config';
|
||||||
import NextAuth from "next-auth";
|
import NextAuth from 'next-auth';
|
||||||
|
|
||||||
const handler = NextAuth(authOptions);
|
const handler = NextAuth(authOptions);
|
||||||
export { handler as GET, handler as POST };
|
export { handler as GET, handler as POST };
|
||||||
|
@ -20,7 +20,10 @@ export async function POST(req: NextRequest) {
|
|||||||
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 });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return NextResponse.json({ error: 'Failed to add item to cart', message: JSON.stringify(error) }, { status: 500 });
|
return NextResponse.json(
|
||||||
|
{ error: 'Failed to add item to cart', message: JSON.stringify(error) },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +38,10 @@ export async function PUT(req: NextRequest) {
|
|||||||
return NextResponse.json(cart, { status: 200 });
|
return NextResponse.json(cart, { status: 200 });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return NextResponse.json({ error: 'Failed to update cart item', message: JSON.stringify(error) }, { status: 500 });
|
return NextResponse.json(
|
||||||
|
{ error: 'Failed to update cart item', message: JSON.stringify(error) },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +51,9 @@ export async function DELETE(req: NextRequest) {
|
|||||||
const cart = await storeApi.removeFromCart({ key });
|
const cart = await storeApi.removeFromCart({ key });
|
||||||
return NextResponse.json(cart, { status: 200 });
|
return NextResponse.json(cart, { status: 200 });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return NextResponse.json({ error: 'Failed to remove item from cart', message: JSON.stringify(error) }, { status: 500 });
|
return NextResponse.json(
|
||||||
|
{ error: 'Failed to remove item from cart', message: JSON.stringify(error) },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { woocommerce } from "lib/woocomerce/woocommerce";
|
import { woocommerce } from 'lib/woocomerce/woocommerce';
|
||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
export async function POST(req: NextRequest) {
|
export async function POST(req: NextRequest) {
|
||||||
try {
|
try {
|
||||||
|
@ -74,7 +74,7 @@ export default function CheckoutPage() {
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2 className="mt-2 text-2xl font-bold">Shipping info</h2>
|
<h2 className="mt-2 text-2xl font-bold">Shipping info</h2>
|
||||||
<form className="md:grid-cols-6 md:grid-rows-2 gap-4">
|
<form className="gap-4 md:grid-cols-6 md:grid-rows-2">
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<label
|
<label
|
||||||
htmlFor="address_1"
|
htmlFor="address_1"
|
||||||
|
@ -12,7 +12,7 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
const handleLogin = async (event: React.FormEvent) => {
|
const handleLogin = async (event: React.FormEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const res = await signIn('credentials', { username, password, redirect: false, });
|
const res = await signIn('credentials', { username, password, redirect: false });
|
||||||
if (res?.ok) {
|
if (res?.ok) {
|
||||||
router.replace('/');
|
router.replace('/');
|
||||||
} else {
|
} else {
|
||||||
@ -23,7 +23,7 @@ export default function LoginPage() {
|
|||||||
return (
|
return (
|
||||||
<section className="mx-auto mt-4 grid max-w-screen-2xl justify-center gap-4 px-4 pb-4">
|
<section className="mx-auto mt-4 grid max-w-screen-2xl justify-center gap-4 px-4 pb-4">
|
||||||
<h1 className="text-2xl font-bold">Login</h1>
|
<h1 className="text-2xl font-bold">Login</h1>
|
||||||
<div className="flex flex-col h-screen w-full max-w-md">
|
<div className="flex h-screen w-full max-w-md flex-col">
|
||||||
{error && <p className="text-red-500">{error}</p>}
|
{error && <p className="text-red-500">{error}</p>}
|
||||||
<form onSubmit={handleLogin}>
|
<form onSubmit={handleLogin}>
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
@ -67,7 +67,7 @@ export default function LoginPage() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span className="block mt-6 text-center text-sm text-gray-600 dark:text-gray-300">
|
<span className="mt-6 block text-center text-sm text-gray-600 dark:text-gray-300">
|
||||||
Don't have an account?{' '}
|
Don't have an account?{' '}
|
||||||
<a href="/signup" className="text-indigo-600 hover:underline">
|
<a href="/signup" className="text-indigo-600 hover:underline">
|
||||||
Sign up
|
Sign up
|
||||||
|
@ -101,9 +101,9 @@ export default async function ProductPage(props: { params: Promise<{ name: strin
|
|||||||
</Suspense>
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<ProductDescription product={product} variations={variations}/>
|
<ProductDescription product={product} variations={variations} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
<AddToCart product={product} variations={variations}/>
|
<AddToCart product={product} variations={variations} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,8 +16,7 @@ export default function SearchLayout({ children }: { children: React.ReactNode }
|
|||||||
<ChildrenWrapper>{children}</ChildrenWrapper>
|
<ChildrenWrapper>{children}</ChildrenWrapper>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
<div className="order-none flex-none md:order-last md:w-[100px]">
|
<div className="order-none flex-none md:order-last md:w-[100px]"></div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
|
@ -15,7 +15,11 @@ export default async function SearchPage(props: {
|
|||||||
const { sort, q: searchValue } = searchParams as { [key: string]: string };
|
const { sort, q: searchValue } = searchParams as { [key: string]: string };
|
||||||
const { sortKey, order } = sorting.find((item) => item.slug === sort) || defaultSort;
|
const { sortKey, order } = sorting.find((item) => item.slug === sort) || defaultSort;
|
||||||
|
|
||||||
const products = await woocommerce.get('products', { search: searchValue, orderby: sortKey, order });
|
const products = await woocommerce.get('products', {
|
||||||
|
search: searchValue,
|
||||||
|
orderby: sortKey,
|
||||||
|
order
|
||||||
|
});
|
||||||
const resultsText = products.length > 1 ? 'results' : 'result';
|
const resultsText = products.length > 1 ? 'results' : 'result';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -4,21 +4,23 @@ import { useState } from 'react';
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
type FormData = {
|
type FormData = {
|
||||||
username: string;
|
username: string;
|
||||||
email: string;
|
email: string;
|
||||||
password: string;
|
password: string;
|
||||||
confirmPassword: string;
|
confirmPassword: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
const customerSchema = z.object({
|
const customerSchema = z
|
||||||
|
.object({
|
||||||
username: z.string().min(3),
|
username: z.string().min(3),
|
||||||
email: z.string().email({ message: "Invalid email" }),
|
email: z.string().email({ message: 'Invalid email' }),
|
||||||
password: z.string(),
|
password: z.string(),
|
||||||
confirmPassword: z.string(),
|
confirmPassword: z.string()
|
||||||
}).refine((data) => data.password === data.confirmPassword, {
|
})
|
||||||
|
.refine((data) => data.password === data.confirmPassword, {
|
||||||
message: "Passwords don't match",
|
message: "Passwords don't match",
|
||||||
path: ["confirmPassword"],
|
path: ['confirmPassword']
|
||||||
});;
|
});
|
||||||
|
|
||||||
export default function SignUpPage() {
|
export default function SignUpPage() {
|
||||||
const initialState = { username: '', email: '', password: '', confirmPassword: '' };
|
const initialState = { username: '', email: '', password: '', confirmPassword: '' };
|
||||||
@ -27,7 +29,7 @@ export default function SignUpPage() {
|
|||||||
|
|
||||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setFormData((prev) => ({ ...prev, [e.target.name]: e.target.value }));
|
setFormData((prev) => ({ ...prev, [e.target.name]: e.target.value }));
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleSignup = async (event: React.FormEvent) => {
|
const handleSignup = async (event: React.FormEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -37,22 +39,22 @@ export default function SignUpPage() {
|
|||||||
await fetch('/api/customer', {
|
await fetch('/api/customer', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
username: formData.username,
|
username: formData.username,
|
||||||
first_name: '',
|
first_name: '',
|
||||||
last_name: '',
|
last_name: '',
|
||||||
email: formData.email,
|
email: formData.email,
|
||||||
password: formData.password
|
password: formData.password
|
||||||
}),
|
})
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof z.ZodError) {
|
if (error instanceof z.ZodError) {
|
||||||
const errorObj: FormData = initialState;
|
const errorObj: FormData = initialState;
|
||||||
error.errors.forEach((err) => {
|
error.errors.forEach((err) => {
|
||||||
const key = err.path[0] as keyof FormData;
|
const key = err.path[0] as keyof FormData;
|
||||||
errorObj[key] = err.message as string;
|
errorObj[key] = err.message as string;
|
||||||
});
|
});
|
||||||
console.log(errorObj);
|
console.log(errorObj);
|
||||||
setError(errorObj);
|
setError(errorObj);
|
||||||
|
@ -10,7 +10,7 @@ export default function LogoutButton() {
|
|||||||
className="w-full rounded-md bg-indigo-500 p-3 text-white"
|
className="w-full rounded-md bg-indigo-500 p-3 text-white"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
signOut({ redirect: false });
|
signOut({ redirect: false });
|
||||||
router.replace('/')
|
router.replace('/');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Logout
|
Logout
|
||||||
|
@ -6,12 +6,16 @@ import { useProduct } from 'components/product/product-context';
|
|||||||
import { Product, ProductVariations } from 'lib/woocomerce/models/product';
|
import { Product, ProductVariations } from 'lib/woocomerce/models/product';
|
||||||
import { useCart } from './cart-context';
|
import { useCart } from './cart-context';
|
||||||
|
|
||||||
function SubmitButton({disabled = false}: {disabled: boolean}) {
|
function SubmitButton({ disabled = false }: { disabled: boolean }) {
|
||||||
const buttonClasses =
|
const buttonClasses =
|
||||||
'relative flex w-full items-center justify-center rounded-full bg-blue-600 p-4 tracking-wide text-white';
|
'relative flex w-full items-center justify-center rounded-full bg-blue-600 p-4 tracking-wide text-white';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button aria-label="Please select an option" disabled={disabled} className={clsx(buttonClasses, disabled ? 'opacity-50 cursor-not-allowed' : '')}>
|
<button
|
||||||
|
aria-label="Please select an option"
|
||||||
|
disabled={disabled}
|
||||||
|
className={clsx(buttonClasses, disabled ? 'cursor-not-allowed opacity-50' : '')}
|
||||||
|
>
|
||||||
<div className="absolute left-0 ml-4">
|
<div className="absolute left-0 ml-4">
|
||||||
<PlusIcon className="h-5" />
|
<PlusIcon className="h-5" />
|
||||||
</div>
|
</div>
|
||||||
@ -20,11 +24,20 @@ function SubmitButton({disabled = false}: {disabled: boolean}) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AddToCart({ product, variations }: { product: Product, variations?: ProductVariations[] }) {
|
export function AddToCart({
|
||||||
|
product,
|
||||||
|
variations
|
||||||
|
}: {
|
||||||
|
product: Product;
|
||||||
|
variations?: ProductVariations[];
|
||||||
|
}) {
|
||||||
const { setNewCart } = useCart();
|
const { setNewCart } = useCart();
|
||||||
const { state } = useProduct();
|
const { state } = useProduct();
|
||||||
const productVariant = variations?.find((variation) => variation.id.toString() === state.variation);
|
const productVariant = variations?.find(
|
||||||
const variation = productVariant?.attributes.map((attr) => ({ attribute: attr.name, value: attr.option })) || [];
|
(variation) => variation.id.toString() === state.variation
|
||||||
|
);
|
||||||
|
const variation =
|
||||||
|
productVariant?.attributes.map((attr) => ({ attribute: attr.name, value: attr.option })) || [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
@ -42,7 +55,7 @@ export function AddToCart({ product, variations }: { product: Product, variation
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SubmitButton disabled={variations?.length && !state.variation ? true : false}/>
|
<SubmitButton disabled={variations?.length && !state.variation ? true : false} />
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ export function CartProvider({ children }: { children: React.ReactNode }) {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchCart();
|
fetchCart();
|
||||||
|
@ -10,7 +10,6 @@ type Menu = {
|
|||||||
path: string;
|
path: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export function FooterMenuItem({ item }: { item: Menu }) {
|
export function FooterMenuItem({ item }: { item: Menu }) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const [active, setActive] = useState(pathname === item.path);
|
const [active, setActive] = useState(pathname === item.path);
|
||||||
|
@ -24,10 +24,10 @@ export default async function Footer() {
|
|||||||
title: 'Shop',
|
title: 'Shop',
|
||||||
path: '/shop'
|
path: '/shop'
|
||||||
},
|
},
|
||||||
...categories.map((category) => ({
|
...categories.map((category) => ({
|
||||||
title: category.name,
|
title: category.name,
|
||||||
path: path.join('/collection', category.id.toString())
|
path: path.join('/collection', category.id.toString())
|
||||||
}))
|
}))
|
||||||
] as Menu[];
|
] as Menu[];
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
const copyrightDate = 2023 + (currentYear > 2023 ? `-${currentYear}` : '');
|
const copyrightDate = 2023 + (currentYear > 2023 ? `-${currentYear}` : '');
|
||||||
|
@ -14,15 +14,15 @@ function FilterItemList({ list }: { list: ListItem[] }) {
|
|||||||
{list.map((item: ListItem, i) => (
|
{list.map((item: ListItem, i) => (
|
||||||
<FilterItem key={i} item={item} />
|
<FilterItem key={i} item={item} />
|
||||||
))}
|
))}
|
||||||
<Slider
|
<Slider
|
||||||
className="max-w-md"
|
className="max-w-md"
|
||||||
defaultValue={[100, 500]}
|
defaultValue={[100, 500]}
|
||||||
formatOptions={{style: "currency", currency: "USD"}}
|
formatOptions={{ style: 'currency', currency: 'USD' }}
|
||||||
label="Price Range"
|
label="Price Range"
|
||||||
maxValue={1000}
|
maxValue={1000}
|
||||||
minValue={0}
|
minValue={0}
|
||||||
step={50}
|
step={50}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,5 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const NextAuthProvider = ({ children }: Props) => {
|
export const NextAuthProvider = ({ children }: Props) => {
|
||||||
|
|
||||||
return <SessionProvider>{children}</SessionProvider>;
|
return <SessionProvider>{children}</SessionProvider>;
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,7 @@ type ProductState = {
|
|||||||
image?: string;
|
image?: string;
|
||||||
} & {
|
} & {
|
||||||
variation?: string;
|
variation?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
type ProductContextType = {
|
type ProductContextType = {
|
||||||
state: ProductState;
|
state: ProductState;
|
||||||
@ -55,7 +55,7 @@ export function ProductProvider({ children }: { children: React.ReactNode }) {
|
|||||||
const newState = { variation };
|
const newState = { variation };
|
||||||
setOptimisticState(newState);
|
setOptimisticState(newState);
|
||||||
return { ...state, ...newState };
|
return { ...state, ...newState };
|
||||||
}
|
};
|
||||||
|
|
||||||
const value = useMemo(
|
const value = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
@ -4,15 +4,26 @@ import Prose from 'components/prose';
|
|||||||
import { Product, ProductVariations } from 'lib/woocomerce/models/product';
|
import { Product, ProductVariations } from 'lib/woocomerce/models/product';
|
||||||
import { useProduct } from './product-context';
|
import { useProduct } from './product-context';
|
||||||
|
|
||||||
export function ProductDescription({ product, variations }: { product: Product, variations?: ProductVariations[] }) {
|
export function ProductDescription({
|
||||||
|
product,
|
||||||
|
variations
|
||||||
|
}: {
|
||||||
|
product: Product;
|
||||||
|
variations?: ProductVariations[];
|
||||||
|
}) {
|
||||||
const { state } = useProduct();
|
const { state } = useProduct();
|
||||||
const productVariant = variations?.find((variation) => variation.id.toString() === state.variation);
|
const productVariant = variations?.find(
|
||||||
|
(variation) => variation.id.toString() === state.variation
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mb-6 flex flex-col border-b pb-6 dark:border-neutral-700">
|
<div className="mb-6 flex flex-col border-b pb-6 dark:border-neutral-700">
|
||||||
<div className="mr-auto w-auto rounded-full bg-blue-600 p-2 text-sm text-white">
|
<div className="mr-auto w-auto rounded-full bg-blue-600 p-2 text-sm text-white">
|
||||||
<Price amount={productVariant ? productVariant.price : product.price} currencyCode="EUR" />
|
<Price
|
||||||
|
amount={productVariant ? productVariant.price : product.price}
|
||||||
|
currencyCode="EUR"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{product.description ? (
|
{product.description ? (
|
||||||
|
@ -5,7 +5,6 @@ import { useProduct, useUpdateURL } from 'components/product/product-context';
|
|||||||
import { Attribute } from 'lib/woocomerce/models/base';
|
import { Attribute } from 'lib/woocomerce/models/base';
|
||||||
import { ProductVariations } from 'lib/woocomerce/models/product';
|
import { ProductVariations } from 'lib/woocomerce/models/product';
|
||||||
|
|
||||||
|
|
||||||
type FilterVariation = {
|
type FilterVariation = {
|
||||||
name: string | undefined;
|
name: string | undefined;
|
||||||
values: string[] | undefined;
|
values: string[] | undefined;
|
||||||
@ -13,7 +12,7 @@ type FilterVariation = {
|
|||||||
|
|
||||||
export function VariantSelector({
|
export function VariantSelector({
|
||||||
options,
|
options,
|
||||||
variations,
|
variations
|
||||||
}: {
|
}: {
|
||||||
options: Partial<Attribute>[];
|
options: Partial<Attribute>[];
|
||||||
variations: ProductVariations[];
|
variations: ProductVariations[];
|
||||||
@ -21,9 +20,9 @@ export function VariantSelector({
|
|||||||
const { state, updateOption } = useProduct();
|
const { state, updateOption } = useProduct();
|
||||||
const updateURL = useUpdateURL();
|
const updateURL = useUpdateURL();
|
||||||
|
|
||||||
const combinations: FilterVariation[] = options?.map(attribute => ({
|
const combinations: FilterVariation[] = options?.map((attribute) => ({
|
||||||
name: attribute.name,
|
name: attribute.name,
|
||||||
values: attribute?.options?.map(option => option),
|
values: attribute?.options?.map((option) => option)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return combinations.map((option) => (
|
return combinations.map((option) => (
|
||||||
@ -41,12 +40,21 @@ export function VariantSelector({
|
|||||||
formAction={() => {
|
formAction={() => {
|
||||||
if (!optionNameLowerCase) return;
|
if (!optionNameLowerCase) return;
|
||||||
let newState = updateOption(optionNameLowerCase, value);
|
let newState = updateOption(optionNameLowerCase, value);
|
||||||
const keys = Object.keys(newState).filter((key) => key !== 'id' && key !== 'image' && key !== 'variation');
|
const keys = Object.keys(newState).filter(
|
||||||
const variant = variations.find((variation) => {
|
(key) => key !== 'id' && key !== 'image' && key !== 'variation'
|
||||||
return variation?.attributes?.every((attr) => attr.name && keys.includes(attr.name) && newState[attr.name] === attr.option);
|
);
|
||||||
})?.id?.toString();
|
const variant = variations
|
||||||
|
.find((variation) => {
|
||||||
|
return variation?.attributes?.every(
|
||||||
|
(attr) =>
|
||||||
|
attr.name &&
|
||||||
|
keys.includes(attr.name) &&
|
||||||
|
newState[attr.name] === attr.option
|
||||||
|
);
|
||||||
|
})
|
||||||
|
?.id?.toString();
|
||||||
if (variant) {
|
if (variant) {
|
||||||
newState = {...newState, variation: variant};
|
newState = { ...newState, variation: variant };
|
||||||
}
|
}
|
||||||
updateURL(newState);
|
updateURL(newState);
|
||||||
}}
|
}}
|
||||||
@ -59,7 +67,7 @@ export function VariantSelector({
|
|||||||
'ring-1 ring-transparent transition duration-300 ease-in-out hover:ring-blue-600':
|
'ring-1 ring-transparent transition duration-300 ease-in-out hover:ring-blue-600':
|
||||||
!isActive,
|
!isActive,
|
||||||
'relative z-10 cursor-not-allowed overflow-hidden bg-neutral-100 text-neutral-500 ring-1 ring-neutral-300 before:absolute before:inset-x-0 before:-z-10 before:h-px before:-rotate-45 before:bg-neutral-300 before:transition-transform dark:bg-neutral-900 dark:text-neutral-400 dark:ring-neutral-700 before:dark:bg-neutral-700':
|
'relative z-10 cursor-not-allowed overflow-hidden bg-neutral-100 text-neutral-500 ring-1 ring-neutral-300 before:absolute before:inset-x-0 before:-z-10 before:h-px before:-rotate-45 before:bg-neutral-300 before:transition-transform dark:bg-neutral-900 dark:text-neutral-400 dark:ring-neutral-700 before:dark:bg-neutral-700':
|
||||||
''
|
''
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
@ -42,7 +42,7 @@ export const authOptions = {
|
|||||||
console.debug('Set session token', token.user);
|
console.debug('Set session token', token.user);
|
||||||
session.user = token.user;
|
session.user = token.user;
|
||||||
return session;
|
return session;
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
async signIn() {
|
async signIn() {
|
||||||
|
@ -226,7 +226,9 @@ export default class WooCommerceRestApi<T extends WooRestApiOptions> {
|
|||||||
|
|
||||||
const queryParams: string[] = [];
|
const queryParams: string[] = [];
|
||||||
for (const key in params) {
|
for (const key in params) {
|
||||||
queryParams.push(`${encodeURIComponent(key)}=${encodeURIComponent(params[key] as string | number | boolean)}`);
|
queryParams.push(
|
||||||
|
`${encodeURIComponent(key)}=${encodeURIComponent(params[key] as string | number | boolean)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryParams.length > 0) {
|
if (queryParams.length > 0) {
|
||||||
|
@ -15,12 +15,12 @@ export type OrderPayload = {
|
|||||||
payment_method: string;
|
payment_method: string;
|
||||||
payment_data?: PaymentMethodData[];
|
payment_data?: PaymentMethodData[];
|
||||||
customer_note?: string;
|
customer_note?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type PaymentMethodData = {
|
export type PaymentMethodData = {
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
class WooCommerceStoreApiClient {
|
class WooCommerceStoreApiClient {
|
||||||
private client: AxiosInstance;
|
private client: AxiosInstance;
|
||||||
@ -53,7 +53,6 @@ class WooCommerceStoreApiClient {
|
|||||||
this.client.defaults.headers['cart-token'] = cartToken;
|
this.client.defaults.headers['cart-token'] = cartToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async getCart(params?: Record<string, string | number>): Promise<Cart> {
|
async getCart(params?: Record<string, string | number>): Promise<Cart> {
|
||||||
return this.client.get<Cart>('/cart', { params }).then(async (response) => {
|
return this.client.get<Cart>('/cart', { params }).then(async (response) => {
|
||||||
this._seCartToken(response.headers['cart-token']);
|
this._seCartToken(response.headers['cart-token']);
|
||||||
@ -94,6 +93,7 @@ class WooCommerceStoreApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Example usage.
|
// Example usage.
|
||||||
const baseURL = process.env.WOOCOMMERCE_STORE_API_URL ?? 'http://wordpress.localhost/wp-json/wc/store/v1';
|
const baseURL =
|
||||||
|
process.env.WOOCOMMERCE_STORE_API_URL ?? 'http://wordpress.localhost/wp-json/wc/store/v1';
|
||||||
|
|
||||||
export const storeApi = new WooCommerceStoreApiClient(baseURL);
|
export const storeApi = new WooCommerceStoreApiClient(baseURL);
|
||||||
|
@ -2,10 +2,8 @@ import WooCommerceRestApi, { WooRestApiOptions } from './models/client';
|
|||||||
|
|
||||||
const option: WooRestApiOptions = {
|
const option: WooRestApiOptions = {
|
||||||
url: process.env.WOOCOMMERCE_URL ?? 'http://wordpress.localhost',
|
url: process.env.WOOCOMMERCE_URL ?? 'http://wordpress.localhost',
|
||||||
consumerKey:
|
consumerKey: process.env.WOOCOMMERCE_CONSUMER_KEY ?? '',
|
||||||
process.env.WOOCOMMERCE_CONSUMER_KEY ?? '',
|
consumerSecret: process.env.WOOCOMMERCE_CONSUMER_SECRET ?? '',
|
||||||
consumerSecret:
|
|
||||||
process.env.WOOCOMMERCE_CONSUMER_SECRET ?? '',
|
|
||||||
isHttps: false,
|
isHttps: false,
|
||||||
version: 'wc/v3',
|
version: 'wc/v3',
|
||||||
queryStringAuth: false // Force Basic Authentication as query string true and using under
|
queryStringAuth: false // Force Basic Authentication as query string true and using under
|
||||||
|
2291
pnpm-lock.yaml
generated
2291
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user