@promakeai/cli 0.0.6 → 0.1.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.
Files changed (114) hide show
  1. package/dist/index.js +31 -31
  2. package/dist/registry/about-page.json +4 -2
  3. package/dist/registry/about-section.json +2 -2
  4. package/dist/registry/announcement-bar.json +43 -0
  5. package/dist/registry/auth-core.json +43 -0
  6. package/dist/registry/auth.json +1 -1
  7. package/dist/registry/blog-list-page.json +3 -2
  8. package/dist/registry/blog-section.json +1 -1
  9. package/dist/registry/cart-page.json +3 -3
  10. package/dist/registry/case-study-page.json +48 -0
  11. package/dist/registry/checkout-page.json +6 -5
  12. package/dist/registry/coming-soon-page-minimal.json +45 -0
  13. package/dist/registry/coming-soon-page.json +47 -0
  14. package/dist/registry/contact-info-grid.json +1 -1
  15. package/dist/registry/contact-page-centered.json +2 -2
  16. package/dist/registry/contact-page-map-overlay.json +4 -3
  17. package/dist/registry/contact-page-map-split.json +4 -3
  18. package/dist/registry/contact-page-split.json +3 -3
  19. package/dist/registry/contact-page.json +5 -3
  20. package/dist/registry/cookie-consent.json +43 -0
  21. package/dist/registry/cookies-page.json +3 -1
  22. package/dist/registry/cta-section.json +1 -1
  23. package/dist/registry/db.json +1 -1
  24. package/dist/registry/docs/about-page.md +5 -0
  25. package/dist/registry/docs/announcement-bar.md +38 -0
  26. package/dist/registry/docs/auth-core.md +64 -0
  27. package/dist/registry/docs/blog-list-page.md +1 -0
  28. package/dist/registry/docs/case-study-page.md +39 -0
  29. package/dist/registry/docs/checkout-page.md +2 -1
  30. package/dist/registry/docs/coming-soon-page-minimal.md +32 -0
  31. package/dist/registry/docs/coming-soon-page.md +37 -0
  32. package/dist/registry/docs/contact-page-map-overlay.md +2 -2
  33. package/dist/registry/docs/contact-page-map-split.md +2 -2
  34. package/dist/registry/docs/contact-page.md +5 -0
  35. package/dist/registry/docs/cookie-consent.md +37 -0
  36. package/dist/registry/docs/cookies-page.md +5 -0
  37. package/dist/registry/docs/ecommerce-core.md +4 -3
  38. package/dist/registry/docs/forgot-password-page-split.md +45 -0
  39. package/dist/registry/docs/forgot-password-page.md +14 -5
  40. package/dist/registry/docs/header-ecommerce.md +1 -0
  41. package/dist/registry/docs/hero-carousel.md +37 -0
  42. package/dist/registry/docs/landing-page-app.md +43 -0
  43. package/dist/registry/docs/landing-page-saas.md +41 -0
  44. package/dist/registry/docs/login-page-split.md +13 -4
  45. package/dist/registry/docs/login-page.md +17 -4
  46. package/dist/registry/docs/logo-cloud.md +33 -0
  47. package/dist/registry/docs/masonry-grid.md +37 -0
  48. package/dist/registry/docs/my-orders-page.md +44 -0
  49. package/dist/registry/docs/order-confirmation-page.md +41 -0
  50. package/dist/registry/docs/portfolio-page.md +38 -0
  51. package/dist/registry/docs/pricing-page.md +38 -0
  52. package/dist/registry/docs/privacy-page.md +5 -0
  53. package/dist/registry/docs/product-quick-view.md +37 -0
  54. package/dist/registry/docs/reading-progress.md +31 -0
  55. package/dist/registry/docs/register-page-split.md +45 -0
  56. package/dist/registry/docs/register-page.md +14 -7
  57. package/dist/registry/docs/reset-password-page-split.md +45 -0
  58. package/dist/registry/docs/reset-password-page.md +36 -0
  59. package/dist/registry/docs/share-buttons.md +37 -0
  60. package/dist/registry/docs/team-page.md +38 -0
  61. package/dist/registry/docs/terms-page.md +5 -0
  62. package/dist/registry/docs/timeline-section.md +37 -0
  63. package/dist/registry/docs/video-hero.md +41 -0
  64. package/dist/registry/ecommerce-core.json +17 -1
  65. package/dist/registry/empty-page.json +1 -1
  66. package/dist/registry/faq-categorized.json +1 -1
  67. package/dist/registry/faq-simple.json +1 -1
  68. package/dist/registry/favorites-ecommerce-block.json +1 -1
  69. package/dist/registry/feature-section.json +2 -2
  70. package/dist/registry/footer.json +1 -1
  71. package/dist/registry/forgot-password-page-split.json +50 -0
  72. package/dist/registry/forgot-password-page.json +9 -7
  73. package/dist/registry/header-ecommerce.json +3 -2
  74. package/dist/registry/header-mega.json +1 -1
  75. package/dist/registry/hero-carousel.json +45 -0
  76. package/dist/registry/hero-cta.json +2 -2
  77. package/dist/registry/hero-gradient.json +1 -1
  78. package/dist/registry/hero.json +1 -1
  79. package/dist/registry/index.json +22 -2
  80. package/dist/registry/landing-page-app.json +47 -0
  81. package/dist/registry/landing-page-saas.json +47 -0
  82. package/dist/registry/login-page-split.json +11 -7
  83. package/dist/registry/login-page.json +4 -4
  84. package/dist/registry/logo-cloud.json +41 -0
  85. package/dist/registry/masonry-grid.json +43 -0
  86. package/dist/registry/my-orders-page.json +52 -0
  87. package/dist/registry/order-confirmation-page.json +49 -0
  88. package/dist/registry/portfolio-page.json +45 -0
  89. package/dist/registry/pricing-page.json +47 -0
  90. package/dist/registry/pricing-section.json +1 -1
  91. package/dist/registry/privacy-page.json +3 -1
  92. package/dist/registry/product-detail-block.json +1 -1
  93. package/dist/registry/product-quick-view.json +46 -0
  94. package/dist/registry/products-page.json +3 -3
  95. package/dist/registry/reading-progress.json +43 -0
  96. package/dist/registry/register-page-split.json +50 -0
  97. package/dist/registry/register-page.json +9 -7
  98. package/dist/registry/reset-password-page-split.json +50 -0
  99. package/dist/registry/reset-password-page.json +39 -0
  100. package/dist/registry/share-buttons.json +46 -0
  101. package/dist/registry/team-page.json +47 -0
  102. package/dist/registry/terms-page.json +3 -1
  103. package/dist/registry/testimonials-carousel.json +1 -1
  104. package/dist/registry/testimonials-grid.json +1 -1
  105. package/dist/registry/timeline-section.json +43 -0
  106. package/dist/registry/video-hero.json +42 -0
  107. package/package.json +1 -1
  108. package/template/index.html +5 -5
  109. package/template/src/App.tsx +4 -0
  110. package/template/src/components/GoogleAnalytics.tsx +34 -0
  111. package/template/src/components/Layout.tsx +1 -1
  112. package/template/src/components/ScriptInjector.tsx +62 -0
  113. package/template/src/constants/constants.json +8 -2
  114. package/template/src/pages/Index.tsx +5 -1
