detail page port

This commit is contained in:
nicwands
2026-05-29 11:22:56 -04:00
parent b85d28c142
commit e22d75c50a
65 changed files with 7006 additions and 4044 deletions

10
libs/resolveEventType.ts Normal file
View File

@@ -0,0 +1,10 @@
enum EVENT_TYPE {
'Ticket Purchase' = 'product',
'Free RSVP' = 'rsvp',
}
export const resolveEventType = (
label: 'Ticket Purchase' | 'Free RSVP',
): EVENT_TYPE => {
return EVENT_TYPE[label]
}

133
libs/shopify/cart.js Normal file
View File

@@ -0,0 +1,133 @@
import { gql } from 'graphql-request'
import { IMAGE_FRAGMENT, PRICE_FRAGMENT } from './fragments'
export const CART_FRAGMENT = gql`
fragment CartFields on Cart {
id
checkoutUrl
cost {
subtotalAmount {
...PriceFields
}
}
totalQuantity
discountCodes {
code
applicable
}
buyerIdentity {
email
customer {
id
}
}
lines(first: 100) {
edges {
node {
id
cost {
totalAmount {
...PriceFields
}
}
quantity
merchandise {
... on ProductVariant {
id
product {
handle
title
}
image {
...ImageFields
}
selectedOptions {
name
value
}
}
}
}
}
}
}
`
export const CREATE_CART = gql`
${PRICE_FRAGMENT}
${IMAGE_FRAGMENT}
${CART_FRAGMENT}
mutation createCart($input: CartInput) {
cartCreate(input: $input) {
cart {
...CartFields
}
}
}
`
export const ADD_TO_CART = gql`
${PRICE_FRAGMENT}
${IMAGE_FRAGMENT}
${CART_FRAGMENT}
mutation addToCart($cartId: ID!, $lines: [CartLineInput!]!) {
cartLinesAdd(cartId: $cartId, lines: $lines) {
cart {
...CartFields
}
}
}
`
export const REMOVE_FROM_CART = gql`
${PRICE_FRAGMENT}
${IMAGE_FRAGMENT}
${CART_FRAGMENT}
mutation removeFromCart($cartId: ID!, $lineIds: [ID!]!) {
cartLinesRemove(cartId: $cartId, lineIds: $lineIds) {
cart {
...CartFields
}
}
}
`
export const UPDATE_DISCOUNT_CODES = gql`
${PRICE_FRAGMENT}
${IMAGE_FRAGMENT}
${CART_FRAGMENT}
mutation updateDiscountCodes($cartId: ID!, $discountCodes: [String!]!) {
cartDiscountCodesUpdate(
cartId: $cartId
discountCodes: $discountCodes
) {
cart {
...CartFields
}
}
}
`
export const UPDATE_BUYER_ID = gql`
${PRICE_FRAGMENT}
${IMAGE_FRAGMENT}
${CART_FRAGMENT}
mutation updateBuyerId(
$cartId: ID!
$buyerIdentity: CartBuyerIdentityInput!
) {
cartBuyerIdentityUpdate(
cartId: $cartId
buyerIdentity: $buyerIdentity
) {
cart {
...CartFields
}
}
}
`

View File

@@ -0,0 +1,52 @@
import { gql } from 'graphql-request'
import { IMAGE_FRAGMENT, PRICE_FRAGMENT } from './fragments'
import { PRODUCT_FRAGMENT } from './product'
export const COLLECTION_FRAGMENT = gql`
fragment CollectionFields on Collection {
id
handle
title
description
image {
...ImageFields
}
products(first: 100) {
edges {
node {
...ProductFields
}
}
}
}
`
export const GET_COLLECTIONS = gql`
${IMAGE_FRAGMENT}
${PRICE_FRAGMENT}
${PRODUCT_FRAGMENT}
${COLLECTION_FRAGMENT}
query getCollections($first: Int!) {
collections(first: $first) {
edges {
node {
...CollectionFields
}
}
}
}
`
export const GET_COLLECTION_BY_HANDLE = gql`
${IMAGE_FRAGMENT}
${PRICE_FRAGMENT}
${PRODUCT_FRAGMENT}
${COLLECTION_FRAGMENT}
query getCollectionByHandle($handle: String) {
collection(handle: $handle) {
...CollectionFields
}
}
`

83
libs/shopify/customer.js Normal file
View File

@@ -0,0 +1,83 @@
import { gql } from 'graphql-request'
import { IMAGE_FRAGMENT, PRICE_FRAGMENT } from './fragments'
export const GET_CUSTOMER = gql`
${IMAGE_FRAGMENT}
${PRICE_FRAGMENT}
query getCustomer {
customer {
id
defaultAddress {
address1
address2
city
zoneCode
zip
country
}
firstName
lastName
emailAddress {
emailAddress
}
orders(first: 100) {
edges {
node {
id
name
number
createdAt
statusPageUrl
totalPrice {
amount
currencyCode
}
lineItems(first: 100) {
edges {
node {
id
name
image {
...ImageFields
}
price {
...PriceFields
}
}
}
}
}
}
}
}
}
`
export const UPDATE_CUSTOMER = gql`
mutation updateCustomerAndAddress(
$address: CustomerAddressInput!
$input: CustomerUpdateInput!
) {
customerAddressCreate(address: $address, defaultAddress: true) {
customerAddress {
address1
address2
city
province
country
}
userErrors {
code
field
message
}
}
customerUpdate(input: $input) {
customer {
firstName
lastName
}
}
}
`

