payaza-storefront-layouts 1.0.7 → 1.0.8

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.
@@ -8,7 +8,7 @@ import Link from 'next/link';
8
8
  import Image from 'next/image';
9
9
  import { useState, useEffect } from 'react';
10
10
  import { formatCurrency } from '../../../lib/utils';
11
- import { getLayoutText, getBannerImage, getTextContent } from '../../../lib/utils/asset-helpers';
11
+ import { getLayoutText, getBannerImage, getTextContent, normalizeStoreImageUrl } from '../../../lib/utils/asset-helpers';
12
12
  import { shouldUseAPI } from '../../../lib/utils/demo-detection';
13
13
  import { TestimonialCard } from '../../shared/components/TestimonialCard';
14
14
  import { PromoBanner } from '../../shared/components/PromoBanner';
@@ -68,7 +68,7 @@ export function FoodHomePage({ storeConfig }) {
68
68
  const showBadges = layoutConfig?.sections?.hero?.showBadges !== false &&
69
69
  (layoutConfig?.hero?.showBadges !== false || layoutConfig?.sections?.hero?.showBadges === undefined);
70
70
  return {
71
- image: slider.image || '',
71
+ image: normalizeStoreImageUrl(slider.image) || '',
72
72
  badge: (showBadges && slider.badge && slider.badge.trim() !== '') ? slider.badge : "#1 Food Delivery in Town",
73
73
  title: slider.title || "Taste the",
74
74
  highlight: slider.highlight || "Extraordinary", // Food layout specific
@@ -93,7 +93,7 @@ export function FoodHomePage({ storeConfig }) {
93
93
  const showBadges = layoutConfig?.sections?.hero?.showBadges !== false &&
94
94
  (layoutConfig?.hero?.showBadges !== false || layoutConfig?.sections?.hero?.showBadges === undefined);
95
95
  return {
96
- image: slider.image || '',
96
+ image: normalizeStoreImageUrl(slider.image) || '',
97
97
  badge: (showBadges && slider.badge && slider.badge.trim() !== '') ? slider.badge : "#1 Food Delivery in Town",
98
98
  title: slider.title || "Taste the",
99
99
  highlight: slider.highlight || "Extraordinary", // Food layout specific
@@ -1,4 +1,11 @@
1
1
  import { StoreConfig } from '../../lib/store-types';
2
+ /**
3
+ * Normalizes store image URLs to absolute URLs
4
+ * Handles both absolute URLs (R2/Cloudflare/etc.) and relative paths
5
+ * @param raw - The raw image URL (can be relative or absolute)
6
+ * @returns Normalized absolute URL or null if invalid
7
+ */
8
+ export declare function normalizeStoreImageUrl(raw: unknown): string | null;
2
9
  /**
3
10
  * Gets text content from backend assignedText for real stores, or returns fallback for demo stores
4
11
  * @param storeConfig - The store configuration
@@ -1 +1 @@
1
- {"version":3,"file":"asset-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/asset-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAoBhD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,MAAM,CAuBR;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,EAAE,GACzB,MAAM,EAAE,CAkEV;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,MAAM,CAoBR;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,MAAM,CAsDR;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACrC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,MAAM,CA8BR;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACvC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,WAAW,EAAE,MAAM,GAClB,MAAM,CAcR;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,GACnB,MAAM,CAwCR;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,MAAM,CA+BR;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAC1C,MAAM,GAAG,IAAI,CAoBf;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,gBAAgB,EACrF,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACf,MAAM,CAgDR;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7D,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,QAAQ,EAAE;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG;QAAE,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,gBAAgB,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;CAAE,GACrJ,CAAC,CAWH"}
1
+ {"version":3,"file":"asset-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/asset-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAYhD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAuClE;AAUD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,MAAM,CAuBR;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,EAAE,GACzB,MAAM,EAAE,CAkEV;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,MAAM,CAoBR;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,MAAM,CAsDR;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACrC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,MAAM,CA8BR;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACvC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,WAAW,EAAE,MAAM,GAClB,MAAM,CAcR;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,GACnB,MAAM,CAwCR;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,MAAM,CA+BR;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAC1C,MAAM,GAAG,IAAI,CAoBf;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,gBAAgB,EACrF,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACf,MAAM,CAgDR;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7D,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAC3C,QAAQ,EAAE;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG;QAAE,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,gBAAgB,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;CAAE,GACrJ,CAAC,CAWH"}
@@ -10,6 +10,49 @@ function normalizeAssetUrl(url) {
10
10
  return null;
11
11
  return trimmed;
12
12
  }
13
+ /**
14
+ * Normalizes store image URLs to absolute URLs
15
+ * Handles both absolute URLs (R2/Cloudflare/etc.) and relative paths
16
+ * @param raw - The raw image URL (can be relative or absolute)
17
+ * @returns Normalized absolute URL or null if invalid
18
+ */
19
+ export function normalizeStoreImageUrl(raw) {
20
+ // Handle null, undefined, or non-string values
21
+ if (raw === null || raw === undefined)
22
+ return null;
23
+ if (typeof raw !== 'string')
24
+ return null;
25
+ const trimmed = raw.trim();
26
+ if (!trimmed)
27
+ return null;
28
+ if (trimmed === 'undefined' || trimmed === 'null' || trimmed === '')
29
+ return null;
30
+ // Absolute URLs (R2/Cloudflare/etc.) - return as-is
31
+ if (/^https?:\/\//i.test(trimmed)) {
32
+ return trimmed;
33
+ }
34
+ // Backend-served uploads (relative path)
35
+ // Try to get API base URL from environment or use default
36
+ const apiBase = typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_API_URL
37
+ ? process.env.NEXT_PUBLIC_API_URL
38
+ : (typeof window !== 'undefined'
39
+ ? window.location.origin.replace(/:\d+$/, ':4002') // Try to infer from current origin
40
+ : 'http://localhost:4002');
41
+ // Handle paths starting with /uploads/
42
+ if (trimmed.startsWith('/uploads/')) {
43
+ return `${apiBase}${trimmed}`;
44
+ }
45
+ // Handle paths starting with uploads/ (no leading slash)
46
+ if (trimmed.startsWith('uploads/')) {
47
+ return `${apiBase}/${trimmed}`;
48
+ }
49
+ // Handle paths starting with / (other backend paths)
50
+ if (trimmed.startsWith('/')) {
51
+ return `${apiBase}${trimmed}`;
52
+ }
53
+ // As a last resort, return as-is (could already be a resolvable relative asset)
54
+ return trimmed;
55
+ }
13
56
  function pickFirstAssetUrl(...candidates) {
14
57
  for (const c of candidates) {
15
58
  const normalized = normalizeAssetUrl(c);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payaza-storefront-layouts",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Shared layout components for StoreFront applications",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",