@@ -0,0 +1,45 @@
1
+ # Register Page Split
2
+
3
+ Split-screen registration page with form on the left and full-height image on the right. Features username, email, password fields with confirmation. Uses customerClient for API calls.
4
+
5
+ ## Files
6
+
7
+ | Target | Type |
8
+ |--------|------|
9
+ | `$modules$/register-page-split/index.ts` | index |
10
+ | `$modules$/register-page-split/register-page-split.tsx` | page |
11
+ | `$modules$/register-page-split/lang/en.json` | lang |
12
+ | `$modules$/register-page-split/lang/tr.json` | lang |
13
+
14
+ ## Exports
15
+
16
+ **Components/Functions:** `RegisterPageSplit`, `default`
17
+
18
+ ```typescript
19
+ import { RegisterPageSplit, default } from '@/modules/register-page-split';
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ import RegisterPageSplit from '@/modules/register-page-split';
26
+
27
+ <RegisterPageSplit
28
+ image="/images/register-bg.jpg"
29
+ />
30
+
31
+ • Installed at: src/modules/register-page-split/
32
+ • Customize text: src/modules/register-page-split/lang/*.json
33
+ • API Integration:
34
+ - customerClient.auth.register() for registration
35
+ - Shows success state after registration
36
+ • Add to your router as a page component
37
+ ```
38
+
39
+ ## Dependencies
40
+
41
+ This component requires:
42
+ - `button`
43
+ - `input`
44
+ - `auth-core`
45
+ - `api`
@@ -1,6 +1,6 @@
1
1
  # Register Page
2
2
 
3
- Registration page with name, email, password form, social OAuth buttons (Google, Microsoft), and sign in link. Centered card layout with responsive design.
3
+ Centered card registration page with Layout wrapper. Features username, email, password fields with confirmation, success state after registration. Uses useAuth hook from auth-core for API calls.
4
4
 
5
5
  ## Files
6
6
 
@@ -24,11 +24,16 @@ import { RegisterPage, default } from '@/modules/register-page';
24
24
  ```
25
25
  import RegisterPage from '@/modules/register-page';
26
26
 
27
- <RegisterPage
28
- onSubmit={(name, email, password) => console.log(name, email, password)}
29
- onGoogleSignup={() => console.log('Google')}
30
- onMicrosoftSignup={() => console.log('Microsoft')}
31
- />
27
+ <RegisterPage />
28
+
29
+ Installed at: src/modules/register-page/
30
+ Customize text: src/modules/register-page/lang/*.json
31
+ • Uses useAuth() hook from auth-core:
32
+ const { register } = useAuth();
33
+ await register(username, email, password);
34
+ • Shows success state after registration
35
+ • Redirects authenticated users to home
36
+ • Add to your router as a page component
32
37
  ```
33
38
 
34
39
  ## Dependencies
@@ -36,4 +41,6 @@ import RegisterPage from '@/modules/register-page';
36
41
  This component requires:
37
42
  - `button`
38
43
  - `input`
39
- - `label`
44
+ - `card`
45
+ - `auth-core`
46
+ - `api`
@@ -0,0 +1,45 @@
1
+ # Reset Password Page Split
2
+
3
+ Split-screen password reset page with form on the left and full-height image on the right. Features new password input with confirmation, validates reset code from URL. Uses customerClient for API calls.
4
+
5
+ ## Files
6
+
7
+ | Target | Type |
8
+ |--------|------|
9
+ | `$modules$/reset-password-page-split/index.ts` | index |
10
+ | `$modules$/reset-password-page-split/reset-password-page-split.tsx` | page |
11
+ | `$modules$/reset-password-page-split/lang/en.json` | lang |
12
+ | `$modules$/reset-password-page-split/lang/tr.json` | lang |
13
+
14
+ ## Exports
15
+
16
+ **Components/Functions:** `ResetPasswordPageSplit`, `default`
17
+
18
+ ```typescript
19
+ import { ResetPasswordPageSplit, default } from '@/modules/reset-password-page-split';
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ import ResetPasswordPageSplit from '@/modules/reset-password-page-split';
26
+
27
+ <ResetPasswordPageSplit
28
+ image="/images/reset-bg.jpg"
29
+ />
30
+
31
+ • Installed at: src/modules/reset-password-page-split/
32
+ • Customize text: src/modules/reset-password-page-split/lang/*.json
33
+ • API Integration:
34
+ - customerClient.auth.resetPassword() for resetting password
35
+ - Expects ?code= and ?username= URL parameters from email link
36
+ • Add to your router as a page component
37
+ ```
38
+
39
+ ## Dependencies
40
+
41
+ This component requires:
42
+ - `button`
43
+ - `input`
44
+ - `auth-core`
45
+ - `api`
@@ -0,0 +1,36 @@
1
+ # Reset Password Page
2
+
3
+ Split-screen password reset page with form on the left and full-height image on the right. Features new password input with confirmation, validates reset code from URL. Clean minimal design with API integration and responsive layout.
4
+
5
+ ## Files
6
+
7
+ | Target | Type |
8
+ |--------|------|
9
+ | `$modules$/reset-password-page/index.ts` | index |
10
+ | `$modules$/reset-password-page/reset-password-page.tsx` | page |
11
+ | `$modules$/reset-password-page/lang/en.json` | lang |
12
+ | `$modules$/reset-password-page/lang/tr.json` | lang |
13
+
14
+ ## Usage
15
+
16
+ ```
17
+ import ResetPasswordPage from '@/modules/reset-password-page';
18
+
19
+ <ResetPasswordPage
20
+ image="/images/reset-bg.jpg"
21
+ />
22
+
23
+ • Installed at: src/modules/reset-password-page/
24
+ • Customize text: src/modules/reset-password-page/lang/*.json
25
+ • Uses customerClient.auth.resetPassword() for API
26
+ • Expects ?code= URL parameter from email link
27
+ • Add to your router as a page component
28
+ ```
29
+
30
+ ## Dependencies
31
+
32
+ This component requires:
33
+ - `button`
34
+ - `input`
35
+ - `auth`
36
+ - `api`
@@ -0,0 +1,37 @@
1
+ # Share Buttons
2
+
3
+ Social media share buttons with copy link functionality. Supports Twitter/X, Facebook, LinkedIn, WhatsApp, Email, and copy to clipboard.
4
+
5
+ ## Files
6
+
7
+ | Target | Type |
8
+ |--------|------|
9
+ | `$modules$/share-buttons/share-buttons.tsx` | component |
10
+ | `$modules$/share-buttons/index.ts` | index |
11
+ | `$modules$/share-buttons/lang/en.json` | lang |
12
+ | `$modules$/share-buttons/lang/tr.json` | lang |
13
+
14
+ ## Exports
15
+
16
+ **Components/Functions:** `ShareButtons`
17
+
18
+ ```typescript
19
+ import { ShareButtons } from '@/modules/share-buttons';
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ import { ShareButtons } from '@/modules/share-buttons';
26
+
27
+ <ShareButtons />
28
+
29
+ • Installed at: src/modules/share-buttons/
30
+ • Props: url, title, platforms[], layout, size, showLabels
31
+ ```
32
+
33
+ ## Dependencies
34
+
35
+ This component requires:
36
+ - `button`
37
+ - `tooltip`
@@ -0,0 +1,38 @@
1
+ # Team Page
2
+
3
+ Team members page with responsive grid layout, member cards with photo, name, role, bio, and social links. Includes staggered animations, hover effects, and a join team CTA section.
4
+
5
+ ## Files
6
+
7
+ | Target | Type |
8
+ |--------|------|
9
+ | `$modules$/team-page/index.ts` | index |
10
+ | `$modules$/team-page/team-page.tsx` | page |
11
+ | `$modules$/team-page/lang/en.json` | lang |
12
+ | `$modules$/team-page/lang/tr.json` | lang |
13
+
14
+ ## Exports
15
+
16
+ **Components/Functions:** `TeamPage`, `default`
17
+
18
+ ```typescript
19
+ import { TeamPage, default } from '@/modules/team-page';
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ import { TeamPage } from '@/modules/team-page';
26
+
27
+ <Route path="/team" element={<TeamPage />} />
28
+
29
+ • 6 team member cards with social links
30
+ • StaggerContainer grid animation
31
+ • Join team CTA section
32
+ • Customizable via lang files
33
+ ```
34
+
35
+ ## Dependencies
36
+
37
+ This component requires:
38
+ - `animations`
@@ -30,3 +30,8 @@ import { TermsPage } from '@/modules/terms-page';
30
30
  • Sections: account, use, IP, liability, termination
