@mohasinac/appkit 2.7.22 → 2.7.24

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.
Files changed (51) hide show
  1. package/dist/client.d.ts +4 -0
  2. package/dist/client.js +3 -0
  3. package/dist/features/auth/consent-otp.js +8 -8
  4. package/dist/features/auth/permissions/constants.d.ts +1 -1
  5. package/dist/features/auth/permissions/constants.js +2 -0
  6. package/dist/features/before-after/messages/en.json +7 -7
  7. package/dist/features/collections/messages/en.json +9 -9
  8. package/dist/features/consultation/messages/en.json +24 -24
  9. package/dist/features/contact/email.js +179 -179
  10. package/dist/features/corporate/messages/en.json +25 -25
  11. package/dist/features/loyalty/messages/en.json +18 -18
  12. package/dist/features/media/messages/en.json +63 -63
  13. package/dist/features/pre-orders/messages/en.json +12 -12
  14. package/dist/features/site-settings/components/ActionPermissionsManager.d.ts +7 -0
  15. package/dist/features/site-settings/components/ActionPermissionsManager.js +99 -0
  16. package/dist/features/site-settings/components/NavPermissionsManager.d.ts +18 -0
  17. package/dist/features/site-settings/components/NavPermissionsManager.js +33 -0
  18. package/dist/features/whatsapp-bot/messages/en.json +6 -6
  19. package/dist/index.d.ts +4 -0
  20. package/dist/index.js +3 -0
  21. package/dist/next/routing/route-map.d.ts +4 -0
  22. package/dist/next/routing/route-map.js +2 -0
  23. package/dist/styles.css +21 -21
  24. package/dist/tailwind-utilities.css +1 -1
  25. package/dist/tokens/tokens.css +436 -436
  26. package/dist/ui/components/ActiveFilterChips.style.css +66 -66
  27. package/dist/ui/components/AvatarDisplay.style.css +46 -46
  28. package/dist/ui/components/BackgroundRenderer.style.css +31 -31
  29. package/dist/ui/components/Breadcrumb.style.css +60 -60
  30. package/dist/ui/components/CountdownDisplay.style.css +4 -4
  31. package/dist/ui/components/Div.style.css +6 -6
  32. package/dist/ui/components/EmptyState.style.css +28 -28
  33. package/dist/ui/components/FlowDiagram.style.css +77 -77
  34. package/dist/ui/components/FormGrid.style.css +32 -32
  35. package/dist/ui/components/ImageGallery.style.css +163 -163
  36. package/dist/ui/components/ImageLightbox.style.css +58 -58
  37. package/dist/ui/components/ItemRow.style.css +33 -33
  38. package/dist/ui/components/Layout.style.css +229 -229
  39. package/dist/ui/components/Menu.style.css +6 -6
  40. package/dist/ui/components/NavigationLoader.style.css +19 -19
  41. package/dist/ui/components/ResponsiveView.style.css +69 -69
  42. package/dist/ui/components/RoleBadge.style.css +7 -7
  43. package/dist/ui/components/SectionTabs.style.css +164 -164
  44. package/dist/ui/components/Semantic.style.css +14 -14
  45. package/dist/ui/components/SkipToMain.style.css +34 -34
  46. package/dist/ui/components/SortDropdown.style.css +12 -12
  47. package/dist/ui/components/StatusBadge.style.css +5 -5
  48. package/dist/ui/components/UnsavedChangesModal.style.css +33 -33
  49. package/dist/ui/components/ViewToggle.style.css +50 -50
  50. package/dist/ui/components/index.style.css +78 -78
  51. package/package.json +1 -1
