mirror of
https://github.com/vercel/commerce.git
synced 2025-06-12 19:01:22 +00:00
Merge branch 'main' of https://github.com/vercel/commerce into turbo
This commit is contained in:
commit
0c8c668fdd
@ -146,7 +146,7 @@ If your project was started with a "Deploy with Vercel" button, you can use Verc
|
|||||||
2. Link local instance with Vercel and Github accounts (creates .vercel file): `vercel link`
|
2. Link local instance with Vercel and Github accounts (creates .vercel file): `vercel link`
|
||||||
3. Download your environment variables: `vercel env pull .env.local`
|
3. Download your environment variables: `vercel env pull .env.local`
|
||||||
|
|
||||||
Next, you're free to customize the starter. More updates coming soon. Stay tuned.
|
Next, you're free to customize the starter. More updates coming soon. Stay tuned..
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
24506
package-lock.json
generated
24506
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -27,15 +27,15 @@ export const handler: MutationHook<LoginHook> = {
|
|||||||
useHook:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { revalidate } = useCustomer()
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function login(input) {
|
async function login(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -32,15 +32,15 @@ export const handler: MutationHook<SignupHook> = {
|
|||||||
useHook:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { revalidate } = useCustomer()
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function signup(input) {
|
async function signup(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ export const handler: MutationHook<AddItemHook> = {
|
|||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { data: customer } = useCustomer()
|
const { data: customer } = useCustomer()
|
||||||
const { revalidate } = useWishlist()
|
const { mutate } = useWishlist()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function addItem(item) {
|
async function addItem(item) {
|
||||||
@ -30,10 +30,10 @@ export const handler: MutationHook<AddItemHook> = {
|
|||||||
|
|
||||||
// TODO: add validations before doing the fetch
|
// TODO: add validations before doing the fetch
|
||||||
const data = await fetch({ input: { item } })
|
const data = await fetch({ input: { item } })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate, customer]
|
[fetch, mutate, customer]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ export const handler: MutationHook<RemoveItemHook> = {
|
|||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
({ wishlist } = {}) => {
|
({ wishlist } = {}) => {
|
||||||
const { data: customer } = useCustomer()
|
const { data: customer } = useCustomer()
|
||||||
const { revalidate } = useWishlist(wishlist)
|
const { mutate } = useWishlist(wishlist)
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function removeItem(input) {
|
async function removeItem(input) {
|
||||||
@ -31,10 +31,10 @@ export const handler: MutationHook<RemoveItemHook> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await fetch({ input: { itemId: String(input.id) } })
|
const data = await fetch({ input: { itemId: String(input.id) } })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate, customer]
|
[fetch, mutate, customer]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { ConfigInterface } from 'swr'
|
import type { SWRConfiguration } from 'swr'
|
||||||
import type { CommerceError } from './errors'
|
import type { CommerceError } from './errors'
|
||||||
import type { ResponseState } from './use-data'
|
import type { ResponseState } from './use-data'
|
||||||
|
|
||||||
@ -10,10 +10,9 @@ export type Override<T, K> = Omit<T, keyof K> & K
|
|||||||
/**
|
/**
|
||||||
* Returns the properties in T with the properties in type K changed from optional to required
|
* Returns the properties in T with the properties in type K changed from optional to required
|
||||||
*/
|
*/
|
||||||
export type PickRequired<T, K extends keyof T> = Omit<T, K> &
|
export type PickRequired<T, K extends keyof T> = Omit<T, K> & {
|
||||||
{
|
[P in K]-?: NonNullable<T[P]>
|
||||||
[P in K]-?: NonNullable<T[P]>
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Core fetcher added by CommerceProvider
|
* Core fetcher added by CommerceProvider
|
||||||
@ -141,7 +140,7 @@ export type MutationHookContext<H extends MutationSchemaBase> = {
|
|||||||
: (context: { input: H['fetcherInput'] }) => H['data'] | Promise<H['data']>
|
: (context: { input: H['fetcherInput'] }) => H['data'] | Promise<H['data']>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SwrOptions<Data, Input = null, Result = any> = ConfigInterface<
|
export type SwrOptions<Data, Input = null, Result = any> = SWRConfiguration<
|
||||||
Data,
|
Data,
|
||||||
CommerceError,
|
CommerceError,
|
||||||
HookFetcher<Data, Input, Result>
|
HookFetcher<Data, Input, Result>
|
||||||
|
@ -18,7 +18,7 @@ export default function getAllProductsOperation({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const productsFormatted =
|
const productsFormatted =
|
||||||
data?.map((product) => normalizeProduct(product)) || []
|
data?.map((product: any) => normalizeProduct(product)) || []
|
||||||
|
|
||||||
return {
|
return {
|
||||||
products: productsFormatted,
|
products: productsFormatted,
|
||||||
|
@ -12,8 +12,10 @@ export default async function sdkFetch<
|
|||||||
>(
|
>(
|
||||||
resource: Resource,
|
resource: Resource,
|
||||||
method: Method,
|
method: Method,
|
||||||
...variables: Parameters<Commerce[Resource][Method]>
|
...variables: Parameters<Commerce[Resource][Method] | any>
|
||||||
): Promise<ReturnType<Commerce[Resource][Method]>> {
|
): Promise<ReturnType<Commerce[Resource][Method] | any>> {
|
||||||
|
//@ts-ignore
|
||||||
|
// Provider TODO: Fix types here.
|
||||||
const data = await commerce[resource][method](...variables)
|
const data = await commerce[resource][method](...variables)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,12 @@ export default useLogin as UseLogin<typeof handler>
|
|||||||
export const handler: MutationHook<LoginHook> = {
|
export const handler: MutationHook<LoginHook> = {
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
url: '/api/login',
|
url: '/api/login',
|
||||||
method: 'POST'
|
method: 'POST',
|
||||||
},
|
},
|
||||||
async fetcher({ input: { email, password }, options, fetch }) {
|
async fetcher({ input: { email, password }, options, fetch }) {
|
||||||
if (!(email && password)) {
|
if (!(email && password)) {
|
||||||
throw new CommerceError({
|
throw new CommerceError({
|
||||||
message:
|
message: 'An email and password are required to login',
|
||||||
'An email and password are required to login',
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,17 +25,19 @@ export const handler: MutationHook<LoginHook> = {
|
|||||||
body: { email, password },
|
body: { email, password },
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
useHook: ({ fetch }) => () => {
|
useHook:
|
||||||
const { revalidate } = useCustomer()
|
({ fetch }) =>
|
||||||
const {revalidate: revalidateCart} = useCart()
|
() => {
|
||||||
return useCallback(
|
const { mutate } = useCustomer()
|
||||||
async function login(input) {
|
const { mutate: mutateCart } = useCart()
|
||||||
const data = await fetch({ input })
|
return useCallback(
|
||||||
await revalidate()
|
async function login(input) {
|
||||||
await revalidateCart()
|
const data = await fetch({ input })
|
||||||
return data
|
await mutate()
|
||||||
},
|
await mutateCart()
|
||||||
[fetch, revalidate, revalidateCart]
|
return data
|
||||||
)
|
},
|
||||||
},
|
[fetch, mutate, mutateCart]
|
||||||
|
)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,18 @@ export const handler: MutationHook<SignupHook> = {
|
|||||||
body: { firstName, lastName, email, password },
|
body: { firstName, lastName, email, password },
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
useHook: ({ fetch }) => () => {
|
useHook:
|
||||||
const { revalidate } = useCustomer()
|
({ fetch }) =>
|
||||||
|
() => {
|
||||||
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function signup(input) {
|
async function signup(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -13,24 +13,26 @@ export const handler: MutationHook<AddItemHook> = {
|
|||||||
url: '/api/wishlist',
|
url: '/api/wishlist',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
},
|
},
|
||||||
useHook: ({ fetch }) => () => {
|
useHook:
|
||||||
const { data: customer } = useCustomer()
|
({ fetch }) =>
|
||||||
const { revalidate } = useWishlist()
|
() => {
|
||||||
|
const { data: customer } = useCustomer()
|
||||||
|
const { mutate } = useWishlist()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function addItem(item) {
|
async function addItem(item) {
|
||||||
if (!customer) {
|
if (!customer) {
|
||||||
// A signed customer is required in order to have a wishlist
|
// A signed customer is required in order to have a wishlist
|
||||||
throw new CommerceError({
|
throw new CommerceError({
|
||||||
message: 'Signed customer not found',
|
message: 'Signed customer not found',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// TODO: add validations before doing the fetch
|
// TODO: add validations before doing the fetch
|
||||||
const data = await fetch({ input: { item } })
|
const data = await fetch({ input: { item } })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate, customer]
|
[fetch, mutate, customer]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -15,24 +15,26 @@ export const handler: MutationHook<RemoveItemHook> = {
|
|||||||
url: '/api/wishlist',
|
url: '/api/wishlist',
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
},
|
},
|
||||||
useHook: ({ fetch }) => ({ wishlist } = {}) => {
|
useHook:
|
||||||
const { data: customer } = useCustomer()
|
({ fetch }) =>
|
||||||
const { revalidate } = useWishlist(wishlist)
|
({ wishlist } = {}) => {
|
||||||
|
const { data: customer } = useCustomer()
|
||||||
|
const { mutate } = useWishlist(wishlist)
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function removeItem(input) {
|
async function removeItem(input) {
|
||||||
if (!customer) {
|
if (!customer) {
|
||||||
// A signed customer is required in order to have a wishlist
|
// A signed customer is required in order to have a wishlist
|
||||||
throw new CommerceError({
|
throw new CommerceError({
|
||||||
message: 'Signed customer not found',
|
message: 'Signed customer not found',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await fetch({ input: { itemId: String(input.id) } })
|
const data = await fetch({ input: { itemId: String(input.id) } })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate, customer]
|
[fetch, mutate, customer]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -49,15 +49,15 @@ export const handler: MutationHook<LoginHook> = {
|
|||||||
useHook:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { revalidate } = useCustomer()
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function login(input) {
|
async function login(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -42,15 +42,15 @@ export const handler: MutationHook<SignupHook> = {
|
|||||||
useHook:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { revalidate } = useCustomer()
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function signup(input) {
|
async function signup(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -49,15 +49,15 @@ export const handler: MutationHook<LoginHook> = {
|
|||||||
useHook:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { revalidate } = useCustomer()
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function login(input) {
|
async function login(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -53,15 +53,15 @@ export const handler: MutationHook<SignupHook> = {
|
|||||||
useHook:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { revalidate } = useCustomer()
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function signup(input) {
|
async function signup(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ An integration of [Spree Commerce](https://spreecommerce.org/) within NextJS Com
|
|||||||
- They rely on [taxonomies'](https://dev-docs.spreecommerce.org/internals/products#taxons-and-taxonomies) permalinks in Spree.
|
- They rely on [taxonomies'](https://dev-docs.spreecommerce.org/internals/products#taxons-and-taxonomies) permalinks in Spree.
|
||||||
- Go to the Spree admin panel and create `Categories` and `Brands` taxonomies if they don't exist and copy their permalinks into `.env.local` in NextJS Commerce.
|
- Go to the Spree admin panel and create `Categories` and `Brands` taxonomies if they don't exist and copy their permalinks into `.env.local` in NextJS Commerce.
|
||||||
|
|
||||||
1. Finally, run `yarn dev` :tada:
|
1. Finally, run `npm run dev` :tada:
|
||||||
|
|
||||||
[1]: https://spreecommerce.org/
|
[1]: https://spreecommerce.org/
|
||||||
[2]: https://github.com/vercel/commerce
|
[2]: https://github.com/vercel/commerce
|
||||||
|
@ -71,9 +71,9 @@ export const handler: MutationHook<LoginHook> = {
|
|||||||
async function login(input) {
|
async function login(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
|
|
||||||
await customer.revalidate()
|
await customer.mutate()
|
||||||
await cart.revalidate()
|
await cart.mutate()
|
||||||
await wishlist.revalidate()
|
await wishlist.mutate()
|
||||||
|
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
|
@ -81,9 +81,9 @@ export const handler: MutationHook<SignupHook> = {
|
|||||||
async (input) => {
|
async (input) => {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
|
|
||||||
await customer.revalidate()
|
await customer.mutate()
|
||||||
await cart.revalidate()
|
await cart.mutate()
|
||||||
await wishlist.revalidate()
|
await wishlist.mutate()
|
||||||
|
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
|
@ -75,7 +75,7 @@ export const handler: MutationHook<ExplicitWishlistAddItemHook> = {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await wishlist.revalidate()
|
await wishlist.mutate()
|
||||||
|
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
|
@ -62,7 +62,7 @@ export const handler: MutationHook<ExplicitWishlistRemoveItemHook> = {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await wishlist.revalidate()
|
await wishlist.mutate()
|
||||||
|
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
|
@ -62,15 +62,15 @@ export const handler: MutationHook<LoginHook> = {
|
|||||||
useHook:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { revalidate } = useCustomer()
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function login(input) {
|
async function login(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -47,15 +47,15 @@ export const handler: MutationHook<SignupHook> = {
|
|||||||
useHook:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { revalidate } = useCustomer()
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function signup(input) {
|
async function signup(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -39,15 +39,15 @@ export const handler: MutationHook<LoginHook> = {
|
|||||||
useHook:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { revalidate } = useCustomer()
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function login(input) {
|
async function login(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -57,15 +57,15 @@ export const handler: MutationHook<SignupHook> = {
|
|||||||
useHook:
|
useHook:
|
||||||
({ fetch }) =>
|
({ fetch }) =>
|
||||||
() => {
|
() => {
|
||||||
const { revalidate } = useCustomer()
|
const { mutate } = useCustomer()
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function signup(input) {
|
async function signup(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await revalidate()
|
await mutate()
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
[fetch, revalidate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,7 @@ import useLogin from '@framework/auth/use-login'
|
|||||||
import { useUI } from '@components/ui/context'
|
import { useUI } from '@components/ui/context'
|
||||||
import { validate } from 'email-validator'
|
import { validate } from 'email-validator'
|
||||||
|
|
||||||
interface Props {}
|
const LoginView: React.FC = () => {
|
||||||
|
|
||||||
const LoginView: FC<Props> = () => {
|
|
||||||
// Form State
|
// Form State
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
@ -35,8 +33,8 @@ const LoginView: FC<Props> = () => {
|
|||||||
})
|
})
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
closeModal()
|
closeModal()
|
||||||
} catch ({ errors }) {
|
} catch (e: any) {
|
||||||
setMessage(errors[0].message)
|
setMessage(e.errors[0].message)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
setDisabled(false)
|
setDisabled(false)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import { useCheckoutContext } from '../context'
|
|||||||
const CheckoutSidebarView: FC = () => {
|
const CheckoutSidebarView: FC = () => {
|
||||||
const [loadingSubmit, setLoadingSubmit] = useState(false)
|
const [loadingSubmit, setLoadingSubmit] = useState(false)
|
||||||
const { setSidebarView, closeSidebar } = useUI()
|
const { setSidebarView, closeSidebar } = useUI()
|
||||||
const { data: cartData, revalidate: refreshCart } = useCart()
|
const { data: cartData, mutate: refreshCart } = useCart()
|
||||||
const { data: checkoutData, submit: onCheckout } = useCheckout()
|
const { data: checkoutData, submit: onCheckout } = useCheckout()
|
||||||
const { clearCheckoutFields } = useCheckoutContext()
|
const { clearCheckoutFields } = useCheckoutContext()
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
.root {
|
.root {
|
||||||
@apply text-center p-6 bg-primary text-sm flex-row justify-center items-center font-medium fixed bottom-0 w-full z-30 transition-all duration-300 ease-out;
|
@apply text-center p-6 bg-primary text-sm flex-row
|
||||||
|
justify-center items-center font-medium fixed bottom-0
|
||||||
@screen md {
|
w-full z-30 transition-all duration-300 ease-out
|
||||||
@apply flex text-left;
|
md:flex md:text-left;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,16 +16,6 @@
|
|||||||
|
|
||||||
.dropdownMenu {
|
.dropdownMenu {
|
||||||
@apply fixed right-0 top-12 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
|
@apply fixed right-0 top-12 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
|
||||||
|
|
||||||
@screen lg {
|
|
||||||
@apply absolute border border-accent-1 shadow-lg w-56 h-auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.closeButton {
|
|
||||||
@screen md {
|
|
||||||
@apply hidden;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
@ -44,3 +34,15 @@
|
|||||||
.icon.active {
|
.icon.active {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@screen lg {
|
||||||
|
.dropdownMenu {
|
||||||
|
@apply absolute border border-accent-1 shadow-lg w-56 h-auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@screen md {
|
||||||
|
.closeButton {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
.dropdownMenu {
|
@screen lg {
|
||||||
@apply fixed right-0 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
|
.dropdownMenu {
|
||||||
|
|
||||||
@screen lg {
|
|
||||||
@apply absolute top-10 border border-accent-1 shadow-lg w-56 h-auto;
|
@apply absolute top-10 border border-accent-1 shadow-lg w-56 h-auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdownMenu {
|
||||||
|
@apply fixed right-0 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
|
||||||
|
}
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
@apply text-primary flex cursor-pointer px-6 py-3 flex transition ease-in-out duration-150 leading-6 font-medium items-center;
|
@apply text-primary flex cursor-pointer px-6 py-3 flex transition ease-in-out duration-150 leading-6 font-medium items-center;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
|
@ -13,52 +13,50 @@ interface SwatchProps {
|
|||||||
label?: string | null
|
label?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const Swatch: React.FC<Omit<ButtonProps, 'variant'> & SwatchProps> = React.memo(
|
const Swatch: React.FC<Omit<ButtonProps, 'variant'> & SwatchProps> = ({
|
||||||
({
|
active,
|
||||||
active,
|
className,
|
||||||
className,
|
color = '',
|
||||||
color = '',
|
label = null,
|
||||||
label = null,
|
variant = 'size',
|
||||||
variant = 'size',
|
...props
|
||||||
...props
|
}) => {
|
||||||
}) => {
|
variant = variant?.toLowerCase()
|
||||||
variant = variant?.toLowerCase()
|
|
||||||
|
|
||||||
if (label) {
|
if (label) {
|
||||||
label = label?.toLowerCase()
|
label = label?.toLowerCase()
|
||||||
}
|
|
||||||
|
|
||||||
const swatchClassName = cn(
|
|
||||||
s.swatch,
|
|
||||||
{
|
|
||||||
[s.color]: color,
|
|
||||||
[s.active]: active,
|
|
||||||
[s.size]: variant === 'size',
|
|
||||||
[s.dark]: color ? isDark(color) : false,
|
|
||||||
[s.textLabel]: !color && label && label.length > 3,
|
|
||||||
},
|
|
||||||
className
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
role="option"
|
|
||||||
aria-selected={active}
|
|
||||||
aria-label={variant && label ? `${variant} ${label}` : 'Variant Swatch'}
|
|
||||||
className={swatchClassName}
|
|
||||||
{...(label && color && { title: label })}
|
|
||||||
style={color ? { backgroundColor: color } : {}}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{color && active && (
|
|
||||||
<span>
|
|
||||||
<Check />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{!color ? label : null}
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
export default Swatch
|
const swatchClassName = cn(
|
||||||
|
s.swatch,
|
||||||
|
{
|
||||||
|
[s.color]: color,
|
||||||
|
[s.active]: active,
|
||||||
|
[s.size]: variant === 'size',
|
||||||
|
[s.dark]: color ? isDark(color) : false,
|
||||||
|
[s.textLabel]: !color && label && label.length > 3,
|
||||||
|
},
|
||||||
|
className
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
role="option"
|
||||||
|
aria-selected={active}
|
||||||
|
aria-label={variant && label ? `${variant} ${label}` : 'Variant Swatch'}
|
||||||
|
className={swatchClassName}
|
||||||
|
{...(label && color && { title: label })}
|
||||||
|
style={color ? { backgroundColor: color } : {}}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{color && active && (
|
||||||
|
<span>
|
||||||
|
<Check />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{!color ? label : null}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(Swatch)
|
||||||
|
@ -21,6 +21,7 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/display-name
|
||||||
const Button: React.FC<ButtonProps> = forwardRef((props, buttonRef) => {
|
const Button: React.FC<ButtonProps> = forwardRef((props, buttonRef) => {
|
||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
|
@ -10,7 +10,7 @@ export interface CollapseProps {
|
|||||||
children: ReactNode
|
children: ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const Collapse: FC<CollapseProps> = React.memo(({ title, children }) => {
|
const Collapse: FC<CollapseProps> = ({ title, children }) => {
|
||||||
const [isActive, setActive] = useState(false)
|
const [isActive, setActive] = useState(false)
|
||||||
const [ref, { height: viewHeight }] = useMeasure()
|
const [ref, { height: viewHeight }] = useMeasure()
|
||||||
|
|
||||||
@ -41,6 +41,6 @@ const Collapse: FC<CollapseProps> = React.memo(({ title, children }) => {
|
|||||||
</a.div>
|
</a.div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
}
|
||||||
|
|
||||||
export default Collapse
|
export default React.memo(Collapse)
|
||||||
|
@ -1,53 +1,25 @@
|
|||||||
.root {
|
.root {
|
||||||
@apply grid grid-cols-1 gap-0;
|
@apply grid grid-cols-1 gap-0;
|
||||||
|
}
|
||||||
@screen lg {
|
.root > * {
|
||||||
@apply grid-cols-3 grid-rows-2;
|
@apply row-span-1 bg-transparent box-border overflow-hidden;
|
||||||
}
|
height: 500px;
|
||||||
|
max-height: 800px;
|
||||||
& > * {
|
|
||||||
@apply row-span-1 bg-transparent box-border overflow-hidden;
|
|
||||||
height: 500px;
|
|
||||||
max-height: 800px;
|
|
||||||
|
|
||||||
@screen lg {
|
|
||||||
@apply col-span-1;
|
|
||||||
height: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.default {
|
.default > * {
|
||||||
& > * {
|
@apply bg-transparent;
|
||||||
@apply bg-transparent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.layoutNormal {
|
.layoutNormal {
|
||||||
@apply gap-3;
|
@apply gap-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@screen md {
|
|
||||||
.layoutNormal > * {
|
|
||||||
max-height: min-content !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@screen lg {
|
|
||||||
.layoutNormal > * {
|
|
||||||
max-height: 400px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.layoutA {
|
.layoutA {
|
||||||
& > *:nth-child(6n + 1),
|
& > *:nth-child(6n + 1),
|
||||||
& > *:nth-child(6n + 5) {
|
& > *:nth-child(6n + 5) {
|
||||||
@apply row-span-2;
|
@apply row-span-2 lg:col-span-2;
|
||||||
height: var(--row-height);
|
height: var(--row-height);
|
||||||
|
|
||||||
@screen lg {
|
|
||||||
@apply col-span-2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.filled {
|
&.filled {
|
||||||
@ -72,12 +44,8 @@
|
|||||||
.layoutB {
|
.layoutB {
|
||||||
& > *:nth-child(6n + 2),
|
& > *:nth-child(6n + 2),
|
||||||
& > *:nth-child(6n + 4) {
|
& > *:nth-child(6n + 4) {
|
||||||
@apply row-span-2;
|
@apply row-span-2 lg:col-span-2;
|
||||||
height: var(--row-height);
|
height: var(--row-height);
|
||||||
|
|
||||||
@screen lg {
|
|
||||||
@apply col-span-2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.filled {
|
&.filled {
|
||||||
@ -102,12 +70,8 @@
|
|||||||
.layoutC {
|
.layoutC {
|
||||||
& > *:nth-child(12n + 1),
|
& > *:nth-child(12n + 1),
|
||||||
& > *:nth-child(12n + 8) {
|
& > *:nth-child(12n + 8) {
|
||||||
@apply row-span-2;
|
@apply row-span-2 lg:col-span-2;
|
||||||
height: var(--row-height);
|
height: var(--row-height);
|
||||||
|
|
||||||
@screen lg {
|
|
||||||
@apply col-span-2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.filled {
|
&.filled {
|
||||||
@ -130,12 +94,8 @@
|
|||||||
.layoutD {
|
.layoutD {
|
||||||
& > *:nth-child(12n + 2),
|
& > *:nth-child(12n + 2),
|
||||||
& > *:nth-child(12n + 7) {
|
& > *:nth-child(12n + 7) {
|
||||||
@apply row-span-2;
|
@apply row-span-2 lg:col-span-2;
|
||||||
height: var(--row-height);
|
height: var(--row-height);
|
||||||
|
|
||||||
@screen lg {
|
|
||||||
@apply col-span-2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.filled {
|
&.filled {
|
||||||
@ -152,3 +112,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@screen md {
|
||||||
|
.layoutNormal > * {
|
||||||
|
max-height: min-content !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@screen lg {
|
||||||
|
.root {
|
||||||
|
@apply grid-cols-3 grid-rows-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root > * {
|
||||||
|
@apply col-span-1;
|
||||||
|
height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layoutNormal > * {
|
||||||
|
max-height: 400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -31,8 +31,8 @@ const WishlistButton: FC<Props> = ({
|
|||||||
const itemInWishlist = data?.items?.find(
|
const itemInWishlist = data?.items?.find(
|
||||||
// @ts-ignore Wishlist is not always enabled
|
// @ts-ignore Wishlist is not always enabled
|
||||||
(item) =>
|
(item) =>
|
||||||
item.product_id === Number(productId) &&
|
item.product_id === productId &&
|
||||||
(item.variant_id as any) === Number(variant.id)
|
item.variant_id === variant.id
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleWishlistChange = async (e: any) => {
|
const handleWishlistChange = async (e: any) => {
|
||||||
|
@ -48,6 +48,7 @@ export default function Home({
|
|||||||
imgProps={{
|
imgProps={{
|
||||||
width: i === 0 ? 1080 : 540,
|
width: i === 0 ? 1080 : 540,
|
||||||
height: i === 0 ? 1080 : 540,
|
height: i === 0 ? 1080 : 540,
|
||||||
|
priority: true,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: [
|
plugins: [
|
||||||
|
'tailwindcss/nesting',
|
||||||
'tailwindcss',
|
'tailwindcss',
|
||||||
'postcss-nesting',
|
'autoprefixer',
|
||||||
'postcss-flexbugs-fixes',
|
'postcss-flexbugs-fixes',
|
||||||
[
|
[
|
||||||
'postcss-preset-env',
|
'postcss-preset-env',
|
||||||
|
@ -1,19 +1,9 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
future: {
|
content: [
|
||||||
purgeLayersByDefault: true,
|
'./pages/**/*.{js,ts,jsx,tsx}',
|
||||||
applyComplexClasses: true,
|
'./components/**/*.{js,ts,jsx,tsx}',
|
||||||
},
|
],
|
||||||
purge: {
|
safelist: ['outline-none'],
|
||||||
content: [
|
|
||||||
'./pages/**/*.{js,ts,jsx,tsx}',
|
|
||||||
'./components/**/*.{js,ts,jsx,tsx}',
|
|
||||||
],
|
|
||||||
options: {
|
|
||||||
safelist: {
|
|
||||||
standard: ['outline-none'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
maxWidth: {
|
maxWidth: {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
|
"useUnknownInCatchVariables": false,
|
||||||
"paths": {
|
"paths": {
|
||||||
"@lib/*": ["lib/*"],
|
"@lib/*": ["lib/*"],
|
||||||
"@utils/*": ["utils/*"],
|
"@utils/*": ["utils/*"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user