31
31
  • Edit content in lang/en.json
32
32
  ```
33
+
34
+ ## Dependencies
35
+
36
+ This component requires:
37
+ - `animations`
@@ -0,0 +1,37 @@
1
+ # Timeline Section
2
+
3
+ Vertical timeline with alternating left/right items. Perfect for company history, roadmaps, or process steps.
4
+
5
+ ## Files
6
+
7
+ | Target | Type |
8
+ |--------|------|
9
+ | `$modules$/timeline-section/timeline-section.tsx` | component |
10
+ | `$modules$/timeline-section/index.ts` | index |
11
+ | `$modules$/timeline-section/lang/en.json` | lang |
12
+ | `$modules$/timeline-section/lang/tr.json` | lang |
13
+
14
+ ## Exports
15
+
16
+ **Components/Functions:** `TimelineSection`
17
+
18
+ ```typescript
19
+ import { TimelineSection } from '@/modules/timeline-section';
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ import { TimelineSection } from '@/modules/timeline-section';
26
+
27
+ <TimelineSection />
28
+
29
+ • Installed at: src/modules/timeline-section/
30
+ • Customize content: lang/en/timeline-section.json
31
+ • Props: items[], title, subtitle
32
+ ```
33
+
34
+ ## Dependencies
35
+
36
+ This component requires:
37
+ - `animations`
@@ -0,0 +1,41 @@
1
+ # Video Hero Section
2
+
3
+ Full-width hero section with autoplaying video background, gradient overlay, headline, description, CTA buttons, and animated stats. Includes scroll indicator and FadeIn animations.
4
+
5
+ ## Files
6
+
7
+ | Target | Type |
8
+ |--------|------|
9
+ | `$modules$/video-hero/index.ts` | index |
10
+ | `$modules$/video-hero/video-hero.tsx` | block |
11
+ | `$modules$/video-hero/lang/en.json` | lang |
12
+ | `$modules$/video-hero/lang/tr.json` | lang |
13
+
14
+ ## Exports
15
+
16
+ **Components/Functions:** `VideoHero`
17
+
18
+ ```typescript
19
+ import { VideoHero } from '@/modules/video-hero';
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ import { VideoHero } from '@/modules/video-hero';
26
+
27
+ <VideoHero
28
+ videoSrc="/videos/hero.mp4"
29
+ posterSrc="/images/hero-poster.jpg"
30
+ />
31
+
32
+ • Muted autoplay video
33
+ • Fallback poster image
34
+ • Responsive overlay text
35
+ • Scroll indicator
36
+ ```
37
+
38
+ ## Dependencies
39
+
40
+ This component requires:
41
+ - `animations`
@@ -13,7 +13,7 @@
13
13
  "path": "ecommerce-core/index.ts",
14
14
  "type": "registry:index",
15
15
  "target": "$modules$/ecommerce-core/index.ts",
16
- "content": "// Types\r\nexport * from './types';\r\n\r\n// Stores (Zustand)\r\nexport { useCartStore, useCart } from './stores/cart-store';\r\nexport { useFavoritesStore, useFavorites } from './stores/favorites-store';\r\n\r\n// Hooks\r\nexport { useProducts, useProductBySlug, useFeaturedProducts, useCategories } from './useProducts';\r\nexport { useSearch } from './useSearch';\r\n\r\n// Utilities\r\nexport { formatPrice } from './format-price';\r\n"
16
+ "content": "// Types\r\nexport * from './types';\r\n\r\n// Stores (Zustand)\r\nexport { useCartStore, useCart } from './stores/cart-store';\r\nexport { useFavoritesStore, useFavorites } from './stores/favorites-store';\r\n\r\n// Hooks\r\nexport { useProducts, useProductBySlug, useFeaturedProducts, useCategories } from './useProducts';\r\nexport { useSearch } from './useSearch';\r\n\r\n// Utilities\r\nexport { formatPrice } from './format-price';\r\n\r\n// Payment Config\r\nexport {\r\n type PaymentMethod,\r\n type OnlinePaymentProvider,\r\n type PaymentMethodConfig,\r\n PAYMENT_METHOD_CONFIGS,\r\n ONLINE_PROVIDER_CONFIGS,\r\n getAvailablePaymentMethods,\r\n getOnlinePaymentProviders,\r\n getFilteredPaymentMethodConfigs,\r\n isPaymentMethodAvailable,\r\n isOnlineProviderAvailable,\r\n} from './payment-config';\r\n"
17
17
  },
18
18
  {
19
19
  "path": "ecommerce-core/types.ts",
@@ -51,6 +51,12 @@
51
51
  "target": "$modules$/ecommerce-core/format-price.ts",
52
52
  "content": "export function formatPrice(price: number, currency: string = \"USD\"): string {\r\n return new Intl.NumberFormat(\"en-US\", {\r\n style: \"currency\",\r\n currency: currency,\r\n }).format(price);\r\n}\r\n"
53
53
  },
54
+ {
55
+ "path": "ecommerce-core/payment-config.ts",
56
+ "type": "registry:lib",
57
+ "target": "$modules$/ecommerce-core/payment-config.ts",
58
+ "content": "// Payment configuration utility\r\n// Parses environment variables and provides payment method configuration\r\n\r\nexport type PaymentMethod = \"card\" | \"transfer\" | \"cash\";\r\nexport type OnlinePaymentProvider = \"stripe\" | \"iyzico\";\r\n\r\nexport interface PaymentMethodConfig {\r\n id: PaymentMethod;\r\n label: string;\r\n description: string;\r\n icon: string; // Icon component name from lucide-react\r\n requiresOnlineProvider?: boolean;\r\n}\r\n\r\n// Parse comma-separated env variable into array\r\nconst parseEnvArray = (envVar: string | undefined): string[] => {\r\n if (!envVar) return [];\r\n return envVar.split(\",\").map((item) => item.trim()).filter(Boolean);\r\n};\r\n\r\n// Get available payment methods from environment\r\nexport const getAvailablePaymentMethods = (): PaymentMethod[] => {\r\n const methods = parseEnvArray(import.meta.env.VITE_AVAILABLE_PAYMENT_METHODS);\r\n if (methods.length === 0) {\r\n // Default to all methods if not configured\r\n return [\"card\", \"transfer\", \"cash\"];\r\n }\r\n return methods as PaymentMethod[];\r\n};\r\n\r\n// Get available online payment providers from environment\r\nexport const getOnlinePaymentProviders = (): OnlinePaymentProvider[] => {\r\n const providers = parseEnvArray(import.meta.env.VITE_ONLINE_PAYMENT_METHODS);\r\n if (providers.length === 0) {\r\n // Default to stripe if not configured\r\n return [\"stripe\"];\r\n }\r\n return providers as OnlinePaymentProvider[];\r\n};\r\n\r\n// Payment method configurations with display information\r\nexport const PAYMENT_METHOD_CONFIGS: Record<PaymentMethod, PaymentMethodConfig> = {\r\n card: {\r\n id: \"card\",\r\n label: \"Credit/Debit Card\",\r\n description: \"Pay securely with your credit or debit card\",\r\n icon: \"CreditCard\",\r\n requiresOnlineProvider: true,\r\n },\r\n transfer: {\r\n id: \"transfer\",\r\n label: \"Bank Transfer\",\r\n description: \"Transfer payment to our bank account\",\r\n icon: \"Banknote\",\r\n },\r\n cash: {\r\n id: \"cash\",\r\n label: \"Cash on Delivery\",\r\n description: \"Pay when your order arrives at your doorstep\",\r\n icon: \"Truck\",\r\n },\r\n};\r\n\r\n// Online payment provider configurations\r\nexport const ONLINE_PROVIDER_CONFIGS: Record<OnlinePaymentProvider, { label: string; description: string }> = {\r\n stripe: {\r\n label: \"Stripe\",\r\n description: \"Secure payment processing by Stripe\",\r\n },\r\n iyzico: {\r\n label: \"iyzico\",\r\n description: \"Secure payment processing by iyzico\",\r\n },\r\n};\r\n\r\n// Check if a payment method is available\r\nexport const isPaymentMethodAvailable = (method: PaymentMethod): boolean => {\r\n const available = getAvailablePaymentMethods();\r\n return available.includes(method);\r\n};\r\n\r\n// Check if an online provider is available\r\nexport const isOnlineProviderAvailable = (provider: OnlinePaymentProvider): boolean => {\r\n const available = getOnlinePaymentProviders();\r\n return available.includes(provider);\r\n};\r\n\r\n// Get filtered payment method configs (only available ones)\r\nexport const getFilteredPaymentMethodConfigs = (): PaymentMethodConfig[] => {\r\n const availableMethods = getAvailablePaymentMethods();\r\n return availableMethods\r\n .map((method) => PAYMENT_METHOD_CONFIGS[method])\r\n .filter(Boolean);\r\n};\r\n"
59
+ },
54
60
  {
55
61
  "path": "ecommerce-core/lang/en.json",
56
62
  "type": "registry:lang",
@@ -72,15 +78,25 @@
72
78
  "CartState",
73
79
  "Category",
74
80
  "FavoritesContextType",
81
+ "OnlinePaymentProvider",
75
82
  "Order",
76
83
  "OrderItem",
84
+ "PaymentMethod",
85
+ "PaymentMethodConfig",
77
86
  "Product",
78
87
  "ProductCategory",
79
88
  "ProductVariant",
80
89
  "User"
81
90
  ],
82
91
  "variables": [
92
+ "ONLINE_PROVIDER_CONFIGS",
93
+ "PAYMENT_METHOD_CONFIGS",
83
94
  "formatPrice",
95
+ "getAvailablePaymentMethods",
96
+ "getFilteredPaymentMethodConfigs",
97
+ "getOnlinePaymentProviders",
98
+ "isOnlineProviderAvailable",
99
+ "isPaymentMethodAvailable",
84
100
  "useCart",
85
101
  "useCartStore",
86
102
  "useCategories",
@@ -20,7 +20,7 @@
20
20
  "path": "empty-page/empty-page.tsx",
21
21
  "type": "registry:page",
22
22
  "target": "$modules$/empty-page/empty-page.tsx",
23
- "content": "import { useTranslation } from \"react-i18next\";\nimport { usePageTitle } from \"@/hooks/use-page-title\";\nimport { Layout } from \"@/components/Layout\";\n\nexport function EmptyPage() {\n const { t } = useTranslation(\"empty-page\");\n usePageTitle({ title: t(\"title\") });\n\n return (\n <Layout>\n <div className=\"min-h-screen bg-muted/30 py-12\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n <h1 className=\"text-3xl font-bold\">{t(\"heading\")}</h1>\n <p className=\"text-muted-foreground mt-2\">{t(\"description\")}</p>\n\n {/* Add your page content here */}\n </div>\n </div>\n </Layout>\n );\n}\n"
23
+ "content": "import { useTranslation } from \"react-i18next\";\nimport { usePageTitle } from \"@/hooks/use-page-title\";\nimport { Layout } from \"@/components/Layout\";\n\nexport function EmptyPage() {\n const { t } = useTranslation(\"empty-page\");\n usePageTitle({ title: t(\"title\") });\n\n return (\n <Layout>\n <div className=\"min-h-screen bg-muted/30 py-12\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n <h1 className=\"text-3xl font-bold\">{t(\"heading\")}</h1>\n <p className=\"text-muted-foreground mt-2\">{t(\"description\")}</p>\n\n {/* Add your page content here */}\n </div>\n </div>\n </Layout>\n );\n}\n\nexport default EmptyPage;\n"
24
24
  },
25
25
  {
26
26
  "path": "empty-page/lang/en.json",
@@ -24,7 +24,7 @@
24
24
  "path": "faq-categorized/lang/en.json",
25
25
  "type": "registry:lang",
26
26
  "target": "$modules$/faq-categorized/lang/en.json",
27
- "content": "{\r\n \"title\": \"Frequently Asked Questions\",\r\n \"subtitle\": \"AI will customize this subtitle to match your FAQ section purpose.\",\r\n \"generalTitle\": \"General\",\r\n \"general1Q\": \"Replace this with your first general question\",\r\n \"general1A\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. AI will replace this answer with relevant information based on your project context.\",\r\n \"general2Q\": \"This is a placeholder question that needs customization\",\r\n \"general2A\": \"This answer will be automatically generated by AI based on your industry and service offerings. Sed do eiusmod tempor incididunt ut labore.\",\r\n \"general3Q\": \"Customize this question for your FAQ section\",\r\n \"general3A\": \"AI will generate appropriate answers based on your site needs. Ut enim ad minim veniam, quis nostrud exercitation ullamco.\",\r\n \"billingTitle\": \"Billing\",\r\n \"billing1Q\": \"Replace with your billing-related question\",\r\n \"billing1A\": \"Placeholder answer text. AI will customize this content to provide accurate billing information for your plan.\",\r\n \"billing2Q\": \"This question should be replaced with real billing FAQ\",\r\n \"billing2A\": \"Lorem ipsum dolor sit amet. AI will replace this with contextually appropriate billing information for your service.\",\r\n \"billing3Q\": \"Customize this billing question\",\r\n \"billing3A\": \"This is placeholder text that will be replaced by AI with relevant billing answers based on your payment structure.\",\r\n \"technicalTitle\": \"Technical\",\r\n \"technical1Q\": \"Replace with your technical question\",\r\n \"technical1A\": \"AI will customize this technical answer based on your product or service specifications. Duis aute irure dolor in reprehenderit.\",\r\n \"technical2Q\": \"This is a placeholder technical question\",\r\n \"technical2A\": \"Placeholder answer. AI will generate appropriate technical information based on your platform capabilities.\",\r\n \"technical3Q\": \"Customize this final technical question\",\r\n \"technical3A\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. AI will replace this with relevant technical details for your offering.\"\r\n}\r\n"
27
+ "content": "{\r\n \"title\": \"Frequently Asked Questions\",\r\n \"subtitle\": \"Ask Promake to customize this subtitle to match your FAQ section purpose.\",\r\n \"generalTitle\": \"General\",\r\n \"general1Q\": \"Replace this with your first general question\",\r\n \"general1A\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ask Promake to replace this answer with relevant information based on your project context.\",\r\n \"general2Q\": \"This is a placeholder question that needs customization\",\r\n \"general2A\": \"This answer will be automatically generated by Promake based on your industry and service offerings. Sed do eiusmod tempor incididunt ut labore.\",\r\n \"general3Q\": \"Customize this question for your FAQ section\",\r\n \"general3A\": \"Ask Promake to generate appropriate answers based on your site needs. Ut enim ad minim veniam, quis nostrud exercitation ullamco.\",\r\n \"billingTitle\": \"Billing\",\r\n \"billing1Q\": \"Replace with your billing-related question\",\r\n \"billing1A\": \"Placeholder answer text. Ask Promake to customize this content to provide accurate billing information for your plan.\",\r\n \"billing2Q\": \"This question should be replaced with real billing FAQ\",\r\n \"billing2A\": \"Lorem ipsum dolor sit amet. Ask Promake to replace this with contextually appropriate billing information for your service.\",\r\n \"billing3Q\": \"Customize this billing question\",\r\n \"billing3A\": \"This is placeholder text that will be replaced by Promake with relevant billing answers based on your payment structure.\",\r\n \"technicalTitle\": \"Technical\",\r\n \"technical1Q\": \"Replace with your technical question\",\r\n \"technical1A\": \"Ask Promake to customize this technical answer based on your product or service specifications. Duis aute irure dolor in reprehenderit.\",\r\n \"technical2Q\": \"This is a placeholder technical question\",\r\n \"technical2A\": \"Placeholder answer. Ask Promake to generate appropriate technical information based on your platform capabilities.\",\r\n \"technical3Q\": \"Customize this final technical question\",\r\n \"technical3A\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ask Promake to replace this with relevant technical details for your offering.\"\r\n}\r\n"
28
28
  },
29
29
  {
30
30
  "path": "faq-categorized/lang/tr.json",
@@ -24,7 +24,7 @@
24
24
  "path": "faq-simple/lang/en.json",
25
25
  "type": "registry:lang",
26
26
  "target": "$modules$/faq-simple/lang/en.json",
27
- "content": "{\r\n \"title\": \"Frequently Asked Questions\",\r\n \"subtitle\": \"AI will customize this subtitle based on your service or product offering.\",\r\n \"q1\": \"Replace this question with your first FAQ\",\r\n \"a1\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. AI will replace this answer with relevant information.\",\r\n \"q2\": \"This is a placeholder question that needs to be customized\",\r\n \"a2\": \"This answer will be automatically replaced by AI based on your project context and the question above. Ut enim ad minim veniam, quis nostrud exercitation.\",\r\n \"q3\": \"Customize this question to match your service\",\r\n \"a3\": \"AI will generate appropriate answers based on your site goals and audience. Duis aute irure dolor in reprehenderit in voluptate velit esse.\",\r\n \"q4\": \"Replace with your actual frequently asked question\",\r\n \"a4\": \"Placeholder answer text. AI will customize this content to provide accurate information about your product or service offerings.\",\r\n \"q5\": \"This question should be replaced with real FAQ content\",\r\n \"a5\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. AI will replace this with contextually appropriate information for your site.\",\r\n \"q6\": \"Customize this final question for your FAQ section\",\r\n \"a6\": \"This is placeholder text that will be replaced by AI with relevant answers based on your specific needs and audience questions.\"\r\n}\r\n"
27
+ "content": "{\r\n \"title\": \"Frequently Asked Questions\",\r\n \"subtitle\": \"Ask Promake to customize this subtitle based on your service or product offering.\",\r\n \"q1\": \"Replace this question with your first FAQ\",\r\n \"a1\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ask Promake to replace this answer with relevant information.\",\r\n \"q2\": \"This is a placeholder question that needs to be customized\",\r\n \"a2\": \"This answer will be automatically replaced by Promake based on your project context and the question above. Ut enim ad minim veniam, quis nostrud exercitation.\",\r\n \"q3\": \"Customize this question to match your service\",\r\n \"a3\": \"Ask Promake to generate appropriate answers based on your site goals and audience. Duis aute irure dolor in reprehenderit in voluptate velit esse.\",\r\n \"q4\": \"Replace with your actual frequently asked question\",\r\n \"a4\": \"Placeholder answer text. Ask Promake to customize this content to provide accurate information about your product or service offerings.\",\r\n \"q5\": \"This question should be replaced with real FAQ content\",\r\n \"a5\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ask Promake to replace this with contextually appropriate information for your site.\",\r\n \"q6\": \"Customize this final question for your FAQ section\",\r\n \"a6\": \"This is placeholder text that will be replaced by Promake with relevant answers based on your specific needs and audience questions.\"\r\n}\r\n"
28
28
  },
29
29
  {
30
30
  "path": "faq-simple/lang/tr.json",
@@ -19,7 +19,7 @@
19
19
  "path": "favorites-ecommerce-block/favorites-ecommerce-block.tsx",
20
20
  "type": "registry:block",
21
21
  "target": "$modules$/favorites-ecommerce-block/favorites-ecommerce-block.tsx",
22
- "content": "import { Link } from \"react-router\";\nimport { Heart, ShoppingBag } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { ProductCard } from \"@/modules/product-card/product-card\";\nimport { useTranslation } from \"react-i18next\";\nimport type { Product } from \"@/modules/ecommerce-core/types\";\n\ninterface FavoritesEcommerceBlockProps {\n favorites: Product[];\n onClearAll?: () => void;\n}\n\nexport function FavoritesEcommerceBlock({\n favorites,\n onClearAll,\n}: FavoritesEcommerceBlockProps) {\n const { t } = useTranslation(\"favorites-ecommerce-block\");\n\n // Empty State\n if (favorites.length === 0) {\n return (\n <div className=\"min-h-screen bg-muted/30 py-12\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n <div className=\"text-center max-w-md mx-auto\">\n <Heart className=\"w-16 h-16 text-muted-foreground mx-auto mb-6\" />\n <h1 className=\"text-3xl font-bold text-foreground mb-4\">\n {t(\"noFavoritesYet\", \"No Favorites Yet\")}\n </h1>\n <p className=\"text-muted-foreground mb-8\">\n {t(\n \"noFavoritesDescription\",\n \"Start browsing our products and add items to your favorites by clicking the heart icon.\"\n )}\n </p>\n <Button asChild size=\"lg\">\n <Link to=\"/products\">\n <ShoppingBag className=\"w-5 h-5 mr-2\" />\n {t(\"browseProducts\", \"Browse Products\")}\n </Link>\n </Button>\n </div>\n </div>\n </div>\n );\n }\n\n // Favorites Grid\n return (\n <div className=\"min-h-screen bg-muted/30 py-12\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n {/* Header */}\n <div className=\"flex items-center justify-between mb-8\">\n <div>\n <h1 className=\"text-3xl font-bold text-foreground mb-2\">\n {t(\"title\", \"My Favorites\")}\n </h1>\n <p className=\"text-muted-foreground\">\n {favorites.length}{\" \"}\n {t(\n \"itemsInFavorites\",\n `item${favorites.length !== 1 ? \"s\" : \"\"} in your favorites`\n )}\n </p>\n </div>\n {onClearAll && (\n <Button variant=\"outline\" onClick={onClearAll}>\n {t(\"clearAll\", \"Clear All\")}\n </Button>\n )}\n </div>\n\n {/* Products Grid */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6\">\n {favorites.map((product) => (\n <ProductCard key={product.id} product={product} variant=\"grid\" />\n ))}\n </div>\n </div>\n </div>\n );\n}\n"
22
+ "content": "import { Link } from \"react-router\";\nimport { Heart, ShoppingBag } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { ProductCard } from \"@/modules/product-card/product-card\";\nimport { useTranslation } from \"react-i18next\";\nimport type { Product } from \"@/modules/ecommerce-core/types\";\n\ninterface FavoritesEcommerceBlockProps {\n favorites: Product[];\n onClearAll?: () => void;\n}\n\nexport function FavoritesEcommerceBlock({\n favorites = [],\n onClearAll,\n}: FavoritesEcommerceBlockProps) {\n const { t } = useTranslation(\"favorites-ecommerce-block\");\n\n // Empty State\n if (favorites.length === 0) {\n return (\n <div className=\"min-h-screen bg-muted/30 py-12\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n <div className=\"text-center max-w-md mx-auto\">\n <Heart className=\"w-16 h-16 text-muted-foreground mx-auto mb-6\" />\n <h1 className=\"text-3xl font-bold text-foreground mb-4\">\n {t(\"noFavoritesYet\", \"No Favorites Yet\")}\n </h1>\n <p className=\"text-muted-foreground mb-8\">\n {t(\n \"noFavoritesDescription\",\n \"Start browsing our products and add items to your favorites by clicking the heart icon.\"\n )}\n </p>\n <Button asChild size=\"lg\">\n <Link to=\"/products\">\n <ShoppingBag className=\"w-5 h-5 mr-2\" />\n {t(\"browseProducts\", \"Browse Products\")}\n </Link>\n </Button>\n </div>\n </div>\n </div>\n );\n }\n\n // Favorites Grid\n return (\n <div className=\"min-h-screen bg-muted/30 py-12\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n {/* Header */}\n <div className=\"flex items-center justify-between mb-8\">\n <div>\n <h1 className=\"text-3xl font-bold text-foreground mb-2\">\n {t(\"title\", \"My Favorites\")}\n </h1>\n <p className=\"text-muted-foreground\">\n {favorites.length}{\" \"}\n {t(\n \"itemsInFavorites\",\n `item${favorites.length !== 1 ? \"s\" : \"\"} in your favorites`\n )}\n </p>\n </div>\n {onClearAll && (\n <Button variant=\"outline\" onClick={onClearAll}>\n {t(\"clearAll\", \"Clear All\")}\n </Button>\n )}\n </div>\n\n {/* Products Grid */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6\">\n {favorites.map((product) => (\n <ProductCard key={product.id} product={product} variant=\"grid\" />\n ))}\n </div>\n </div>\n </div>\n );\n}\n"
23
23
  },
