-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
309 changed files
with
89,903 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.next | ||
node_modules | ||
gql | ||
|
||
dist | ||
/dist | ||
dist/* | ||
dist/**/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* eslint-env es6 */ | ||
/* eslint-disable no-console */ | ||
|
||
module.exports = { | ||
globals: { | ||
React: true, | ||
JSX: true, | ||
}, | ||
extends: ["next", "prettier", "react-app", "react-app/jest", "plugin:storybook/recommended", "plugin:tailwindcss/recommended"], | ||
parserOptions: { | ||
babelOptions: { | ||
presets: [require.resolve("next/babel")], | ||
}, | ||
ecmaVersion: "latest", | ||
}, | ||
env: { | ||
es6: true, | ||
}, | ||
rules: { | ||
"tailwindcss/no-custom-classname": "off", | ||
"testing-library/prefer-screen-queries": "off", | ||
"@next/next/no-html-link-for-pages": "off", | ||
"@typescript-eslint/no-unused-vars": [ | ||
"warn", | ||
{ | ||
argsIgnorePattern: "^_", | ||
varsIgnorePattern: "^_", | ||
}, | ||
], | ||
"sort-imports": [ | ||
"error", | ||
{ | ||
ignoreCase: true, | ||
ignoreDeclarationSort: true, | ||
}, | ||
], | ||
"tailwindcss/classnames-order": "off", | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
.next/ | ||
out/ | ||
build | ||
|
||
build/** | ||
dist/** | ||
**/dist/** | ||
.next/** | ||
|
||
|
||
/.npm-only-allow | ||
|
||
storybook-static/ | ||
playwright-report/ | ||
playwright/.cache/ | ||
test-results/ | ||
|
||
graph.svg | ||
|
||
# testing | ||
coverage | ||
.vercel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { ApiType, shopifyApiProject } from "@shopify/api-codegen-preset" | ||
|
||
export default { | ||
schema: ["https://shopify.dev/storefront-graphql-direct-proxy/2024-01", "https://shopify.dev/admin-graphql-direct-proxy/2024-01"], | ||
documents: ["./**/*.{js,ts,jsx,tsx}"], | ||
projects: { | ||
default: shopifyApiProject({ | ||
apiType: ApiType.Storefront, | ||
apiVersion: "2024-01", | ||
documents: ["./lib/shopify/**/*.storefront.{js,ts,jsx,tsx}", "./lib/shopify/**/fragments/*.{js,ts,jsx,tsx}"], | ||
outputDir: "./lib/shopify/types", | ||
}), | ||
admin: shopifyApiProject({ | ||
apiType: ApiType.Admin, | ||
apiVersion: "2024-01", | ||
documents: ["./lib/shopify/**/*.admin.{js,ts,jsx,tsx}"], | ||
outputDir: "./lib/shopify/types/admin", | ||
}), | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.next | ||
node_modules | ||
gql |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { dirname, join } from "path" | ||
import type { StorybookConfig } from "@storybook/nextjs" | ||
const config: StorybookConfig = { | ||
stories: ["../components/**/*.mdx", "../components/**/*.stories.@(js|jsx|ts|tsx)"], | ||
addons: [getAbsolutePath("@storybook/addon-links"), getAbsolutePath("@storybook/addon-essentials"), getAbsolutePath("@storybook/addon-interactions")], | ||
framework: { | ||
name: getAbsolutePath("@storybook/nextjs"), | ||
options: {}, | ||
}, | ||
features: { | ||
experimentalRSC: true, | ||
}, | ||
docs: { | ||
autodocs: "tag", | ||
}, | ||
typescript: { | ||
check: false, | ||
checkOptions: {}, | ||
reactDocgen: "react-docgen-typescript", | ||
reactDocgenTypescriptOptions: { | ||
shouldExtractLiteralValuesFromEnum: true, | ||
propFilter: (prop) => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true), | ||
}, | ||
}, | ||
} | ||
export default config | ||
|
||
function getAbsolutePath(value: string): any { | ||
return dirname(require.resolve(join(value, "package.json"))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import type { Preview } from "@storybook/react" | ||
|
||
import "../app/globals.css" | ||
|
||
const preview: Preview = { | ||
parameters: { | ||
actions: { argTypesRegex: "^on[A-Z].*" }, | ||
controls: { | ||
matchers: { | ||
color: /(background|color)$/i, | ||
date: /Date$/, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
export default preview |
35 changes: 35 additions & 0 deletions
35
starters/shopify-algolia/app/.well-known/vercel/flags/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { NextRequest, NextResponse } from "next/server" | ||
import { verifyAccess, type ApiData } from "@vercel/flags" | ||
|
||
export async function GET(request: NextRequest) { | ||
const access = await verifyAccess(request.headers.get("Authorization")) | ||
if (!access) return NextResponse.json(null, { status: 401 }) | ||
|
||
const apiData = { | ||
definitions: { | ||
isVercelAnalyticsEnabled: { | ||
description: "Controls whether the new feature is visible", | ||
options: [ | ||
{ value: false, label: "Off" }, | ||
{ value: true, label: "On" }, | ||
], | ||
}, | ||
isGoogleTagManagerEnabled: { | ||
description: "Controls whether the new feature is visible", | ||
options: [ | ||
{ value: false, label: "Off" }, | ||
{ value: true, label: "On" }, | ||
], | ||
}, | ||
isSpeedInsightsEnabled: { | ||
description: "Controls whether the new feature is visible", | ||
options: [ | ||
{ value: false, label: "Off" }, | ||
{ value: true, label: "On" }, | ||
], | ||
}, | ||
}, | ||
} as ApiData | ||
|
||
return NextResponse.json<ApiData>(apiData) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import Link from "next/link" | ||
|
||
export default function AccessDenied() { | ||
return ( | ||
<div className="mx-auto flex max-w-container-sm flex-col gap-16 px-4 py-32 text-4xl md:py-64"> | ||
<p>Looks like you don't have access to this page. If you were logged in before your session might've expired. Please log in again! 😊 </p> | ||
|
||
<Link href="/" className="text-2xl underline hover:no-underline"> | ||
Go Home | ||
</Link> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
"use server" | ||
|
||
import { revalidateTag, unstable_cache } from "next/cache" | ||
import { cookies } from "next/headers" | ||
import { storefrontClient } from "clients/storefrontClient" | ||
import { COOKIE_CART_ID, TAGS } from "constants/index" | ||
import { isDemoMode } from "utils/demoUtils" | ||
|
||
export const getCart = unstable_cache(async (cartId: string) => storefrontClient.getCart(cartId), [TAGS.CART], { revalidate: 60 * 15, tags: [TAGS.CART] }) | ||
|
||
export async function addCartItem(prevState: any, variantId: string) { | ||
if (isDemoMode()) return { ok: false, message: "Demo mode active. Filtering, searching, and adding to cart disabled." } | ||
if (!variantId) return { ok: false } | ||
|
||
let cartId = cookies().get(COOKIE_CART_ID)?.value | ||
let cart | ||
|
||
if (cartId) cart = await storefrontClient.getCart(cartId) | ||
|
||
if (!cartId || !cart) { | ||
cart = await storefrontClient.createCart([]) | ||
cartId = cart?.id | ||
cartId && cookies().set(COOKIE_CART_ID, cartId) | ||
|
||
revalidateTag(TAGS.CART) | ||
} | ||
|
||
const itemAvailability = await getItemAvailability(cartId, variantId) | ||
|
||
if (!itemAvailability || itemAvailability.inCartQuantity >= itemAvailability.inStockQuantity) | ||
return { | ||
ok: false, | ||
message: "This product is out of stock", | ||
} | ||
|
||
await storefrontClient.createCartItem(cartId!, [{ merchandiseId: variantId, quantity: 1 }]) | ||
revalidateTag(TAGS.CART) | ||
|
||
return { ok: true } | ||
} | ||
|
||
export async function getItemAvailability(cartId: string | null | undefined, variantId: string | null | undefined) { | ||
if (!cartId || !variantId) return { inCartQuantity: 0, inStockQuantity: Infinity } | ||
|
||
const cart = await storefrontClient.getCart(cartId) | ||
const cartItem = cart?.items?.find((item) => item.merchandise.id === variantId) | ||
|
||
return { inCartQuantity: cartItem?.quantity ?? 0, inStockQuantity: cartItem?.merchandise.quantityAvailable ?? Infinity } | ||
} | ||
|
||
export async function removeCartItem(prevState: any, itemId: string) { | ||
const cartId = cookies().get(COOKIE_CART_ID)?.value | ||
|
||
if (!cartId) return { ok: false } | ||
|
||
await storefrontClient.deleteCartItem(cartId!, [itemId]) | ||
revalidateTag(TAGS.CART) | ||
|
||
return { ok: true } | ||
} | ||
|
||
export async function updateItemQuantity(prevState: any, payload: { itemId: string; variantId: string; quantity: number }) { | ||
const cartId = cookies().get(COOKIE_CART_ID)?.value | ||
|
||
if (!cartId) return { ok: false } | ||
|
||
const { itemId, variantId, quantity } = payload | ||
|
||
if (quantity === 0) { | ||
await storefrontClient.deleteCartItem(cartId, [itemId]) | ||
revalidateTag(TAGS.CART) | ||
return { ok: true } | ||
} | ||
|
||
const itemAvailability = await getItemAvailability(cartId, variantId) | ||
if (!itemAvailability || quantity > itemAvailability.inStockQuantity) | ||
return { | ||
ok: false, | ||
message: "This product is out of stock", | ||
} | ||
|
||
await storefrontClient.updateCartItem(cartId, [{ id: itemId, merchandiseId: variantId, quantity }]) | ||
|
||
revalidateTag(TAGS.CART) | ||
return { ok: true } | ||
} |
26 changes: 26 additions & 0 deletions
26
starters/shopify-algolia/app/actions/collection.actions.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
"use server" | ||
|
||
import { unstable_cache } from "next/cache" | ||
import { algolia } from "clients/search" | ||
import { getDemoSingleCategory, isDemoMode } from "utils/demoUtils" | ||
import type { PlatformCollection } from "lib/shopify/types" | ||
import { env } from "env.mjs" | ||
|
||
export const getCollection = unstable_cache( | ||
async (slug: string) => { | ||
if (isDemoMode()) return getDemoSingleCategory(slug) | ||
|
||
const results = await algolia.search<PlatformCollection>({ | ||
indexName: env.ALGOLIA_CATEGORIES_INDEX, | ||
searchParams: { | ||
filters: algolia.filterBuilder().where("handle", slug).build(), | ||
hitsPerPage: 1, | ||
attributesToRetrieve: ["handle", "title", "seo"], | ||
}, | ||
}) | ||
|
||
return results.hits.find(Boolean) || null | ||
}, | ||
["category-by-handle"], | ||
{ revalidate: 3600 } | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
"use server" | ||
|
||
import { COOKIE_FAVORITES } from "constants/index" | ||
import { cookies } from "next/headers" | ||
|
||
export async function toggleFavoriteProduct(prevState: any, handle: string) { | ||
const handles = await getParsedFavoritesHandles() | ||
const isFavorite = handles.includes(handle) | ||
const newFavorites = handles.includes(handle) ? handles.filter((i) => i !== handle) : [...handles, handle] | ||
|
||
cookies().set(COOKIE_FAVORITES, JSON.stringify(newFavorites)) | ||
|
||
return !isFavorite | ||
} | ||
|
||
export async function getParsedFavoritesHandles() { | ||
const favoritesCookie = cookies().get(COOKIE_FAVORITES)?.value || "[]" | ||
const favoritesHandles = JSON.parse(favoritesCookie) as string[] | ||
return favoritesHandles | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
"use server" | ||
|
||
import { storefrontClient } from "clients/storefrontClient" | ||
import { unstable_cache } from "next/cache" | ||
|
||
export const getPage = unstable_cache(async (handle: string) => await storefrontClient.getPage(handle), ["page"], { revalidate: 3600 }) | ||
|
||
export const getAllPages = unstable_cache(async () => await storefrontClient.getAllPages(), ["page"], { revalidate: 3600 }) |
Oops, something went wrong.