@promakeai/cli 0.0.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.
Files changed (285) hide show
  1. package/dist/index.js +212 -0
  2. package/dist/registry/about-page.json +45 -0
  3. package/dist/registry/about-section.json +40 -0
  4. package/dist/registry/animations.json +69 -0
  5. package/dist/registry/bento-grid-section.json +42 -0
  6. package/dist/registry/blog-core.json +74 -0
  7. package/dist/registry/blog-list-page.json +48 -0
  8. package/dist/registry/blog-section.json +43 -0
  9. package/dist/registry/cards-carousel-section.json +46 -0
  10. package/dist/registry/cart-drawer.json +43 -0
  11. package/dist/registry/cart-page.json +47 -0
  12. package/dist/registry/category-section.json +43 -0
  13. package/dist/registry/checkout-page.json +47 -0
  14. package/dist/registry/contact-info-grid.json +40 -0
  15. package/dist/registry/contact-page-centered.json +50 -0
  16. package/dist/registry/contact-page-map-overlay.json +54 -0
  17. package/dist/registry/contact-page-map-split.json +54 -0
  18. package/dist/registry/contact-page-split.json +49 -0
  19. package/dist/registry/contact-page.json +45 -0
  20. package/dist/registry/content-section.json +40 -0
  21. package/dist/registry/cookies-page.json +45 -0
  22. package/dist/registry/cta-section.json +40 -0
  23. package/dist/registry/docs/about-page.md +32 -0
  24. package/dist/registry/docs/about-section.md +33 -0
  25. package/dist/registry/docs/animations.md +44 -0
  26. package/dist/registry/docs/bento-grid-section.md +40 -0
  27. package/dist/registry/docs/blog-core.md +37 -0
  28. package/dist/registry/docs/blog-list-page.md +38 -0
  29. package/dist/registry/docs/blog-section.md +39 -0
  30. package/dist/registry/docs/cards-carousel-section.md +39 -0
  31. package/dist/registry/docs/cart-drawer.md +42 -0
  32. package/dist/registry/docs/cart-page.md +37 -0
  33. package/dist/registry/docs/category-section.md +34 -0
  34. package/dist/registry/docs/checkout-page.md +38 -0
  35. package/dist/registry/docs/contact-info-grid.md +33 -0
  36. package/dist/registry/docs/contact-page-centered.md +41 -0
  37. package/dist/registry/docs/contact-page-map-overlay.md +44 -0
  38. package/dist/registry/docs/contact-page-map-split.md +44 -0
  39. package/dist/registry/docs/contact-page-split.md +40 -0
  40. package/dist/registry/docs/contact-page.md +33 -0
  41. package/dist/registry/docs/content-section.md +35 -0
  42. package/dist/registry/docs/cookies-page.md +32 -0
  43. package/dist/registry/docs/cta-section.md +32 -0
  44. package/dist/registry/docs/ecommerce-core.md +41 -0
  45. package/dist/registry/docs/empty-page.md +31 -0
  46. package/dist/registry/docs/faq-categorized.md +38 -0
  47. package/dist/registry/docs/faq-simple.md +38 -0
  48. package/dist/registry/docs/favorites-blog-block.md +38 -0
  49. package/dist/registry/docs/favorites-ecommerce-block.md +38 -0
  50. package/dist/registry/docs/feature-section.md +33 -0
  51. package/dist/registry/docs/featured-products.md +38 -0
  52. package/dist/registry/docs/footer-detailed.md +33 -0
  53. package/dist/registry/docs/footer-minimal.md +32 -0
  54. package/dist/registry/docs/footer.md +32 -0
  55. package/dist/registry/docs/google-map.md +36 -0
  56. package/dist/registry/docs/header-centered-pill.md +37 -0
  57. package/dist/registry/docs/header-ecommerce.md +38 -0
  58. package/dist/registry/docs/header-mega.md +40 -0
  59. package/dist/registry/docs/header-minimal.md +38 -0
  60. package/dist/registry/docs/header-simple.md +32 -0
  61. package/dist/registry/docs/hero-cta.md +38 -0
  62. package/dist/registry/docs/hero-gradient.md +33 -0
  63. package/dist/registry/docs/hero-grid.md +40 -0
  64. package/dist/registry/docs/hero-profile.md +33 -0
  65. package/dist/registry/docs/hero.md +32 -0
  66. package/dist/registry/docs/login-page-split.md +40 -0
  67. package/dist/registry/docs/login-page.md +39 -0
  68. package/dist/registry/docs/newsletter-section.md +40 -0
  69. package/dist/registry/docs/order-card-compact.md +37 -0
  70. package/dist/registry/docs/order-detail-block.md +37 -0
  71. package/dist/registry/docs/orders-list-block.md +40 -0
  72. package/dist/registry/docs/payment-success-block.md +32 -0
  73. package/dist/registry/docs/post-card.md +37 -0
  74. package/dist/registry/docs/post-detail-block.md +37 -0
  75. package/dist/registry/docs/pricing-card.md +37 -0
  76. package/dist/registry/docs/pricing-section.md +39 -0
  77. package/dist/registry/docs/privacy-page.md +32 -0
  78. package/dist/registry/docs/product-card-detailed.md +42 -0
  79. package/dist/registry/docs/product-card-hover.md +35 -0
  80. package/dist/registry/docs/product-card.md +37 -0
  81. package/dist/registry/docs/product-detail-block.md +37 -0
  82. package/dist/registry/docs/product-detail-section.md +45 -0
  83. package/dist/registry/docs/products-page.md +39 -0
  84. package/dist/registry/docs/related-posts-block.md +38 -0
  85. package/dist/registry/docs/related-products-block.md +38 -0
  86. package/dist/registry/docs/service-card.md +34 -0
  87. package/dist/registry/docs/skill-card.md +33 -0
  88. package/dist/registry/docs/terms-page.md +32 -0
  89. package/dist/registry/docs/testimonials-carousel.md +40 -0
  90. package/dist/registry/docs/testimonials-grid.md +39 -0
  91. package/dist/registry/ecommerce-core.json +95 -0
  92. package/dist/registry/empty-page.json +45 -0
  93. package/dist/registry/faq-categorized.json +42 -0
  94. package/dist/registry/faq-simple.json +42 -0
  95. package/dist/registry/favorites-blog-block.json +43 -0
  96. package/dist/registry/favorites-ecommerce-block.json +43 -0
  97. package/dist/registry/feature-section.json +40 -0
  98. package/dist/registry/featured-products.json +43 -0
  99. package/dist/registry/footer-detailed.json +43 -0
  100. package/dist/registry/footer-minimal.json +40 -0
  101. package/dist/registry/footer.json +40 -0
  102. package/dist/registry/google-map.json +31 -0
  103. package/dist/registry/header-centered-pill.json +45 -0
  104. package/dist/registry/header-ecommerce.json +42 -0
  105. package/dist/registry/header-mega.json +47 -0
  106. package/dist/registry/header-minimal.json +45 -0
  107. package/dist/registry/header-simple.json +43 -0
  108. package/dist/registry/hero-cta.json +42 -0
  109. package/dist/registry/hero-gradient.json +40 -0
  110. package/dist/registry/hero-grid.json +42 -0
  111. package/dist/registry/hero-profile.json +62 -0
  112. package/dist/registry/hero.json +40 -0
  113. package/dist/registry/index.json +70 -0
  114. package/dist/registry/login-page-split.json +47 -0
  115. package/dist/registry/login-page.json +49 -0
  116. package/dist/registry/newsletter-section.json +44 -0
  117. package/dist/registry/order-card-compact.json +42 -0
  118. package/dist/registry/order-detail-block.json +42 -0
  119. package/dist/registry/orders-list-block.json +45 -0
  120. package/dist/registry/payment-success-block.json +40 -0
  121. package/dist/registry/post-card.json +42 -0
  122. package/dist/registry/post-detail-block.json +42 -0
  123. package/dist/registry/pricing-card.json +40 -0
  124. package/dist/registry/pricing-section.json +43 -0
  125. package/dist/registry/privacy-page.json +45 -0
  126. package/dist/registry/product-card-detailed.json +45 -0
  127. package/dist/registry/product-card-hover.json +40 -0
  128. package/dist/registry/product-card.json +42 -0
  129. package/dist/registry/product-detail-block.json +42 -0
  130. package/dist/registry/product-detail-section.json +46 -0
  131. package/dist/registry/products-page.json +48 -0
  132. package/dist/registry/related-posts-block.json +43 -0
  133. package/dist/registry/related-products-block.json +43 -0
  134. package/dist/registry/service-card.json +28 -0
  135. package/dist/registry/skill-card.json +28 -0
  136. package/dist/registry/terms-page.json +45 -0
  137. package/dist/registry/testimonials-carousel.json +44 -0
  138. package/dist/registry/testimonials-grid.json +43 -0
  139. package/package.json +52 -0
  140. package/template/.env +6 -0
  141. package/template/.prettierignore +3 -0
  142. package/template/.prettierrc +1 -0
  143. package/template/README.md +73 -0
  144. package/template/bun.lock +1007 -0
  145. package/template/components.json +22 -0
  146. package/template/eslint.config.js +32 -0
  147. package/template/index.html +285 -0
  148. package/template/package.json +92 -0
  149. package/template/promake.json +6 -0
  150. package/template/public/_redirects +1 -0
  151. package/template/public/data/database.db +0 -0
  152. package/template/public/favicon.svg +1 -0
  153. package/template/public/images/placeholder.png +0 -0
  154. package/template/public/robots.txt +14 -0
  155. package/template/scripts/init-db.ts +131 -0
  156. package/template/src/App.tsx +33 -0
  157. package/template/src/components/Footer.tsx +100 -0
  158. package/template/src/components/Header.tsx +79 -0
  159. package/template/src/components/Hero.tsx +69 -0
  160. package/template/src/components/LanguageSwitcher.tsx +47 -0
  161. package/template/src/components/Layout.tsx +25 -0
  162. package/template/src/components/Logo.tsx +64 -0
  163. package/template/src/components/ThemeSwitcher.tsx +58 -0
  164. package/template/src/components/ui/accordion.tsx +64 -0
  165. package/template/src/components/ui/alert-dialog.tsx +155 -0
  166. package/template/src/components/ui/alert.tsx +66 -0
  167. package/template/src/components/ui/aspect-ratio.tsx +11 -0
  168. package/template/src/components/ui/avatar.tsx +51 -0
  169. package/template/src/components/ui/badge.tsx +46 -0
  170. package/template/src/components/ui/breadcrumb.tsx +109 -0
  171. package/template/src/components/ui/button-group.tsx +83 -0
  172. package/template/src/components/ui/button.tsx +62 -0
  173. package/template/src/components/ui/calendar.tsx +220 -0
  174. package/template/src/components/ui/card.tsx +92 -0
  175. package/template/src/components/ui/carousel.tsx +239 -0
  176. package/template/src/components/ui/chart.tsx +357 -0
  177. package/template/src/components/ui/checkbox.tsx +32 -0
  178. package/template/src/components/ui/collapsible.tsx +31 -0
  179. package/template/src/components/ui/command.tsx +182 -0
  180. package/template/src/components/ui/context-menu.tsx +252 -0
  181. package/template/src/components/ui/dialog.tsx +141 -0
  182. package/template/src/components/ui/drawer.tsx +135 -0
  183. package/template/src/components/ui/dropdown-menu.tsx +255 -0
  184. package/template/src/components/ui/empty.tsx +104 -0
  185. package/template/src/components/ui/field.tsx +246 -0
  186. package/template/src/components/ui/form.tsx +168 -0
  187. package/template/src/components/ui/hover-card.tsx +44 -0
  188. package/template/src/components/ui/input-group.tsx +170 -0
  189. package/template/src/components/ui/input-otp.tsx +75 -0
  190. package/template/src/components/ui/input.tsx +21 -0
  191. package/template/src/components/ui/item.tsx +193 -0
  192. package/template/src/components/ui/kbd.tsx +28 -0
  193. package/template/src/components/ui/label.tsx +24 -0
  194. package/template/src/components/ui/menubar.tsx +274 -0
  195. package/template/src/components/ui/navigation-menu.tsx +168 -0
  196. package/template/src/components/ui/pagination.tsx +127 -0
  197. package/template/src/components/ui/popover.tsx +48 -0
  198. package/template/src/components/ui/progress.tsx +29 -0
  199. package/template/src/components/ui/radio-group.tsx +45 -0
  200. package/template/src/components/ui/resizable.tsx +54 -0
  201. package/template/src/components/ui/scroll-area.tsx +58 -0
  202. package/template/src/components/ui/select.tsx +188 -0
  203. package/template/src/components/ui/separator.tsx +28 -0
  204. package/template/src/components/ui/sheet.tsx +137 -0
  205. package/template/src/components/ui/sidebar.tsx +726 -0
  206. package/template/src/components/ui/skeleton.tsx +13 -0
  207. package/template/src/components/ui/slider.tsx +63 -0
  208. package/template/src/components/ui/sonner.tsx +38 -0
  209. package/template/src/components/ui/spinner.tsx +16 -0
  210. package/template/src/components/ui/switch.tsx +31 -0
  211. package/template/src/components/ui/table.tsx +114 -0
  212. package/template/src/components/ui/tabs.tsx +66 -0
  213. package/template/src/components/ui/textarea.tsx +18 -0
  214. package/template/src/components/ui/toggle-group.tsx +81 -0
  215. package/template/src/components/ui/toggle.tsx +45 -0
  216. package/template/src/components/ui/tooltip.tsx +61 -0
  217. package/template/src/constants/constants.json +58 -0
  218. package/template/src/hooks/use-is-mobile.ts +21 -0
  219. package/template/src/hooks/use-page-title.ts +49 -0
  220. package/template/src/hooks/use-theme.ts +57 -0
  221. package/template/src/index.css +128 -0
  222. package/template/src/lang/en/about.json +4 -0
  223. package/template/src/lang/en/contact.json +39 -0
  224. package/template/src/lang/en/cookies.json +4 -0
  225. package/template/src/lang/en/footer.json +12 -0
  226. package/template/src/lang/en/forgotPassword.json +37 -0
  227. package/template/src/lang/en/header.json +10 -0
  228. package/template/src/lang/en/hero.json +8 -0
  229. package/template/src/lang/en/index.json +30 -0
  230. package/template/src/lang/en/login.json +18 -0
  231. package/template/src/lang/en/notfound.json +7 -0
  232. package/template/src/lang/en/privacy.json +4 -0
  233. package/template/src/lang/en/register.json +25 -0
  234. package/template/src/lang/en/terms.json +4 -0
  235. package/template/src/lang/index.ts +86 -0
  236. package/template/src/lang/tr/about.json +4 -0
  237. package/template/src/lang/tr/contact.json +39 -0
  238. package/template/src/lang/tr/cookies.json +4 -0
  239. package/template/src/lang/tr/footer.json +12 -0
  240. package/template/src/lang/tr/forgotPassword.json +37 -0
  241. package/template/src/lang/tr/header.json +10 -0
  242. package/template/src/lang/tr/hero.json +8 -0
  243. package/template/src/lang/tr/index.json +30 -0
  244. package/template/src/lang/tr/login.json +18 -0
  245. package/template/src/lang/tr/notfound.json +7 -0
  246. package/template/src/lang/tr/privacy.json +4 -0
  247. package/template/src/lang/tr/register.json +25 -0
  248. package/template/src/lang/tr/terms.json +4 -0
  249. package/template/src/lib/api.ts +237 -0
  250. package/template/src/lib/storage.ts +109 -0
  251. package/template/src/lib/utils.ts +15 -0
  252. package/template/src/main.tsx +13 -0
  253. package/template/src/modules/api/USAGE.md +515 -0
  254. package/template/src/modules/api/customer-client.ts +20 -0
  255. package/template/src/modules/api/get-error-message.ts +18 -0
  256. package/template/src/modules/api/validation/en.json +29 -0
  257. package/template/src/modules/api/validation/tr.json +29 -0
  258. package/template/src/modules/auth/USAGE.md +248 -0
  259. package/template/src/modules/auth/auth-header-menu.tsx +123 -0
  260. package/template/src/modules/auth/auth-store.ts +57 -0
  261. package/template/src/modules/auth/forgot-password-page.tsx +371 -0
  262. package/template/src/modules/auth/login-page.tsx +183 -0
  263. package/template/src/modules/auth/register-page.tsx +252 -0
  264. package/template/src/modules/auth/use-auth.ts +273 -0
  265. package/template/src/modules/db/adapters/IDataAdapter.ts +26 -0
  266. package/template/src/modules/db/adapters/SqliteAdapter.ts +364 -0
  267. package/template/src/modules/db/adapters/index.ts +2 -0
  268. package/template/src/modules/db/config.ts +59 -0
  269. package/template/src/modules/db/core/DataManager.ts +125 -0
  270. package/template/src/modules/db/core/types.ts +101 -0
  271. package/template/src/modules/db/index.ts +42 -0
  272. package/template/src/modules/db/react/QueryProvider.tsx +16 -0
  273. package/template/src/modules/db/react/index.ts +23 -0
  274. package/template/src/modules/db/react/queryClient.ts +64 -0
  275. package/template/src/modules/db/react/useRepository.ts +400 -0
  276. package/template/src/modules/db/utils/parsers.ts +96 -0
  277. package/template/src/pages/Index.tsx +108 -0
  278. package/template/src/pages/NotFound.tsx +35 -0
  279. package/template/src/router.tsx +14 -0
  280. package/template/src/types/index.ts +0 -0
  281. package/template/src/vite-env.d.ts +1 -0
  282. package/template/tsconfig.app.json +32 -0
  283. package/template/tsconfig.json +17 -0
  284. package/template/tsconfig.node.json +26 -0
  285. package/template/vite.config.ts +74 -0