24
24
  {
25
25
  "path": "favorites-ecommerce-block/lang/en.json",
@@ -16,13 +16,13 @@
16
16
  "path": "feature-section/feature-section.tsx",
17
17
  "type": "registry:component",
18
18
  "target": "$modules$/feature-section/feature-section.tsx",
19
- "content": "import { Link } from \"react-router\";\nimport { Button } from \"@/components/ui/button\";\nimport { useTranslation } from \"react-i18next\";\n\nexport function FeatureSection() {\n const { t } = useTranslation(\"feature-section\");\n\n return (\n <section className=\"py-20 bg-muted/30\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-12 items-center\">\n <div>\n <h2 className=\"text-3xl lg:text-4xl font-bold mb-6 text-foreground\">\n {t(\"heading\", \"Your Business Title Here\")}\n </h2>\n <p className=\"text-lg text-muted-foreground mb-6\">\n {t(\n \"description\",\n \"This is where your main business description will appear. AI will customize this content based on your specific industry and services.\"\n )}\n </p>\n <div className=\"space-y-4 mb-8\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-2 h-2 bg-primary rounded-full\"></div>\n <span className=\"text-foreground\">\n {t(\"feature1\", \"Key feature or benefit #1\")}\n </span>\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"w-2 h-2 bg-primary rounded-full\"></div>\n <span className=\"text-foreground\">\n {t(\"feature2\", \"Key feature or benefit #2\")}\n </span>\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"w-2 h-2 bg-primary rounded-full\"></div>\n <span className=\"text-foreground\">\n {t(\"feature3\", \"Key feature or benefit #3\")}\n </span>\n </div>\n </div>\n <div className=\"flex gap-4\">\n <Button asChild>\n <Link to=\"/about\">{t(\"primaryButton\", \"Learn More\")}</Link>\n </Button>\n <Button variant=\"outline\" asChild>\n <Link to=\"/contact\">{t(\"secondaryButton\", \"Get Started\")}</Link>\n </Button>\n </div>\n </div>\n <div>\n <div className=\"aspect-square bg-gradient-to-br from-primary/10 to-primary/5 rounded-2xl overflow-hidden\">\n <img\n src=\"/images/placeholder.png\"\n alt={t(\"imageAlt\", \"Business Solutions\")}\n className=\"w-full h-full object-cover\"\n />\n </div>\n </div>\n </div>\n </div>\n </section>\n );\n}\n"
19
+ "content": "import { Link } from \"react-router\";\nimport { Button } from \"@/components/ui/button\";\nimport { useTranslation } from \"react-i18next\";\n\nexport function FeatureSection() {\n const { t } = useTranslation(\"feature-section\");\n\n return (\n <section className=\"py-20 bg-muted/30\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-12 items-center\">\n <div>\n <h2 className=\"text-3xl lg:text-4xl font-bold mb-6 text-foreground\">\n {t(\"heading\", \"Your Business Title Here\")}\n </h2>\n <p className=\"text-lg text-muted-foreground mb-6\">\n {t(\n \"description\",\n \"This is where your main business description will appear. Ask Promake to customize this content based on your specific industry and services.\"\n )}\n </p>\n <div className=\"space-y-4 mb-8\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-2 h-2 bg-primary rounded-full\"></div>\n <span className=\"text-foreground\">\n {t(\"feature1\", \"Key feature or benefit #1\")}\n </span>\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"w-2 h-2 bg-primary rounded-full\"></div>\n <span className=\"text-foreground\">\n {t(\"feature2\", \"Key feature or benefit #2\")}\n </span>\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"w-2 h-2 bg-primary rounded-full\"></div>\n <span className=\"text-foreground\">\n {t(\"feature3\", \"Key feature or benefit #3\")}\n </span>\n </div>\n </div>\n <div className=\"flex gap-4\">\n <Button asChild>\n <Link to=\"/about\">{t(\"primaryButton\", \"Learn More\")}</Link>\n </Button>\n <Button variant=\"outline\" asChild>\n <Link to=\"/contact\">{t(\"secondaryButton\", \"Get Started\")}</Link>\n </Button>\n </div>\n </div>\n <div>\n <div className=\"aspect-square bg-gradient-to-br from-primary/10 to-primary/5 rounded-2xl overflow-hidden\">\n <img\n src=\"/images/placeholder.png\"\n alt={t(\"imageAlt\", \"Business Solutions\")}\n className=\"w-full h-full object-cover\"\n />\n </div>\n </div>\n </div>\n </div>\n </section>\n );\n}\n"
20
20
  },
