mirror of
https://github.com/vercel/commerce.git
synced 2025-05-17 06:56:59 +00:00
Merge branch 'main' into custom-fields
This commit is contained in:
commit
57aadb739f
@ -58,7 +58,7 @@
|
|||||||
"uuidv4": "^6.2.13"
|
"uuidv4": "^6.2.13"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
@ -74,8 +74,7 @@
|
|||||||
"@types/node-fetch": "^2.6.2",
|
"@types/node-fetch": "^2.6.2",
|
||||||
"@types/react": "^18.0.14",
|
"@types/react": "^18.0.14",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"node-fetch": "^2.6.7",
|
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -8,8 +8,8 @@ const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({
|
|||||||
config,
|
config,
|
||||||
}) => {
|
}) => {
|
||||||
const { cookies } = req
|
const { cookies } = req
|
||||||
const cartId = cookies.get(config.cartCookie)
|
const cartId = cookies.get(config.cartCookie)?.value
|
||||||
const customerToken = cookies.get(config.customerCookie)
|
const customerToken = cookies.get(config.customerCookie)?.value
|
||||||
|
|
||||||
if (!cartId) {
|
if (!cartId) {
|
||||||
return { redirectTo: '/cart' }
|
return { redirectTo: '/cart' }
|
||||||
|
@ -27,7 +27,7 @@ export type Customer = NonNullable<GetLoggedInCustomerQuery['customer']>
|
|||||||
|
|
||||||
const getLoggedInCustomer: CustomerEndpoint['handlers']['getLoggedInCustomer'] =
|
const getLoggedInCustomer: CustomerEndpoint['handlers']['getLoggedInCustomer'] =
|
||||||
async ({ req, config }) => {
|
async ({ req, config }) => {
|
||||||
const token = req.cookies.get(config.customerCookie)
|
const token = req.cookies.get(config.customerCookie)?.value
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
const { data } = await config.fetch<GetLoggedInCustomerQuery>(
|
const { data } = await config.fetch<GetLoggedInCustomerQuery>(
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
"zod": "^3.19.1"
|
"zod": "^3.19.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
@ -68,7 +68,7 @@
|
|||||||
"@types/node-fetch": "2.6.2",
|
"@types/node-fetch": "2.6.2",
|
||||||
"@types/react": "^18.0.14",
|
"@types/react": "^18.0.14",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -29,7 +29,7 @@ const cartEndpoint: GetAPISchema<
|
|||||||
|
|
||||||
let output
|
let output
|
||||||
const { cookies } = req
|
const { cookies } = req
|
||||||
const cartId = cookies.get(config.cartCookie)
|
const cartId = cookies.get(config.cartCookie)?.value
|
||||||
|
|
||||||
// Return current cart info
|
// Return current cart info
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
|
@ -22,7 +22,7 @@ const checkoutEndpoint: GetAPISchema<
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { cookies } = req
|
const { cookies } = req
|
||||||
const cartId = cookies.get(config.cartCookie)!
|
const cartId = cookies.get(config.cartCookie)?.value
|
||||||
const input = await getInput(req)
|
const input = await getInput(req)
|
||||||
|
|
||||||
// Get checkout
|
// Get checkout
|
||||||
|
@ -33,7 +33,7 @@ const customerShippingEndpoint: GetAPISchema<
|
|||||||
const { cookies } = req
|
const { cookies } = req
|
||||||
|
|
||||||
// Cart id might be usefull for anonymous shopping
|
// Cart id might be usefull for anonymous shopping
|
||||||
const cartId = cookies.get(config.cartCookie)
|
const cartId = cookies.get(config.cartCookie)?.value
|
||||||
|
|
||||||
// Return customer addresses
|
// Return customer addresses
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
|
@ -31,7 +31,7 @@ const customerCardEndpoint: GetAPISchema<
|
|||||||
const { cookies } = req
|
const { cookies } = req
|
||||||
|
|
||||||
// Cart id might be usefull for anonymous shopping
|
// Cart id might be usefull for anonymous shopping
|
||||||
const cartId = cookies.get(config.cartCookie)
|
const cartId = cookies.get(config.cartCookie)?.value
|
||||||
|
|
||||||
// Create or add a card
|
// Create or add a card
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { CustomerSchema } from '../../../types/customer'
|
import type { CustomerSchema } from '../../../types/customer'
|
||||||
import type { GetAPISchema } from '../..'
|
import type { GetAPISchema } from '../..'
|
||||||
|
import { z } from 'zod'
|
||||||
import { parse } from '../../utils'
|
import { parse } from '../../utils'
|
||||||
import validateHandlers from '../../utils/validate-handlers'
|
import validateHandlers from '../../utils/validate-handlers'
|
||||||
|
|
||||||
@ -19,7 +19,14 @@ const customerEndpoint: GetAPISchema<
|
|||||||
const body = null
|
const body = null
|
||||||
const output = await handlers['getLoggedInCustomer']({ ...ctx, body })
|
const output = await handlers['getLoggedInCustomer']({ ...ctx, body })
|
||||||
|
|
||||||
return output ? parse(output, customerSchema) : { status: 204 }
|
return output
|
||||||
|
? parse(
|
||||||
|
output,
|
||||||
|
z.object({
|
||||||
|
customer: customerSchema,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
: { status: 204 }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default customerEndpoint
|
export default customerEndpoint
|
||||||
|
@ -18,7 +18,7 @@ const signupEndpoint: GetAPISchema<
|
|||||||
|
|
||||||
const input = await getInput(req)
|
const input = await getInput(req)
|
||||||
const { cookies } = req
|
const { cookies } = req
|
||||||
const cartId = cookies.get(config.cartCookie)
|
const cartId = cookies.get(config.cartCookie)?.value
|
||||||
|
|
||||||
const body = signupBodySchema.parse({ ...input, cartId })
|
const body = signupBodySchema.parse({ ...input, cartId })
|
||||||
return handlers['signup']({ ...ctx, body })
|
return handlers['signup']({ ...ctx, body })
|
||||||
|
@ -28,7 +28,7 @@ const wishlistEndpoint: GetAPISchema<
|
|||||||
const { cookies } = req
|
const { cookies } = req
|
||||||
const input = await getInput(req)
|
const input = await getInput(req)
|
||||||
|
|
||||||
const customerToken = cookies.get(config.customerCookie)
|
const customerToken = cookies.get(config.customerCookie)?.value
|
||||||
const products = new URL(req.url).searchParams.get('products')
|
const products = new URL(req.url).searchParams.get('products')
|
||||||
|
|
||||||
// Return current wishlist info
|
// Return current wishlist info
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
"lodash.debounce": "^4.0.8"
|
"lodash.debounce": "^4.0.8"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
@ -71,7 +71,7 @@
|
|||||||
"@types/node": "^17.0.8",
|
"@types/node": "^17.0.8",
|
||||||
"@types/react": "^18.0.14",
|
"@types/react": "^18.0.14",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -53,11 +53,12 @@
|
|||||||
"lodash.debounce": "^4.0.8"
|
"lodash.debounce": "^4.0.8"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.20.5",
|
||||||
"@graphql-codegen/cli": "^2.7.0",
|
"@graphql-codegen/cli": "^2.7.0",
|
||||||
"@graphql-codegen/schema-ast": "^2.4.1",
|
"@graphql-codegen/schema-ast": "^2.4.1",
|
||||||
"@graphql-codegen/typescript": "^2.4.2",
|
"@graphql-codegen/typescript": "^2.4.2",
|
||||||
@ -71,7 +72,7 @@
|
|||||||
"@types/react": "^18.0.14",
|
"@types/react": "^18.0.14",
|
||||||
"graphql": "^16.0.0",
|
"graphql": "^16.0.0",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -8,7 +8,8 @@ const removeItem: CartEndpoint['handlers']['removeItem'] = async ({
|
|||||||
body: { itemId },
|
body: { itemId },
|
||||||
config,
|
config,
|
||||||
}) => {
|
}) => {
|
||||||
const encodedToken = req.cookies.get(config.customerCookie)
|
const encodedToken = req.cookies.get(config.customerCookie)?.value
|
||||||
|
|
||||||
const token = encodedToken
|
const token = encodedToken
|
||||||
? Buffer.from(encodedToken, 'base64').toString('ascii')
|
? Buffer.from(encodedToken, 'base64').toString('ascii')
|
||||||
: null
|
: null
|
||||||
|
@ -8,7 +8,7 @@ const updateItem: CartEndpoint['handlers']['updateItem'] = async ({
|
|||||||
body: { itemId, item },
|
body: { itemId, item },
|
||||||
config,
|
config,
|
||||||
}) => {
|
}) => {
|
||||||
const encodedToken = req.cookies.get(config.cartCookie)
|
const encodedToken = req.cookies.get(config.cartCookie)?.value
|
||||||
const token = encodedToken
|
const token = encodedToken
|
||||||
? Buffer.from(encodedToken, 'base64').toString('ascii')
|
? Buffer.from(encodedToken, 'base64').toString('ascii')
|
||||||
: null
|
: null
|
||||||
|
@ -19,7 +19,7 @@ export default class CookieHandler {
|
|||||||
this.config = config
|
this.config = config
|
||||||
this.request = req
|
this.request = req
|
||||||
|
|
||||||
const encodedToken = req.cookies.get(config.customerCookie)
|
const encodedToken = req.cookies.get(config.customerCookie)?.value
|
||||||
const token = parseCookie(encodedToken)
|
const token = parseCookie(encodedToken)
|
||||||
this.accessToken = token ? token.accessToken : null
|
this.accessToken = token ? token.accessToken : null
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ export default class CookieHandler {
|
|||||||
}
|
}
|
||||||
isShopperCookieAnonymous() {
|
isShopperCookieAnonymous() {
|
||||||
const customerCookieKey = this.config.customerCookie
|
const customerCookieKey = this.config.customerCookie
|
||||||
const shopperCookie = this.request.cookies.get(customerCookieKey)
|
const shopperCookie = this.request.cookies.get(customerCookieKey)?.value
|
||||||
const shopperSession = parseCookie(shopperCookie)
|
const shopperSession = parseCookie(shopperCookie)
|
||||||
const isAnonymous = shopperSession?.customerAccount ? false : true
|
const isAnonymous = shopperSession?.customerAccount ? false : true
|
||||||
return isAnonymous
|
return isAnonymous
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
"@vercel/commerce": "workspace:*"
|
"@vercel/commerce": "workspace:*"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
@ -62,7 +62,7 @@
|
|||||||
"@types/react": "^18.0.14",
|
"@types/react": "^18.0.14",
|
||||||
"@types/node-fetch": "2.6.2",
|
"@types/node-fetch": "2.6.2",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
"cookie": "^0.4.1"
|
"cookie": "^0.4.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
@ -66,7 +66,7 @@
|
|||||||
"@types/cookie": "^0.4.1",
|
"@types/cookie": "^0.4.1",
|
||||||
"@types/node-fetch": "^2.6.2",
|
"@types/node-fetch": "^2.6.2",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -10,7 +10,7 @@ const addItem: CartEndpoint['handlers']['addItem'] = async ({
|
|||||||
config: { restBuyerFetch, cartCookie, tokenCookie },
|
config: { restBuyerFetch, cartCookie, tokenCookie },
|
||||||
}) => {
|
}) => {
|
||||||
// Get token
|
// Get token
|
||||||
let token = req.cookies.get(tokenCookie)
|
let token = req.cookies.get(tokenCookie)?.value
|
||||||
let headers: any = {}
|
let headers: any = {}
|
||||||
|
|
||||||
// Create an order if it doesn't exist
|
// Create an order if it doesn't exist
|
||||||
|
@ -16,7 +16,7 @@ const getCart: CartEndpoint['handlers']['getCart'] = async ({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Get token
|
// Get token
|
||||||
const token = req.cookies.get(tokenCookie)
|
const token = req.cookies.get(tokenCookie)?.value
|
||||||
|
|
||||||
// Get cart & line items
|
// Get cart & line items
|
||||||
const [cart, { Items }] = await Promise.all([
|
const [cart, { Items }] = await Promise.all([
|
||||||
|
@ -7,7 +7,7 @@ const removeItem: CartEndpoint['handlers']['removeItem'] = async ({
|
|||||||
body: { cartId, itemId },
|
body: { cartId, itemId },
|
||||||
config: { restBuyerFetch, tokenCookie },
|
config: { restBuyerFetch, tokenCookie },
|
||||||
}) => {
|
}) => {
|
||||||
const token = req.cookies.get(tokenCookie)
|
const token = req.cookies.get(tokenCookie)?.value
|
||||||
|
|
||||||
// Remove the item to the order
|
// Remove the item to the order
|
||||||
await restBuyerFetch(
|
await restBuyerFetch(
|
||||||
|
@ -9,7 +9,7 @@ const updateItem: CartEndpoint['handlers']['updateItem'] = async ({
|
|||||||
body: { cartId, itemId, item },
|
body: { cartId, itemId, item },
|
||||||
config: { restBuyerFetch, tokenCookie },
|
config: { restBuyerFetch, tokenCookie },
|
||||||
}) => {
|
}) => {
|
||||||
const token = req.cookies.get(tokenCookie)
|
const token = req.cookies.get(tokenCookie)?.value
|
||||||
|
|
||||||
// Store specs
|
// Store specs
|
||||||
let specs: RawVariant['Specs'] = []
|
let specs: RawVariant['Specs'] = []
|
||||||
|
@ -7,7 +7,7 @@ const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
|
|||||||
body: { search, categoryId },
|
body: { search, categoryId },
|
||||||
config: { restBuyerFetch, tokenCookie },
|
config: { restBuyerFetch, tokenCookie },
|
||||||
}) => {
|
}) => {
|
||||||
const token = req.cookies.get(tokenCookie)
|
const token = req.cookies.get(tokenCookie)?.value
|
||||||
|
|
||||||
//Use a dummy base as we only care about the relative path
|
//Use a dummy base as we only care about the relative path
|
||||||
const url = new URL('/me/products', 'http://a')
|
const url = new URL('/me/products', 'http://a')
|
||||||
|
@ -5,7 +5,7 @@ const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({
|
|||||||
body: { cartId },
|
body: { cartId },
|
||||||
config: { restBuyerFetch },
|
config: { restBuyerFetch },
|
||||||
}) => {
|
}) => {
|
||||||
const token = req.cookies.get('token')
|
const token = req.cookies.get('token')?.value
|
||||||
|
|
||||||
// Register credit card
|
// Register credit card
|
||||||
const payments = await restBuyerFetch(
|
const payments = await restBuyerFetch(
|
||||||
|
@ -5,7 +5,7 @@ const submitCheckout: CheckoutEndpoint['handlers']['submitCheckout'] = async ({
|
|||||||
body: { cartId },
|
body: { cartId },
|
||||||
config: { restBuyerFetch, tokenCookie },
|
config: { restBuyerFetch, tokenCookie },
|
||||||
}) => {
|
}) => {
|
||||||
const token = req.cookies.get(tokenCookie)
|
const token = req.cookies.get(tokenCookie)?.value
|
||||||
|
|
||||||
// Submit order
|
// Submit order
|
||||||
await restBuyerFetch('POST', `/orders/Outgoing/${cartId}/submit`, null, {
|
await restBuyerFetch('POST', `/orders/Outgoing/${cartId}/submit`, null, {
|
||||||
|
@ -5,7 +5,7 @@ const addItem: CustomerAddressEndpoint['handlers']['addItem'] = async ({
|
|||||||
body: { item, cartId },
|
body: { item, cartId },
|
||||||
config: { restBuyerFetch, tokenCookie },
|
config: { restBuyerFetch, tokenCookie },
|
||||||
}) => {
|
}) => {
|
||||||
const token = req.cookies.get(tokenCookie)
|
const token = req.cookies.get(tokenCookie)?.value
|
||||||
|
|
||||||
// Register address
|
// Register address
|
||||||
const address = await restBuyerFetch('POST', `/me/addresses`, {
|
const address = await restBuyerFetch('POST', `/me/addresses`, {
|
||||||
|
@ -7,7 +7,7 @@ const addItem: CustomerCardEndpoint['handlers']['addItem'] = async ({
|
|||||||
config: { restBuyerFetch, tokenCookie },
|
config: { restBuyerFetch, tokenCookie },
|
||||||
}) => {
|
}) => {
|
||||||
// Get token
|
// Get token
|
||||||
const token = req.cookies.get(tokenCookie)
|
const token = req.cookies.get(tokenCookie)?.value
|
||||||
|
|
||||||
const [exp_month, exp_year] = item.cardExpireDate.split('/')
|
const [exp_month, exp_year] = item.cardExpireDate.split('/')
|
||||||
const stripeToken = await fetch('https://api.stripe.com/v1/tokens', {
|
const stripeToken = await fetch('https://api.stripe.com/v1/tokens', {
|
||||||
|
@ -54,11 +54,12 @@
|
|||||||
"lodash.debounce": "^4.0.8"
|
"lodash.debounce": "^4.0.8"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.20.5",
|
||||||
"@graphql-codegen/cli": "^2.7.0",
|
"@graphql-codegen/cli": "^2.7.0",
|
||||||
"@graphql-codegen/schema-ast": "^2.4.1",
|
"@graphql-codegen/schema-ast": "^2.4.1",
|
||||||
"@graphql-codegen/typescript": "^2.4.2",
|
"@graphql-codegen/typescript": "^2.4.2",
|
||||||
@ -73,7 +74,7 @@
|
|||||||
"@types/react": "^18.0.14",
|
"@types/react": "^18.0.14",
|
||||||
"graphql": "^16.0.0",
|
"graphql": "^16.0.0",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
"commerce-sdk": "^2.7.0"
|
"commerce-sdk": "^2.7.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
@ -63,7 +63,7 @@
|
|||||||
"@types/react": "^18.0.14",
|
"@types/react": "^18.0.14",
|
||||||
"@types/node-fetch": "^2.6.2",
|
"@types/node-fetch": "^2.6.2",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -54,11 +54,12 @@
|
|||||||
"lodash.debounce": "^4.0.8"
|
"lodash.debounce": "^4.0.8"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.20.5",
|
||||||
"@graphql-codegen/cli": "2.7.0",
|
"@graphql-codegen/cli": "2.7.0",
|
||||||
"@graphql-codegen/schema-ast": "^2.4.1",
|
"@graphql-codegen/schema-ast": "^2.4.1",
|
||||||
"@graphql-codegen/typescript": "^2.6.0",
|
"@graphql-codegen/typescript": "^2.6.0",
|
||||||
@ -69,10 +70,10 @@
|
|||||||
"@types/js-cookie": "3.0.2",
|
"@types/js-cookie": "3.0.2",
|
||||||
"@types/lodash.debounce": "^4.0.7",
|
"@types/lodash.debounce": "^4.0.7",
|
||||||
"@types/node": "^18.0.3",
|
"@types/node": "^18.0.3",
|
||||||
"@types/react": "^18.0.14",
|
|
||||||
"@types/node-fetch": "2.6.2",
|
"@types/node-fetch": "2.6.2",
|
||||||
"graphql": "^16.0.0",
|
"@types/react": "^18.0.14",
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
|
"graphql": "^16.0.0",
|
||||||
"lint-staged": "^13.0.3",
|
"lint-staged": "^13.0.3",
|
||||||
"next": "^12.2.1",
|
"next": "^12.2.1",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
|
@ -11,15 +11,16 @@ const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({
|
|||||||
config,
|
config,
|
||||||
}) => {
|
}) => {
|
||||||
const { cookies } = req
|
const { cookies } = req
|
||||||
const checkoutUrl = cookies.get(SHOPIFY_CHECKOUT_URL_COOKIE)
|
const checkoutUrl = cookies.get(SHOPIFY_CHECKOUT_URL_COOKIE)?.value
|
||||||
const customerCookie = cookies.get(SHOPIFY_CUSTOMER_TOKEN_COOKIE)
|
const customerCookie = cookies.get(SHOPIFY_CUSTOMER_TOKEN_COOKIE)?.value
|
||||||
|
|
||||||
if (customerCookie) {
|
if (customerCookie) {
|
||||||
try {
|
try {
|
||||||
await config.fetch(associateCustomerWithCheckoutMutation, {
|
await config.fetch(associateCustomerWithCheckoutMutation, {
|
||||||
variables: {
|
variables: {
|
||||||
checkoutId: cookies.get(SHOPIFY_CHECKOUT_ID_COOKIE),
|
checkoutId: cookies.get(SHOPIFY_CHECKOUT_ID_COOKIE)?.value,
|
||||||
customerAccessToken: cookies.get(SHOPIFY_CUSTOMER_TOKEN_COOKIE),
|
customerAccessToken: cookies.get(SHOPIFY_CUSTOMER_TOKEN_COOKIE)
|
||||||
|
?.value,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -11,7 +11,7 @@ export const getSearchVariables = ({
|
|||||||
let query = ''
|
let query = ''
|
||||||
|
|
||||||
if (search) {
|
if (search) {
|
||||||
query += `product_type:"${search}" OR title:"${search}" OR tag:"${search}" `
|
query += `(product_type:${search}) OR (title:${search}) OR (tag:${search}) `
|
||||||
}
|
}
|
||||||
|
|
||||||
if (brandId) {
|
if (brandId) {
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
"swr": "^1.3.0"
|
"swr": "^1.3.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
@ -68,7 +68,7 @@
|
|||||||
"@types/node-fetch": "^2.6.2",
|
"@types/node-fetch": "^2.6.2",
|
||||||
"@types/react": "^18.0.14",
|
"@types/react": "^18.0.14",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
"swell-js": "^4.0.0-next.0"
|
"swell-js": "^4.0.0-next.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
@ -68,7 +68,7 @@
|
|||||||
"@types/node-fetch": "^2.6.2",
|
"@types/node-fetch": "^2.6.2",
|
||||||
"@types/react": "^18.0.14",
|
"@types/react": "^18.0.14",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -7,7 +7,7 @@ const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({
|
|||||||
req,
|
req,
|
||||||
}) => {
|
}) => {
|
||||||
const { cookies } = req
|
const { cookies } = req
|
||||||
const checkoutUrl = cookies.get(SWELL_CHECKOUT_URL_COOKIE)
|
const checkoutUrl = cookies.get(SWELL_CHECKOUT_URL_COOKIE)?.value
|
||||||
|
|
||||||
if (checkoutUrl) {
|
if (checkoutUrl) {
|
||||||
return { redirectTo: checkoutUrl }
|
return { redirectTo: checkoutUrl }
|
||||||
|
@ -52,11 +52,12 @@
|
|||||||
"@vercel/commerce": "workspace:*"
|
"@vercel/commerce": "workspace:*"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"next": "^12",
|
"next": "^13",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18"
|
"react-dom": "^18"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.20.5",
|
||||||
"@graphql-codegen/cli": "2.7.0",
|
"@graphql-codegen/cli": "2.7.0",
|
||||||
"@graphql-codegen/schema-ast": "^2.4.1",
|
"@graphql-codegen/schema-ast": "^2.4.1",
|
||||||
"@graphql-codegen/typescript": "^2.4.2",
|
"@graphql-codegen/typescript": "^2.4.2",
|
||||||
@ -69,7 +70,7 @@
|
|||||||
"@types/node-fetch": "^2.6.2",
|
"@types/node-fetch": "^2.6.2",
|
||||||
"graphql": "^16.0.0",
|
"graphql": "^16.0.0",
|
||||||
"lint-staged": "^12.1.7",
|
"lint-staged": "^12.1.7",
|
||||||
"next": "^12.0.8",
|
"next": "^13.0.6",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
850
pnpm-lock.yaml
generated
850
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -119,3 +119,9 @@ a {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media not all and (min-resolution: 0.001dpcm) {
|
||||||
|
img[loading='lazy'] {
|
||||||
|
clip-path: inset(0.5px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,13 +17,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.productImage {
|
.productImage {
|
||||||
position: absolute;
|
@apply w-full h-full object-cover;
|
||||||
transform: scale(1.9);
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
left: 30% !important;
|
|
||||||
top: 30% !important;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.productName {
|
.productName {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ChangeEvent, FocusEventHandler, useEffect, useState } from 'react'
|
import { ChangeEvent, useEffect, useState } from 'react'
|
||||||
import cn from 'clsx'
|
import cn from 'clsx'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
@ -84,31 +84,26 @@ const CartItem = ({
|
|||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row space-x-4 py-4">
|
<div className="flex flex-row space-x-4 py-4">
|
||||||
<div className="w-16 h-16 bg-violet relative overflow-hidden cursor-pointer z-0">
|
<div className="w-16 h-16 bg-violet relative overflow-hidden cursor-pointer">
|
||||||
<Link href={`/product/${item.path}`}>
|
<Link href={`/product/${item.path}`}>
|
||||||
<a>
|
|
||||||
<Image
|
<Image
|
||||||
onClick={() => closeSidebarIfPresent()}
|
onClick={() => closeSidebarIfPresent()}
|
||||||
className={s.productImage}
|
className={s.productImage}
|
||||||
width={150}
|
width={64}
|
||||||
height={150}
|
height={64}
|
||||||
src={item.variant.image?.url || placeholderImg}
|
src={item.variant.image?.url || placeholderImg}
|
||||||
alt={item.variant.image?.alt || 'Product Image'}
|
alt={item.variant.image?.alt || 'Product Image'}
|
||||||
unoptimized
|
|
||||||
/>
|
/>
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 flex flex-col text-base">
|
<div className="flex-1 flex flex-col text-base">
|
||||||
<Link href={`/product/${item.path}`}>
|
<Link href={`/product/${item.path}`}>
|
||||||
<a>
|
|
||||||
<span
|
<span
|
||||||
className={s.productName}
|
className={s.productName}
|
||||||
onClick={() => closeSidebarIfPresent()}
|
onClick={() => closeSidebarIfPresent()}
|
||||||
>
|
>
|
||||||
{item.name}
|
{item.name}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
{options && options.length > 0 && (
|
{options && options.length > 0 && (
|
||||||
<div className="flex items-center pb-1">
|
<div className="flex items-center pb-1">
|
||||||
|
@ -74,11 +74,9 @@ const CartSidebarView: FC = () => {
|
|||||||
<>
|
<>
|
||||||
<div className="px-4 sm:px-6 flex-1">
|
<div className="px-4 sm:px-6 flex-1">
|
||||||
<Link href="/cart">
|
<Link href="/cart">
|
||||||
<a>
|
|
||||||
<Text variant="sectionHeading" onClick={handleClose}>
|
<Text variant="sectionHeading" onClick={handleClose}>
|
||||||
My Cart
|
My Cart
|
||||||
</Text>
|
</Text>
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
<ul className={s.lineItemsList}>
|
<ul className={s.lineItemsList}>
|
||||||
{data!.lineItems.map((item: any) => (
|
{data!.lineItems.map((item: any) => (
|
||||||
|
@ -55,9 +55,7 @@ const CheckoutSidebarView: FC = () => {
|
|||||||
>
|
>
|
||||||
<div className="px-4 sm:px-6 flex-1">
|
<div className="px-4 sm:px-6 flex-1">
|
||||||
<Link href="/cart">
|
<Link href="/cart">
|
||||||
<a>
|
|
||||||
<Text variant="sectionHeading">Checkout</Text>
|
<Text variant="sectionHeading">Checkout</Text>
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<PaymentWidget
|
<PaymentWidget
|
||||||
|
@ -7,6 +7,7 @@ import getSlug from '@lib/get-slug'
|
|||||||
import { Github, Vercel } from '@components/icons'
|
import { Github, Vercel } from '@components/icons'
|
||||||
import { Logo, Container } from '@components/ui'
|
import { Logo, Container } from '@components/ui'
|
||||||
import { I18nWidget } from '@components/common'
|
import { I18nWidget } from '@components/common'
|
||||||
|
import ThemeSwitcher from '@components/ui/ThemeSwitcher'
|
||||||
import s from './Footer.module.css'
|
import s from './Footer.module.css'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -31,30 +32,34 @@ const Footer: FC<Props> = ({ className, pages }) => {
|
|||||||
<Container>
|
<Container>
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 border-b border-accent-2 py-12 text-primary bg-primary transition-colors duration-150">
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 border-b border-accent-2 py-12 text-primary bg-primary transition-colors duration-150">
|
||||||
<div className="col-span-1 lg:col-span-2">
|
<div className="col-span-1 lg:col-span-2">
|
||||||
<Link href="/">
|
<Link
|
||||||
<a className="flex flex-initial items-center font-bold md:mr-24">
|
href="/"
|
||||||
|
className="flex flex-initial items-center font-bold md:mr-24"
|
||||||
|
>
|
||||||
<span className="rounded-full border border-accent-6 mr-2">
|
<span className="rounded-full border border-accent-6 mr-2">
|
||||||
<Logo />
|
<Logo />
|
||||||
</span>
|
</span>
|
||||||
<span>ACME</span>
|
<span>ACME</span>
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-1 lg:col-span-8">
|
<div className="col-span-1 lg:col-span-7">
|
||||||
<div className="grid md:grid-rows-4 md:grid-cols-3 md:grid-flow-col">
|
<div className="grid md:grid-rows-4 md:grid-cols-3 md:grid-flow-col">
|
||||||
{[...links, ...sitePages].map((page) => (
|
{[...links, ...sitePages].map((page) => (
|
||||||
<span key={page.url} className="py-3 md:py-0 md:pb-4">
|
<span key={page.url} className="py-3 md:py-0 md:pb-4">
|
||||||
<Link href={page.url!}>
|
<Link
|
||||||
<a className="text-accent-9 hover:text-accent-6 transition ease-in-out duration-150">
|
href={page.url!}
|
||||||
|
className="text-accent-9 hover:text-accent-6 transition ease-in-out duration-150"
|
||||||
|
>
|
||||||
{page.name}
|
{page.name}
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-1 lg:col-span-2 flex items-start lg:justify-end text-primary">
|
<div className="col-span-1 lg:col-span-3 flex items-start lg:justify-end text-primary">
|
||||||
<div className="flex space-x-6 items-center h-10">
|
<div className="flex space-x-4 items-center h-10">
|
||||||
|
<ThemeSwitcher />
|
||||||
|
<I18nWidget />
|
||||||
<a
|
<a
|
||||||
className={s.link}
|
className={s.link}
|
||||||
aria-label="Github Repository"
|
aria-label="Github Repository"
|
||||||
@ -62,7 +67,6 @@ const Footer: FC<Props> = ({ className, pages }) => {
|
|||||||
>
|
>
|
||||||
<Github />
|
<Github />
|
||||||
</a>
|
</a>
|
||||||
<I18nWidget />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,29 +24,21 @@ const HomeAllProductsGrid: FC<Props> = ({
|
|||||||
<div className={s.aside}>
|
<div className={s.aside}>
|
||||||
<ul className="mb-10">
|
<ul className="mb-10">
|
||||||
<li className="py-1 text-base font-bold tracking-wide">
|
<li className="py-1 text-base font-bold tracking-wide">
|
||||||
<Link href={getCategoryPath('')}>
|
<Link href={getCategoryPath('')}>All Categories</Link>
|
||||||
<a>All Categories</a>
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
{categories?.map((cat: any) => (
|
{categories?.map((cat: any) => (
|
||||||
<li key={cat.path} className="py-1 text-accent-8 text-base">
|
<li key={cat.path} className="py-1 text-accent-8 text-base">
|
||||||
<Link href={getCategoryPath(cat.path)}>
|
<Link href={getCategoryPath(cat.path)}>{cat.name}</Link>
|
||||||
<a>{cat.name}</a>
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
<ul className="">
|
<ul className="">
|
||||||
<li className="py-1 text-base font-bold tracking-wide">
|
<li className="py-1 text-base font-bold tracking-wide">
|
||||||
<Link href={getDesignerPath('')}>
|
<Link href={getDesignerPath('')}>All Designers</Link>
|
||||||
<a>All Designers</a>
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
{brands?.map(({ path, name }) => (
|
{brands?.map(({ path, name }) => (
|
||||||
<li key={path} className="py-1 text-accent-8 text-base">
|
<li key={path} className="py-1 text-accent-8 text-base">
|
||||||
<Link href={getDesignerPath(path)}>
|
<Link href={getDesignerPath(path)}>{name}</Link>
|
||||||
<a>{name}</a>
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@ -60,6 +52,7 @@ const HomeAllProductsGrid: FC<Props> = ({
|
|||||||
product={product}
|
product={product}
|
||||||
variant="simple"
|
variant="simple"
|
||||||
imgProps={{
|
imgProps={{
|
||||||
|
alt: product.name,
|
||||||
width: 480,
|
width: 480,
|
||||||
height: 480,
|
height: 480,
|
||||||
}}
|
}}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
@apply h-10 px-2 rounded-md border border-accent-2 flex items-center justify-center transition-colors ease-linear;
|
@apply h-10 pl-2 pr-1 rounded-md border border-accent-2 flex items-center justify-center transition-colors ease-linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:hover {
|
.button:hover {
|
||||||
@ -32,7 +32,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon.active {
|
.icon.active {
|
||||||
transform: rotate(180deg);
|
transform: rotate(90deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@screen lg {
|
@screen lg {
|
||||||
|
@ -3,7 +3,7 @@ import Link from 'next/link'
|
|||||||
import { FC, useState } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import s from './I18nWidget.module.css'
|
import s from './I18nWidget.module.css'
|
||||||
import { Cross, ChevronUp } from '@components/icons'
|
import { Cross, ChevronRight } from '@components/icons'
|
||||||
import ClickOutside from '@lib/click-outside'
|
import ClickOutside from '@lib/click-outside'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
interface LOCALE_DATA {
|
interface LOCALE_DATA {
|
||||||
@ -54,14 +54,14 @@ const I18nWidget: FC = () => {
|
|||||||
<Image
|
<Image
|
||||||
width="20"
|
width="20"
|
||||||
height="20"
|
height="20"
|
||||||
className="block mr-2 w-5"
|
className="block w-5"
|
||||||
src={`/${LOCALES_MAP[currentLocale].img.filename}`}
|
src={`/${LOCALES_MAP[currentLocale].img.filename}`}
|
||||||
alt={LOCALES_MAP[currentLocale].img.alt}
|
alt={LOCALES_MAP[currentLocale].img.alt}
|
||||||
unoptimized
|
unoptimized
|
||||||
/>
|
/>
|
||||||
{options && (
|
{options && (
|
||||||
<span className="cursor-pointer">
|
<span className="cursor-pointer ml-1">
|
||||||
<ChevronUp className={cn(s.icon, { [s.active]: display })} />
|
<ChevronRight className={cn(s.icon, { [s.active]: display })} />
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
@ -81,13 +81,13 @@ const I18nWidget: FC = () => {
|
|||||||
<ul>
|
<ul>
|
||||||
{options.map((locale) => (
|
{options.map((locale) => (
|
||||||
<li key={locale}>
|
<li key={locale}>
|
||||||
<Link href={currentPath} locale={locale}>
|
<Link
|
||||||
<a
|
href={currentPath}
|
||||||
|
locale={locale}
|
||||||
className={cn(s.item)}
|
className={cn(s.item)}
|
||||||
onClick={() => setDisplay(false)}
|
onClick={() => setDisplay(false)}
|
||||||
>
|
>
|
||||||
{LOCALES_MAP[locale].name}
|
{LOCALES_MAP[locale].name}
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
@ -19,18 +19,16 @@ const Navbar: FC<NavbarProps> = ({ links }) => (
|
|||||||
<Container clean className="mx-auto max-w-8xl px-6">
|
<Container clean className="mx-auto max-w-8xl px-6">
|
||||||
<div className={s.nav}>
|
<div className={s.nav}>
|
||||||
<div className="flex items-center flex-1">
|
<div className="flex items-center flex-1">
|
||||||
<Link href="/">
|
<Link href="/" className={s.logo} aria-label="Logo">
|
||||||
<a className={s.logo} aria-label="Logo">
|
|
||||||
<Logo />
|
<Logo />
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
<nav className={s.navMenu}>
|
<nav className={s.navMenu}>
|
||||||
<Link href="/search">
|
<Link href="/search" className={s.link}>
|
||||||
<a className={s.link}>All</a>
|
All
|
||||||
</Link>
|
</Link>
|
||||||
{links?.map((l) => (
|
{links?.map((l) => (
|
||||||
<Link href={l.href} key={l.href}>
|
<Link href={l.href} key={l.href} className={s.link}>
|
||||||
<a className={s.link}>{l.label}</a>
|
{l.label}
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</nav>
|
</nav>
|
||||||
|
@ -17,9 +17,7 @@ export default function MenuSidebarView({
|
|||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li className={s.item} onClick={() => closeSidebar()}>
|
<li className={s.item} onClick={() => closeSidebar()}>
|
||||||
<Link href="/search">
|
<Link href="/search">All</Link>
|
||||||
<a>All</a>
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
{links.map((l: any) => (
|
{links.map((l: any) => (
|
||||||
<li
|
<li
|
||||||
@ -27,9 +25,7 @@ export default function MenuSidebarView({
|
|||||||
className={s.item}
|
className={s.item}
|
||||||
onClick={() => closeSidebar()}
|
onClick={() => closeSidebar()}
|
||||||
>
|
>
|
||||||
<Link href={l.href}>
|
<Link href={l.href}>{l.label}</Link>
|
||||||
<a>{l.label}</a>
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -59,7 +59,7 @@ const UserNav: React.FC<{
|
|||||||
)}
|
)}
|
||||||
{process.env.COMMERCE_WISHLIST_ENABLED && (
|
{process.env.COMMERCE_WISHLIST_ENABLED && (
|
||||||
<li className={s.item}>
|
<li className={s.item}>
|
||||||
<Link href="/wishlist">
|
<Link href="/wishlist" legacyBehavior>
|
||||||
<a onClick={closeSidebarIfPresent} aria-label="Wishlist">
|
<a onClick={closeSidebarIfPresent} aria-label="Wishlist">
|
||||||
<Heart />
|
<Heart />
|
||||||
</a>
|
</a>
|
||||||
|
19
site/components/icons/System.tsx
Normal file
19
site/components/icons/System.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const System = ({ ...props }) => (
|
||||||
|
<svg
|
||||||
|
data-testid="geist-icon"
|
||||||
|
fill="none"
|
||||||
|
height="16"
|
||||||
|
shapeRendering="geometricPrecision"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
className="text-current"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path d="M2 13.381h20M8.66 19.05V22m6.84-2.95V22m-8.955 0h10.932M4 19.05h16a2 2 0 002-2V4a2 2 0 00-2-2H4a2 2 0 00-2 2v13.05a2 2 0 002 2z"></path>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default System
|
@ -11,6 +11,7 @@ export { default as Cross } from './Cross'
|
|||||||
export { default as Minus } from './Minus'
|
export { default as Minus } from './Minus'
|
||||||
export { default as Check } from './Check'
|
export { default as Check } from './Check'
|
||||||
export { default as Github } from './Github'
|
export { default as Github } from './Github'
|
||||||
|
export { default as System } from './System'
|
||||||
export { default as Vercel } from './Vercel'
|
export { default as Vercel } from './Vercel'
|
||||||
export { default as MapPin } from './MapPin'
|
export { default as MapPin } from './MapPin'
|
||||||
export { default as ArrowLeft } from './ArrowLeft'
|
export { default as ArrowLeft } from './ArrowLeft'
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
.root:hover {
|
.root:hover {
|
||||||
& .productImage {
|
& .productImage {
|
||||||
transform: scale(1.2625);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
& .header .name span,
|
& .header .name span,
|
||||||
@ -69,16 +69,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.imageContainer {
|
.imageContainer {
|
||||||
@apply flex items-center justify-center overflow-hidden;
|
@apply flex items-center justify-center overflow-hidden w-full h-full;
|
||||||
}
|
|
||||||
|
|
||||||
.imageContainer > div {
|
|
||||||
min-width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.imageContainer .productImage {
|
.imageContainer .productImage {
|
||||||
@apply transform transition-transform duration-500
|
@apply transform transition-transform duration-500 object-cover w-auto h-full;
|
||||||
object-cover scale-120;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.root .wishlistButton {
|
.root .wishlistButton {
|
||||||
|
@ -38,25 +38,25 @@ const ProductCard: FC<Props> = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={`/product/${product.slug}`}>
|
<Link
|
||||||
<a className={rootClassName} aria-label={product.name}>
|
href={`/product/${product.slug}`}
|
||||||
|
className={rootClassName}
|
||||||
|
aria-label={product.name}
|
||||||
|
>
|
||||||
{variant === 'slim' && (
|
{variant === 'slim' && (
|
||||||
<>
|
<>
|
||||||
<div className={s.header}>
|
<div className={s.header}>
|
||||||
<span>{product.name}</span>
|
<span>{product.name}</span>
|
||||||
</div>
|
</div>
|
||||||
{product?.images && (
|
{product?.images && (
|
||||||
<div>
|
|
||||||
<Image
|
<Image
|
||||||
quality="85"
|
quality="85"
|
||||||
src={product.images[0]?.url || placeholderImg}
|
src={product.images[0]?.url || placeholderImg}
|
||||||
alt={product.name || 'Product Image'}
|
alt={product.name || 'Product Image'}
|
||||||
height={320}
|
height={320}
|
||||||
width={320}
|
width={320}
|
||||||
layout="fixed"
|
|
||||||
{...imgProps}
|
{...imgProps}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -82,7 +82,6 @@ const ProductCard: FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
<div className={s.imageContainer}>
|
<div className={s.imageContainer}>
|
||||||
{product?.images && (
|
{product?.images && (
|
||||||
<div>
|
|
||||||
<Image
|
<Image
|
||||||
alt={product.name || 'Product Image'}
|
alt={product.name || 'Product Image'}
|
||||||
className={s.productImage}
|
className={s.productImage}
|
||||||
@ -90,10 +89,8 @@ const ProductCard: FC<Props> = ({
|
|||||||
height={540}
|
height={540}
|
||||||
width={540}
|
width={540}
|
||||||
quality="85"
|
quality="85"
|
||||||
layout="responsive"
|
|
||||||
{...imgProps}
|
{...imgProps}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@ -114,7 +111,6 @@ const ProductCard: FC<Props> = ({
|
|||||||
/>
|
/>
|
||||||
<div className={s.imageContainer}>
|
<div className={s.imageContainer}>
|
||||||
{product?.images && (
|
{product?.images && (
|
||||||
<div>
|
|
||||||
<Image
|
<Image
|
||||||
alt={product.name || 'Product Image'}
|
alt={product.name || 'Product Image'}
|
||||||
className={s.productImage}
|
className={s.productImage}
|
||||||
@ -122,15 +118,12 @@ const ProductCard: FC<Props> = ({
|
|||||||
height={540}
|
height={540}
|
||||||
width={540}
|
width={540}
|
||||||
quality="85"
|
quality="85"
|
||||||
layout="responsive"
|
|
||||||
{...imgProps}
|
{...imgProps}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer .img {
|
.sliderContainer .img {
|
||||||
@apply w-full h-auto max-h-full object-cover;
|
@apply w-auto h-full max-h-full object-cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
|
@ -19,11 +19,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.thumb.selected {
|
.thumb.selected {
|
||||||
@apply bg-white;
|
@apply bg-white/30;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumb img {
|
.thumb img {
|
||||||
height: 85% !important;
|
@apply h-full w-full object-cover transition duration-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.album {
|
.album {
|
||||||
@ -44,10 +44,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@screen md {
|
@screen md {
|
||||||
.thumb:hover {
|
.thumb:hover img {
|
||||||
transform: scale(1.02);
|
@apply scale-110;
|
||||||
}
|
}
|
||||||
|
|
||||||
.album {
|
.album {
|
||||||
height: 182px;
|
height: 182px;
|
||||||
}
|
}
|
||||||
|
@ -17,15 +17,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.imageContainer {
|
.imageContainer {
|
||||||
@apply text-center h-full relative;
|
@apply flex items-center justify-center w-full h-full relative;
|
||||||
}
|
|
||||||
|
|
||||||
.imageContainer > span {
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliderContainer .img {
|
.sliderContainer .img {
|
||||||
@apply w-full h-full max-h-full object-cover;
|
@apply object-cover h-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
|
@ -80,6 +80,7 @@ const ProductView: FC<ProductViewProps> = ({ product, relatedProducts }) => {
|
|||||||
variant="simple"
|
variant="simple"
|
||||||
className="animated fadeIn"
|
className="animated fadeIn"
|
||||||
imgProps={{
|
imgProps={{
|
||||||
|
alt: p.name,
|
||||||
width: 300,
|
width: 300,
|
||||||
height: 300,
|
height: 300,
|
||||||
}}
|
}}
|
||||||
|
@ -125,6 +125,7 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
|||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
href={{ pathname: getCategoryPath('', brand), query }}
|
href={{ pathname: getCategoryPath('', brand), query }}
|
||||||
|
legacyBehavior
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
onClick={(e) => handleClick(e, 'categories')}
|
onClick={(e) => handleClick(e, 'categories')}
|
||||||
@ -151,6 +152,7 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
|||||||
pathname: getCategoryPath(cat.path, brand),
|
pathname: getCategoryPath(cat.path, brand),
|
||||||
query,
|
query,
|
||||||
}}
|
}}
|
||||||
|
legacyBehavior
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
onClick={(e) => handleClick(e, 'categories')}
|
onClick={(e) => handleClick(e, 'categories')}
|
||||||
@ -226,6 +228,7 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
|||||||
pathname: getDesignerPath('', category),
|
pathname: getDesignerPath('', category),
|
||||||
query,
|
query,
|
||||||
}}
|
}}
|
||||||
|
legacyBehavior
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
onClick={(e) => handleClick(e, 'brands')}
|
onClick={(e) => handleClick(e, 'brands')}
|
||||||
@ -252,6 +255,7 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
|||||||
pathname: getDesignerPath(path, category),
|
pathname: getDesignerPath(path, category),
|
||||||
query,
|
query,
|
||||||
}}
|
}}
|
||||||
|
legacyBehavior
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
onClick={(e) => handleClick(e, 'brands')}
|
onClick={(e) => handleClick(e, 'brands')}
|
||||||
@ -326,6 +330,7 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
|||||||
imgProps={{
|
imgProps={{
|
||||||
width: 480,
|
width: 480,
|
||||||
height: 480,
|
height: 480,
|
||||||
|
alt: product.name,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
@ -390,7 +395,10 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
|||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Link href={{ pathname, query: filterQuery({ q }) }}>
|
<Link
|
||||||
|
href={{ pathname, query: filterQuery({ q }) }}
|
||||||
|
legacyBehavior
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
onClick={(e) => handleClick(e, 'sort')}
|
onClick={(e) => handleClick(e, 'sort')}
|
||||||
className={
|
className={
|
||||||
@ -416,6 +424,7 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
|||||||
pathname,
|
pathname,
|
||||||
query: filterQuery({ q, sort: key }),
|
query: filterQuery({ q, sort: key }),
|
||||||
}}
|
}}
|
||||||
|
legacyBehavior
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
onClick={(e) => handleClick(e, 'sort')}
|
onClick={(e) => handleClick(e, 'sort')}
|
||||||
|
@ -17,11 +17,12 @@ const Hero: FC<HeroProps> = ({ headline, description }) => {
|
|||||||
<h2 className={s.title}>{headline}</h2>
|
<h2 className={s.title}>{headline}</h2>
|
||||||
<div className={s.description}>
|
<div className={s.description}>
|
||||||
<p>{description}</p>
|
<p>{description}</p>
|
||||||
<Link href="/">
|
<Link
|
||||||
<a className="flex items-center text-accent-0 pt-3 font-bold hover:underline cursor-pointer w-max-content">
|
href="/"
|
||||||
|
className="flex items-center text-accent-0 pt-3 font-bold hover:underline cursor-pointer w-max-content"
|
||||||
|
>
|
||||||
Read it here
|
Read it here
|
||||||
<ArrowRight width="20" heigh="20" className="ml-1" />
|
<ArrowRight width="20" heigh="20" className="ml-1" />
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,8 +6,8 @@ const Link: React.FC<
|
|||||||
}
|
}
|
||||||
> = ({ href, children, ...props }) => {
|
> = ({ href, children, ...props }) => {
|
||||||
return (
|
return (
|
||||||
<NextLink href={href}>
|
<NextLink href={href} {...props}>
|
||||||
<a {...props}>{children}</a>
|
{children}
|
||||||
</NextLink>
|
</NextLink>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
22
site/components/ui/ThemeSwitcher/ThemeIcon.tsx
Normal file
22
site/components/ui/ThemeSwitcher/ThemeIcon.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Moon, Sun, System } from '@components/icons'
|
||||||
|
|
||||||
|
interface ThemeIconProps {
|
||||||
|
theme?: string
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const ThemeIcon = ({ theme, ...props }: ThemeIconProps) => {
|
||||||
|
switch (theme) {
|
||||||
|
case 'light':
|
||||||
|
return <Sun {...props} />
|
||||||
|
|
||||||
|
case 'dark':
|
||||||
|
return <Moon {...props} />
|
||||||
|
|
||||||
|
default:
|
||||||
|
return <System {...props} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThemeIcon
|
80
site/components/ui/ThemeSwitcher/ThemeSwitcher.tsx
Normal file
80
site/components/ui/ThemeSwitcher/ThemeSwitcher.tsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { ChevronRight, Cross } from '@components/icons'
|
||||||
|
import { useToggleTheme } from '@lib/hooks/useToggleTheme'
|
||||||
|
import cn from 'clsx'
|
||||||
|
import ClickOutside from '@lib/click-outside'
|
||||||
|
import ThemeIcon from './ThemeIcon'
|
||||||
|
|
||||||
|
const ThemeSwitcher = () => {
|
||||||
|
const [display, setDisplay] = useState(false)
|
||||||
|
const { theme, themes, setTheme } = useToggleTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ClickOutside active={display} onClick={() => setDisplay(false)}>
|
||||||
|
<div className="relative">
|
||||||
|
<div
|
||||||
|
className="flex items-center relative"
|
||||||
|
onClick={() => setDisplay(!display)}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className={
|
||||||
|
'w-[125px] h-10 pl-2 pr-1 rounded-md border border-accent-2 flex items-center justify-between transition-colors ease-linear hover:border-accent-3 hover:shadow-sm'
|
||||||
|
}
|
||||||
|
aria-label="Theme Switcher"
|
||||||
|
>
|
||||||
|
<span className="flex flex-shrink items-center">
|
||||||
|
<ThemeIcon width={20} height={20} theme={theme} />
|
||||||
|
<span className={cn('capitalize leading-none ml-2')}>
|
||||||
|
{theme}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span className="cursor-pointer">
|
||||||
|
<ChevronRight
|
||||||
|
className={cn('transition duration-300', {
|
||||||
|
['rotate-90']: display,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="absolute top-0 right-0">
|
||||||
|
{themes.length && display ? (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
'fixed shadow-lg right-0 top-12 mt-2 origin-top-right w-full h-full outline-none bg-accent-0 z-40 lg:absolute lg:border lg:border-accent-1 lg:shadow-lg lg:w-56 lg:h-auto'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="flex flex-row justify-end px-6">
|
||||||
|
<button
|
||||||
|
className="md:hidden"
|
||||||
|
onClick={() => setDisplay(false)}
|
||||||
|
aria-label="Close panel"
|
||||||
|
>
|
||||||
|
<Cross className="h-6 w-6" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
{themes.map((t: string) => (
|
||||||
|
<li key={t}>
|
||||||
|
<button
|
||||||
|
className="flex w-full capitalize cursor-pointer px-6 py-3 transition ease-in-out duration-150 text-primary leading-6 font-medium items-center hover:bg-accent-1"
|
||||||
|
role={'link'}
|
||||||
|
onClick={() => {
|
||||||
|
setTheme(t)
|
||||||
|
setDisplay(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ClickOutside>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThemeSwitcher
|
1
site/components/ui/ThemeSwitcher/index.ts
Normal file
1
site/components/ui/ThemeSwitcher/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './ThemeSwitcher'
|
@ -73,9 +73,7 @@ const WishlistCard: React.FC<{
|
|||||||
<div className={s.description}>
|
<div className={s.description}>
|
||||||
<div className="flex-1 mb-6">
|
<div className="flex-1 mb-6">
|
||||||
<h3 className="text-2xl mb-2 -mt-1">
|
<h3 className="text-2xl mb-2 -mt-1">
|
||||||
<Link href={`/product${product.path}`}>
|
<Link href={`/product${product.path}`}>{product.name}</Link>
|
||||||
<a>{product.name}</a>
|
|
||||||
</Link>
|
|
||||||
</h3>
|
</h3>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<Text html={product.description} />
|
<Text html={product.description} />
|
||||||
|
11
site/lib/hooks/useToggleTheme.ts
Normal file
11
site/lib/hooks/useToggleTheme.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { useTheme } from 'next-themes'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
export const useToggleTheme = () => {
|
||||||
|
const { theme, themes, setTheme } = useTheme()
|
||||||
|
const [themeValue, setThemeValue] = useState<string>('system')
|
||||||
|
|
||||||
|
useEffect(() => setThemeValue(theme), [theme])
|
||||||
|
|
||||||
|
return { theme: themeValue, setTheme, themes }
|
||||||
|
}
|
@ -22,10 +22,10 @@
|
|||||||
"@vercel/commerce-local": "workspace:*",
|
"@vercel/commerce-local": "workspace:*",
|
||||||
"@vercel/commerce-ordercloud": "workspace:*",
|
"@vercel/commerce-ordercloud": "workspace:*",
|
||||||
"@vercel/commerce-saleor": "workspace:*",
|
"@vercel/commerce-saleor": "workspace:*",
|
||||||
|
"@vercel/commerce-sfcc": "workspace:*",
|
||||||
"@vercel/commerce-shopify": "workspace:*",
|
"@vercel/commerce-shopify": "workspace:*",
|
||||||
"@vercel/commerce-spree": "workspace:*",
|
"@vercel/commerce-spree": "workspace:*",
|
||||||
"@vercel/commerce-swell": "workspace:*",
|
"@vercel/commerce-swell": "workspace:*",
|
||||||
"@vercel/commerce-sfcc": "workspace:*",
|
|
||||||
"@vercel/commerce-vendure": "workspace:*",
|
"@vercel/commerce-vendure": "workspace:*",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"body-scroll-lock": "^4.0.0-beta.0",
|
"body-scroll-lock": "^4.0.0-beta.0",
|
||||||
@ -35,7 +35,7 @@
|
|||||||
"keen-slider": "^6.7.0",
|
"keen-slider": "^6.7.0",
|
||||||
"lodash.random": "^3.2.0",
|
"lodash.random": "^3.2.0",
|
||||||
"lodash.throttle": "^4.1.1",
|
"lodash.throttle": "^4.1.1",
|
||||||
"next": "^12.3.0",
|
"next": "^13.0.4",
|
||||||
"next-themes": "^0.2.0",
|
"next-themes": "^0.2.0",
|
||||||
"postcss": "^8.3.5",
|
"postcss": "^8.3.5",
|
||||||
"postcss-nesting": "^10.1.10",
|
"postcss-nesting": "^10.1.10",
|
||||||
|
@ -46,6 +46,7 @@ export default function Home({
|
|||||||
key={product.id}
|
key={product.id}
|
||||||
product={product}
|
product={product}
|
||||||
imgProps={{
|
imgProps={{
|
||||||
|
alt: product.name,
|
||||||
width: i === 0 ? 1080 : 540,
|
width: i === 0 ? 1080 : 540,
|
||||||
height: i === 0 ? 1080 : 540,
|
height: i === 0 ? 1080 : 540,
|
||||||
priority: true,
|
priority: true,
|
||||||
@ -68,6 +69,7 @@ export default function Home({
|
|||||||
key={product.id}
|
key={product.id}
|
||||||
product={product}
|
product={product}
|
||||||
imgProps={{
|
imgProps={{
|
||||||
|
alt: product.name,
|
||||||
width: i === 0 ? 1080 : 540,
|
width: i === 0 ? 1080 : 540,
|
||||||
height: i === 0 ? 1080 : 540,
|
height: i === 0 ? 1080 : 540,
|
||||||
}}
|
}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user