package/dist/client.d.ts CHANGED
@@ -196,3 +196,7 @@ export { MEGABYTE, MAX_IMAGE_BYTES, MAX_PDF_BYTES, MAX_VIDEO_BYTES, MAX_LABEL, M
196
196
  export type { MediaKind, AllowedImageMime, AllowedVideoMime, AllowedDocMime, AllowedMime, } from "./_internal/shared/media/limits";
197
197
  export { ScamAwarenessModal } from "./features/scams/components/ScamAwarenessModal";
198
198
  export type { ScamAwarenessModalProps } from "./features/scams/components/ScamAwarenessModal";
199
+ export { ActionPermissionsManager } from "./features/site-settings/components/ActionPermissionsManager";
200
+ export type { ActionPermissionsManagerProps } from "./features/site-settings/components/ActionPermissionsManager";
201
+ export { NavPermissionsManager } from "./features/site-settings/components/NavPermissionsManager";
202
+ export type { NavPermissionsManagerProps, NavGroup as NavPermissionsGroup, NavItem as NavPermissionsItem } from "./features/site-settings/components/NavPermissionsManager";
package/dist/client.js CHANGED
@@ -226,3 +226,6 @@ export { LISTING_TYPE_REGISTRY, pluginFor } from "./_internal/shared/listing-typ
226
226
  // Media upload limits — shared by client uploaders + server sign/finalize routes.
227
227
  export { MEGABYTE, MAX_IMAGE_BYTES, MAX_PDF_BYTES, MAX_VIDEO_BYTES, MAX_LABEL, MAX_BYTES, ALLOWED_IMAGE_MIMES, ALLOWED_VIDEO_MIMES, ALLOWED_DOC_MIMES, ALLOWED_MIMES, ALLOWED_TYPES_LABEL, MIME_TO_EXT, PDF_MAGIC, VIDEO_CONVERSION_HINTS, classifyMime, isAllowedMime, maxBytesFor, getConversionHint, } from "./_internal/shared/media/limits";
228
228
  export { ScamAwarenessModal } from "./features/scams/components/ScamAwarenessModal";
229
+ // [CLIENT-ONLY] — Admin panel components for action/nav permission management.
230
+ export { ActionPermissionsManager } from "./features/site-settings/components/ActionPermissionsManager";
231
+ export { NavPermissionsManager } from "./features/site-settings/components/NavPermissionsManager";
@@ -106,14 +106,14 @@ export async function patchConsentOtp(uid, addressId, data) {
106
106
  export function buildConsentOtpEmail(recipientName, code, siteName) {
107
107
  return {
108
108
  subject: `${siteName}: Consent verification code - shipping to ${recipientName}`,
109
- html: `
110
- <div style="font-family:sans-serif;max-width:480px;margin:0 auto;padding:24px">
111
- <h2 style="margin-bottom:8px">Third-Party Shipping Consent</h2>
112
- <p style="color:#555">You are about to place an order that will be shipped to <strong>${escapeHtml(recipientName)}</strong>.</p>
113
- <p style="color:#555">Enter this code to confirm your consent:</p>
114
- <div style="font-size:36px;font-weight:bold;letter-spacing:8px;text-align:center;margin:24px 0;padding:16px;background:#f3f4f6;border-radius:8px">${code}</div>
115
- <p style="color:#888;font-size:12px">This code expires in ${CONSENT_OTP_EXPIRY_MINUTES} minutes. If you did not request this, please ignore this email.</p>
116
- </div>
109
+ html: `
110
+ <div style="font-family:sans-serif;max-width:480px;margin:0 auto;padding:24px">
111
+ <h2 style="margin-bottom:8px">Third-Party Shipping Consent</h2>
112
+ <p style="color:#555">You are about to place an order that will be shipped to <strong>${escapeHtml(recipientName)}</strong>.</p>
113
+ <p style="color:#555">Enter this code to confirm your consent:</p>
114
+ <div style="font-size:36px;font-weight:bold;letter-spacing:8px;text-align:center;margin:24px 0;padding:16px;background:#f3f4f6;border-radius:8px">${code}</div>
115
+ <p style="color:#888;font-size:12px">This code expires in ${CONSENT_OTP_EXPIRY_MINUTES} minutes. If you did not request this, please ignore this email.</p>
116
+ </div>
117
117
  `,
118
118
  };
119
119
  }
@@ -11,7 +11,7 @@
11
11
  * Permission naming: admin:resource:action
12
12
  * Ban action naming: plain verb phrase — write_reviews, place_bids, etc.
13
13
  */
14
- export type Permission = "admin:dashboard:view" | "admin:users:read" | "admin:users:write" | "admin:users:delete" | "admin:user-bans:read" | "admin:user-bans:write" | "admin:products:read" | "admin:products:write" | "admin:products:delete" | "admin:orders:read" | "admin:orders:write" | "admin:returns:read" | "admin:returns:write" | "admin:stores:read" | "admin:stores:write" | "admin:store-addresses:read" | "admin:analytics:view" | "admin:payouts:read" | "admin:payouts:write" | "admin:categories:read" | "admin:categories:write" | "admin:categories:delete" | "admin:brands:read" | "admin:brands:write" | "admin:brands:delete" | "admin:coupons:read" | "admin:coupons:write" | "admin:coupons:delete" | "admin:deals:read" | "admin:deals:write" | "admin:featured:read" | "admin:featured:write" | "admin:reviews:read" | "admin:reviews:write" | "admin:reviews:delete" | "admin:blog:read" | "admin:blog:write" | "admin:blog:delete" | "admin:blog:publish" | "admin:bids:read" | "admin:bids:write" | "admin:media:read" | "admin:media:write" | "admin:media:delete" | "admin:site:read" | "admin:site:write" | "admin:navigation:read" | "admin:navigation:write" | "admin:sections:read" | "admin:sections:write" | "admin:carousel:read" | "admin:carousel:write" | "admin:carousel:delete" | "admin:ads:read" | "admin:ads:write" | "admin:ads:delete" | "admin:faqs:read" | "admin:faqs:write" | "admin:faqs:delete" | "admin:newsletter:read" | "admin:newsletter:write" | "admin:contact:read" | "admin:events:read" | "admin:events:write" | "admin:events:delete" | "admin:event-entries:read" | "admin:event-entries:write" | "admin:support-tickets:read" | "admin:support-tickets:write" | "admin:support-tickets:assign" | "admin:support-tickets:close" | "admin:scammers:read" | "admin:scammers:write" | "admin:scammers:verify" | "admin:scammers:delete" | "admin:sessions:read" | "admin:sessions:delete" | "admin:notifications:read" | "admin:notifications:write" | "admin:carts:read" | "admin:wishlists:read" | "admin:feature-flags:read" | "admin:feature-flags:write" | "admin:copilot:view" | "admin:team:read" | "admin:team:write";
14
+ export type Permission = "admin:dashboard:view" | "admin:users:read" | "admin:users:write" | "admin:users:delete" | "admin:user-bans:read" | "admin:user-bans:write" | "admin:products:read" | "admin:products:write" | "admin:products:delete" | "admin:orders:read" | "admin:orders:write" | "admin:returns:read" | "admin:returns:write" | "admin:stores:read" | "admin:stores:write" | "admin:store-addresses:read" | "admin:analytics:view" | "admin:payouts:read" | "admin:payouts:write" | "admin:categories:read" | "admin:categories:write" | "admin:categories:delete" | "admin:brands:read" | "admin:brands:write" | "admin:brands:delete" | "admin:coupons:read" | "admin:coupons:write" | "admin:coupons:delete" | "admin:deals:read" | "admin:deals:write" | "admin:featured:read" | "admin:featured:write" | "admin:reviews:read" | "admin:reviews:write" | "admin:reviews:delete" | "admin:blog:read" | "admin:blog:write" | "admin:blog:delete" | "admin:blog:publish" | "admin:bids:read" | "admin:bids:write" | "admin:media:read" | "admin:media:write" | "admin:media:delete" | "admin:site:read" | "admin:site:write" | "admin:settings:write" | "admin:navigation:read" | "admin:navigation:write" | "admin:sections:read" | "admin:sections:write" | "admin:carousel:read" | "admin:carousel:write" | "admin:carousel:delete" | "admin:ads:read" | "admin:ads:write" | "admin:ads:delete" | "admin:faqs:read" | "admin:faqs:write" | "admin:faqs:delete" | "admin:newsletter:read" | "admin:newsletter:write" | "admin:contact:read" | "admin:events:read" | "admin:events:write" | "admin:events:delete" | "admin:event-entries:read" | "admin:event-entries:write" | "admin:support-tickets:read" | "admin:support-tickets:write" | "admin:support-tickets:assign" | "admin:support-tickets:close" | "admin:scammers:read" | "admin:scammers:write" | "admin:scammers:verify" | "admin:scammers:delete" | "admin:sessions:read" | "admin:sessions:delete" | "admin:notifications:read" | "admin:notifications:write" | "admin:carts:read" | "admin:wishlists:read" | "admin:feature-flags:read" | "admin:feature-flags:write" | "admin:copilot:view" | "admin:team:read" | "admin:team:write";
15
15
  /**
16
16
  * Granular user actions that can be soft-banned individually.
17
17
  * A user may have multiple simultaneous soft bans of different types.
@@ -112,6 +112,7 @@ export const PERMISSION_GROUPS = {
112
112
  "admin:dashboard:view",
113
113
  "admin:site:read",
114
114
  "admin:site:write",
115
+ "admin:settings:write",
115
116
  "admin:navigation:read",
116
117
  "admin:navigation:write",
117
118
  "admin:sections:read",
@@ -268,6 +269,7 @@ export const ROUTE_PERMISSION_MAP = {
268
269
  "/admin/bids": "admin:bids:read",
269
270
  "/admin/media": "admin:media:read",
270
271
  "/admin/site": "admin:site:read",
272
+ "/admin/settings": "admin:settings:write",
271
273
  "/admin/navigation": "admin:navigation:read",
272
274
  "/admin/sections": "admin:sections:read",
273
275
  "/admin/carousel": "admin:carousel:read",
@@ -1,8 +1,8 @@
1
- {
2
- "title": "Real Results",
3
- "subtitle": "See the transformation with our Ayurvedic products",
4
- "labelBefore": "Before",
5
- "labelAfter": "After",
6
- "weeks": "{count} weeks",
7
- "noItems": "No transformation stories yet"
1
+ {
2
+ "title": "Real Results",
3
+ "subtitle": "See the transformation with our Ayurvedic products",
4
+ "labelBefore": "Before",
5
+ "labelAfter": "After",
6
+ "weeks": "{count} weeks",
7
+ "noItems": "No transformation stories yet"
8
8
  }
@@ -1,10 +1,10 @@
1
- {
2
- "collections": {
3
- "title": "Collections",
4
- "subtitle": "Shop by collection",
5
- "viewAll": "View all collections",
6
- "items": "{count} items",
7
- "empty": "No collections found.",
8
- "notFound": "Collection not found."
9
- }
1
+ {
2
+ "collections": {
3
+ "title": "Collections",
4
+ "subtitle": "Shop by collection",
5
+ "viewAll": "View all collections",
6
+ "items": "{count} items",
7
+ "empty": "No collections found.",
8
+ "notFound": "Collection not found."
9
+ }
10
10
  }
@@ -1,25 +1,25 @@
1
- {
2
- "title": "Book a Consultation",
3
- "subtitle": "Get personalised Ayurvedic guidance",
4
- "form": {
5
- "name": "Full name",
6
- "email": "Email address",
7
- "phone": "Phone number",
8
- "preferredDate": "Preferred date",
9
- "preferredTime": "Preferred time",
10
- "mode": "Consultation mode",
11
- "modeRemote": "Remote (Video Call)",
12
- "modeInPerson": "In-Person",
13
- "message": "Additional notes (optional)",
14
- "submit": "Book Consultation",
15
- "submitting": "Booking..."
16
- },
17
- "status": {
18
- "pending": "Pending",
19
- "confirmed": "Confirmed",
20
- "completed": "Completed",
21
- "cancelled": "Cancelled"
22
- },
23
- "success": "Your consultation has been booked. We\u2019ll confirm shortly.",
24
- "error": "Failed to book consultation. Please try again."
1
+ {
2
+ "title": "Book a Consultation",
3
+ "subtitle": "Get personalised Ayurvedic guidance",
4
+ "form": {
5
+ "name": "Full name",
6
+ "email": "Email address",
7
+ "phone": "Phone number",
8
+ "preferredDate": "Preferred date",
9
+ "preferredTime": "Preferred time",
10
+ "mode": "Consultation mode",
11
+ "modeRemote": "Remote (Video Call)",
12
+ "modeInPerson": "In-Person",
13
+ "message": "Additional notes (optional)",
14
+ "submit": "Book Consultation",
15
+ "submitting": "Booking..."
16
+ },
17
+ "status": {
18
+ "pending": "Pending",
19
+ "confirmed": "Confirmed",
20
+ "completed": "Completed",
21
+ "cancelled": "Cancelled"
22
+ },
23
+ "success": "Your consultation has been booked. We\u2019ll confirm shortly.",
24
+ "error": "Failed to book consultation. Please try again."
25
25
  }
@@ -81,34 +81,34 @@ export async function sendOrderConfirmationEmail(params) {
81
81
  const orderUrl = `${siteUrl}/user/orders/view/${orderId}`;
82
82
  const formattedTotal = formatCurrency(totalPrice, currency);
83
83
  const itemsHtml = items && items.length > 1
84
- ? `
85
- <table width="100%" cellpadding="8" cellspacing="0" border="0" style="border-collapse: collapse; margin-bottom: 8px;">
86
- <thead>
87
- <tr style="background-color: #e9ecef;">
88
- <th style="text-align: left; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Product</th>
89
- <th style="text-align: center; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Qty</th>
90
- <th style="text-align: right; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Amount</th>
91
- </tr>
92
- </thead>
93
- <tbody>
84
+ ? `
85
+ <table width="100%" cellpadding="8" cellspacing="0" border="0" style="border-collapse: collapse; margin-bottom: 8px;">
86
+ <thead>
87
+ <tr style="background-color: #e9ecef;">
88
+ <th style="text-align: left; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Product</th>
89
+ <th style="text-align: center; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Qty</th>
90
+ <th style="text-align: right; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Amount</th>
91
+ </tr>
92
+ </thead>
93
+ <tbody>
94
94
  ${items
95
- .map((item, index) => `
96
- <tr style="background-color: ${index % 2 === 0 ? "#ffffff" : "#f8f9fa"}; border-top: 1px solid #e9ecef;">
97
- <td style="font-size: 14px; color: #333; padding: 8px 12px;">${item.productTitle}</td>
98
- <td style="font-size: 14px; color: #333; text-align: center; padding: 8px 12px;">${item.quantity}</td>
99
- <td style="font-size: 14px; color: #333; text-align: right; padding: 8px 12px;">${formatCurrency(item.totalPrice, currency)}</td>
95
+ .map((item, index) => `
96
+ <tr style="background-color: ${index % 2 === 0 ? "#ffffff" : "#f8f9fa"}; border-top: 1px solid #e9ecef;">
97
+ <td style="font-size: 14px; color: #333; padding: 8px 12px;">${item.productTitle}</td>
98
+ <td style="font-size: 14px; color: #333; text-align: center; padding: 8px 12px;">${item.quantity}</td>
99
+ <td style="font-size: 14px; color: #333; text-align: right; padding: 8px 12px;">${formatCurrency(item.totalPrice, currency)}</td>
100
100
  </tr>`)
101
- .join("")}
102
- </tbody>
101
+ .join("")}
102
+ </tbody>
103
103
  </table>`
104
- : `
105
- <tr>
106
- <td style="color: #666; font-size: 14px;">Product</td>
107
- <td style="color: #333; font-size: 14px;">${productTitle}</td>
108
- </tr>
109
- <tr>
110
- <td style="color: #666; font-size: 14px;">Quantity</td>
111
- <td style="color: #333; font-size: 14px;">${quantity}</td>
104
+ : `
105
+ <tr>
106
+ <td style="color: #666; font-size: 14px;">Product</td>
107
+ <td style="color: #333; font-size: 14px;">${productTitle}</td>
108
+ </tr>
109
+ <tr>
110
+ <td style="color: #666; font-size: 14px;">Quantity</td>
111
+ <td style="color: #333; font-size: 14px;">${quantity}</td>
112
112
  </tr>`;
113
113
  const itemsText = items && items.length > 1
114
114
  ? items
@@ -119,88 +119,88 @@ export async function sendOrderConfirmationEmail(params) {
119
119
  const { data, error } = await sendConfiguredEmail({
120
120
  to,
121
121
  subject: `Order Confirmed — ${orderId}`,
122
- html: `
123
- <!DOCTYPE html>
124
- <html>
125
- <head>
126
- <meta charset="utf-8">
127
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
128
- <title>Order Confirmation</title>
129
- </head>
130
- <body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f5f5f5;">
131
- <table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color: #f5f5f5; padding: 40px 0;">
132
- <tr>
133
- <td align="center">
134
- <table width="600" cellpadding="0" cellspacing="0" border="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
135
- <tr>
136
- <td style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); padding: 40px; text-align: center;">
137
- <p style="font-size: 48px; margin: 0 0 12px;">✅</p>
138
- <h1 style="color: #ffffff; margin: 0; font-size: 28px; font-weight: 600;">Order Confirmed!</h1>
139
- </td>
140
- </tr>
141
- <tr>
142
- <td style="padding: 40px;">
143
- <p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 20px;">Hi ${userName},</p>
144
- <p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">
145
- Thank you for your order! We've received it and will process it shortly.
146
- </p>
147
- <table width="100%" cellpadding="12" cellspacing="0" border="0" style="background-color: #f8f9fa; border-radius: 8px; margin-bottom: 24px;">
148
- <tr>
149
- <td style="color: #666; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; border-bottom: 1px solid #e9ecef;" colspan="2">Order Details</td>
150
- </tr>
151
- <tr>
152
- <td style="color: #666; font-size: 14px; width: 40%;">Order ID</td>
153
- <td style="color: #333; font-size: 14px; font-weight: 600;">${orderId}</td>
154
- </tr>
122
+ html: `
123
+ <!DOCTYPE html>
124
+ <html>
125
+ <head>
126
+ <meta charset="utf-8">
127
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
128
+ <title>Order Confirmation</title>
129
+ </head>
130
+ <body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f5f5f5;">
131
+ <table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color: #f5f5f5; padding: 40px 0;">
132
+ <tr>
133
+ <td align="center">
134
+ <table width="600" cellpadding="0" cellspacing="0" border="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
135
+ <tr>
136
+ <td style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); padding: 40px; text-align: center;">
137
+ <p style="font-size: 48px; margin: 0 0 12px;">✅</p>
138
+ <h1 style="color: #ffffff; margin: 0; font-size: 28px; font-weight: 600;">Order Confirmed!</h1>
139
+ </td>
140
+ </tr>
141
+ <tr>
142
+ <td style="padding: 40px;">
143
+ <p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 20px;">Hi ${userName},</p>
144
+ <p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">
145
+ Thank you for your order! We've received it and will process it shortly.
146
+ </p>
147
+ <table width="100%" cellpadding="12" cellspacing="0" border="0" style="background-color: #f8f9fa; border-radius: 8px; margin-bottom: 24px;">
148
+ <tr>
149
+ <td style="color: #666; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; border-bottom: 1px solid #e9ecef;" colspan="2">Order Details</td>
150
+ </tr>
151
+ <tr>
152
+ <td style="color: #666; font-size: 14px; width: 40%;">Order ID</td>
153
+ <td style="color: #333; font-size: 14px; font-weight: 600;">${orderId}</td>
154
+ </tr>
155
155
  ${items && items.length > 1
156
- ? `
157
- <tr>
158
- <td style="color: #666; font-size: 14px; vertical-align: top;" colspan="2">
159
- <div style="font-weight: 600; margin-bottom: 8px;">Items (${items.length})</div>
160
- ${itemsHtml}
161
- </td>
156
+ ? `
157
+ <tr>
158
+ <td style="color: #666; font-size: 14px; vertical-align: top;" colspan="2">
159
+ <div style="font-weight: 600; margin-bottom: 8px;">Items (${items.length})</div>
160
+ ${itemsHtml}
161
+ </td>
162
162
  </tr>`
163
- : itemsHtml}
164
- <tr>
165
- <td style="color: #666; font-size: 14px;">Total</td>
166
- <td style="color: #333; font-size: 14px; font-weight: 700;">${formattedTotal}</td>
167
- </tr>
168
- <tr>
169
- <td style="color: #666; font-size: 14px;">Payment</td>
170
- <td style="color: #333; font-size: 14px;">${paymentMethod === "cod" ? "Cash on Delivery" : "Online Payment"}</td>
171
- </tr>
172
- <tr>
173
- <td style="color: #666; font-size: 14px; vertical-align: top;">Ship to</td>
174
- <td style="color: #333; font-size: 14px;">${shippingAddress}</td>
175
- </tr>
176
- </table>
177
- <table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0;">
178
- <tr>
179
- <td align="center">
180
- <a href="${orderUrl}" style="display: inline-block; padding: 14px 40px; background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 16px; font-weight: 600;">
181
- View Order
182
- </a>
183
- </td>
184
- </tr>
185
- </table>
186
- <p style="color: #999; font-size: 13px; line-height: 1.6; margin: 0;">
187
- We'll send you another email when your order is shipped.
188
- </p>
189
- </td>
190
- </tr>
191
- <tr>
192
- <td style="background-color: #f8f9fa; padding: 24px; text-align: center; border-top: 1px solid #eee;">
193
- <p style="color: #999; font-size: 12px; margin: 0;">
194
- © ${currentYear()} ${siteName}. All rights reserved.
195
- </p>
196
- </td>
197
- </tr>
198
- </table>
199
- </td>
200
- </tr>
201
- </table>
202
- </body>
203
- </html>
163
+ : itemsHtml}
164
+ <tr>
165
+ <td style="color: #666; font-size: 14px;">Total</td>
166
+ <td style="color: #333; font-size: 14px; font-weight: 700;">${formattedTotal}</td>
167
+ </tr>
168
+ <tr>
169
+ <td style="color: #666; font-size: 14px;">Payment</td>
170
+ <td style="color: #333; font-size: 14px;">${paymentMethod === "cod" ? "Cash on Delivery" : "Online Payment"}</td>
171
+ </tr>
172
+ <tr>
173
+ <td style="color: #666; font-size: 14px; vertical-align: top;">Ship to</td>
174
+ <td style="color: #333; font-size: 14px;">${shippingAddress}</td>
175
+ </tr>
176
+ </table>
177
+ <table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0;">
178
+ <tr>
179
+ <td align="center">
180
+ <a href="${orderUrl}" style="display: inline-block; padding: 14px 40px; background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 16px; font-weight: 600;">
181
+ View Order
182
+ </a>
183
+ </td>
184
+ </tr>
185
+ </table>
186
+ <p style="color: #999; font-size: 13px; line-height: 1.6; margin: 0;">
187
+ We'll send you another email when your order is shipped.
188
+ </p>
189
+ </td>
190
+ </tr>
191
+ <tr>
192
+ <td style="background-color: #f8f9fa; padding: 24px; text-align: center; border-top: 1px solid #eee;">
193
+ <p style="color: #999; font-size: 12px; margin: 0;">
194
+ © ${currentYear()} ${siteName}. All rights reserved.
195
+ </p>
196
+ </td>
197
+ </tr>
198
+ </table>
199
+ </td>
200
+ </tr>
201
+ </table>
202
+ </body>
203
+ </html>
204
204
  `,
205
205
  text: `Hi ${userName},\n\nYour order ${orderId} has been confirmed!\n\n${itemsText}\nTotal: ${formattedTotal}\nPayment: ${paymentMethod === "cod" ? "Cash on Delivery" : "Online Payment"}\nShip to: ${shippingAddress}\n\nView your order: ${orderUrl}\n\n© ${currentYear()} ${siteName}`,
206
206
  });
@@ -224,27 +224,27 @@ export async function sendContactEmail(params) {
224
224
  to: supportEmail,
225
225
  replyTo: email,
226
226
  subject: `[Contact] ${subject}`,
227
- html: `
228
- <!DOCTYPE html>
229
- <html>
230
- <head><meta charset="utf-8"><title>Contact Form</title></head>
231
- <body style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; padding: 40px 0;">
232
- <table width="600" style="margin: 0 auto; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
233
- <tr><td style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 32px; text-align: center;">
234
- <h1 style="color: #fff; margin: 0; font-size: 24px;">New Contact Message</h1>
235
- </td></tr>
236
- <tr><td style="padding: 32px;">
237
- <p><strong>From:</strong> ${name} &lt;${email}&gt;</p>
238
- <p><strong>Subject:</strong> ${subject}</p>
239
- <hr style="border: none; border-top: 1px solid #eee; margin: 16px 0;">
240
- <p style="white-space: pre-wrap;">${message}</p>
241
- </td></tr>
242
- <tr><td style="background: #f9f9f9; padding: 16px; text-align: center; color: #888; font-size: 12px;">
243
- © ${currentYear()} ${siteName}
244
- </td></tr>
245
- </table>
246
- </body>
247
- </html>
227
+ html: `
228
+ <!DOCTYPE html>
229
+ <html>
230
+ <head><meta charset="utf-8"><title>Contact Form</title></head>
231
+ <body style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; padding: 40px 0;">
232
+ <table width="600" style="margin: 0 auto; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
233
+ <tr><td style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 32px; text-align: center;">
234
+ <h1 style="color: #fff; margin: 0; font-size: 24px;">New Contact Message</h1>
235
+ </td></tr>
236
+ <tr><td style="padding: 32px;">
237
+ <p><strong>From:</strong> ${name} &lt;${email}&gt;</p>
238
+ <p><strong>Subject:</strong> ${subject}</p>
239
+ <hr style="border: none; border-top: 1px solid #eee; margin: 16px 0;">
240
+ <p style="white-space: pre-wrap;">${message}</p>
241
+ </td></tr>
242
+ <tr><td style="background: #f9f9f9; padding: 16px; text-align: center; color: #888; font-size: 12px;">
243
+ © ${currentYear()} ${siteName}
244
+ </td></tr>
245
+ </table>
246
+ </body>
247
+ </html>
248
248
  `,
249
249
  text: `From: ${name} <${email}>\nSubject: ${subject}\n\n${message}`,
250
250
  });
@@ -271,59 +271,59 @@ export async function sendSiteSettingsChangedEmail(params) {
271
271
  const { data, error } = await sendConfiguredEmail({
272
272
  to: adminEmails,
273
273
  subject: `Site settings updated by ${changedByEmail}`,
274
- html: `
275
- <!DOCTYPE html>
276
- <html>
277
- <head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"></head>
278
- <body style="margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;background-color:#f5f5f5;">
279
- <table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:#f5f5f5;padding:40px 0;">
280
- <tr><td align="center">
281
- <table width="600" cellpadding="0" cellspacing="0" border="0" style="background-color:#ffffff;border-radius:8px;overflow:hidden;box-shadow:0 2px 8px rgba(0,0,0,0.1);">
282
- <tr>
283
- <td style="background:linear-gradient(135deg,#10b981 0%,#059669 100%);padding:40px;text-align:center;">
284
- <p style="font-size:48px;margin:0 0 12px;">⚙️</p>
285
- <h1 style="color:#ffffff;margin:0;font-size:24px;font-weight:600;">Site Settings Changed</h1>
286
- <p style="color:#d1fae5;margin:8px 0 0;font-size:14px;">${timestamp}</p>
287
- </td>
288
- </tr>
289
- <tr>
290
- <td style="padding:40px;">
291
- <p style="color:#333;font-size:16px;line-height:1.6;margin:0 0 20px;">
292
- <strong>${changedByEmail}</strong> has updated the following site settings:
293
- </p>
294
- <table width="100%" cellpadding="12" cellspacing="0" border="0" style="background:#f8f9fa;border-radius:8px;margin:0 0 24px;">
295
- <tr>
296
- <td style="color:#6b7280;font-size:13px;font-weight:600;text-transform:uppercase;">Changed Fields</td>
297
- <td style="color:#111827;font-size:14px;">${changedFields.map((field) => `<code style="background:#e5e7eb;padding:2px 6px;border-radius:3px;">${field}</code>`).join("&ensp;")}</td>
298
- </tr>
299
- <tr>
300
- <td style="color:#6b7280;font-size:13px;font-weight:600;text-transform:uppercase;">Changed By</td>
301
- <td style="color:#111827;font-size:14px;">${changedByEmail}</td>
302
- </tr>
303
- <tr>
304
- <td style="color:#6b7280;font-size:13px;font-weight:600;text-transform:uppercase;">Timestamp</td>
305
- <td style="color:#111827;font-size:14px;">${timestamp}</td>
306
- </tr>
307
- </table>
308
- <table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:24px 0;">
309
- <tr><td align="center">
310
- <a href="${settingsUrl}" style="display:inline-block;padding:14px 40px;background:linear-gradient(135deg,#10b981 0%,#059669 100%);color:#ffffff;text-decoration:none;border-radius:6px;font-size:15px;font-weight:600;">
311
- View Settings
312
- </a>
313
- </td></tr>
314
- </table>
315
- </td>
316
- </tr>
317
- <tr>
318
- <td style="background-color:#f8f9fa;padding:24px;text-align:center;border-top:1px solid #eeeeee;">
319
- <p style="color:#9ca3af;font-size:12px;margin:0;">© ${currentYear()} ${siteName}. Automated notification — do not reply.</p>
320
- </td>
321
- </tr>
322
- </table>
323
- </td></tr>
324
- </table>
325
- </body>
326
- </html>
274
+ html: `
275
+ <!DOCTYPE html>
276
+ <html>
277
+ <head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"></head>
278
+ <body style="margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;background-color:#f5f5f5;">
279
+ <table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:#f5f5f5;padding:40px 0;">
280
+ <tr><td align="center">
281
+ <table width="600" cellpadding="0" cellspacing="0" border="0" style="background-color:#ffffff;border-radius:8px;overflow:hidden;box-shadow:0 2px 8px rgba(0,0,0,0.1);">
282
+ <tr>
283
+ <td style="background:linear-gradient(135deg,#10b981 0%,#059669 100%);padding:40px;text-align:center;">
284
+ <p style="font-size:48px;margin:0 0 12px;">⚙️</p>
285
+ <h1 style="color:#ffffff;margin:0;font-size:24px;font-weight:600;">Site Settings Changed</h1>
286
+ <p style="color:#d1fae5;margin:8px 0 0;font-size:14px;">${timestamp}</p>
287
+ </td>
288
+ </tr>
289
+ <tr>
290
+ <td style="padding:40px;">
291
+ <p style="color:#333;font-size:16px;line-height:1.6;margin:0 0 20px;">
292
+ <strong>${changedByEmail}</strong> has updated the following site settings:
293
+ </p>
294
+ <table width="100%" cellpadding="12" cellspacing="0" border="0" style="background:#f8f9fa;border-radius:8px;margin:0 0 24px;">
295
+ <tr>
296
+ <td style="color:#6b7280;font-size:13px;font-weight:600;text-transform:uppercase;">Changed Fields</td>
297
+ <td style="color:#111827;font-size:14px;">${changedFields.map((field) => `<code style="background:#e5e7eb;padding:2px 6px;border-radius:3px;">${field}</code>`).join("&ensp;")}</td>
298
+ </tr>
299
+ <tr>
300
+ <td style="color:#6b7280;font-size:13px;font-weight:600;text-transform:uppercase;">Changed By</td>
301
+ <td style="color:#111827;font-size:14px;">${changedByEmail}</td>
302
+ </tr>
303
+ <tr>
304
+ <td style="color:#6b7280;font-size:13px;font-weight:600;text-transform:uppercase;">Timestamp</td>
305
+ <td style="color:#111827;font-size:14px;">${timestamp}</td>
306
+ </tr>
307
+ </table>
308
+ <table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:24px 0;">
309
+ <tr><td align="center">
310
+ <a href="${settingsUrl}" style="display:inline-block;padding:14px 40px;background:linear-gradient(135deg,#10b981 0%,#059669 100%);color:#ffffff;text-decoration:none;border-radius:6px;font-size:15px;font-weight:600;">
311
+ View Settings
312
+ </a>
313
+ </td></tr>
314
+ </table>
315
+ </td>
316
+ </tr>
317
+ <tr>
318
+ <td style="background-color:#f8f9fa;padding:24px;text-align:center;border-top:1px solid #eeeeee;">
319
+ <p style="color:#9ca3af;font-size:12px;margin:0;">© ${currentYear()} ${siteName}. Automated notification — do not reply.</p>
320
+ </td>
321
+ </tr>
322
+ </table>
323
+ </td></tr>
324
+ </table>
325
+ </body>
326
+ </html>
327
327
  `,
328
328
  text: `Site settings updated by ${changedByEmail}\n\nChanged fields: ${changedFields.join(", ")}\n\nView at: ${settingsUrl}`,
329
329
  });
@@ -1,26 +1,26 @@
1
- {
2
- "title": "Corporate Gifting",
3
- "subtitle": "Premium Ayurvedic gifts for your team and clients",
4
- "form": {
5
- "companyName": "Company name",
6
- "contactPerson": "Contact person",
7
- "designation": "Designation (optional)",
8
- "email": "Business email",
9
- "phone": "Phone number",
10
- "units": "Number of units",
11
- "budgetPerUnit": "Budget per unit (optional)",
12
- "deliveryDate": "Required by (optional)",
13
- "customBranding": "Custom branding required",
14
- "message": "Additional requirements (optional)",
15
- "submit": "Submit Inquiry",
16
- "submitting": "Submitting..."
17
- },
18
- "status": {
19
- "new": "New",
20
- "in_progress": "In Progress",
21
- "won": "Won",
22
- "lost": "Lost"
23
- },
24
- "success": "Your inquiry has been submitted. Our team will contact you within 24 hours.",
25
- "error": "Failed to submit inquiry. Please try again."
1
+ {
2
+ "title": "Corporate Gifting",
3
+ "subtitle": "Premium Ayurvedic gifts for your team and clients",
4
+ "form": {
5
+ "companyName": "Company name",
6
+ "contactPerson": "Contact person",
7
+ "designation": "Designation (optional)",
8
+ "email": "Business email",
9
+ "phone": "Phone number",
10
+ "units": "Number of units",
11
+ "budgetPerUnit": "Budget per unit (optional)",
12
+ "deliveryDate": "Required by (optional)",
13
+ "customBranding": "Custom branding required",
14
+ "message": "Additional requirements (optional)",
15
+ "submit": "Submit Inquiry",
16
+ "submitting": "Submitting..."
17
+ },
18
+ "status": {
19
+ "new": "New",
20
+ "in_progress": "In Progress",
21
+ "won": "Won",
22
+ "lost": "Lost"
23
+ },
24
+ "success": "Your inquiry has been submitted. Our team will contact you within 24 hours.",
25
+ "error": "Failed to submit inquiry. Please try again."
26
26
  }