21
21
  {
22
22
  "path": "feature-section/lang/en.json",
23
23
  "type": "registry:lang",
24
24
  "target": "$modules$/feature-section/lang/en.json",
25
- "content": "{\r\n \"heading\": \"Your Site Title Here\",\r\n \"description\": \"This is where your main site description will appear. AI will customize this content based on your specific goals and audience.\",\r\n \"feature1\": \"Key feature or benefit #1\",\r\n \"feature2\": \"Key feature or benefit #2\",\r\n \"feature3\": \"Key feature or benefit #3\",\r\n \"primaryButton\": \"Learn More\",\r\n \"secondaryButton\": \"Get Started\",\r\n \"imageAlt\": \"Site Preview\"\r\n}\r\n"
25
+ "content": "{\r\n \"heading\": \"Your Site Title Here\",\r\n \"description\": \"This is where your main site description will appear. Ask Promake to customize this content based on your specific goals and audience.\",\r\n \"feature1\": \"Key feature or benefit #1\",\r\n \"feature2\": \"Key feature or benefit #2\",\r\n \"feature3\": \"Key feature or benefit #3\",\r\n \"primaryButton\": \"Learn More\",\r\n \"secondaryButton\": \"Get Started\",\r\n \"imageAlt\": \"Site Preview\"\r\n}\r\n"
26
26
  },
