astro-tractstack 2.2.10 → 2.3.1
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/README.md +1 -1
- package/bin/create-tractstack.js +2 -2
- package/dist/index.js +177 -18
- package/package.json +4 -2
- package/templates/custom/minimal/CodeHook.astro +22 -5
- package/templates/custom/shopify/Cart.tsx +372 -0
- package/templates/custom/shopify/CartIcon.tsx +47 -0
- package/templates/custom/shopify/CartModal.tsx +63 -0
- package/templates/custom/shopify/CheckoutModal.tsx +576 -0
- package/templates/custom/shopify/NativeBookingCalendar.tsx +375 -0
- package/templates/custom/shopify/ShopifyCartManager.tsx +200 -0
- package/templates/custom/shopify/ShopifyCheckout.tsx +167 -0
- package/templates/custom/shopify/ShopifyProductGrid.tsx +247 -0
- package/templates/custom/shopify/ShopifyServiceList.tsx +135 -0
- package/templates/custom/shopify/cart.astro +23 -0
- package/templates/custom/with-examples/CodeHook.astro +17 -1
- package/templates/custom/with-examples/ProductGrid.astro +1 -1
- package/templates/src/client/app.js +4 -2
- package/templates/src/components/Footer.astro +4 -4
- package/templates/src/components/Header.astro +44 -12
- package/templates/src/components/edit/pane/AddPanePanel_new.tsx +3 -3
- package/templates/src/components/edit/pane/AiRestylePaneModal.tsx +2 -2
- package/templates/src/components/edit/pane/steps/AiCreativeDesignStep.tsx +2 -2
- package/templates/src/components/edit/pane/steps/AiLibraryCopyStep.tsx +3 -3
- package/templates/src/components/edit/pane/steps/AiRefineDesignStep.tsx +2 -2
- package/templates/src/components/edit/pane/steps/AiStandardDesignStep.tsx +7 -7
- package/templates/src/components/form/advanced/APIConfigSection.tsx +407 -38
- package/templates/src/components/form/shopify/SchedulingSection.tsx +354 -0
- package/templates/src/components/storykeep/Dashboard.tsx +18 -4
- package/templates/src/components/storykeep/Dashboard_Advanced.tsx +1 -0
- package/templates/src/components/storykeep/Dashboard_Content.tsx +5 -96
- package/templates/src/components/storykeep/Dashboard_Shopify.tsx +668 -0
- package/templates/src/components/storykeep/StoryKeepBackdrop.astro +43 -23
- package/templates/src/components/storykeep/controls/content/BeliefTable.tsx +14 -5
- package/templates/src/components/storykeep/controls/content/ContentBrowser.tsx +0 -14
- package/templates/src/components/storykeep/controls/content/KnownResourceForm.tsx +36 -13
- package/templates/src/components/storykeep/controls/content/KnownResourceTable.tsx +5 -2
- package/templates/src/components/storykeep/controls/content/ManageContent.tsx +4 -11
- package/templates/src/components/storykeep/controls/content/MenuTable.tsx +14 -5
- package/templates/src/components/storykeep/controls/content/ProductTable.tsx +333 -0
- package/templates/src/components/storykeep/controls/content/ResourceBulkIngest.tsx +9 -5
- package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +108 -8
- package/templates/src/components/storykeep/controls/content/ResourceTable.tsx +13 -4
- package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +14 -5
- package/templates/src/components/storykeep/shopify/ShopifyDashboard.tsx +111 -0
- package/templates/src/components/storykeep/shopify/ShopifyDashboard_Bookings.tsx +393 -0
- package/templates/src/components/storykeep/shopify/ShopifyDashboard_Products.tsx +46 -0
- package/templates/src/components/storykeep/shopify/ShopifyDashboard_Schedule.tsx +78 -0
- package/templates/src/components/storykeep/shopify/ShopifyDashboard_Search.tsx +55 -0
- package/templates/src/components/storykeep/shopify/ShopifyDashboard_Services.tsx +47 -0
- package/templates/src/lib/resources.ts +11 -21
- package/templates/src/pages/api/auth/lookup-lead.ts +72 -0
- package/templates/src/pages/api/booking/availability.ts +72 -0
- package/templates/src/pages/api/booking/cancel.ts +73 -0
- package/templates/src/pages/api/booking/confirm.ts +82 -0
- package/templates/src/pages/api/booking/hold.ts +75 -0
- package/templates/src/pages/api/booking/list.ts +66 -0
- package/templates/src/pages/api/booking/metrics.ts +60 -0
- package/templates/src/pages/api/booking/release.ts +76 -0
- package/templates/src/pages/api/sandbox.ts +2 -2
- package/templates/src/pages/api/shopify/createCart.ts +69 -0
- package/templates/src/pages/api/shopify/getProducts.ts +64 -0
- package/templates/src/pages/storykeep/login.astro +26 -24
- package/templates/src/pages/storykeep/logout.astro +1 -10
- package/templates/src/pages/storykeep/manage.astro +69 -0
- package/templates/src/pages/storykeep/{content.astro → pages.astro} +4 -8
- package/templates/src/pages/storykeep/shopify.astro +101 -0
- package/templates/src/stores/navigation.ts +3 -42
- package/templates/src/stores/nodes.ts +3 -1
- package/templates/src/stores/resources.ts +7 -10
- package/templates/src/stores/shopify.ts +266 -0
- package/templates/src/types/tractstack.ts +75 -0
- package/templates/src/utils/api/advancedConfig.ts +7 -1
- package/templates/src/utils/api/advancedHelpers.ts +87 -7
- package/templates/src/utils/api/bookingHelpers.ts +125 -0
- package/templates/src/utils/api/brandHelpers.ts +14 -0
- package/templates/src/utils/api/resourceConfig.ts +13 -5
- package/templates/src/utils/auth.ts +29 -9
- package/templates/src/utils/compositor/aiGeneration.ts +3 -3
- package/templates/src/utils/compositor/aiPaneParser.ts +2 -2
- package/templates/src/utils/customHelpers.ts +49 -0
- package/templates/src/utils/helpers.ts +59 -0
- package/templates/src/utils/profileStorage.ts +5 -0
- package/templates/src/utils/tenantResolver.ts +2 -1
- package/utils/inject-files.ts +161 -2
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import { headerResourcesStore, HEADER_RESOURCES_TTL } from '@/stores/resources';
|
|
2
2
|
import type { ResourceNode } from '@/types/compositorTypes';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Fetches resource nodes based on categories, with server-side in-memory caching
|
|
6
|
-
* to prevent redundant API calls for high-traffic, site-wide components.
|
|
7
|
-
*
|
|
8
|
-
* @param tenantId The ID of the current tenant.
|
|
9
|
-
* @param categories An array of resource category slugs to fetch.
|
|
10
|
-
* @param ttl Optional. The Time-To-Live for the cache in milliseconds. Defaults to 5 minutes.
|
|
11
|
-
* @returns A promise that resolves to an array of ResourceNode objects.
|
|
12
|
-
*/
|
|
13
4
|
export async function getHeaderResources(
|
|
14
5
|
tenantId: string,
|
|
15
6
|
categories: string[],
|
|
@@ -17,13 +8,16 @@ export async function getHeaderResources(
|
|
|
17
8
|
): Promise<ResourceNode[]> {
|
|
18
9
|
const cache = headerResourcesStore.get();
|
|
19
10
|
const now = Date.now();
|
|
11
|
+
const cacheKey = [...categories].sort().join(',');
|
|
20
12
|
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
if (
|
|
14
|
+
cache.key === cacheKey &&
|
|
15
|
+
cache.data.length > 0 &&
|
|
16
|
+
now - cache.lastFetched < ttl
|
|
17
|
+
) {
|
|
23
18
|
return cache.data;
|
|
24
19
|
}
|
|
25
20
|
|
|
26
|
-
// If no categories are requested, there's nothing to fetch.
|
|
27
21
|
if (!categories || categories.length === 0) {
|
|
28
22
|
return [];
|
|
29
23
|
}
|
|
@@ -32,7 +26,6 @@ export async function getHeaderResources(
|
|
|
32
26
|
import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
|
|
33
27
|
|
|
34
28
|
try {
|
|
35
|
-
// THIS IS THE CORRECTED ENDPOINT
|
|
36
29
|
const response = await fetch(`${goBackend}/api/v1/nodes/resources`, {
|
|
37
30
|
method: 'POST',
|
|
38
31
|
headers: {
|
|
@@ -44,26 +37,23 @@ export async function getHeaderResources(
|
|
|
44
37
|
|
|
45
38
|
if (!response.ok) {
|
|
46
39
|
console.error(
|
|
47
|
-
`Failed to fetch
|
|
40
|
+
`Failed to fetch resources for [${cacheKey}]. Status: ${response.status}`
|
|
48
41
|
);
|
|
49
|
-
|
|
50
|
-
return cache.data;
|
|
42
|
+
return cache.key === cacheKey ? cache.data : [];
|
|
51
43
|
}
|
|
52
44
|
|
|
53
|
-
// The backend returns a payload like { resources: [...] }
|
|
54
45
|
const responsePayload = await response.json();
|
|
55
46
|
const resources: ResourceNode[] = responsePayload.resources || [];
|
|
56
47
|
|
|
57
|
-
// Update the store with the new data and timestamp.
|
|
58
48
|
headerResourcesStore.set({
|
|
59
49
|
data: resources,
|
|
60
50
|
lastFetched: now,
|
|
51
|
+
key: cacheKey,
|
|
61
52
|
});
|
|
62
53
|
|
|
63
54
|
return resources;
|
|
64
55
|
} catch (error) {
|
|
65
|
-
console.error('Error fetching
|
|
66
|
-
|
|
67
|
-
return cache.data;
|
|
56
|
+
console.error('Error fetching resources:', error);
|
|
57
|
+
return cache.key === cacheKey ? cache.data : [];
|
|
68
58
|
}
|
|
69
59
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { APIRoute } from '@/types/astro';
|
|
2
|
+
|
|
3
|
+
export const POST: APIRoute = async ({ request, locals }) => {
|
|
4
|
+
const GO_BACKEND =
|
|
5
|
+
import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
const body = await request.text();
|
|
9
|
+
|
|
10
|
+
const controller = new AbortController();
|
|
11
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
12
|
+
const tenantId =
|
|
13
|
+
locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(`${GO_BACKEND}/api/v1/auth/lookup-lead`, {
|
|
17
|
+
method: 'POST',
|
|
18
|
+
headers: {
|
|
19
|
+
'Content-Type': 'application/json',
|
|
20
|
+
'X-Tenant-ID': tenantId,
|
|
21
|
+
},
|
|
22
|
+
body: body,
|
|
23
|
+
signal: controller.signal,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
clearTimeout(timeoutId);
|
|
27
|
+
|
|
28
|
+
const data = await response.json();
|
|
29
|
+
|
|
30
|
+
return new Response(JSON.stringify(data), {
|
|
31
|
+
status: response.status,
|
|
32
|
+
headers: {
|
|
33
|
+
'Content-Type': 'application/json',
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
} catch (fetchError) {
|
|
37
|
+
clearTimeout(timeoutId);
|
|
38
|
+
|
|
39
|
+
if (fetchError instanceof Error && fetchError.name === 'AbortError') {
|
|
40
|
+
console.error('Lookup-lead request timeout');
|
|
41
|
+
return new Response(
|
|
42
|
+
JSON.stringify({
|
|
43
|
+
success: false,
|
|
44
|
+
error: 'Request timeout - please try again',
|
|
45
|
+
}),
|
|
46
|
+
{
|
|
47
|
+
status: 408,
|
|
48
|
+
headers: {
|
|
49
|
+
'Content-Type': 'application/json',
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
throw fetchError;
|
|
55
|
+
}
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Lookup-lead API proxy error:', error);
|
|
58
|
+
|
|
59
|
+
return new Response(
|
|
60
|
+
JSON.stringify({
|
|
61
|
+
success: false,
|
|
62
|
+
error: 'Failed to connect to backend service',
|
|
63
|
+
}),
|
|
64
|
+
{
|
|
65
|
+
status: 500,
|
|
66
|
+
headers: {
|
|
67
|
+
'Content-Type': 'application/json',
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { APIRoute } from '@/types/astro';
|
|
2
|
+
|
|
3
|
+
export const GET: APIRoute = async ({ request, locals }) => {
|
|
4
|
+
const GO_BACKEND =
|
|
5
|
+
import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
const url = new URL(request.url);
|
|
9
|
+
const searchParams = url.searchParams;
|
|
10
|
+
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
13
|
+
const tenantId =
|
|
14
|
+
locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const response = await fetch(
|
|
18
|
+
`${GO_BACKEND}/api/v1/bookings/availability?${searchParams.toString()}`,
|
|
19
|
+
{
|
|
20
|
+
method: 'GET',
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
'X-Tenant-ID': tenantId,
|
|
24
|
+
...(request.headers.get('Authorization') && {
|
|
25
|
+
Authorization: request.headers.get('Authorization')!,
|
|
26
|
+
}),
|
|
27
|
+
},
|
|
28
|
+
signal: controller.signal,
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
clearTimeout(timeoutId);
|
|
33
|
+
|
|
34
|
+
const data = await response.json();
|
|
35
|
+
|
|
36
|
+
return new Response(JSON.stringify(data), {
|
|
37
|
+
status: response.status,
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
} catch (fetchError) {
|
|
43
|
+
clearTimeout(timeoutId);
|
|
44
|
+
|
|
45
|
+
if (fetchError instanceof Error && fetchError.name === 'AbortError') {
|
|
46
|
+
return new Response(
|
|
47
|
+
JSON.stringify({
|
|
48
|
+
success: false,
|
|
49
|
+
error: 'Availability lookup timeout',
|
|
50
|
+
}),
|
|
51
|
+
{
|
|
52
|
+
status: 408,
|
|
53
|
+
headers: { 'Content-Type': 'application/json' },
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
throw fetchError;
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error('Availability API proxy error:', error);
|
|
61
|
+
return new Response(
|
|
62
|
+
JSON.stringify({
|
|
63
|
+
success: false,
|
|
64
|
+
error: 'Failed to connect to backend service',
|
|
65
|
+
}),
|
|
66
|
+
{
|
|
67
|
+
status: 500,
|
|
68
|
+
headers: { 'Content-Type': 'application/json' },
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { APIRoute } from '@/types/astro';
|
|
2
|
+
import { getAdminToken } from '@/utils/auth';
|
|
3
|
+
|
|
4
|
+
export const POST: APIRoute = async (context) => {
|
|
5
|
+
const { request, locals } = context;
|
|
6
|
+
const GO_BACKEND =
|
|
7
|
+
import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const body = await request.json();
|
|
11
|
+
const { traceId } = body;
|
|
12
|
+
|
|
13
|
+
if (!traceId) {
|
|
14
|
+
return new Response(
|
|
15
|
+
JSON.stringify({ success: false, error: 'traceId is required' }),
|
|
16
|
+
{ status: 400, headers: { 'Content-Type': 'application/json' } }
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const controller = new AbortController();
|
|
21
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
22
|
+
const tenantId =
|
|
23
|
+
locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
|
|
24
|
+
const token = getAdminToken(context);
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const response = await fetch(
|
|
28
|
+
`${GO_BACKEND}/api/v1/bookings/${traceId}/cancel`,
|
|
29
|
+
{
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: {
|
|
32
|
+
'Content-Type': 'application/json',
|
|
33
|
+
'X-Tenant-ID': tenantId,
|
|
34
|
+
...(token && { Authorization: `Bearer ${token}` }),
|
|
35
|
+
...(request.headers.get('Authorization') && {
|
|
36
|
+
Authorization: request.headers.get('Authorization')!,
|
|
37
|
+
}),
|
|
38
|
+
},
|
|
39
|
+
signal: controller.signal,
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
clearTimeout(timeoutId);
|
|
44
|
+
const data = await response.json();
|
|
45
|
+
|
|
46
|
+
return new Response(JSON.stringify(data), {
|
|
47
|
+
status: response.status,
|
|
48
|
+
headers: { 'Content-Type': 'application/json' },
|
|
49
|
+
});
|
|
50
|
+
} catch (fetchError) {
|
|
51
|
+
clearTimeout(timeoutId);
|
|
52
|
+
if (fetchError instanceof Error && fetchError.name === 'AbortError') {
|
|
53
|
+
return new Response(
|
|
54
|
+
JSON.stringify({
|
|
55
|
+
success: false,
|
|
56
|
+
error: 'Booking cancellation timeout',
|
|
57
|
+
}),
|
|
58
|
+
{ status: 408, headers: { 'Content-Type': 'application/json' } }
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
throw fetchError;
|
|
62
|
+
}
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error('Booking cancellation API proxy error:', error);
|
|
65
|
+
return new Response(
|
|
66
|
+
JSON.stringify({
|
|
67
|
+
success: false,
|
|
68
|
+
error: 'Failed to connect to backend service',
|
|
69
|
+
}),
|
|
70
|
+
{ status: 500, headers: { 'Content-Type': 'application/json' } }
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { APIRoute } from '@/types/astro';
|
|
2
|
+
|
|
3
|
+
export const POST: APIRoute = async ({ request, locals }) => {
|
|
4
|
+
const GO_BACKEND =
|
|
5
|
+
import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
const { traceId } = await request.json();
|
|
9
|
+
|
|
10
|
+
if (!traceId) {
|
|
11
|
+
return new Response(JSON.stringify({ error: 'traceId is required' }), {
|
|
12
|
+
status: 400,
|
|
13
|
+
headers: { 'Content-Type': 'application/json' },
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
19
|
+
const tenantId =
|
|
20
|
+
locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const response = await fetch(`${GO_BACKEND}/api/v1/bookings/confirm`, {
|
|
24
|
+
method: 'POST',
|
|
25
|
+
headers: {
|
|
26
|
+
'Content-Type': 'application/json',
|
|
27
|
+
'X-Tenant-ID': tenantId,
|
|
28
|
+
...(request.headers.get('Authorization') && {
|
|
29
|
+
Authorization: request.headers.get('Authorization')!,
|
|
30
|
+
}),
|
|
31
|
+
},
|
|
32
|
+
body: JSON.stringify({ traceId }),
|
|
33
|
+
signal: controller.signal,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
clearTimeout(timeoutId);
|
|
37
|
+
|
|
38
|
+
const data = await response.json();
|
|
39
|
+
|
|
40
|
+
return new Response(JSON.stringify(data), {
|
|
41
|
+
status: response.status,
|
|
42
|
+
headers: {
|
|
43
|
+
'Content-Type': 'application/json',
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
} catch (fetchError) {
|
|
47
|
+
clearTimeout(timeoutId);
|
|
48
|
+
|
|
49
|
+
if (fetchError instanceof Error && fetchError.name === 'AbortError') {
|
|
50
|
+
console.error('Confirm-booking request timeout');
|
|
51
|
+
return new Response(
|
|
52
|
+
JSON.stringify({
|
|
53
|
+
success: false,
|
|
54
|
+
error: 'Request timeout - please try again',
|
|
55
|
+
}),
|
|
56
|
+
{
|
|
57
|
+
status: 408,
|
|
58
|
+
headers: {
|
|
59
|
+
'Content-Type': 'application/json',
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
throw fetchError;
|
|
65
|
+
}
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error('Confirm-booking API proxy error:', error);
|
|
68
|
+
|
|
69
|
+
return new Response(
|
|
70
|
+
JSON.stringify({
|
|
71
|
+
success: false,
|
|
72
|
+
error: 'Failed to connect to backend service',
|
|
73
|
+
}),
|
|
74
|
+
{
|
|
75
|
+
status: 500,
|
|
76
|
+
headers: {
|
|
77
|
+
'Content-Type': 'application/json',
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { APIRoute } from '@/types/astro';
|
|
2
|
+
|
|
3
|
+
export const POST: APIRoute = async ({ request, locals }) => {
|
|
4
|
+
const GO_BACKEND =
|
|
5
|
+
import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
const body = await request.text();
|
|
9
|
+
|
|
10
|
+
const controller = new AbortController();
|
|
11
|
+
const timeoutId = setTimeout(() => controller.abort(), 30000);
|
|
12
|
+
const tenantId =
|
|
13
|
+
locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(`${GO_BACKEND}/api/v1/bookings/hold`, {
|
|
17
|
+
method: 'POST',
|
|
18
|
+
headers: {
|
|
19
|
+
'Content-Type': 'application/json',
|
|
20
|
+
'X-Tenant-ID': tenantId,
|
|
21
|
+
...(request.headers.get('Authorization') && {
|
|
22
|
+
Authorization: request.headers.get('Authorization')!,
|
|
23
|
+
}),
|
|
24
|
+
},
|
|
25
|
+
body: body,
|
|
26
|
+
signal: controller.signal,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
clearTimeout(timeoutId);
|
|
30
|
+
|
|
31
|
+
const data = await response.json();
|
|
32
|
+
|
|
33
|
+
return new Response(JSON.stringify(data), {
|
|
34
|
+
status: response.status,
|
|
35
|
+
headers: {
|
|
36
|
+
'Content-Type': 'application/json',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
} catch (fetchError) {
|
|
40
|
+
clearTimeout(timeoutId);
|
|
41
|
+
|
|
42
|
+
if (fetchError instanceof Error && fetchError.name === 'AbortError') {
|
|
43
|
+
console.error('Hold-slot request timeout');
|
|
44
|
+
return new Response(
|
|
45
|
+
JSON.stringify({
|
|
46
|
+
success: false,
|
|
47
|
+
error: 'Request timeout - please try again',
|
|
48
|
+
}),
|
|
49
|
+
{
|
|
50
|
+
status: 408,
|
|
51
|
+
headers: {
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
throw fetchError;
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error('Hold-slot API proxy error:', error);
|
|
61
|
+
|
|
62
|
+
return new Response(
|
|
63
|
+
JSON.stringify({
|
|
64
|
+
success: false,
|
|
65
|
+
error: 'Failed to connect to backend service',
|
|
66
|
+
}),
|
|
67
|
+
{
|
|
68
|
+
status: 500,
|
|
69
|
+
headers: {
|
|
70
|
+
'Content-Type': 'application/json',
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { APIRoute } from '@/types/astro';
|
|
2
|
+
import { getAdminToken } from '@/utils/auth';
|
|
3
|
+
|
|
4
|
+
export const GET: APIRoute = async (context) => {
|
|
5
|
+
const { request, locals } = context;
|
|
6
|
+
const GO_BACKEND =
|
|
7
|
+
import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const url = new URL(request.url);
|
|
11
|
+
const searchParams = url.searchParams;
|
|
12
|
+
|
|
13
|
+
const controller = new AbortController();
|
|
14
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
15
|
+
const tenantId =
|
|
16
|
+
locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
|
|
17
|
+
const token = getAdminToken(context);
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(
|
|
21
|
+
`${GO_BACKEND}/api/v1/bookings/list?${searchParams.toString()}`,
|
|
22
|
+
{
|
|
23
|
+
method: 'GET',
|
|
24
|
+
headers: {
|
|
25
|
+
'Content-Type': 'application/json',
|
|
26
|
+
'X-Tenant-ID': tenantId,
|
|
27
|
+
...(token && { Authorization: `Bearer ${token}` }),
|
|
28
|
+
...(request.headers.get('Authorization') && {
|
|
29
|
+
Authorization: request.headers.get('Authorization')!,
|
|
30
|
+
}),
|
|
31
|
+
},
|
|
32
|
+
signal: controller.signal,
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
clearTimeout(timeoutId);
|
|
37
|
+
const data = await response.json();
|
|
38
|
+
|
|
39
|
+
return new Response(JSON.stringify(data), {
|
|
40
|
+
status: response.status,
|
|
41
|
+
headers: { 'Content-Type': 'application/json' },
|
|
42
|
+
});
|
|
43
|
+
} catch (fetchError) {
|
|
44
|
+
clearTimeout(timeoutId);
|
|
45
|
+
if (fetchError instanceof Error && fetchError.name === 'AbortError') {
|
|
46
|
+
return new Response(
|
|
47
|
+
JSON.stringify({
|
|
48
|
+
success: false,
|
|
49
|
+
error: 'Booking list lookup timeout',
|
|
50
|
+
}),
|
|
51
|
+
{ status: 408, headers: { 'Content-Type': 'application/json' } }
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
throw fetchError;
|
|
55
|
+
}
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Booking list API proxy error:', error);
|
|
58
|
+
return new Response(
|
|
59
|
+
JSON.stringify({
|
|
60
|
+
success: false,
|
|
61
|
+
error: 'Failed to connect to backend service',
|
|
62
|
+
}),
|
|
63
|
+
{ status: 500, headers: { 'Content-Type': 'application/json' } }
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { APIRoute } from '@/types/astro';
|
|
2
|
+
import { getAdminToken } from '@/utils/auth';
|
|
3
|
+
|
|
4
|
+
export const GET: APIRoute = async (context) => {
|
|
5
|
+
const { request, locals } = context;
|
|
6
|
+
const GO_BACKEND =
|
|
7
|
+
import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const controller = new AbortController();
|
|
11
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
12
|
+
const tenantId =
|
|
13
|
+
locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
|
|
14
|
+
const token = getAdminToken(context);
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const response = await fetch(`${GO_BACKEND}/api/v1/bookings/metrics`, {
|
|
18
|
+
method: 'GET',
|
|
19
|
+
headers: {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
'X-Tenant-ID': tenantId,
|
|
22
|
+
...(token && { Authorization: `Bearer ${token}` }),
|
|
23
|
+
...(request.headers.get('Authorization') && {
|
|
24
|
+
Authorization: request.headers.get('Authorization')!,
|
|
25
|
+
}),
|
|
26
|
+
},
|
|
27
|
+
signal: controller.signal,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
clearTimeout(timeoutId);
|
|
31
|
+
const data = await response.json();
|
|
32
|
+
|
|
33
|
+
return new Response(JSON.stringify(data), {
|
|
34
|
+
status: response.status,
|
|
35
|
+
headers: { 'Content-Type': 'application/json' },
|
|
36
|
+
});
|
|
37
|
+
} catch (fetchError) {
|
|
38
|
+
clearTimeout(timeoutId);
|
|
39
|
+
if (fetchError instanceof Error && fetchError.name === 'AbortError') {
|
|
40
|
+
return new Response(
|
|
41
|
+
JSON.stringify({
|
|
42
|
+
success: false,
|
|
43
|
+
error: 'Booking metrics lookup timeout',
|
|
44
|
+
}),
|
|
45
|
+
{ status: 408, headers: { 'Content-Type': 'application/json' } }
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
throw fetchError;
|
|
49
|
+
}
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('Booking metrics API proxy error:', error);
|
|
52
|
+
return new Response(
|
|
53
|
+
JSON.stringify({
|
|
54
|
+
success: false,
|
|
55
|
+
error: 'Failed to connect to backend service',
|
|
56
|
+
}),
|
|
57
|
+
{ status: 500, headers: { 'Content-Type': 'application/json' } }
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { APIRoute } from '@/types/astro';
|
|
2
|
+
|
|
3
|
+
export const POST: APIRoute = async ({ request, locals }) => {
|
|
4
|
+
const GO_BACKEND =
|
|
5
|
+
import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
const { traceId } = await request.json();
|
|
9
|
+
|
|
10
|
+
if (!traceId) {
|
|
11
|
+
return new Response(JSON.stringify({ error: 'traceId is required' }), {
|
|
12
|
+
status: 400,
|
|
13
|
+
headers: { 'Content-Type': 'application/json' },
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
19
|
+
const tenantId =
|
|
20
|
+
locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const response = await fetch(
|
|
24
|
+
`${GO_BACKEND}/api/v1/bookings/hold/${traceId}`,
|
|
25
|
+
{
|
|
26
|
+
method: 'DELETE',
|
|
27
|
+
headers: {
|
|
28
|
+
'X-Tenant-ID': tenantId,
|
|
29
|
+
...(request.headers.get('Authorization') && {
|
|
30
|
+
Authorization: request.headers.get('Authorization')!,
|
|
31
|
+
}),
|
|
32
|
+
},
|
|
33
|
+
signal: controller.signal,
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
clearTimeout(timeoutId);
|
|
38
|
+
|
|
39
|
+
return new Response(JSON.stringify({ success: response.ok }), {
|
|
40
|
+
status: response.status,
|
|
41
|
+
headers: {
|
|
42
|
+
'Content-Type': 'application/json',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
} catch (fetchError) {
|
|
46
|
+
clearTimeout(timeoutId);
|
|
47
|
+
|
|
48
|
+
if (fetchError instanceof Error && fetchError.name === 'AbortError') {
|
|
49
|
+
return new Response(
|
|
50
|
+
JSON.stringify({
|
|
51
|
+
success: false,
|
|
52
|
+
error: 'Release-hold request timeout',
|
|
53
|
+
}),
|
|
54
|
+
{
|
|
55
|
+
status: 408,
|
|
56
|
+
headers: { 'Content-Type': 'application/json' },
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
throw fetchError;
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('Release-hold API proxy error:', error);
|
|
64
|
+
|
|
65
|
+
return new Response(
|
|
66
|
+
JSON.stringify({
|
|
67
|
+
success: false,
|
|
68
|
+
error: 'Failed to connect to backend service',
|
|
69
|
+
}),
|
|
70
|
+
{
|
|
71
|
+
status: 500,
|
|
72
|
+
headers: { 'Content-Type': 'application/json' },
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
@@ -69,14 +69,14 @@ export const POST: APIRoute = async ({ request, locals }) => {
|
|
|
69
69
|
const body = await request.json();
|
|
70
70
|
const { action, payload } = body;
|
|
71
71
|
|
|
72
|
-
if (action !== '
|
|
72
|
+
if (action !== 'aai') {
|
|
73
73
|
return new Response(
|
|
74
74
|
JSON.stringify({ success: false, error: 'Invalid action.' }),
|
|
75
75
|
{ status: 400, headers: { 'Content-Type': 'application/json' } }
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
const backendResponse = await fetch(`${goBackend}/api/v1/aai/
|
|
79
|
+
const backendResponse = await fetch(`${goBackend}/api/v1/aai/aai`, {
|
|
80
80
|
method: 'POST',
|
|
81
81
|
headers: {
|
|
82
82
|
'Content-Type': 'application/json',
|