19
libs/shopify/fragments.js Normal file
View File

@@ -0,0 +1,19 @@
// Misc fragments used throughout
import { gql } from 'graphql-request'
export const IMAGE_FRAGMENT = gql`
fragment ImageFields on Image {
url
altText
width
height
}
`
export const PRICE_FRAGMENT = gql`
fragment PriceFields on MoneyV2 {
amount
currencyCode
}
`

20
libs/shopify/menu.js Normal file
View File

@@ -0,0 +1,20 @@
import { gql } from 'graphql-request'
export const GET_MENU = gql`
query getMenu($handle: String!) {
menu(handle: $handle) {
id
title
items {
id
title
url
items {
id
title
url
}
}
}
}
`

143
libs/shopify/product.js Normal file
View File

@@ -0,0 +1,143 @@
import { gql } from 'graphql-request'
import { IMAGE_FRAGMENT, PRICE_FRAGMENT } from './fragments'
// Base fragment for product
// with product metafield of a list of files (images)
// called 'community_images'
export const PRODUCT_FRAGMENT = gql`
fragment ProductFields on Product {
id
handle
title
descriptionHtml
metafields(
identifiers: [
{ namespace: "custom", key: "community_images" }
{ namespace: "custom", key: "size_guide" }
{ namespace: "custom", key: "member_gated" }
{ namespace: "custom", key: "member_discounted" }
]
) {
key
namespace
id
type
value
references(first: 100) {
edges {
node {
... on MediaImage {
image {
...ImageFields
}
}
}
}
}
}
featuredImage {
...ImageFields
}
priceRange {
minVariantPrice {
...PriceFields
}
}
options {
id
name
optionValues {
id
name
}
}
sellingPlanGroups(first: 1) {
edges {
node {
name
options {
name
values
}
sellingPlans(first: 3) {
edges {
node {
id
name
description
recurringDeliveries
options {
name
value
}
}
}
}
}
}
}
}
`
export const GET_PRODUCTS = gql`
${IMAGE_FRAGMENT}
${PRICE_FRAGMENT}
${PRODUCT_FRAGMENT}
query getProducts($first: Int!) {
products(first: $first) {
edges {
node {
...ProductFields
}
}
}
}
`
export const GET_PRODUCT_BY_HANDLE = gql`
${IMAGE_FRAGMENT}
${PRICE_FRAGMENT}
${PRODUCT_FRAGMENT}
query getProductByHandle($handle: String!) {
product(handle: $handle) {
...ProductFields
images(first: 100) {
edges {
node {
...ImageFields
}
}
}
variants(first: 100) {
edges {
node {
id
title
selectedOptions {
name
value
}
price {
...PriceFields
}
availableForSale
}
}
}
}
}
`
export const GET_PRODUCT_RECOMMENDATIONS = gql`
${IMAGE_FRAGMENT}
${PRICE_FRAGMENT}
${PRODUCT_FRAGMENT}
query getProductRecommendations($handle: String!) {
productRecommendations(productHandle: $handle) {
...ProductFields
}
}
`

View File

@@ -1,25 +1,39 @@
const colors = {
black: '#181818',
white: '#D5D5D5',
'grey-100': '#747474',
green: '#87FF5B',
blue: '#5B92FF',
purple: '#94079E',
red: '#D40202',
import gsap from 'gsap'
const generateShades = (colors) => {
const result = {}
for (const [key, value] of Object.entries(colors)) {
result[key] = value
for (let i = 0; i <= 19; i++) {
const split = gsap.utils.splitColor(value)
const rgb = split.toString().replaceAll(',', ' ')
const alpha = parseInt((((i / 20) * 0xff) / 255) * 100)
result[`${key}-${i * 5}`] = `rgb(${rgb} / ${alpha}%)`
}
}
return result
}
const colors = generateShades({
black: '#0B0D0B',
white: '#FCFCF6',
purple: '#541CDC',
})
const themes = {
dark: {
bg: colors.black,
fg: colors.white,
accent: colors.green,
link: colors.blue,
},
light: {
bg: colors.white,
fg: colors.black,
accent: colors.purple,
link: colors.blue,
contrast: colors.purple,
},
dark: {
bg: colors.black,
fg: colors.white,
contrast: colors.purple,
},
}
@@ -29,20 +43,23 @@ const breakpoints = {
const viewports = {
mobile: {
width: 440,
height: 956,
width: 480,
height: 872,
},
desktop: {
width: 1728,
height: 1117,
width: 1920,
height: 1080,
},
}
export { colors, themes, breakpoints, viewports }
const scrollSmoothing = 0.7
export { colors, themes, breakpoints, viewports, scrollSmoothing }
export default {
colors,
themes,
breakpoints,
viewports,
scrollSmoothing,
}