27
27
  {
28
28
  "path": "feature-section/lang/tr.json",
@@ -22,7 +22,7 @@
22
22
  "path": "footer/lang/en.json",
23
23
  "type": "registry:lang",
24
24
  "target": "$modules$/footer/lang/en.json",
25
- "content": "{\r\n \"description\": \"AI will customize this footer description based on your site's purpose and brand.\",\r\n \"quickLinks\": \"Quick Links\",\r\n \"about\": \"About\",\r\n \"contact\": \"Contact\",\r\n \"legal\": \"Legal\",\r\n \"privacy\": \"Privacy Policy\",\r\n \"terms\": \"Terms of Service\",\r\n \"cookies\": \"Cookie Policy\",\r\n \"contactTitle\": \"Contact\",\r\n \"allRightsReserved\": \"All rights reserved.\"\r\n}\r\n"
25
+ "content": "{\r\n \"description\": \"Ask Promake to customize this footer description based on your site's purpose and brand.\",\r\n \"quickLinks\": \"Quick Links\",\r\n \"about\": \"About\",\r\n \"contact\": \"Contact\",\r\n \"legal\": \"Legal\",\r\n \"privacy\": \"Privacy Policy\",\r\n \"terms\": \"Terms of Service\",\r\n \"cookies\": \"Cookie Policy\",\r\n \"contactTitle\": \"Contact\",\r\n \"allRightsReserved\": \"All rights reserved.\"\r\n}\r\n"
26
26
  },