@@ -0,0 +1,18 @@
1
+ {
2
+ "title": "GiriÅŸ Yap",
3
+ "description": "Siparişlerinize, favorilerinize ve daha fazlasına erişmek için hesabınıza giriş yapın.",
4
+ "cardTitle": "GiriÅŸ",
5
+ "username": "Kullanıcı Adı",
6
+ "usernamePlaceholder": "Kullanıcı adınızı girin",
7
+ "password": "Åžifre",
8
+ "passwordPlaceholder": "Åžifrenizi girin",
9
+ "forgotPassword": "Åžifremi unuttum?",
10
+ "submit": "GiriÅŸ Yap",
11
+ "submitting": "Giriş yapılıyor...",
12
+ "noAccount": "Hesabınız yok mu?",
13
+ "registerLink": "Hesap oluÅŸturun",
14
+ "toastSuccessTitle": "Tekrar hoÅŸ geldiniz!",
15
+ "toastSuccessDesc": "Başarıyla giriş yaptınız.",
16
+ "toastErrorTitle": "Giriş başarısız",
17
+ "errorGeneric": "Giriş başarısız. Lütfen tekrar deneyin."
18
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "pageNotFound": "Sayfa Bulunamadı",
3
+ "pageNotFoundDev": "Bu sayfayı henüz oluşturmadın",
4
+ "description": "Üzgünüz, aradığınız sayfa bulunamadı. Taşınmış veya mevcut olmayabilir.",
5
+ "descriptionDev": "Bu sayfayı oluşturmak için Promake'i kullanabilirsin.",
6
+ "goHome": "Ana Sayfaya Git"
7
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "Gizlilik Politikası",
3
+ "content": "Gizlilik politikası içeriğimiz şu anda hazırlanmaktadır. Verilerinizi nasıl işlediğimiz hakkında detaylı bilgi için lütfen tekrar kontrol edin."
4
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "title": "Hesap OluÅŸtur",
3
+ "description": "Bugün bize katılın ve özel avantajlardan, sipariş takibinden ve daha fazlasından yararlanın.",
4
+ "cardTitle": "Kayıt Ol",
5
+ "username": "Kullanıcı Adı",
6
+ "usernamePlaceholder": "Bir kullanıcı adı seçin",
7
+ "email": "E-posta",
8
+ "emailPlaceholder": "E-posta adresinizi girin",
9
+ "password": "Åžifre",
10
+ "passwordPlaceholder": "Bir ÅŸifre oluÅŸturun",
11
+ "confirmPassword": "Åžifre Tekrar",
12
+ "confirmPasswordPlaceholder": "Åžifrenizi tekrar girin",
13
+ "submit": "Hesap OluÅŸtur",
14
+ "submitting": "Hesap oluÅŸturuluyor...",
15
+ "hasAccount": "Zaten hesabınız var mı?",
16
+ "loginLink": "Giriş yapın",
17
+ "passwordMismatch": "Åžifreler eÅŸleÅŸmiyor",
18
+ "toastSuccessTitle": "Hesap oluÅŸturuldu!",
19
+ "toastSuccessDesc": "Lütfen hesabınızı doğrulamak için e-postanızı kontrol edin.",
20
+ "toastErrorTitle": "Kayıt başarısız",
21
+ "errorGeneric": "Kayıt başarısız. Lütfen tekrar deneyin.",
22
+ "successTitle": "Hesap OluÅŸturuldu!",
23
+ "successMessage": "Giriş yapmadan önce lütfen hesabınızı doğrulamak için e-postanızı kontrol edin.",
24
+ "goToLogin": "Giriş Sayfasına Git"
25
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "Kullanım Şartları",
3
+ "content": "Kullanım şartları içeriğimiz şu anda hazırlanmaktadır. Hizmetlerimizi kullanma şartları ve koşulları hakkında detaylı bilgi için lütfen tekrar kontrol edin."
4
+ }
@@ -0,0 +1,237 @@
1
+ import axios, { type AxiosInstance, type AxiosResponse } from "axios";
2
+ import constants from "@/constants/constants.json";
3
+
4
+ // API service class
5
+ class ApiService {
6
+ private axiosInstance: AxiosInstance;
7
+ private settings: any = null;
8
+
9
+ constructor() {
10
+ // Default configuration - will be updated when settings load
11
+ this.axiosInstance = axios.create({
12
+ baseURL: "https://backend.promake.ai/api",
13
+ timeout: 30000,
14
+ headers: {
15
+ "Content-Type": "application/json",
16
+ },
17
+ });
18
+
19
+ // Request interceptor to add site slug
20
+ this.axiosInstance.interceptors.request.use(
21
+ (config) => {
22
+ if (this.settings?.site?.slug) {
23
+ config.headers["X-Site-Slug"] = this.settings.site.slug;
24
+ }
25
+ return config;
26
+ },
27
+ (error) => {
28
+ return Promise.reject(error);
29
+ },
30
+ );
31
+
32
+ // Response interceptor for error handling
33
+ this.axiosInstance.interceptors.response.use(
34
+ (response: AxiosResponse) => response,
35
+ (error) => {
36
+ console.error("API Error:", {
37
+ status: error.response?.status,
38
+ statusText: error.response?.statusText,
39
+ data: error.response?.data,
40
+ url: error.config?.url,
41
+ });
42
+ return Promise.reject(error);
43
+ },
44
+ );
45
+ }
46
+
47
+ // Update settings for API configuration
48
+ updateSettings(settings: any) {
49
+ this.settings = settings;
50
+ if (settings?.api?.baseUrl) {
51
+ this.axiosInstance.defaults.baseURL = settings.api.baseUrl;
52
+ }
53
+ if (settings?.api?.timeout) {
54
+ this.axiosInstance.defaults.timeout = settings.api.timeout;
55
+ }
56
+ }
57
+
58
+ // Get endpoint from settings
59
+ private getEndpoint(key: string): string {
60
+ return this.settings?.api?.endpoints?.[key] || `/${key}`;
61
+ }
62
+
63
+ // Order API methods
64
+ async createOrder(orderData: {
65
+ user_id: string;
66
+ total_price: number;
67
+ status: string;
68
+ payment_method: string;
69
+ shipping_address: any;
70
+ notes?: string | null;
71
+ items: Array<{
72
+ product_id: number;
73
+ quantity: number;
74
+ price: number;
75
+ }>;
76
+ }): Promise<{ orderId: number; success: boolean }> {
77
+ try {
78
+ const response = await this.axiosInstance.post(
79
+ this.getEndpoint("orders"),
80
+ {
81
+ site_slug: this.settings?.site?.slug || "promake",
82
+ order: {
83
+ user_id: orderData.user_id,
84
+ total_price: orderData.total_price,
85
+ status: orderData.status,
86
+ payment_method: orderData.payment_method,
87
+ shipping_address: orderData.shipping_address,
88
+ notes: orderData.notes,
89
+ },
90
+ items: orderData.items,
91
+ },
92
+ );
93
+
94
+ return {
95
+ orderId: response.data.order_id,
96
+ success: true,
97
+ };
98
+ } catch (error: any) {
99
+ console.error("Order creation failed:", error);
100
+ throw new Error(error.response?.data?.message || "Order creation failed");
101
+ }
102
+ }
103
+
104
+ // Generic form submission to mail service
105
+ async submitForm(
106
+ formData: Record<string, any>,
107
+ formConfig: {
108
+ email_subject1: string;
109
+ email_subject2: string;
110
+ fields: Array<{ name: string; required: boolean }>;
111
+ },
112
+ currentLanguage: string = "en",
113
+ ): Promise<{ success: boolean; message: string }> {
114
+ try {
115
+ // Extract customer email from form data
116
+ const customerEmail = formData["email"];
117
+ if (!customerEmail) {
118
+ throw new Error("Email field is required in form data");
119
+ }
120
+
121
+ // Get site owner email from ENV
122
+ const tenantEmail = import.meta.env.VITE_TENANT_MAIL;
123
+ if (!tenantEmail) {
124
+ throw new Error("VITE_TENANT_MAIL environment variable is not set");
125
+ }
126
+
127
+ // Convert formData to backend expected format with required info from config
128
+ const data: Record<string, { required: boolean; value: any }> = {};
129
+
130
+ formConfig.fields.forEach((field) => {
131
+ data[field.name] = {
132
+ required: field.required,
133
+ value: formData[field.name] || null,
134
+ };
135
+ });
136
+
137
+ // Get mail service URL from ENV
138
+ const mailServiceUrl =
139
+ import.meta.env.VITE_MAIL_SERVICE_URL ||
140
+ "https://mail.promake.ai/api/v1/send-mail";
141
+
142
+ // Make request to mail service
143
+ const response = await axios.post(
144
+ mailServiceUrl,
145
+ {
146
+ target_email1: customerEmail,
147
+ target_email2: tenantEmail,
148
+ email_subject1: formConfig.email_subject1,
149
+ email_subject2: formConfig.email_subject2,
150
+ data: data,
151
+ },
152
+ {
153
+ headers: {
154
+ "Accept-Language": currentLanguage,
155
+ "Content-Type": "application/json",
156
+ },
157
+ },
158
+ );
159
+
160
+ return {
161
+ success: true,
162
+ message: response.data.message || "Form submitted successfully",
163
+ };
164
+ } catch (error: any) {
165
+ console.error("Form submission failed:", error);
166
+ throw new Error(error.response?.data?.message || "Failed to submit form");
167
+ }
168
+ }
169
+
170
+ // DEPRECATED: Use submitForm instead
171
+ // Keeping for backward compatibility
172
+ async submitContactForm(contactData: {
173
+ name: string;
174
+ email: string;
175
+ subject?: string;
176
+ message: string;
177
+ }): Promise<{ success: boolean; message: string }> {
178
+ console.warn("submitContactForm is deprecated. Use submitForm instead.");
179
+ return this.submitForm(
180
+ contactData,
181
+ {
182
+ email_subject1: "Contact Form Submission",
183
+ email_subject2: "New Contact Form",
184
+ fields: [
185
+ { name: "name", required: true },
186
+ { name: "email", required: true },
187
+ { name: "subject", required: false },
188
+ { name: "message", required: true },
189
+ ],
190
+ },
191
+ "en",
192
+ );
193
+ }
194
+
195
+ // Get order by ID (for order confirmation page)
196
+ async getOrderById(orderId: number): Promise<any | null> {
197
+ try {
198
+ const response = await this.axiosInstance.get(
199
+ `${this.getEndpoint("orders")}/${orderId}?site_slug=${
200
+ this.settings?.site?.slug
201
+ }`,
202
+ );
203
+ return response.data.order || null;
204
+ } catch (error: any) {
205
+ console.error("Failed to fetch order:", error);
206
+ return null;
207
+ }
208
+ }
209
+ }
210
+
211
+ // Create singleton instance
212
+ const apiService = new ApiService();
213
+
214
+ // Hook to use API service with settings
215
+ export const useApiService = () => {
216
+ // Reconstruct settings object for ApiService.updateSettings
217
+ const settings = {
218
+ site: {
219
+ slug: constants.site.slug,
220
+ },
221
+ api: {
222
+ baseUrl: constants.api.baseUrl,
223
+ timeout: constants.api.timeout,
224
+ endpoints: constants.api.endpoints,
225
+ },
226
+ };
227
+
228
+ // Update API service settings when they change
229
+ if (settings && apiService) {
230
+ apiService.updateSettings(settings);
231
+ }
232
+
233
+ return apiService;
234
+ };
235
+
236
+ // Export the service for direct use
237
+ export default apiService;
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Site-specific localStorage utility
3
+ * Prevents localStorage conflicts between different templates on same domain
4
+ * Uses a unique site ID generated on first load
5
+ */
6
+
7
+ let sitePrefix: string | null = null;
8
+ const SITE_ID_KEY = "__site_id__"; // Raw key, no prefix
9
+
10
+ /**
11
+ * Generate a unique site ID (UUID v4)
12
+ */
13
+ const generateSiteId = (): string => {
14
+ return (
15
+ "site_" +
16
+ "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
17
+ const r = (Math.random() * 16) | 0;
18
+ const v = c === "x" ? r : (r & 0x3) | 0x8;
19
+ return v.toString(16);
20
+ })
21
+ );
22
+ };
23
+
24
+ /**
25
+ * Get or create site-specific localStorage prefix
26
+ * Each site gets a unique ID on first load
27
+ */
28
+ const getSitePrefix = (): string => {
29
+ if (sitePrefix) return sitePrefix;
30
+
31
+ try {
32
+ // Check if site already has a unique ID
33
+ let siteId = localStorage.getItem(SITE_ID_KEY);
34
+
35
+ if (!siteId) {
36
+ // First load - generate and save unique site ID
37
+ siteId = generateSiteId();
38
+ localStorage.setItem(SITE_ID_KEY, siteId);
39
+ console.log("🆔 Generated new site ID:", siteId);
40
+ }
41
+
42
+ sitePrefix = siteId;
43
+ return sitePrefix;
44
+ } catch (error) {
45
+ console.error("Failed to get/create site ID:", error);
46
+ // Fallback to timestamp-based ID
47
+ sitePrefix = "site_" + Date.now();
48
+ return sitePrefix;
49
+ }
50
+ };
51
+
52
+ /**
53
+ * Get site-specific localStorage key
54
+ */
55
+ export const getStorageKey = (key: string): string => {
56
+ const prefix = getSitePrefix();
57
+ return `${prefix}_${key}`;
58
+ };
59
+
60
+ /**
61
+ * Get item from localStorage with site-specific key
62
+ */
63
+ export const getItem = (key: string): string | null => {
64
+ try {
65
+ return localStorage.getItem(getStorageKey(key));
66
+ } catch (error) {
67
+ console.error(`Error reading from localStorage (${key}):`, error);
68
+ return null;
69
+ }
70
+ };
71
+
72
+ /**
73
+ * Set item to localStorage with site-specific key
74
+ */
75
+ export const setItem = (key: string, value: string): void => {
76
+ try {
77
+ localStorage.setItem(getStorageKey(key), value);
78
+ } catch (error) {
79
+ console.error(`Error writing to localStorage (${key}):`, error);
80
+ }
81
+ };
82
+
83
+ /**
84
+ * Remove item from localStorage with site-specific key
85
+ */
86
+ export const removeItem = (key: string): void => {
87
+ try {
88
+ localStorage.removeItem(getStorageKey(key));
89
+ } catch (error) {
90
+ console.error(`Error removing from localStorage (${key}):`, error);
91
+ }
92
+ };
93
+
94
+ /**
95
+ * Clear all site-specific items from localStorage
96
+ */
97
+ export const clearSiteStorage = (): void => {
98
+ try {
99
+ const prefix = getSitePrefix();
100
+ const keys = Object.keys(localStorage);
101
+ keys.forEach((key) => {
102
+ if (key.startsWith(`${prefix}_`)) {
103
+ localStorage.removeItem(key);
104
+ }
105
+ });
106
+ } catch (error) {
107
+ console.error("Error clearing site storage:", error);
108
+ }
109
+ };
@@ -0,0 +1,15 @@
1
+ import { clsx, type ClassValue } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ export function formatPrice(price: number, currency: string = "USD"): string {
9
+ return new Intl.NumberFormat("en-US", {
10
+ style: "currency",
11
+ currency: currency,
12
+ minimumFractionDigits: 0,
13
+ maximumFractionDigits: 2,
14
+ }).format(price);
15
+ }
@@ -0,0 +1,13 @@
1
+ import "./lang";
2
+ import "./index.css";
3
+ import { StrictMode } from "react";
4
+ import { createRoot } from "react-dom/client";
5
+ import { Toaster } from "@/components/ui/sonner";
6
+ import App from "@/App.tsx";
7
+
8
+ createRoot(document.getElementById("root")!).render(
9
+ <StrictMode>
10
+ <App />
11
+ <Toaster />
12
+ </StrictMode>,
13
+ );