astro-tractstack 2.3.4 → 2.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +14 -4
- package/package.json +1 -1
- package/templates/custom/customHelpers.ts +45 -0
- package/templates/custom/shopify/Cart.tsx +2 -2
- package/templates/custom/shopify/CartIcon.tsx +1 -1
- package/templates/custom/shopify/CheckoutModal.tsx +3 -3
- package/templates/custom/shopify/ShopifyCartManager.tsx +3 -3
- package/templates/custom/shopify/ShopifyCheckout.tsx +1 -1
- package/templates/custom/shopify/ShopifyProductGrid.tsx +1 -1
- package/templates/custom/shopify/ShopifyServiceList.tsx +1 -1
- package/templates/custom/shopify/shopifyCustomHelper.ts +10 -0
- package/templates/{src/utils/customHelpers.ts → custom/shopify/shopifyHelpers.ts} +0 -74
- package/templates/src/components/Header.astro +1 -1
- package/templates/src/components/codehooks/SearchWidget.tsx +1 -1
- package/templates/src/components/search/SearchResults.tsx +1 -1
- package/templates/src/components/search/SearchWrapper.tsx +1 -1
- package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +1 -1
- package/templates/src/components/storykeep/shopify/ShopifyDashboard_Sales.tsx +1 -1
- package/utils/inject-files.ts +14 -4
- /package/templates/{src/utils/booking → custom/shopify}/appointmentMode.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -2341,13 +2341,23 @@ async function y(t, e, c) {
|
|
|
2341
2341
|
protected: !0
|
|
2342
2342
|
},
|
|
2343
2343
|
{
|
|
2344
|
-
src: t("../templates/
|
|
2345
|
-
dest: "src/
|
|
2344
|
+
src: t("../templates/custom/customHelpers.ts"),
|
|
2345
|
+
dest: "src/custom/customHelpers.ts",
|
|
2346
2346
|
protected: !0
|
|
2347
2347
|
},
|
|
2348
2348
|
{
|
|
2349
|
-
src: t("../templates/
|
|
2350
|
-
dest: "src/
|
|
2349
|
+
src: t("../templates/custom/shopify/shopifyCustomHelper.ts"),
|
|
2350
|
+
dest: "src/custom/shopify/shopifyCustomHelper.ts",
|
|
2351
|
+
protected: !0
|
|
2352
|
+
},
|
|
2353
|
+
{
|
|
2354
|
+
src: t("../templates/custom/shopify/shopifyHelpers.ts"),
|
|
2355
|
+
dest: "src/custom/shopify/shopifyHelpers.ts",
|
|
2356
|
+
protected: !0
|
|
2357
|
+
},
|
|
2358
|
+
{
|
|
2359
|
+
src: t("../templates/custom/shopify/appointmentMode.ts"),
|
|
2360
|
+
dest: "src/custom/shopify/appointmentMode.ts",
|
|
2351
2361
|
protected: !0
|
|
2352
2362
|
},
|
|
2353
2363
|
{
|
package/package.json
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// URL Helper: Strip category prefix from slug
|
|
2
|
+
// e.g., "people-bleako" -> "bleako"
|
|
3
|
+
export function getCleanSlug(categorySlug: string, fullSlug: string): string {
|
|
4
|
+
const prefix = `${categorySlug}-`;
|
|
5
|
+
return fullSlug.startsWith(prefix) ? fullSlug.slice(prefix.length) : fullSlug;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Build proper URL for resource
|
|
9
|
+
// e.g., category="people", slug="people-bleako" -> "/people/bleako"
|
|
10
|
+
export function getResourceUrl(categorySlug: string, fullSlug: string): string {
|
|
11
|
+
const cleanSlug = getCleanSlug(categorySlug, fullSlug);
|
|
12
|
+
return `/${categorySlug}/${cleanSlug}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Image Helper: Placeholder implementation
|
|
16
|
+
export function getResourceImage(
|
|
17
|
+
id: string,
|
|
18
|
+
slug: string,
|
|
19
|
+
category: string
|
|
20
|
+
): string {
|
|
21
|
+
console.log(`please define getResourceImage`, id, slug, category);
|
|
22
|
+
return '/static.jpg';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getResourceDescription(
|
|
26
|
+
id: string,
|
|
27
|
+
slug: string,
|
|
28
|
+
category: string
|
|
29
|
+
): string | null {
|
|
30
|
+
console.log(`please define getResourceDescription`, id, slug, category);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Initialize search data - override in custom implementation
|
|
35
|
+
export function initSearch(): void {
|
|
36
|
+
// Default implementation does nothing
|
|
37
|
+
// Override this function in your custom implementation to load search data
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Field Visibility Controls for ResourceForm
|
|
41
|
+
export const resourceFormHideFields = ['shopifyImage'];
|
|
42
|
+
|
|
43
|
+
// Field Formatting Controls for ResourceForm
|
|
44
|
+
// Fields listed here will be treated as JSON objects but rendered as stringified text areas
|
|
45
|
+
export const resourceJsonifyFields = ['shopifyData', 'shopifyImage'];
|
|
@@ -12,14 +12,14 @@ import {
|
|
|
12
12
|
type CartItemState,
|
|
13
13
|
} from '@/stores/shopify';
|
|
14
14
|
import { getShopifyImage } from '@/utils/helpers';
|
|
15
|
-
import { deriveAppointmentConstraints } from '@/
|
|
15
|
+
import { deriveAppointmentConstraints } from '@/custom/shopify/appointmentMode';
|
|
16
16
|
import {
|
|
17
17
|
getServiceLinkedProduct,
|
|
18
18
|
getServiceVariantIdFromCanonicalProduct,
|
|
19
19
|
getSharedFeeChargeLineSummary,
|
|
20
20
|
isSharedFeeService,
|
|
21
21
|
parsePrimaryShopifyProductData,
|
|
22
|
-
} from '@/
|
|
22
|
+
} from '@/custom/shopify/shopifyHelpers';
|
|
23
23
|
import type { ResourceNode } from '@/types/compositorTypes';
|
|
24
24
|
|
|
25
25
|
interface CartProps {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useStore } from '@nanostores/react';
|
|
2
2
|
import { cartStore } from '@/stores/shopify';
|
|
3
|
-
import { getCartIconCount } from '@/
|
|
3
|
+
import { getCartIconCount } from '@/custom/shopify/shopifyHelpers';
|
|
4
4
|
import type { ResourceNode } from '@/types/compositorTypes';
|
|
5
5
|
|
|
6
6
|
interface CartIconProps {
|
|
@@ -24,7 +24,8 @@ import { bookingHelpers } from '@/utils/api/bookingHelpers';
|
|
|
24
24
|
import {
|
|
25
25
|
deriveAppointmentConstraints,
|
|
26
26
|
pickInitialAppointmentMode,
|
|
27
|
-
|
|
27
|
+
type AppointmentMode,
|
|
28
|
+
} from '@/custom/shopify/appointmentMode';
|
|
28
29
|
import { NativeBookingCalendar } from './NativeBookingCalendar';
|
|
29
30
|
import { ProfileStorage } from '@/utils/profileStorage';
|
|
30
31
|
import {
|
|
@@ -35,7 +36,7 @@ import {
|
|
|
35
36
|
hasGidBackedCheckout,
|
|
36
37
|
isSharedFeeService,
|
|
37
38
|
parsePrimaryShopifyProductData,
|
|
38
|
-
} from '@/
|
|
39
|
+
} from '@/custom/shopify/shopifyHelpers';
|
|
39
40
|
import type { ResourceNode } from '@/types/compositorTypes';
|
|
40
41
|
|
|
41
42
|
type CheckoutState =
|
|
@@ -45,7 +46,6 @@ type CheckoutState =
|
|
|
45
46
|
| 'SUMMARY'
|
|
46
47
|
| 'PROCESSING'
|
|
47
48
|
| 'SUCCESS';
|
|
48
|
-
type AppointmentMode = 'IN_PERSON' | 'REMOTE';
|
|
49
49
|
|
|
50
50
|
interface CheckoutModalProps {
|
|
51
51
|
maxLength: number;
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
transactionTraceId,
|
|
8
8
|
} from '@/stores/shopify';
|
|
9
9
|
import { bookingHelpers } from '@/utils/api/bookingHelpers';
|
|
10
|
+
import { RESTRICTION_MESSAGES } from '@/custom/shopify/shopifyCustomHelper';
|
|
10
11
|
import {
|
|
11
|
-
RESTRICTION_MESSAGES,
|
|
12
12
|
calculateCartDuration,
|
|
13
13
|
getCartItemKey,
|
|
14
14
|
isSharedFeeService,
|
|
15
|
-
} from '@/
|
|
16
|
-
import { wouldCartHaveImpossibleRemoteMix } from '@/
|
|
15
|
+
} from '@/custom/shopify/shopifyHelpers';
|
|
16
|
+
import { wouldCartHaveImpossibleRemoteMix } from '@/custom/shopify/appointmentMode';
|
|
17
17
|
import type { ResourceNode } from '@/types/compositorTypes';
|
|
18
18
|
import type { CartItemState } from '@/stores/shopify';
|
|
19
19
|
import type { BrandConfigState } from '@/types/tractstack';
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
CART_STATES,
|
|
7
7
|
isShopifyHandoff,
|
|
8
8
|
} from '@/stores/shopify';
|
|
9
|
-
import { buildShopifyCheckoutLines } from '@/
|
|
9
|
+
import { buildShopifyCheckoutLines } from '@/custom/shopify/shopifyHelpers';
|
|
10
10
|
import type { ResourceNode } from '@/types/compositorTypes';
|
|
11
11
|
|
|
12
12
|
interface ShopifyCheckoutProps {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
2
|
import { useStore } from '@nanostores/react';
|
|
3
3
|
import { cartStore, addQueue, type CartAction } from '@/stores/shopify';
|
|
4
|
-
import { collectServiceGids } from '@/
|
|
4
|
+
import { collectServiceGids } from '@/custom/shopify/shopifyHelpers';
|
|
5
5
|
import { getShopifyImage } from '@/utils/helpers';
|
|
6
6
|
import type { ResourceNode } from '@/types/compositorTypes';
|
|
7
7
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const RESTRICTION_MESSAGES = {
|
|
2
|
+
BOOKING: (duration: number) =>
|
|
3
|
+
`This is a ${duration} minute service. On checkout we'll help you book at your convenience.`,
|
|
4
|
+
TERMS: 'Please review the terms for this item before adding it to your cart.',
|
|
5
|
+
MAX_DURATION: (max: number) =>
|
|
6
|
+
`You cannot book more than ${max} minutes of services in one session.`,
|
|
7
|
+
INCOMPATIBLE_REMOTE:
|
|
8
|
+
'This service cannot be combined with the services already in your cart. Some require remote-only delivery while others can only be delivered in person.',
|
|
9
|
+
DEFAULT_ADD: (title: string) => `${title} has been added to your cart.`,
|
|
10
|
+
};
|
|
@@ -2,52 +2,6 @@ import { getCartItemKey as baseGetCartItemKey } from '@/stores/shopify';
|
|
|
2
2
|
import type { CartItemState, CartKeyParams } from '@/stores/shopify';
|
|
3
3
|
import type { ResourceNode } from '@/types/compositorTypes';
|
|
4
4
|
|
|
5
|
-
// URL Helper: Strip category prefix from slug
|
|
6
|
-
// e.g., "people-bleako" -> "bleako"
|
|
7
|
-
export function getCleanSlug(categorySlug: string, fullSlug: string): string {
|
|
8
|
-
const prefix = `${categorySlug}-`;
|
|
9
|
-
return fullSlug.startsWith(prefix) ? fullSlug.slice(prefix.length) : fullSlug;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Build proper URL for resource
|
|
13
|
-
// e.g., category="people", slug="people-bleako" -> "/people/bleako"
|
|
14
|
-
export function getResourceUrl(categorySlug: string, fullSlug: string): string {
|
|
15
|
-
const cleanSlug = getCleanSlug(categorySlug, fullSlug);
|
|
16
|
-
return `/${categorySlug}/${cleanSlug}`;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Image Helper: Placeholder implementation
|
|
20
|
-
export function getResourceImage(
|
|
21
|
-
id: string,
|
|
22
|
-
slug: string,
|
|
23
|
-
category: string
|
|
24
|
-
): string {
|
|
25
|
-
console.log(`please define getResourceImage`, id, slug, category);
|
|
26
|
-
return '/static.jpg';
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function getResourceDescription(
|
|
30
|
-
id: string,
|
|
31
|
-
slug: string,
|
|
32
|
-
category: string
|
|
33
|
-
): string | null {
|
|
34
|
-
console.log(`please define getResourceDescription`, id, slug, category);
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Initialize search data - override in custom implementation
|
|
39
|
-
export function initSearch(): void {
|
|
40
|
-
// Default implementation does nothing
|
|
41
|
-
// Override this function in your custom implementation to load search data
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Field Visibility Controls for ResourceForm
|
|
45
|
-
export const resourceFormHideFields = ['shopifyImage'];
|
|
46
|
-
|
|
47
|
-
// Field Formatting Controls for ResourceForm
|
|
48
|
-
// Fields listed here will be treated as JSON objects but rendered as stringified text areas
|
|
49
|
-
export const resourceJsonifyFields = ['shopifyData', 'shopifyImage'];
|
|
50
|
-
|
|
51
5
|
const SERVICES_ATTR_LIMIT = 255;
|
|
52
6
|
|
|
53
7
|
type CheckoutLineAttribute = { key: string; value: string };
|
|
@@ -70,34 +24,6 @@ export type SharedFeeChargeLineSummary = DepositSummary & {
|
|
|
70
24
|
description?: string;
|
|
71
25
|
};
|
|
72
26
|
|
|
73
|
-
export const RESTRICTION_MESSAGES = {
|
|
74
|
-
BOOKING: (duration: number) =>
|
|
75
|
-
`This is a ${duration} minute service. On checkout we'll help you book at your convenience.`,
|
|
76
|
-
TERMS: 'Please review the terms for this item before adding it to your cart.',
|
|
77
|
-
MAX_DURATION: (max: number) =>
|
|
78
|
-
`You cannot book more than ${max} minutes of services in one session.`,
|
|
79
|
-
INCOMPATIBLE_REMOTE:
|
|
80
|
-
'This service cannot be combined with the services already in your cart. Some require remote-only delivery while others can only be delivered in person.',
|
|
81
|
-
DEFAULT_ADD: (title: string) => `${title} has been added to your cart.`,
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// For CartModal.tsx
|
|
85
|
-
export function checkRestrictions(resource: ResourceNode): boolean {
|
|
86
|
-
// 1. Service / Booking Requirement
|
|
87
|
-
// We check for the explicit option payload value used by services
|
|
88
|
-
if (resource.optionsPayload?.bookingLengthMinutes) {
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// 2. Final Sale / Terms Check
|
|
93
|
-
// Placeholder: In the future, check for flags like resource.optionsPayload?.finalSale
|
|
94
|
-
// if (resource.optionsPayload?.finalSale) {
|
|
95
|
-
// return true;
|
|
96
|
-
// }
|
|
97
|
-
|
|
98
|
-
return false;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
27
|
export function calculateCartDuration(
|
|
102
28
|
cart: Record<string, CartItemState>,
|
|
103
29
|
resources: ResourceNode[]
|
|
@@ -141,7 +141,7 @@ if (hasShopify) {
|
|
|
141
141
|
<div
|
|
142
142
|
class="flex flex-row flex-nowrap justify-between bg-mywhite px-4 pb-3 pt-4 shadow-inner md:px-8"
|
|
143
143
|
>
|
|
144
|
-
<h1 class="truncate text-
|
|
144
|
+
<h1 class="truncate text-2xl text-mydarkgrey">{title}</h1>
|
|
145
145
|
<div class="flex flex-row flex-nowrap items-center gap-x-2">
|
|
146
146
|
{
|
|
147
147
|
!isHome ? (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react';
|
|
2
2
|
import MagnifyingGlassIcon from '@heroicons/react/24/outline/MagnifyingGlassIcon';
|
|
3
|
-
import { initSearch } from '@/
|
|
3
|
+
import { initSearch } from '@/custom/customHelpers';
|
|
4
4
|
import SearchModal from './SearchModal';
|
|
5
5
|
import type { FullContentMapItem } from '@/types/tractstack';
|
|
6
6
|
|
package/utils/inject-files.ts
CHANGED
|
@@ -2385,13 +2385,23 @@ export async function injectTemplateFiles(
|
|
|
2385
2385
|
protected: true,
|
|
2386
2386
|
},
|
|
2387
2387
|
{
|
|
2388
|
-
src: resolve('../templates/
|
|
2389
|
-
dest: 'src/
|
|
2388
|
+
src: resolve('../templates/custom/customHelpers.ts'),
|
|
2389
|
+
dest: 'src/custom/customHelpers.ts',
|
|
2390
2390
|
protected: true,
|
|
2391
2391
|
},
|
|
2392
2392
|
{
|
|
2393
|
-
src: resolve('../templates/
|
|
2394
|
-
dest: 'src/
|
|
2393
|
+
src: resolve('../templates/custom/shopify/shopifyCustomHelper.ts'),
|
|
2394
|
+
dest: 'src/custom/shopify/shopifyCustomHelper.ts',
|
|
2395
|
+
protected: true,
|
|
2396
|
+
},
|
|
2397
|
+
{
|
|
2398
|
+
src: resolve('../templates/custom/shopify/shopifyHelpers.ts'),
|
|
2399
|
+
dest: 'src/custom/shopify/shopifyHelpers.ts',
|
|
2400
|
+
protected: true,
|
|
2401
|
+
},
|
|
2402
|
+
{
|
|
2403
|
+
src: resolve('../templates/custom/shopify/appointmentMode.ts'),
|
|
2404
|
+
dest: 'src/custom/shopify/appointmentMode.ts',
|
|
2395
2405
|
protected: true,
|
|
2396
2406
|
},
|
|
2397
2407
|
{
|
|
File without changes
|