27
27
  {
28
28
  "path": "footer/lang/tr.json",
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "forgot-password-page-split",
3
+ "type": "registry:page",
4
+ "title": "Forgot Password Page Split",
5
+ "description": "Split-screen password recovery page with form on the left and full-height image on the right. Features email form with success state after submission. Uses customerClient for API calls.",
6
+ "registryDependencies": [
7
+ "button",
8
+ "input",
9
+ "auth-core",
10
+ "api"
11
+ ],
12
+ "usage": "import ForgotPasswordPageSplit from '@/modules/forgot-password-page-split';\n\n<ForgotPasswordPageSplit\n image=\"/images/forgot-bg.jpg\"\n/>\n\n• Installed at: src/modules/forgot-password-page-split/\n• Customize text: src/modules/forgot-password-page-split/lang/*.json\n• API Integration:\n - customerClient.auth.forgotPassword() for sending reset email\n - Shows success state after email sent\n• Add to your router as a page component",
13
+ "route": {
14
+ "path": "/forgot-password",
15
+ "componentName": "ForgotPasswordPageSplit"
16
+ },
17
+ "files": [
18
+ {
19
+ "path": "forgot-password-page-split/index.ts",
20
+ "type": "registry:index",
21
+ "target": "$modules$/forgot-password-page-split/index.ts",
22
+ "content": "export * from './forgot-password-page-split';\r\nexport { default } from './forgot-password-page-split';\r\n"
23
+ },
24
+ {
25
+ "path": "forgot-password-page-split/forgot-password-page-split.tsx",
26
+ "type": "registry:page",
27
+ "target": "$modules$/forgot-password-page-split/forgot-password-page-split.tsx",
28
+ "content": "import { useState } from \"react\";\r\nimport { Link } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Logo } from \"@/components/Logo\";\r\nimport { Mail, ArrowLeft, CheckCircle } from \"lucide-react\";\r\nimport { customerClient } from \"@/modules/api/customer-client\";\r\nimport { getErrorMessage } from \"@/modules/api/get-error-message\";\r\n\r\ninterface ForgotPasswordPageSplitProps {\r\n image?: string;\r\n}\r\n\r\nexport function ForgotPasswordPageSplit({\r\n image = \"/images/placeholder.png\",\r\n}: ForgotPasswordPageSplitProps) {\r\n const { t } = useTranslation(\"forgot-password-page-split\");\r\n usePageTitle({ title: t(\"title\", \"Forgot Password\") });\r\n\r\n const [email, setEmail] = useState(\"\");\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [isEmailSent, setIsEmailSent] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n setIsLoading(true);\r\n\r\n try {\r\n await customerClient.auth.forgotPassword({ username: email });\r\n\r\n setIsEmailSent(true);\r\n toast.success(t(\"emailSent\", \"Reset link sent!\"), {\r\n description: t(\"checkInbox\", \"Please check your email inbox.\"),\r\n });\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"forgotPasswordError\", \"Failed to send reset link. Please try again.\")\r\n );\r\n setError(errorMessage);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n // Success state - email sent\r\n if (isEmailSent) {\r\n return (\r\n <section className=\"w-full md:grid md:min-h-screen md:grid-cols-2\">\r\n <div className=\"flex items-center justify-center px-4 py-12\">\r\n <div className=\"mx-auto grid w-full max-w-sm gap-6 text-center\">\r\n <Logo />\r\n <hr />\r\n\r\n <div className=\"flex justify-center\">\r\n <div className=\"w-16 h-16 bg-green-100 dark:bg-green-900/30 rounded-full flex items-center justify-center\">\r\n <CheckCircle className=\"w-8 h-8 text-green-600 dark:text-green-400\" />\r\n </div>\r\n </div>\r\n\r\n <div>\r\n <h1 className=\"text-xl font-bold tracking-tight\">\r\n {t(\"checkYourEmail\", \"Check your email\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground mt-2\">\r\n {t(\"emailSentTo\", \"We've sent a password reset link to\")}\r\n </p>\r\n <p className=\"text-sm font-medium mt-1\">{email}</p>\r\n </div>\r\n\r\n <div className=\"text-sm text-muted-foreground\">\r\n <p>{t(\"didntReceive\", \"Didn't receive the email?\")}</p>\r\n <Button\r\n variant=\"link\"\r\n className=\"p-0 h-auto\"\r\n onClick={() => {\r\n setIsEmailSent(false);\r\n setError(null);\r\n }}\r\n >\r\n {t(\"tryAgain\", \"Click here to try again\")}\r\n </Button>\r\n </div>\r\n\r\n <Link\r\n to=\"/login\"\r\n className=\"inline-flex items-center justify-center gap-2 text-sm text-muted-foreground hover:text-foreground\"\r\n >\r\n <ArrowLeft className=\"w-4 h-4\" />\r\n {t(\"backToLogin\", \"Back to login\")}\r\n </Link>\r\n\r\n <hr />\r\n <p className=\"text-sm text-muted-foreground\">\r\n © {new Date().getFullYear()} {t(\"copyright\", \"All rights reserved.\")}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"hidden p-4 md:block\">\r\n <img\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n width=\"1920\"\r\n height=\"1080\"\r\n alt={t(\"imageAlt\", \"Forgot password background\")}\r\n src={image}\r\n className=\"size-full rounded-lg border bg-muted object-cover object-center\"\r\n />\r\n </div>\r\n </section>\r\n );\r\n }\r\n\r\n return (\r\n <section className=\"w-full md:grid md:min-h-screen md:grid-cols-2\">\r\n <div className=\"flex items-center justify-center px-4 py-12\">\r\n <div className=\"mx-auto grid w-full max-w-sm gap-6\">\r\n <Logo />\r\n <hr />\r\n\r\n <div className=\"flex justify-center\">\r\n <div className=\"w-12 h-12 bg-primary/10 rounded-full flex items-center justify-center\">\r\n <Mail className=\"w-6 h-6 text-primary\" />\r\n </div>\r\n </div>\r\n\r\n <div className=\"text-center\">\r\n <h1 className=\"text-xl font-bold tracking-tight\">\r\n {t(\"title\", \"Forgot Password\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground mt-1\">\r\n {t(\"subtitle\", \"Enter your email to reset your password\")}\r\n </p>\r\n </div>\r\n\r\n {error && (\r\n <div className=\"p-3 text-sm text-red-600 bg-red-50 dark:bg-red-950 dark:text-red-400 rounded-md\">\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit} className=\"grid gap-4\">\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"email\">{t(\"email\", \"Email\")}</Label>\r\n <Input\r\n required\r\n id=\"email\"\r\n type=\"email\"\r\n autoComplete=\"email\"\r\n placeholder={t(\"emailPlaceholder\", \"you@example.com\")}\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n disabled={isLoading}\r\n />\r\n </div>\r\n\r\n <Button type=\"submit\" className=\"w-full\" disabled={isLoading}>\r\n {isLoading ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-primary-foreground border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"sending\", \"Sending...\")}\r\n </>\r\n ) : (\r\n t(\"sendLink\", \"Send Reset Link\")\r\n )}\r\n </Button>\r\n </form>\r\n\r\n <Link\r\n to=\"/login\"\r\n className=\"inline-flex items-center justify-center gap-2 text-sm text-muted-foreground hover:text-foreground\"\r\n >\r\n <ArrowLeft className=\"w-4 h-4\" />\r\n {t(\"backToLogin\", \"Back to login\")}\r\n </Link>\r\n\r\n <hr />\r\n <p className=\"text-sm text-muted-foreground\">\r\n © {new Date().getFullYear()} {t(\"copyright\", \"All rights reserved.\")}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"hidden p-4 md:block\">\r\n <img\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n width=\"1920\"\r\n height=\"1080\"\r\n alt={t(\"imageAlt\", \"Forgot password background\")}\r\n src={image}\r\n className=\"size-full rounded-lg border bg-muted object-cover object-center\"\r\n />\r\n </div>\r\n </section>\r\n );\r\n}\r\n\r\nexport default ForgotPasswordPageSplit;\r\n"
29
+ },
30
+ {
31
+ "path": "forgot-password-page-split/lang/en.json",
32
+ "type": "registry:lang",
33
+ "target": "$modules$/forgot-password-page-split/lang/en.json",
34
+ "content": "{\r\n \"title\": \"Forgot Password\",\r\n \"subtitle\": \"Enter your email to reset your password\",\r\n \"email\": \"Email\",\r\n \"emailPlaceholder\": \"you@example.com\",\r\n \"sendLink\": \"Send Reset Link\",\r\n \"sending\": \"Sending...\",\r\n \"emailSent\": \"Reset link sent!\",\r\n \"checkInbox\": \"Please check your email inbox.\",\r\n \"forgotPasswordError\": \"Failed to send reset link. Please try again.\",\r\n \"checkYourEmail\": \"Check your email\",\r\n \"emailSentTo\": \"We've sent a password reset link to\",\r\n \"didntReceive\": \"Didn't receive the email?\",\r\n \"tryAgain\": \"Click here to try again\",\r\n \"backToLogin\": \"Back to login\",\r\n \"copyright\": \"All rights reserved.\",\r\n \"imageAlt\": \"Forgot password background\"\r\n}\r\n"
35
+ },
36
+ {
37
+ "path": "forgot-password-page-split/lang/tr.json",
38
+ "type": "registry:lang",
39
+ "target": "$modules$/forgot-password-page-split/lang/tr.json",
40
+ "content": "{\r\n \"title\": \"Şifremi Unuttum\",\r\n \"subtitle\": \"Şifrenizi sıfırlamak için e-postanızı girin\",\r\n \"email\": \"E-posta\",\r\n \"emailPlaceholder\": \"ornek@email.com\",\r\n \"sendLink\": \"Sıfırlama Linki Gönder\",\r\n \"sending\": \"Gönderiliyor...\",\r\n \"emailSent\": \"Sıfırlama linki gönderildi!\",\r\n \"checkInbox\": \"Lütfen e-posta gelen kutunuzu kontrol edin.\",\r\n \"forgotPasswordError\": \"Sıfırlama linki gönderilemedi. Lütfen tekrar deneyin.\",\r\n \"checkYourEmail\": \"E-postanızı kontrol edin\",\r\n \"emailSentTo\": \"Şifre sıfırlama linki gönderildi:\",\r\n \"didntReceive\": \"E-posta almadınız mı?\",\r\n \"tryAgain\": \"Tekrar denemek için tıklayın\",\r\n \"backToLogin\": \"Girişe dön\",\r\n \"copyright\": \"Tüm hakları saklıdır.\",\r\n \"imageAlt\": \"Şifre sıfırlama arka planı\"\r\n}\r\n"
41
+ }
42
+ ],
43
+ "exports": {
44
+ "types": [],
45
+ "variables": [
46
+ "ForgotPasswordPageSplit",
47
+ "default"
48
+ ]
49
+ }
50
+ }