@promakeai/cli 0.8.0 → 0.9.0

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.
@@ -24,13 +24,13 @@
24
24
  "path": "order-card-compact/lang/en.json",
25
25
  "type": "registry:lang",
26
26
  "target": "$modules$/order-card-compact/lang/en.json",
27
- "content": "{\r\n \"orderNumber\": \"Order\",\r\n \"total\": \"Total\",\r\n \"items\": \"Items\",\r\n \"viewDetails\": \"View Details\"\r\n}\r\n"
27
+ "content": "{\r\n \"orderNumber\": \"Order\",\r\n \"total\": \"Total\",\r\n \"items\": \"Items\",\r\n \"viewDetails\": \"View Details\",\r\n \"item\": \"Item\",\r\n \"qty\": \"Qty\"\r\n}\r\n"
28
28
  },
29
29
  {
30
30
  "path": "order-card-compact/lang/tr.json",
31
31
  "type": "registry:lang",
32
32
  "target": "$modules$/order-card-compact/lang/tr.json",
33
- "content": "{\r\n \"orderNumber\": \"Sipariş\",\r\n \"total\": \"Toplam\",\r\n \"items\": \"Ürünler\",\r\n \"viewDetails\": \"Detayları Gör\"\r\n}\r\n"
33
+ "content": "{\r\n \"orderNumber\": \"Sipariş\",\r\n \"total\": \"Toplam\",\r\n \"items\": \"Ürünler\",\r\n \"viewDetails\": \"Detayları Gör\",\r\n \"item\": \"Ürün\",\r\n \"qty\": \"Adet\"\r\n}\r\n"
34
34
  }
35
35
  ],
36
36
  "exports": {
@@ -30,13 +30,13 @@
30
30
  "path": "order-confirmation-page/lang/en.json",
31
31
  "type": "registry:lang",
32
32
  "target": "$modules$/order-confirmation-page/lang/en.json",
33
- "content": "{\r\n \"title\": \"Order Confirmed!\",\r\n \"orderNotFound\": \"Order Not Found\",\r\n \"orderNotFoundDescription\": \"We couldn't find the order details. Please check your email for confirmation.\",\r\n \"continueShopping\": \"Continue Shopping\",\r\n \"cashOnDelivery\": \"Cash on Delivery\",\r\n \"bankTransfer\": \"Bank Transfer\",\r\n \"creditCard\": \"Credit Card\",\r\n \"thankYou\": \"Thank you for your order! We've received your order and will process it shortly.\",\r\n \"orderInformation\": \"Order Information\",\r\n \"orderId\": \"Order ID\",\r\n \"orderDate\": \"Order Date\",\r\n \"totalAmount\": \"Total Amount\",\r\n \"paymentMethod\": \"Payment Method\",\r\n \"paymentStatus\": \"Payment Status\",\r\n \"checking\": \"Checking...\",\r\n \"statusError\": \"Error\",\r\n \"paymentSucceeded\": \"Paid\",\r\n \"processing\": \"Processing\",\r\n \"requiresPayment\": \"Requires Payment\",\r\n \"orderStatus\": \"Order Status\",\r\n \"pending\": \"Pending\",\r\n \"deliveryInformation\": \"Delivery Information\",\r\n \"address\": \"Address\",\r\n \"notes\": \"Notes\",\r\n \"orderItems\": \"Order Items\",\r\n \"qty\": \"Qty\",\r\n \"total\": \"Total\",\r\n \"paymentInstructions\": \"Payment Instructions\",\r\n \"bankTransferDetails\": \"Bank Transfer Details\",\r\n \"bankDetailsEmail\": \"Bank details will be sent via email. Please complete the transfer within 48 hours.\",\r\n \"deliveryPayment\": \"Payment on Delivery\",\r\n \"cashOnDeliveryInfo\": \"Cash on Delivery\",\r\n \"codInstructions\": \"Pay when your order arrives. Our delivery team will contact you before delivery.\",\r\n \"backToHome\": \"Back to Home\"\r\n}\r\n"
33
+ "content": "{\r\n \"title\": \"Order Confirmed!\",\r\n \"orderNotFound\": \"Order Not Found\",\r\n \"orderNotFoundDescription\": \"We couldn't find the order details. Please check your email for confirmation.\",\r\n \"continueShopping\": \"Continue Shopping\",\r\n \"cashOnDelivery\": \"Cash on Delivery\",\r\n \"bankTransfer\": \"Bank Transfer\",\r\n \"creditCard\": \"Credit Card\",\r\n \"thankYou\": \"Thank you for your order! We've received your order and will process it shortly.\",\r\n \"orderInformation\": \"Order Information\",\r\n \"orderId\": \"Order ID\",\r\n \"orderDate\": \"Order Date\",\r\n \"totalAmount\": \"Total Amount\",\r\n \"paymentMethod\": \"Payment Method\",\r\n \"paymentStatus\": \"Payment Status\",\r\n \"checking\": \"Checking...\",\r\n \"statusError\": \"Error\",\r\n \"paymentSucceeded\": \"Paid\",\r\n \"processing\": \"Processing\",\r\n \"requiresPayment\": \"Requires Payment\",\r\n \"orderStatus\": \"Order Status\",\r\n \"pending\": \"Pending\",\r\n \"deliveryInformation\": \"Delivery Information\",\r\n \"address\": \"Address\",\r\n \"notes\": \"Notes\",\r\n \"orderItems\": \"Order Items\",\r\n \"qty\": \"Qty\",\r\n \"total\": \"Total\",\r\n \"paymentInstructions\": \"Payment Instructions\",\r\n \"bankTransferDetails\": \"Bank Transfer Details\",\r\n \"bankDetailsEmail\": \"Bank details will be sent via email. Please complete the transfer within 48 hours.\",\r\n \"deliveryPayment\": \"Payment on Delivery\",\r\n \"cashOnDeliveryInfo\": \"Cash on Delivery\",\r\n \"codInstructions\": \"Pay when your order arrives. Our delivery team will contact you before delivery.\",\r\n \"backToHome\": \"Back to Home\",\r\n \"loading\": \"Loading Order...\"\r\n}\r\n"
34
34
  },
35
35
  {
36
36
  "path": "order-confirmation-page/lang/tr.json",
37
37
  "type": "registry:lang",
38
38
  "target": "$modules$/order-confirmation-page/lang/tr.json",
39
- "content": "{\r\n \"title\": \"Sipariş Onaylandı!\",\r\n \"orderNotFound\": \"Sipariş Bulunamadı\",\r\n \"orderNotFoundDescription\": \"Sipariş detaylarını bulamadık. Lütfen onay için e-postanızı kontrol edin.\",\r\n \"continueShopping\": \"Alışverişe Devam Et\",\r\n \"cashOnDelivery\": \"Kapıda Ödeme\",\r\n \"bankTransfer\": \"Havale/EFT\",\r\n \"creditCard\": \"Kredi Kartı\",\r\n \"thankYou\": \"Siparişiniz için teşekkürler! Siparişinizi aldık ve en kısa sürede işleme alacağız.\",\r\n \"orderInformation\": \"Sipariş Bilgileri\",\r\n \"orderId\": \"Sipariş No\",\r\n \"orderDate\": \"Sipariş Tarihi\",\r\n \"totalAmount\": \"Toplam Tutar\",\r\n \"paymentMethod\": \"Ödeme Yöntemi\",\r\n \"paymentStatus\": \"Ödeme Durumu\",\r\n \"checking\": \"Kontrol ediliyor...\",\r\n \"statusError\": \"Hata\",\r\n \"paymentSucceeded\": \"Ödendi\",\r\n \"processing\": \"İşleniyor\",\r\n \"requiresPayment\": \"Ödeme Gerekli\",\r\n \"orderStatus\": \"Sipariş Durumu\",\r\n \"pending\": \"Beklemede\",\r\n \"deliveryInformation\": \"Teslimat Bilgileri\",\r\n \"address\": \"Adres\",\r\n \"notes\": \"Notlar\",\r\n \"orderItems\": \"Sipariş Ürünleri\",\r\n \"qty\": \"Adet\",\r\n \"total\": \"Toplam\",\r\n \"paymentInstructions\": \"Ödeme Talimatları\",\r\n \"bankTransferDetails\": \"Havale/EFT Bilgileri\",\r\n \"bankDetailsEmail\": \"Banka bilgileri e-posta ile gönderilecektir. Lütfen transferi 48 saat içinde tamamlayın.\",\r\n \"deliveryPayment\": \"Teslimatta Ödeme\",\r\n \"cashOnDeliveryInfo\": \"Kapıda Ödeme\",\r\n \"codInstructions\": \"Siparişiniz geldiğinde ödeme yapın. Teslimat ekibimiz teslimat öncesi sizinle iletişime geçecektir.\",\r\n \"backToHome\": \"Ana Sayfaya Dön\"\r\n}\r\n"
39
+ "content": "{\r\n \"title\": \"Sipariş Onaylandı!\",\r\n \"orderNotFound\": \"Sipariş Bulunamadı\",\r\n \"orderNotFoundDescription\": \"Sipariş detaylarını bulamadık. Lütfen onay için e-postanızı kontrol edin.\",\r\n \"continueShopping\": \"Alışverişe Devam Et\",\r\n \"cashOnDelivery\": \"Kapıda Ödeme\",\r\n \"bankTransfer\": \"Havale/EFT\",\r\n \"creditCard\": \"Kredi Kartı\",\r\n \"thankYou\": \"Siparişiniz için teşekkürler! Siparişinizi aldık ve en kısa sürede işleme alacağız.\",\r\n \"orderInformation\": \"Sipariş Bilgileri\",\r\n \"orderId\": \"Sipariş No\",\r\n \"orderDate\": \"Sipariş Tarihi\",\r\n \"totalAmount\": \"Toplam Tutar\",\r\n \"paymentMethod\": \"Ödeme Yöntemi\",\r\n \"paymentStatus\": \"Ödeme Durumu\",\r\n \"checking\": \"Kontrol ediliyor...\",\r\n \"statusError\": \"Hata\",\r\n \"paymentSucceeded\": \"Ödendi\",\r\n \"processing\": \"İşleniyor\",\r\n \"requiresPayment\": \"Ödeme Gerekli\",\r\n \"orderStatus\": \"Sipariş Durumu\",\r\n \"pending\": \"Beklemede\",\r\n \"deliveryInformation\": \"Teslimat Bilgileri\",\r\n \"address\": \"Adres\",\r\n \"notes\": \"Notlar\",\r\n \"orderItems\": \"Sipariş Ürünleri\",\r\n \"qty\": \"Adet\",\r\n \"total\": \"Toplam\",\r\n \"paymentInstructions\": \"Ödeme Talimatları\",\r\n \"bankTransferDetails\": \"Havale/EFT Bilgileri\",\r\n \"bankDetailsEmail\": \"Banka bilgileri e-posta ile gönderilecektir. Lütfen transferi 48 saat içinde tamamlayın.\",\r\n \"deliveryPayment\": \"Teslimatta Ödeme\",\r\n \"cashOnDeliveryInfo\": \"Kapıda Ödeme\",\r\n \"codInstructions\": \"Siparişiniz geldiğinde ödeme yapın. Teslimat ekibimiz teslimat öncesi sizinle iletişime geçecektir.\",\r\n \"backToHome\": \"Ana Sayfaya Dön\",\r\n \"loading\": \"Sipariş Yükleniyor...\"\r\n}\r\n"
40
40
  }
41
41
  ],
42
42
  "exports": {
@@ -24,13 +24,13 @@
24
24
  "path": "post-detail-block/lang/en.json",
25
25
  "type": "registry:lang",
26
26
  "target": "$modules$/post-detail-block/lang/en.json",
27
- "content": "{\r\n \"backToBlog\": \"Back to Blog\",\r\n \"minRead\": \"min read\",\r\n \"views\": \"views\",\r\n \"share\": \"Share\",\r\n \"addToFavorites\": \"Add to Favorites\",\r\n \"removeFromFavorites\": \"Remove from Favorites\",\r\n \"tags\": \"Tags\"\r\n}\r\n"
27
+ "content": "{\r\n \"backToBlog\": \"Back to Blog\",\r\n \"minRead\": \"min read\",\r\n \"views\": \"views\",\r\n \"share\": \"Share\",\r\n \"addToFavorites\": \"Add to Favorites\",\r\n \"removeFromFavorites\": \"Remove from Favorites\",\r\n \"tags\": \"Tags\",\r\n \"authorDescription\": \"Author of this post\"\r\n}\r\n"
28
28
  },
29
29
  {
30
30
  "path": "post-detail-block/lang/tr.json",
31
31
  "type": "registry:lang",
32
32
  "target": "$modules$/post-detail-block/lang/tr.json",
33
- "content": "{\r\n \"backToBlog\": \"Blog'a Dön\",\r\n \"minRead\": \"dk okuma\",\r\n \"views\": \"görüntülenme\",\r\n \"share\": \"Paylaş\",\r\n \"addToFavorites\": \"Favorilere Ekle\",\r\n \"removeFromFavorites\": \"Favorilerden Çıkar\",\r\n \"tags\": \"Etiketler\"\r\n}\r\n"
33
+ "content": "{\r\n \"backToBlog\": \"Blog'a Dön\",\r\n \"minRead\": \"dk okuma\",\r\n \"views\": \"görüntülenme\",\r\n \"share\": \"Paylaş\",\r\n \"addToFavorites\": \"Favorilere Ekle\",\r\n \"removeFromFavorites\": \"Favorilerden Çıkar\",\r\n \"tags\": \"Etiketler\",\r\n \"authorDescription\": \"Bu yazının yazarı\"\r\n}\r\n"
34
34
  }
35
35
  ],
36
36
  "exports": {
@@ -28,13 +28,13 @@
28
28
  "path": "product-card-detailed/lang/en.json",
29
29
  "type": "registry:lang",
30
30
  "target": "$modules$/product-card-detailed/lang/en.json",
31
- "content": "{\r\n \"wishlist\": \"Wishlist\",\r\n \"addToCart\": \"Add to Cart\",\r\n \"buyNow\": \"Buy Now\"\r\n}\r\n"
31
+ "content": "{\r\n \"wishlist\": \"Wishlist\",\r\n \"addToCart\": \"Add to Cart\",\r\n \"buyNow\": \"Buy Now\",\r\n \"addedToCart\": \"Added to cart!\"\r\n}\r\n"
32
32
  },
33
33
  {
34
34
  "path": "product-card-detailed/lang/tr.json",
35
35
  "type": "registry:lang",
36
36
  "target": "$modules$/product-card-detailed/lang/tr.json",
37
- "content": "{\r\n \"wishlist\": \"Favorilere Ekle\",\r\n \"addToCart\": \"Sepete Ekle\",\r\n \"buyNow\": \"Hemen Al\"\r\n}\r\n"
37
+ "content": "{\r\n \"wishlist\": \"Favorilere Ekle\",\r\n \"addToCart\": \"Sepete Ekle\",\r\n \"buyNow\": \"Hemen Al\",\r\n \"addedToCart\": \"Sepete eklendi!\"\r\n}\r\n"
38
38
  }
39
39
  ],
40
40
  "exports": {
@@ -29,13 +29,13 @@
29
29
  "path": "product-detail-section/lang/en.json",
30
30
  "type": "registry:lang",
31
31
  "target": "$modules$/product-detail-section/lang/en.json",
32
- "content": "{\r\n \"reviews\": \"Reviews\",\r\n \"color\": \"Color\",\r\n \"size\": \"Size\",\r\n \"addToCart\": \"Add to Cart\"\r\n}\r\n"
32
+ "content": "{\r\n \"reviews\": \"Reviews\",\r\n \"color\": \"Color\",\r\n \"size\": \"Size\",\r\n \"addToCart\": \"Add to Cart\",\r\n \"addedToCart\": \"Added to cart!\",\r\n \"category\": \"Category\",\r\n \"inStock\": \"In Stock\",\r\n \"outOfStock\": \"Out of Stock\"\r\n}\r\n"
33
33
  },
34
34
  {
35
35
  "path": "product-detail-section/lang/tr.json",
36
36
  "type": "registry:lang",
37
37
  "target": "$modules$/product-detail-section/lang/tr.json",
38
- "content": "{\r\n \"reviews\": \"Değerlendirme\",\r\n \"color\": \"Renk\",\r\n \"size\": \"Beden\",\r\n \"addToCart\": \"Sepete Ekle\"\r\n}\r\n"
38
+ "content": "{\r\n \"reviews\": \"Değerlendirme\",\r\n \"color\": \"Renk\",\r\n \"size\": \"Beden\",\r\n \"addToCart\": \"Sepete Ekle\",\r\n \"addedToCart\": \"Sepete eklendi!\",\r\n \"category\": \"Kategori\",\r\n \"inStock\": \"Stokta\",\r\n \"outOfStock\": \"Stokta Yok\"\r\n}\r\n"
39
39
  }
40
40
  ],
41
41
  "exports": {
@@ -29,13 +29,13 @@
29
29
  "path": "product-quick-view/lang/en.json",
30
30
  "type": "registry:lang",
31
31
  "target": "$modules$/product-quick-view/lang/en.json",
32
- "content": "{\r\n \"size\": \"Size\",\r\n \"color\": \"Color\",\r\n \"quantity\": \"Quantity\",\r\n \"addToCart\": \"Add to Cart\",\r\n \"viewDetails\": \"View Full Details\"\r\n}\r\n"
32
+ "content": "{\r\n \"size\": \"Size\",\r\n \"color\": \"Color\",\r\n \"quantity\": \"Quantity\",\r\n \"addToCart\": \"Add to Cart\",\r\n \"viewDetails\": \"View Full Details\",\r\n \"addedToCart\": \"Added to cart!\",\r\n \"removedFromFavorites\": \"Removed from favorites\",\r\n \"addedToFavorites\": \"Added to favorites!\",\r\n \"category\": \"Category\"\r\n}\r\n"
33
33
  },
34
34
  {
35
35
  "path": "product-quick-view/lang/tr.json",
36
36
  "type": "registry:lang",
37
37
  "target": "$modules$/product-quick-view/lang/tr.json",
38
- "content": "{\r\n \"size\": \"Beden\",\r\n \"color\": \"Renk\",\r\n \"quantity\": \"Adet\",\r\n \"addToCart\": \"Sepete Ekle\",\r\n \"viewDetails\": \"Tüm Detayları Gör\"\r\n}\r\n"
38
+ "content": "{\r\n \"size\": \"Beden\",\r\n \"color\": \"Renk\",\r\n \"quantity\": \"Adet\",\r\n \"addToCart\": \"Sepete Ekle\",\r\n \"viewDetails\": \"Tüm Detayları Gör\",\r\n \"addedToCart\": \"Sepete eklendi!\",\r\n \"removedFromFavorites\": \"Favorilerden çıkarıldı\",\r\n \"addedToFavorites\": \"Favorilere eklendi!\",\r\n \"category\": \"Kategori\"\r\n}\r\n"
39
39
  }
40
40
  ],
41
41
  "exports": {
@@ -23,19 +23,19 @@
23
23
  "path": "register-page-split/register-page-split.tsx",
24
24
  "type": "registry:page",
25
25
  "target": "$modules$/register-page-split/register-page-split.tsx",
26
- "content": "import { useState } from \"react\";\r\nimport { Link, useNavigate } 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 { Logo } from \"@/components/Logo\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { FormField } from \"@/components/FormField\";\r\nimport { PasswordInput } from \"@/components/PasswordInput\";\r\n\r\ninterface RegisterPageSplitProps {\r\n image?: string;\r\n}\r\n\r\nexport function RegisterPageSplit({\r\n image = \"/images/placeholder.png\",\r\n}: RegisterPageSplitProps) {\r\n const { t } = useTranslation(\"register-page-split\");\r\n usePageTitle({ title: t(\"title\", \"Create Account\") });\r\n const navigate = useNavigate();\r\n const { register } = useAuth();\r\n\r\n const [username, setUsername] = useState(\"\");\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [confirmPassword, setConfirmPassword] = useState(\"\");\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (password !== confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n\r\n try {\r\n await register(username, email, password);\r\n\r\n toast.success(t(\"registerSuccess\", \"Account created successfully!\"), {\r\n description: t(\"checkEmail\", \"Please check your email to verify your account.\"),\r\n });\r\n\r\n // Navigate to login page after successful registration\r\n navigate(\"/login\", {\r\n state: {\r\n message: t(\"verifyEmail\", \"Please verify your email before logging in.\"),\r\n email\r\n }\r\n });\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"registerError\", \"Registration failed. Please try again.\")\r\n );\r\n setError(errorMessage);\r\n } finally {\r\n setIsLoading(false);\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 <div>\r\n <h1 className=\"text-xl font-bold tracking-tight\">\r\n {t(\"title\", \"Create Account\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {t(\"subtitle\", \"Sign up to get started\")}\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 <FormField label={t(\"username\", \"Username\")} htmlFor=\"username\" required>\r\n <Input\r\n required\r\n id=\"username\"\r\n type=\"text\"\r\n autoComplete=\"username\"\r\n placeholder={t(\"usernamePlaceholder\", \"johndoe\")}\r\n value={username}\r\n onChange={(e) => setUsername(e.target.value)}\r\n disabled={isLoading}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"email\", \"Email\")} htmlFor=\"email\" required>\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 </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"password\", \"Password\")} htmlFor=\"password\" required>\r\n <PasswordInput\r\n required\r\n name=\"password\"\r\n id=\"password\"\r\n autoComplete=\"new-password\"\r\n placeholder=\"••••••••\"\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"confirmPassword\", \"Confirm Password\")} htmlFor=\"confirm-password\" required>\r\n <PasswordInput\r\n required\r\n id=\"confirm-password\"\r\n name=\"confirm-password\"\r\n autoComplete=\"new-password\"\r\n placeholder=\"••••••••\"\r\n value={confirmPassword}\r\n onChange={(e) => setConfirmPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\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(\"creatingAccount\", \"Creating account...\")}\r\n </>\r\n ) : (\r\n t(\"signUp\", \"Sign Up\")\r\n )}\r\n </Button>\r\n </form>\r\n\r\n <div className=\"text-sm text-center\">\r\n <p>\r\n {t(\"hasAccount\", \"Already have an account?\")}{\" \"}\r\n <Link to=\"/login\" className=\"underline\">\r\n {t(\"signIn\", \"Sign in\")}\r\n </Link>\r\n </p>\r\n </div>\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\", \"Register 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 RegisterPageSplit;\r\n"
26
+ "content": "import { useState } from \"react\";\r\nimport { Link, useNavigate } 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 { Logo } from \"@/components/Logo\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { FormField } from \"@/components/FormField\";\r\nimport { PasswordInput } from \"@/components/PasswordInput\";\r\n\r\ninterface RegisterPageSplitProps {\r\n image?: string;\r\n}\r\n\r\nexport function RegisterPageSplit({\r\n image = \"/images/placeholder.png\",\r\n}: RegisterPageSplitProps) {\r\n const { t } = useTranslation(\"register-page-split\");\r\n usePageTitle({ title: t(\"title\", \"Create Account\") });\r\n const navigate = useNavigate();\r\n const { register } = useAuth();\r\n\r\n const [username, setUsername] = useState(\"\");\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [confirmPassword, setConfirmPassword] = useState(\"\");\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (password !== confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n\r\n try {\r\n await register(username, email, password);\r\n\r\n toast.success(t(\"registerSuccess\", \"Account created successfully!\"), {\r\n description: t(\"registerSuccessDesc\", \"You can now sign in with your credentials.\"),\r\n });\r\n\r\n navigate(\"/login\");\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"registerError\", \"Registration failed. Please try again.\")\r\n );\r\n setError(errorMessage);\r\n } finally {\r\n setIsLoading(false);\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 <div>\r\n <h1 className=\"text-xl font-bold tracking-tight\">\r\n {t(\"title\", \"Create Account\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {t(\"subtitle\", \"Sign up to get started\")}\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 <FormField label={t(\"username\", \"Username\")} htmlFor=\"username\" required>\r\n <Input\r\n required\r\n id=\"username\"\r\n type=\"text\"\r\n autoComplete=\"username\"\r\n placeholder={t(\"usernamePlaceholder\", \"johndoe\")}\r\n value={username}\r\n onChange={(e) => setUsername(e.target.value)}\r\n disabled={isLoading}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"email\", \"Email\")} htmlFor=\"email\" required>\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 </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"password\", \"Password\")} htmlFor=\"password\" required>\r\n <PasswordInput\r\n required\r\n name=\"password\"\r\n id=\"password\"\r\n autoComplete=\"new-password\"\r\n placeholder=\"••••••••\"\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"confirmPassword\", \"Confirm Password\")} htmlFor=\"confirm-password\" required>\r\n <PasswordInput\r\n required\r\n id=\"confirm-password\"\r\n name=\"confirm-password\"\r\n autoComplete=\"new-password\"\r\n placeholder=\"••••••••\"\r\n value={confirmPassword}\r\n onChange={(e) => setConfirmPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\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(\"creatingAccount\", \"Creating account...\")}\r\n </>\r\n ) : (\r\n t(\"signUp\", \"Sign Up\")\r\n )}\r\n </Button>\r\n </form>\r\n\r\n <div className=\"text-sm text-center\">\r\n <p>\r\n {t(\"hasAccount\", \"Already have an account?\")}{\" \"}\r\n <Link to=\"/login\" className=\"underline\">\r\n {t(\"signIn\", \"Sign in\")}\r\n </Link>\r\n </p>\r\n </div>\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\", \"Register 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 RegisterPageSplit;\r\n"
27
27
  },
28
28
  {
29
29
  "path": "register-page-split/lang/en.json",
30
30
  "type": "registry:lang",
31
31
  "target": "$modules$/register-page-split/lang/en.json",
32
- "content": "{\r\n \"title\": \"Create Account\",\r\n \"subtitle\": \"Sign up to get started\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"johndoe\",\r\n \"email\": \"Email\",\r\n \"emailPlaceholder\": \"you@example.com\",\r\n \"password\": \"Password\",\r\n \"confirmPassword\": \"Confirm Password\",\r\n \"passwordMismatch\": \"Passwords do not match\",\r\n \"signUp\": \"Sign Up\",\r\n \"creatingAccount\": \"Creating account...\",\r\n \"registerSuccess\": \"Account created successfully!\",\r\n \"checkEmail\": \"Please check your email to verify your account.\",\r\n \"verifyEmail\": \"Please verify your email before logging in.\",\r\n \"registerError\": \"Registration failed. Please try again.\",\r\n \"hasAccount\": \"Already have an account?\",\r\n \"signIn\": \"Sign in\",\r\n \"copyright\": \"All rights reserved.\",\r\n \"imageAlt\": \"Register background\"\r\n}\r\n"
32
+ "content": "{\r\n \"title\": \"Create Account\",\r\n \"subtitle\": \"Sign up to get started\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"johndoe\",\r\n \"email\": \"Email\",\r\n \"emailPlaceholder\": \"you@example.com\",\r\n \"password\": \"Password\",\r\n \"confirmPassword\": \"Confirm Password\",\r\n \"passwordMismatch\": \"Passwords do not match\",\r\n \"signUp\": \"Sign Up\",\r\n \"creatingAccount\": \"Creating account...\",\r\n \"registerSuccess\": \"Account created successfully!\",\r\n \"registerSuccessDesc\": \"You can now sign in with your credentials.\",\r\n \"registerError\": \"Registration failed. Please try again.\",\r\n \"hasAccount\": \"Already have an account?\",\r\n \"signIn\": \"Sign in\",\r\n \"copyright\": \"All rights reserved.\",\r\n \"imageAlt\": \"Register background\"\r\n}\r\n"
33
33
  },
34
34
  {
35
35
  "path": "register-page-split/lang/tr.json",
36
36
  "type": "registry:lang",
37
37
  "target": "$modules$/register-page-split/lang/tr.json",
38
- "content": "{\r\n \"title\": \"Hesap Oluştur\",\r\n \"subtitle\": \"Başlamak için kaydolun\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"ahmetyilmaz\",\r\n \"email\": \"E-posta\",\r\n \"emailPlaceholder\": \"ornek@email.com\",\r\n \"password\": \"Şifre\",\r\n \"confirmPassword\": \"Şifre Onayı\",\r\n \"passwordMismatch\": \"Şifreler eşleşmiyor\",\r\n \"signUp\": \"Kaydol\",\r\n \"creatingAccount\": \"Hesap oluşturuluyor...\",\r\n \"registerSuccess\": \"Hesap başarıyla oluşturuldu!\",\r\n \"checkEmail\": \"Lütfen hesabınızı doğrulamak için e-postanızı kontrol edin.\",\r\n \"verifyEmail\": \"Lütfen giriş yapmadan önce e-postanızı doğrulayın.\",\r\n \"registerError\": \"Kayıt başarısız. Lütfen tekrar deneyin.\",\r\n \"hasAccount\": \"Zaten hesabınız var mı?\",\r\n \"signIn\": \"Giriş yap\",\r\n \"copyright\": \"Tüm hakları saklıdır.\",\r\n \"imageAlt\": \"Kayıt arka planı\"\r\n}\r\n"
38
+ "content": "{\r\n \"title\": \"Hesap Oluştur\",\r\n \"subtitle\": \"Başlamak için kaydolun\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"ahmetyilmaz\",\r\n \"email\": \"E-posta\",\r\n \"emailPlaceholder\": \"ornek@email.com\",\r\n \"password\": \"Şifre\",\r\n \"confirmPassword\": \"Şifre Onayı\",\r\n \"passwordMismatch\": \"Şifreler eşleşmiyor\",\r\n \"signUp\": \"Kaydol\",\r\n \"creatingAccount\": \"Hesap oluşturuluyor...\",\r\n \"registerSuccess\": \"Hesap başarıyla oluşturuldu!\",\r\n \"registerSuccessDesc\": \"Artık bilgilerinizle giriş yapabilirsiniz.\",\r\n \"registerError\": \"Kayıt başarısız. Lütfen tekrar deneyin.\",\r\n \"hasAccount\": \"Zaten hesabınız var mı?\",\r\n \"signIn\": \"Giriş yap\",\r\n \"copyright\": \"Tüm hakları saklıdır.\",\r\n \"imageAlt\": \"Kayıt arka planı\"\r\n}\r\n"
39
39
  }
40
40
  ],
41
41
  "exports": {
@@ -23,19 +23,19 @@
23
23
  "path": "register-page/register-page.tsx",
24
24
  "type": "registry:page",
25
25
  "target": "$modules$/register-page/register-page.tsx",
26
- "content": "import { useState, useEffect } from \"react\";\r\nimport { Link, useNavigate } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { Layout } from \"@/components/Layout\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\r\nimport { UserPlus, CheckCircle } from \"lucide-react\";\r\nimport { PasswordInput } from \"@/components/PasswordInput\";\r\nimport { FormField } from \"@/components/FormField\";\r\n\r\nexport function RegisterPage() {\r\n const { t } = useTranslation(\"register-page\");\r\n usePageTitle({ title: t(\"title\", \"Create Account\") });\r\n\r\n const navigate = useNavigate();\r\n const { register, isAuthenticated } = useAuth();\r\n\r\n const [formData, setFormData] = useState({\r\n username: \"\",\r\n email: \"\",\r\n password: \"\",\r\n confirmPassword: \"\",\r\n });\r\n const [isSubmitting, setIsSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState(false);\r\n\r\n // Redirect if already authenticated\r\n useEffect(() => {\r\n if (isAuthenticated) {\r\n navigate(\"/\", { replace: true });\r\n }\r\n }, [isAuthenticated, navigate]);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setIsSubmitting(true);\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (formData.password !== formData.confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n toast.error(t(\"toastErrorTitle\", \"Registration failed\"), {\r\n description: t(\"passwordMismatch\", \"Passwords do not match\"),\r\n });\r\n setIsSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await register(formData.username, formData.email, formData.password);\r\n setSuccess(true);\r\n toast.success(t(\"toastSuccessTitle\", \"Account created!\"), {\r\n description: t(\r\n \"toastSuccessDesc\",\r\n \"Please check your email to verify your account.\"\r\n ),\r\n });\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"errorGeneric\", \"Registration failed. Please try again.\")\r\n );\r\n setError(errorMessage);\r\n toast.error(t(\"toastErrorTitle\", \"Registration failed\"), {\r\n description: errorMessage,\r\n });\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n setFormData((prev) => ({\r\n ...prev,\r\n [e.target.name]: e.target.value,\r\n }));\r\n };\r\n\r\n if (success) {\r\n return (\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardContent className=\"pt-6\">\r\n <div className=\"text-center space-y-4\">\r\n <CheckCircle className=\"w-16 h-16 text-green-500 mx-auto\" />\r\n <h2 className=\"text-2xl font-bold text-foreground\">\r\n {t(\"successTitle\", \"Account Created!\")}\r\n </h2>\r\n <p className=\"text-muted-foreground\">\r\n {t(\r\n \"successMessage\",\r\n \"Please check your email to verify your account.\"\r\n )}\r\n </p>\r\n <Button asChild className=\"mt-4\">\r\n <Link to=\"/login\">{t(\"goToLogin\", \"Go to Login\")}</Link>\r\n </Button>\r\n </div>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n {/* Hero Section */}\r\n <div className=\"text-center mb-12\">\r\n <h1 className=\"text-4xl font-bold text-foreground mb-4\">\r\n {t(\"title\", \"Create Account\")}\r\n </h1>\r\n <div className=\"w-16 h-1 bg-primary mx-auto mb-6\"></div>\r\n <p className=\"text-lg text-muted-foreground max-w-xl mx-auto\">\r\n {t(\"description\", \"Create an account to get started\")}\r\n </p>\r\n </div>\r\n\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <UserPlus className=\"w-5 h-5 text-primary\" />\r\n {t(\"cardTitle\", \"Sign Up\")}\r\n </CardTitle>\r\n </CardHeader>\r\n <CardContent>\r\n <form onSubmit={handleSubmit} className=\"space-y-6\">\r\n <FormField\r\n label={t(\"username\", \"Username\")}\r\n htmlFor=\"username\"\r\n required\r\n >\r\n <Input\r\n id=\"username\"\r\n name=\"username\"\r\n type=\"text\"\r\n value={formData.username}\r\n onChange={handleChange}\r\n placeholder={t(\r\n \"usernamePlaceholder\",\r\n \"Enter your username\"\r\n )}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"username\"\r\n />\r\n </FormField>\r\n <FormField\r\n label={t(\"email\", \"Email\")}\r\n htmlFor=\"email\"\r\n required\r\n >\r\n <Input\r\n id=\"email\"\r\n name=\"email\"\r\n type=\"email\"\r\n value={formData.email}\r\n onChange={handleChange}\r\n placeholder={t(\"emailPlaceholder\", \"Enter your email\")}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"email\"\r\n />\r\n </FormField>\r\n <FormField\r\n label={t(\"password\", \"Password\")}\r\n htmlFor=\"password\"\r\n required\r\n >\r\n <PasswordInput\r\n id=\"password\"\r\n name=\"password\"\r\n value={formData.password}\r\n onChange={handleChange}\r\n placeholder={t(\"passwordPlaceholder\", \"Enter password\")}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n />\r\n </FormField>\r\n\r\n <FormField\r\n label={t(\"confirmPassword\", \"Confirm Password\")}\r\n htmlFor=\"confirmPassword\"\r\n required\r\n >\r\n <PasswordInput\r\n id=\"confirmPassword\"\r\n name=\"confirmPassword\"\r\n value={formData.confirmPassword}\r\n onChange={handleChange}\r\n placeholder={t(\"passwordPlaceholder\", \"Enter password\")}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n />\r\n </FormField>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n className=\"w-full\"\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting\r\n ? t(\"submitting\", \"Creating account...\")\r\n : t(\"submit\", \"Create Account\")}\r\n </Button>\r\n\r\n <div className=\"text-center text-sm text-muted-foreground\">\r\n {t(\"hasAccount\", \"Already have an account?\")}{\" \"}\r\n <Link\r\n to=\"/login\"\r\n className=\"text-primary hover:underline font-medium\"\r\n >\r\n {t(\"loginLink\", \"Sign in\")}\r\n </Link>\r\n </div>\r\n </form>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n}\r\n\r\nexport default RegisterPage;\r\n"
26
+ "content": "import { useState, useEffect } from \"react\";\r\nimport { Link, useNavigate } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { Layout } from \"@/components/Layout\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\r\nimport { UserPlus } from \"lucide-react\";\r\nimport { PasswordInput } from \"@/components/PasswordInput\";\r\nimport { FormField } from \"@/components/FormField\";\r\n\r\nexport function RegisterPage() {\r\n const { t } = useTranslation(\"register-page\");\r\n usePageTitle({ title: t(\"title\", \"Create Account\") });\r\n\r\n const navigate = useNavigate();\r\n const { register, isAuthenticated } = useAuth();\r\n\r\n const [formData, setFormData] = useState({\r\n username: \"\",\r\n email: \"\",\r\n password: \"\",\r\n confirmPassword: \"\",\r\n });\r\n const [isSubmitting, setIsSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n // Redirect if already authenticated\r\n useEffect(() => {\r\n if (isAuthenticated) {\r\n navigate(\"/\", { replace: true });\r\n }\r\n }, [isAuthenticated, navigate]);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setIsSubmitting(true);\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (formData.password !== formData.confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n toast.error(t(\"toastErrorTitle\", \"Registration failed\"), {\r\n description: t(\"passwordMismatch\", \"Passwords do not match\"),\r\n });\r\n setIsSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await register(formData.username, formData.email, formData.password);\r\n toast.success(t(\"toastSuccessTitle\", \"Account created!\"), {\r\n description: t(\"toastSuccessDesc\", \"You can now sign in.\"),\r\n });\r\n navigate(\"/login\");\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"errorGeneric\", \"Registration failed. Please try again.\")\r\n );\r\n setError(errorMessage);\r\n toast.error(t(\"toastErrorTitle\", \"Registration failed\"), {\r\n description: errorMessage,\r\n });\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n setFormData((prev) => ({\r\n ...prev,\r\n [e.target.name]: e.target.value,\r\n }));\r\n };\r\n\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n {/* Hero Section */}\r\n <div className=\"text-center mb-12\">\r\n <h1 className=\"text-4xl font-bold text-foreground mb-4\">\r\n {t(\"title\", \"Create Account\")}\r\n </h1>\r\n <div className=\"w-16 h-1 bg-primary mx-auto mb-6\"></div>\r\n <p className=\"text-lg text-muted-foreground max-w-xl mx-auto\">\r\n {t(\"description\", \"Create an account to get started\")}\r\n </p>\r\n </div>\r\n\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <UserPlus className=\"w-5 h-5 text-primary\" />\r\n {t(\"cardTitle\", \"Sign Up\")}\r\n </CardTitle>\r\n </CardHeader>\r\n <CardContent>\r\n <form onSubmit={handleSubmit} className=\"space-y-6\">\r\n <FormField\r\n label={t(\"username\", \"Username\")}\r\n htmlFor=\"username\"\r\n required\r\n >\r\n <Input\r\n id=\"username\"\r\n name=\"username\"\r\n type=\"text\"\r\n value={formData.username}\r\n onChange={handleChange}\r\n placeholder={t(\r\n \"usernamePlaceholder\",\r\n \"Enter your username\"\r\n )}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"username\"\r\n />\r\n </FormField>\r\n <FormField\r\n label={t(\"email\", \"Email\")}\r\n htmlFor=\"email\"\r\n required\r\n >\r\n <Input\r\n id=\"email\"\r\n name=\"email\"\r\n type=\"email\"\r\n value={formData.email}\r\n onChange={handleChange}\r\n placeholder={t(\"emailPlaceholder\", \"Enter your email\")}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"email\"\r\n />\r\n </FormField>\r\n <FormField\r\n label={t(\"password\", \"Password\")}\r\n htmlFor=\"password\"\r\n required\r\n >\r\n <PasswordInput\r\n id=\"password\"\r\n name=\"password\"\r\n value={formData.password}\r\n onChange={handleChange}\r\n placeholder={t(\"passwordPlaceholder\", \"Enter password\")}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n />\r\n </FormField>\r\n\r\n <FormField\r\n label={t(\"confirmPassword\", \"Confirm Password\")}\r\n htmlFor=\"confirmPassword\"\r\n required\r\n >\r\n <PasswordInput\r\n id=\"confirmPassword\"\r\n name=\"confirmPassword\"\r\n value={formData.confirmPassword}\r\n onChange={handleChange}\r\n placeholder={t(\"passwordPlaceholder\", \"Enter password\")}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n />\r\n </FormField>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n className=\"w-full\"\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting\r\n ? t(\"submitting\", \"Creating account...\")\r\n : t(\"submit\", \"Create Account\")}\r\n </Button>\r\n\r\n <div className=\"text-center text-sm text-muted-foreground\">\r\n {t(\"hasAccount\", \"Already have an account?\")}{\" \"}\r\n <Link\r\n to=\"/login\"\r\n className=\"text-primary hover:underline font-medium\"\r\n >\r\n {t(\"loginLink\", \"Sign in\")}\r\n </Link>\r\n </div>\r\n </form>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n}\r\n\r\nexport default RegisterPage;\r\n"
27
27
  },
28
28
  {
29
29
  "path": "register-page/lang/en.json",
30
30
  "type": "registry:lang",
31
31
  "target": "$modules$/register-page/lang/en.json",
32
- "content": "{\r\n \"title\": \"Create Account\",\r\n \"description\": \"Create an account to get started\",\r\n \"cardTitle\": \"Sign Up\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"Enter your username\",\r\n \"email\": \"Email\",\r\n \"emailPlaceholder\": \"Enter your email\",\r\n \"password\": \"Password\",\r\n \"passwordPlaceholder\": \"Enter password\",\r\n \"confirmPassword\": \"Confirm Password\",\r\n \"confirmPasswordPlaceholder\": \"Confirm your password\",\r\n \"passwordMismatch\": \"Passwords do not match\",\r\n \"submit\": \"Create Account\",\r\n \"submitting\": \"Creating account...\",\r\n \"hasAccount\": \"Already have an account?\",\r\n \"loginLink\": \"Sign in\",\r\n \"toastSuccessTitle\": \"Account created!\",\r\n \"toastSuccessDesc\": \"Please check your email to verify your account.\",\r\n \"toastErrorTitle\": \"Registration failed\",\r\n \"errorGeneric\": \"Registration failed. Please try again.\",\r\n \"successTitle\": \"Account Created!\",\r\n \"successMessage\": \"Please check your email to verify your account.\",\r\n \"goToLogin\": \"Go to Login\"\r\n}\r\n"
32
+ "content": "{\r\n \"title\": \"Create Account\",\r\n \"description\": \"Create an account to get started\",\r\n \"cardTitle\": \"Sign Up\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"Enter your username\",\r\n \"email\": \"Email\",\r\n \"emailPlaceholder\": \"Enter your email\",\r\n \"password\": \"Password\",\r\n \"passwordPlaceholder\": \"Enter password\",\r\n \"confirmPassword\": \"Confirm Password\",\r\n \"confirmPasswordPlaceholder\": \"Confirm your password\",\r\n \"passwordMismatch\": \"Passwords do not match\",\r\n \"submit\": \"Create Account\",\r\n \"submitting\": \"Creating account...\",\r\n \"hasAccount\": \"Already have an account?\",\r\n \"loginLink\": \"Sign in\",\r\n \"toastSuccessTitle\": \"Account created!\",\r\n \"toastSuccessDesc\": \"You can now sign in.\",\r\n \"toastErrorTitle\": \"Registration failed\",\r\n \"errorGeneric\": \"Registration failed. Please try again.\"\r\n}\r\n"
33
33
  },
34
34
  {
35
35
  "path": "register-page/lang/tr.json",
36
36
  "type": "registry:lang",
37
37
  "target": "$modules$/register-page/lang/tr.json",
38
- "content": "{\r\n \"title\": \"Hesap Oluştur\",\r\n \"description\": \"Başlamak için bir hesap oluşturun\",\r\n \"cardTitle\": \"Kayıt Ol\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"Kullanıcı adınızı girin\",\r\n \"email\": \"E-posta\",\r\n \"emailPlaceholder\": \"E-posta adresinizi girin\",\r\n \"password\": \"Şifre\",\r\n \"passwordPlaceholder\": \"Şifre girin\",\r\n \"confirmPassword\": \"Şifre Onayı\",\r\n \"confirmPasswordPlaceholder\": \"Şifrenizi onaylayın\",\r\n \"passwordMismatch\": \"Şifreler eşleşmiyor\",\r\n \"submit\": \"Hesap Oluştur\",\r\n \"submitting\": \"Hesap oluşturuluyor...\",\r\n \"hasAccount\": \"Zaten hesabınız var mı?\",\r\n \"loginLink\": \"Giriş yap\",\r\n \"toastSuccessTitle\": \"Hesap oluşturuldu!\",\r\n \"toastSuccessDesc\": \"Lütfen hesabınızı doğrulamak için e-postanızı kontrol edin.\",\r\n \"toastErrorTitle\": \"Kayıt başarısız\",\r\n \"errorGeneric\": \"Kayıt başarısız. Lütfen tekrar deneyin.\",\r\n \"successTitle\": \"Hesap Oluşturuldu!\",\r\n \"successMessage\": \"Lütfen hesabınızı doğrulamak için e-postanızı kontrol edin.\",\r\n \"goToLogin\": \"Girişe Git\"\r\n}\r\n"
38
+ "content": "{\r\n \"title\": \"Hesap Oluştur\",\r\n \"description\": \"Başlamak için bir hesap oluşturun\",\r\n \"cardTitle\": \"Kayıt Ol\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"Kullanıcı adınızı girin\",\r\n \"email\": \"E-posta\",\r\n \"emailPlaceholder\": \"E-posta adresinizi girin\",\r\n \"password\": \"Şifre\",\r\n \"passwordPlaceholder\": \"Şifre girin\",\r\n \"confirmPassword\": \"Şifre Onayı\",\r\n \"confirmPasswordPlaceholder\": \"Şifrenizi onaylayın\",\r\n \"passwordMismatch\": \"Şifreler eşleşmiyor\",\r\n \"submit\": \"Hesap Oluştur\",\r\n \"submitting\": \"Hesap oluşturuluyor...\",\r\n \"hasAccount\": \"Zaten hesabınız var mı?\",\r\n \"loginLink\": \"Giriş yap\",\r\n \"toastSuccessTitle\": \"Hesap oluşturuldu!\",\r\n \"toastSuccessDesc\": \"Artık giriş yapabilirsiniz.\",\r\n \"toastErrorTitle\": \"Kayıt başarısız\",\r\n \"errorGeneric\": \"Kayıt başarısız. Lütfen tekrar deneyin.\"\r\n}\r\n"
39
39
  }
40
40
  ],
41
41
  "exports": {
@@ -23,7 +23,7 @@
23
23
  "path": "reset-password-page-split/reset-password-page-split.tsx",
24
24
  "type": "registry:page",
25
25
  "target": "$modules$/reset-password-page-split/reset-password-page-split.tsx",
26
- "content": "import { useState } from \"react\";\r\nimport { Link, useNavigate, useSearchParams } 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 { Logo } from \"@/components/Logo\";\r\nimport { KeyRound, ArrowLeft, CheckCircle } from \"lucide-react\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { FormField } from \"@/components/FormField\";\r\nimport { PasswordInput } from \"@/components/PasswordInput\";\r\n\r\ninterface ResetPasswordPageSplitProps {\r\n image?: string;\r\n}\r\n\r\nexport function ResetPasswordPageSplit({\r\n image = \"/images/placeholder.png\",\r\n}: ResetPasswordPageSplitProps) {\r\n const { t } = useTranslation(\"reset-password-page-split\");\r\n usePageTitle({ title: t(\"title\", \"Reset Password\") });\r\n const navigate = useNavigate();\r\n const [searchParams] = useSearchParams();\r\n const { resetPassword } = useAuth();\r\n\r\n // Get code and username from URL params\r\n const code = searchParams.get(\"code\") || \"\";\r\n const username = searchParams.get(\"username\") || searchParams.get(\"email\") || \"\";\r\n\r\n const [password, setPassword] = useState(\"\");\r\n const [confirmPassword, setConfirmPassword] = useState(\"\");\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [isSuccess, setIsSuccess] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (password !== confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n return;\r\n }\r\n\r\n // Validate we have required params\r\n if (!code || !username) {\r\n setError(t(\"invalidLink\", \"Invalid or expired reset link. Please request a new one.\"));\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n\r\n try {\r\n await resetPassword(username, code, password);\r\n\r\n setIsSuccess(true);\r\n toast.success(t(\"passwordResetSuccess\", \"Password reset successfully!\"));\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"resetPasswordError\", \"Failed to reset password. 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\r\n if (isSuccess) {\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(\"passwordReset\", \"Password Reset!\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground mt-2\">\r\n {t(\"passwordResetDescription\", \"Your password has been reset successfully. You can now log in with your new password.\")}\r\n </p>\r\n </div>\r\n\r\n <Button onClick={() => navigate(\"/login\")} className=\"w-full\">\r\n {t(\"goToLogin\", \"Go to Login\")}\r\n </Button>\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\", \"Reset 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 // Invalid link state\r\n if (!code || !username) {\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>\r\n <h1 className=\"text-xl font-bold tracking-tight text-red-600\">\r\n {t(\"invalidLinkTitle\", \"Invalid Reset Link\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground mt-2\">\r\n {t(\"invalidLinkDescription\", \"This password reset link is invalid or has expired. Please request a new one.\")}\r\n </p>\r\n </div>\r\n\r\n <Button onClick={() => navigate(\"/forgot-password\")} className=\"w-full\">\r\n {t(\"requestNewLink\", \"Request New Link\")}\r\n </Button>\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\", \"Reset 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 <KeyRound 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\", \"Reset Password\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground mt-1\">\r\n {t(\"subtitle\", \"Enter your new password below\")}\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 <FormField label={t(\"newPassword\", \"New Password\")} htmlFor=\"password\" required>\r\n <PasswordInput\r\n required\r\n id=\"password\"\r\n name=\"password\"\r\n autoComplete=\"new-password\"\r\n placeholder=\"••••••••\"\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"confirmPassword\", \"Confirm Password\")} htmlFor=\"confirm-password\" required>\r\n <PasswordInput\r\n required\r\n id=\"confirm-password\"\r\n name=\"confirm-password\"\r\n autoComplete=\"confirm-password\"\r\n placeholder=\"••••••••\"\r\n value={confirmPassword}\r\n onChange={(e) => setConfirmPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\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(\"resetting\", \"Resetting...\")}\r\n </>\r\n ) : (\r\n t(\"resetPassword\", \"Reset Password\")\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\", \"Reset 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 ResetPasswordPageSplit;\r\n"
26
+ "content": "import { useState } from \"react\";\r\nimport { Link, useNavigate, useSearchParams } 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 { Logo } from \"@/components/Logo\";\r\nimport { KeyRound, ArrowLeft, CheckCircle } from \"lucide-react\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { FormField } from \"@/components/FormField\";\r\nimport { PasswordInput } from \"@/components/PasswordInput\";\r\n\r\ninterface ResetPasswordPageSplitProps {\r\n image?: string;\r\n}\r\n\r\nexport function ResetPasswordPageSplit({\r\n image = \"/images/placeholder.png\",\r\n}: ResetPasswordPageSplitProps) {\r\n const { t } = useTranslation(\"reset-password-page-split\");\r\n usePageTitle({ title: t(\"title\", \"Reset Password\") });\r\n const navigate = useNavigate();\r\n const [searchParams] = useSearchParams();\r\n const { resetPassword } = useAuth();\r\n\r\n // Get code and email from URL params\r\n const code = searchParams.get(\"code\") || \"\";\r\n const email = searchParams.get(\"email\") || \"\";\r\n\r\n const [password, setPassword] = useState(\"\");\r\n const [confirmPassword, setConfirmPassword] = useState(\"\");\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [isSuccess, setIsSuccess] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (password !== confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n return;\r\n }\r\n\r\n // Validate we have required params\r\n if (!code || !email) {\r\n setError(t(\"invalidLink\", \"Invalid or expired reset link. Please request a new one.\"));\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n\r\n try {\r\n await resetPassword(email, code, password);\r\n\r\n setIsSuccess(true);\r\n toast.success(t(\"passwordResetSuccess\", \"Password reset successfully!\"));\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"resetPasswordError\", \"Failed to reset password. 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\r\n if (isSuccess) {\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(\"passwordReset\", \"Password Reset!\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground mt-2\">\r\n {t(\"passwordResetDescription\", \"Your password has been reset successfully. You can now log in with your new password.\")}\r\n </p>\r\n </div>\r\n\r\n <Button onClick={() => navigate(\"/login\")} className=\"w-full\">\r\n {t(\"goToLogin\", \"Go to Login\")}\r\n </Button>\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\", \"Reset 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 // Invalid link state\r\n if (!code || !email) {\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>\r\n <h1 className=\"text-xl font-bold tracking-tight text-red-600\">\r\n {t(\"invalidLinkTitle\", \"Invalid Reset Link\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground mt-2\">\r\n {t(\"invalidLinkDescription\", \"This password reset link is invalid or has expired. Please request a new one.\")}\r\n </p>\r\n </div>\r\n\r\n <Button onClick={() => navigate(\"/forgot-password\")} className=\"w-full\">\r\n {t(\"requestNewLink\", \"Request New Link\")}\r\n </Button>\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\", \"Reset 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 <KeyRound 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\", \"Reset Password\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground mt-1\">\r\n {t(\"subtitle\", \"Enter your new password below\")}\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 <FormField label={t(\"newPassword\", \"New Password\")} htmlFor=\"password\" required>\r\n <PasswordInput\r\n required\r\n id=\"password\"\r\n name=\"password\"\r\n autoComplete=\"new-password\"\r\n placeholder=\"••••••••\"\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"confirmPassword\", \"Confirm Password\")} htmlFor=\"confirm-password\" required>\r\n <PasswordInput\r\n required\r\n id=\"confirm-password\"\r\n name=\"confirm-password\"\r\n autoComplete=\"confirm-password\"\r\n placeholder=\"••••••••\"\r\n value={confirmPassword}\r\n onChange={(e) => setConfirmPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\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(\"resetting\", \"Resetting...\")}\r\n </>\r\n ) : (\r\n t(\"resetPassword\", \"Reset Password\")\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\", \"Reset 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 ResetPasswordPageSplit;\r\n"
27
27
  },
28
28
  {
29
29
  "path": "reset-password-page-split/lang/en.json",
@@ -23,7 +23,7 @@
23
23
  "path": "reset-password-page/reset-password-page.tsx",
24
24
  "type": "registry:page",
25
25
  "target": "$modules$/reset-password-page/reset-password-page.tsx",
26
- "content": "import { useState } from \"react\";\r\nimport { Link, useNavigate, useSearchParams } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { Layout } from \"@/components/Layout\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport {\r\n Card,\r\n CardContent,\r\n CardHeader,\r\n CardTitle,\r\n CardDescription,\r\n} from \"@/components/ui/card\";\r\nimport { KeyRound, ArrowLeft, Eye, EyeOff, CheckCircle2 } from \"lucide-react\";\r\n\r\nexport function ResetPasswordPage() {\r\n const { t } = useTranslation(\"reset-password-page\");\r\n usePageTitle({ title: t(\"title\", \"Reset Password\") });\r\n const navigate = useNavigate();\r\n const [searchParams] = useSearchParams();\r\n const { resetPassword } = useAuth();\r\n\r\n const code = searchParams.get(\"code\") || \"\";\r\n const username =\r\n searchParams.get(\"username\") || searchParams.get(\"email\") || \"\";\r\n\r\n const [password, setPassword] = useState(\"\");\r\n const [confirmPassword, setConfirmPassword] = useState(\"\");\r\n const [showPassword, setShowPassword] = useState(false);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [isSuccess, setIsSuccess] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n if (password !== confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n return;\r\n }\r\n\r\n if (!code || !username) {\r\n setError(\r\n t(\r\n \"invalidLink\",\r\n \"Invalid or expired reset link. Please request a new one.\",\r\n ),\r\n );\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n\r\n try {\r\n await resetPassword(username, code, password);\r\n setIsSuccess(true);\r\n toast.success(\r\n t(\"passwordResetSuccess\", \"Password reset successfully!\"),\r\n );\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\r\n \"resetPasswordError\",\r\n \"Failed to reset password. Please try again.\",\r\n ),\r\n );\r\n setError(errorMessage);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n // Success state\r\n if (isSuccess) {\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardContent className=\"pt-8 pb-8 text-center\">\r\n <CheckCircle2 className=\"w-16 h-16 text-green-500 mx-auto mb-4\" />\r\n <h1 className=\"text-2xl font-bold mb-2\">\r\n {t(\"passwordReset\", \"Password Reset!\")}\r\n </h1>\r\n <p className=\"text-muted-foreground mb-6\">\r\n {t(\r\n \"passwordResetDescription\",\r\n \"Your password has been reset successfully. You can now log in with your new password.\",\r\n )}\r\n </p>\r\n <Button asChild className=\"w-full\">\r\n <Link to=\"/login\">\r\n {t(\"goToLogin\", \"Go to Login\")}\r\n </Link>\r\n </Button>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n }\r\n\r\n // Invalid link state\r\n if (!code || !username) {\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardContent className=\"pt-8 pb-8 text-center\">\r\n <h1 className=\"text-2xl font-bold mb-2 text-red-600\">\r\n {t(\"invalidLinkTitle\", \"Invalid Reset Link\")}\r\n </h1>\r\n <p className=\"text-muted-foreground mb-6\">\r\n {t(\r\n \"invalidLinkDescription\",\r\n \"This password reset link is invalid or has expired. Please request a new one.\",\r\n )}\r\n </p>\r\n <Button\r\n onClick={() => navigate(\"/forgot-password\")}\r\n className=\"w-full mb-3\"\r\n >\r\n {t(\"requestNewLink\", \"Request New Link\")}\r\n </Button>\r\n <Link\r\n to=\"/login\"\r\n className=\"inline-flex items-center justify-center gap-1 text-sm text-muted-foreground hover:text-primary\"\r\n >\r\n <ArrowLeft className=\"w-4 h-4\" />\r\n {t(\"backToLogin\", \"Back to Login\")}\r\n </Link>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n }\r\n\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"text-center mb-12\">\r\n <h1 className=\"text-4xl font-bold text-foreground mb-4\">\r\n {t(\"title\", \"Reset Password\")}\r\n </h1>\r\n <div className=\"w-16 h-1 bg-primary mx-auto mb-6\"></div>\r\n <p className=\"text-lg text-muted-foreground max-w-xl mx-auto\">\r\n {t(\"subtitle\", \"Enter your new password below\")}\r\n </p>\r\n </div>\r\n\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <KeyRound className=\"w-5 h-5 text-primary\" />\r\n {t(\"resetPassword\", \"Reset Password\")}\r\n </CardTitle>\r\n <CardDescription>\r\n {t(\"subtitle\", \"Enter your new password below\")}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent>\r\n <form onSubmit={handleSubmit} className=\"space-y-6\">\r\n <div>\r\n <Label htmlFor=\"password\">\r\n {t(\"newPassword\", \"New Password\")} *\r\n </Label>\r\n <div className=\"relative\">\r\n <Input\r\n id=\"password\"\r\n type={showPassword ? \"text\" : \"password\"}\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n placeholder={t(\r\n \"newPasswordPlaceholder\",\r\n \"Enter new password\",\r\n )}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n minLength={8}\r\n disabled={isLoading}\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowPassword(!showPassword)}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\r\n >\r\n {showPassword ? (\r\n <EyeOff className=\"w-4 h-4\" />\r\n ) : (\r\n <Eye className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {t(\r\n \"passwordRequirements\",\r\n \"At least 8 characters, 1 letter and 1 number\",\r\n )}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <Label htmlFor=\"confirmPassword\">\r\n {t(\"confirmPassword\", \"Confirm Password\")} *\r\n </Label>\r\n <Input\r\n id=\"confirmPassword\"\r\n type={showPassword ? \"text\" : \"password\"}\r\n value={confirmPassword}\r\n onChange={(e) => setConfirmPassword(e.target.value)}\r\n placeholder={t(\r\n \"confirmPasswordPlaceholder\",\r\n \"Confirm new password\",\r\n )}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"new-password\"\r\n minLength={8}\r\n disabled={isLoading}\r\n />\r\n </div>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n size=\"lg\"\r\n className=\"w-full\"\r\n disabled={isLoading}\r\n >\r\n {isLoading ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"resetting\", \"Resetting...\")}\r\n </>\r\n ) : (\r\n t(\"resetPassword\", \"Reset Password\")\r\n )}\r\n </Button>\r\n\r\n <div className=\"text-center\">\r\n <Link\r\n to=\"/login\"\r\n className=\"text-sm text-muted-foreground hover:text-primary inline-flex items-center gap-1\"\r\n >\r\n <ArrowLeft className=\"w-4 h-4\" />\r\n {t(\"backToLogin\", \"Back to Login\")}\r\n </Link>\r\n </div>\r\n </form>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n}\r\n\r\nexport default ResetPasswordPage;\r\n"
26
+ "content": "import { useState } from \"react\";\r\nimport { Link, useNavigate, useSearchParams } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { Layout } from \"@/components/Layout\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport {\r\n Card,\r\n CardContent,\r\n CardHeader,\r\n CardTitle,\r\n CardDescription,\r\n} from \"@/components/ui/card\";\r\nimport { KeyRound, ArrowLeft, Eye, EyeOff, CheckCircle2 } from \"lucide-react\";\r\n\r\nexport function ResetPasswordPage() {\r\n const { t } = useTranslation(\"reset-password-page\");\r\n usePageTitle({ title: t(\"title\", \"Reset Password\") });\r\n const navigate = useNavigate();\r\n const [searchParams] = useSearchParams();\r\n const { resetPassword } = useAuth();\r\n\r\n const code = searchParams.get(\"code\") || \"\";\r\n const email = searchParams.get(\"email\") || \"\";\r\n\r\n const [password, setPassword] = useState(\"\");\r\n const [confirmPassword, setConfirmPassword] = useState(\"\");\r\n const [showPassword, setShowPassword] = useState(false);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [isSuccess, setIsSuccess] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n if (password !== confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n return;\r\n }\r\n\r\n if (!code || !email) {\r\n setError(\r\n t(\r\n \"invalidLink\",\r\n \"Invalid or expired reset link. Please request a new one.\",\r\n ),\r\n );\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n\r\n try {\r\n await resetPassword(email, code, password);\r\n setIsSuccess(true);\r\n toast.success(\r\n t(\"passwordResetSuccess\", \"Password reset successfully!\"),\r\n );\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\r\n \"resetPasswordError\",\r\n \"Failed to reset password. Please try again.\",\r\n ),\r\n );\r\n setError(errorMessage);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n // Success state\r\n if (isSuccess) {\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardContent className=\"pt-8 pb-8 text-center\">\r\n <CheckCircle2 className=\"w-16 h-16 text-green-500 mx-auto mb-4\" />\r\n <h1 className=\"text-2xl font-bold mb-2\">\r\n {t(\"passwordReset\", \"Password Reset!\")}\r\n </h1>\r\n <p className=\"text-muted-foreground mb-6\">\r\n {t(\r\n \"passwordResetDescription\",\r\n \"Your password has been reset successfully. You can now log in with your new password.\",\r\n )}\r\n </p>\r\n <Button asChild className=\"w-full\">\r\n <Link to=\"/login\">\r\n {t(\"goToLogin\", \"Go to Login\")}\r\n </Link>\r\n </Button>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n }\r\n\r\n // Invalid link state\r\n if (!code || !email) {\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardContent className=\"pt-8 pb-8 text-center\">\r\n <h1 className=\"text-2xl font-bold mb-2 text-red-600\">\r\n {t(\"invalidLinkTitle\", \"Invalid Reset Link\")}\r\n </h1>\r\n <p className=\"text-muted-foreground mb-6\">\r\n {t(\r\n \"invalidLinkDescription\",\r\n \"This password reset link is invalid or has expired. Please request a new one.\",\r\n )}\r\n </p>\r\n <Button\r\n onClick={() => navigate(\"/forgot-password\")}\r\n className=\"w-full mb-3\"\r\n >\r\n {t(\"requestNewLink\", \"Request New Link\")}\r\n </Button>\r\n <Link\r\n to=\"/login\"\r\n className=\"inline-flex items-center justify-center gap-1 text-sm text-muted-foreground hover:text-primary\"\r\n >\r\n <ArrowLeft className=\"w-4 h-4\" />\r\n {t(\"backToLogin\", \"Back to Login\")}\r\n </Link>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n }\r\n\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"text-center mb-12\">\r\n <h1 className=\"text-4xl font-bold text-foreground mb-4\">\r\n {t(\"title\", \"Reset Password\")}\r\n </h1>\r\n <div className=\"w-16 h-1 bg-primary mx-auto mb-6\"></div>\r\n <p className=\"text-lg text-muted-foreground max-w-xl mx-auto\">\r\n {t(\"subtitle\", \"Enter your new password below\")}\r\n </p>\r\n </div>\r\n\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <KeyRound className=\"w-5 h-5 text-primary\" />\r\n {t(\"resetPassword\", \"Reset Password\")}\r\n </CardTitle>\r\n <CardDescription>\r\n {t(\"subtitle\", \"Enter your new password below\")}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent>\r\n <form onSubmit={handleSubmit} className=\"space-y-6\">\r\n <div>\r\n <Label htmlFor=\"password\">\r\n {t(\"newPassword\", \"New Password\")} *\r\n </Label>\r\n <div className=\"relative\">\r\n <Input\r\n id=\"password\"\r\n type={showPassword ? \"text\" : \"password\"}\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n placeholder={t(\r\n \"newPasswordPlaceholder\",\r\n \"Enter new password\",\r\n )}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n minLength={8}\r\n disabled={isLoading}\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowPassword(!showPassword)}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\r\n >\r\n {showPassword ? (\r\n <EyeOff className=\"w-4 h-4\" />\r\n ) : (\r\n <Eye className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {t(\r\n \"passwordRequirements\",\r\n \"At least 8 characters, 1 letter and 1 number\",\r\n )}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <Label htmlFor=\"confirmPassword\">\r\n {t(\"confirmPassword\", \"Confirm Password\")} *\r\n </Label>\r\n <Input\r\n id=\"confirmPassword\"\r\n type={showPassword ? \"text\" : \"password\"}\r\n value={confirmPassword}\r\n onChange={(e) => setConfirmPassword(e.target.value)}\r\n placeholder={t(\r\n \"confirmPasswordPlaceholder\",\r\n \"Confirm new password\",\r\n )}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"new-password\"\r\n minLength={8}\r\n disabled={isLoading}\r\n />\r\n </div>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n size=\"lg\"\r\n className=\"w-full\"\r\n disabled={isLoading}\r\n >\r\n {isLoading ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"resetting\", \"Resetting...\")}\r\n </>\r\n ) : (\r\n t(\"resetPassword\", \"Reset Password\")\r\n )}\r\n </Button>\r\n\r\n <div className=\"text-center\">\r\n <Link\r\n to=\"/login\"\r\n className=\"text-sm text-muted-foreground hover:text-primary inline-flex items-center gap-1\"\r\n >\r\n <ArrowLeft className=\"w-4 h-4\" />\r\n {t(\"backToLogin\", \"Back to Login\")}\r\n </Link>\r\n </div>\r\n </form>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n}\r\n\r\nexport default ResetPasswordPage;\r\n"
27
27
  },
28
28
  {
29
29
  "path": "reset-password-page/lang/en.json",
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "verify-email-page",
3
+ "type": "registry:page",
4
+ "title": "Verify Email Page",
5
+ "description": "Email verification page with two-step flow: enter username to request code, then enter verification code. Uses useAuth hook from auth-core for API calls.",
6
+ "registryDependencies": [
7
+ "auth-core",
8
+ "api"
9
+ ],
10
+ "usage": "import VerifyEmailPage from '@/modules/verify-email-page';\n\n<VerifyEmailPage />\n\n• Installed at: src/modules/verify-email-page/\n• Customize text: src/modules/verify-email-page/lang/*.json\n• Uses useAuth() hook from auth-core:\n const { confirmEmail, resendCode } = useAuth();\n await resendCode(username);\n await confirmEmail(username, code);\n• Two-step flow: request code -> enter code to verify\n• Add to your router as a page component",
11
+ "route": {
12
+ "path": "/verify-email",
13
+ "componentName": "VerifyEmailPage"
14
+ },
15
+ "files": [
16
+ {
17
+ "path": "verify-email-page/index.ts",
18
+ "type": "registry:index",
19
+ "target": "$modules$/verify-email-page/index.ts",
20
+ "content": "export * from \"./verify-email-page\";\r\nexport { default } from \"./verify-email-page\";\r\n"
21
+ },
22
+ {
23
+ "path": "verify-email-page/verify-email-page.tsx",
24
+ "type": "registry:page",
25
+ "target": "$modules$/verify-email-page/verify-email-page.tsx",
26
+ "content": "import { useState } from \"react\";\r\nimport { Link } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { Layout } from \"@/components/Layout\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport {\r\n Card,\r\n CardContent,\r\n CardHeader,\r\n CardTitle,\r\n CardDescription,\r\n} from \"@/components/ui/card\";\r\nimport { MailCheck, ArrowLeft, CheckCircle2 } from \"lucide-react\";\r\nimport { FormField } from \"@/components/FormField\";\r\n\r\ntype Step = \"request\" | \"verify\" | \"success\";\r\n\r\nexport function VerifyEmailPage() {\r\n const { t } = useTranslation(\"verify-email-page\");\r\n usePageTitle({ title: t(\"title\", \"Verify Email\") });\r\n\r\n const { confirmEmail, resendCode } = useAuth();\r\n\r\n const [step, setStep] = useState<Step>(\"request\");\r\n const [username, setUsername] = useState(\"\");\r\n const [code, setCode] = useState(\"\");\r\n const [isSubmitting, setIsSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const handleSendCode = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setIsSubmitting(true);\r\n setError(null);\r\n\r\n try {\r\n await resendCode(username);\r\n toast.success(t(\"codeSentTitle\", \"Code Sent!\"), {\r\n description: t(\r\n \"codeSentDesc\",\r\n \"A verification code has been sent to your email.\",\r\n ),\r\n });\r\n setStep(\"verify\");\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"errorSendGeneric\", \"Failed to send verification code. Please try again.\"),\r\n );\r\n setError(errorMessage);\r\n toast.error(t(\"errorTitle\", \"Error\"), {\r\n description: errorMessage,\r\n });\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n const handleVerify = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setIsSubmitting(true);\r\n setError(null);\r\n\r\n try {\r\n await confirmEmail(username, code);\r\n toast.success(t(\"verifiedTitle\", \"Email Verified!\"), {\r\n description: t(\r\n \"verifiedDesc\",\r\n \"Your email has been successfully verified.\",\r\n ),\r\n });\r\n setStep(\"success\");\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"errorVerifyGeneric\", \"Failed to verify email. Please check your code and try again.\"),\r\n );\r\n setError(errorMessage);\r\n toast.error(t(\"errorTitle\", \"Error\"), {\r\n description: errorMessage,\r\n });\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n // Success step\r\n if (step === \"success\") {\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardContent className=\"pt-8 pb-8 text-center\">\r\n <CheckCircle2 className=\"w-16 h-16 text-green-500 mx-auto mb-4\" />\r\n <h1 className=\"text-2xl font-bold mb-2\">\r\n {t(\"successTitle\", \"Email Verified!\")}\r\n </h1>\r\n <p className=\"text-muted-foreground mb-6\">\r\n {t(\r\n \"successDescription\",\r\n \"Your email has been verified. You can now login to your account.\",\r\n )}\r\n </p>\r\n <Button asChild className=\"w-full\">\r\n <Link to=\"/login\">{t(\"goToLogin\", \"Go to Login\")}</Link>\r\n </Button>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n }\r\n\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n {/* Hero Section */}\r\n <div className=\"text-center mb-12\">\r\n <h1 className=\"text-4xl font-bold text-foreground mb-4\">\r\n {t(\"title\", \"Verify Email\")}\r\n </h1>\r\n <div className=\"w-16 h-1 bg-primary mx-auto mb-6\"></div>\r\n <p className=\"text-lg text-muted-foreground max-w-xl mx-auto\">\r\n {step === \"request\"\r\n ? t(\r\n \"descriptionRequest\",\r\n \"Enter your username and we'll send you a verification code.\",\r\n )\r\n : t(\r\n \"descriptionVerify\",\r\n \"Enter the verification code sent to your email.\",\r\n )}\r\n </p>\r\n </div>\r\n\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <MailCheck className=\"w-5 h-5 text-primary\" />\r\n {step === \"request\"\r\n ? t(\"cardTitleRequest\", \"Request Verification Code\")\r\n : t(\"cardTitleVerify\", \"Enter Verification Code\")}\r\n </CardTitle>\r\n <CardDescription>\r\n {step === \"request\"\r\n ? t(\"cardDescRequest\", \"Step 1 of 2: Request a verification code\")\r\n : t(\r\n \"cardDescVerify\",\r\n \"Step 2 of 2: Enter the code to verify your email\",\r\n )}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent>\r\n {step === \"request\" ? (\r\n // Step 1: Request Code\r\n <form onSubmit={handleSendCode} className=\"space-y-6\">\r\n <FormField label={t(\"username\", \"Username\")} htmlFor=\"username\" required>\r\n <Input\r\n id=\"username\"\r\n type=\"text\"\r\n value={username}\r\n onChange={(e) => setUsername(e.target.value)}\r\n placeholder={t(\"usernamePlaceholder\", \"Enter your username\")}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"username\"\r\n />\r\n </FormField>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n size=\"lg\"\r\n className=\"w-full\"\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"sending\", \"Sending...\")}\r\n </>\r\n ) : (\r\n t(\"sendCode\", \"Send Verification Code\")\r\n )}\r\n </Button>\r\n\r\n <div className=\"text-center\">\r\n <Link\r\n to=\"/login\"\r\n className=\"text-sm text-muted-foreground hover:text-primary inline-flex items-center gap-1\"\r\n >\r\n <ArrowLeft className=\"w-4 h-4\" />\r\n {t(\"backToLogin\", \"Back to Login\")}\r\n </Link>\r\n </div>\r\n </form>\r\n ) : (\r\n // Step 2: Verify Code\r\n <form onSubmit={handleVerify} className=\"space-y-6\">\r\n <div className=\"p-3 bg-muted rounded-lg text-sm\">\r\n <span className=\"text-muted-foreground\">\r\n {t(\"codeFor\", \"Verification code for:\")}{\" \"}\r\n </span>\r\n <span className=\"font-medium\">{username}</span>\r\n </div>\r\n <FormField label={t(\"code\", \"Verification Code\")} htmlFor=\"code\" required>\r\n <Input\r\n id=\"code\"\r\n type=\"text\"\r\n value={code}\r\n onChange={(e) => setCode(e.target.value)}\r\n placeholder={t(\"codePlaceholder\", \"Enter 6-digit code\")}\r\n required\r\n className=\"mt-1\"\r\n maxLength={6}\r\n />\r\n </FormField>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n size=\"lg\"\r\n className=\"w-full\"\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"verifying\", \"Verifying...\")}\r\n </>\r\n ) : (\r\n t(\"verifyEmail\", \"Verify Email\")\r\n )}\r\n </Button>\r\n\r\n <div className=\"flex justify-between\">\r\n <button\r\n type=\"button\"\r\n onClick={() => {\r\n setStep(\"request\");\r\n setCode(\"\");\r\n setError(null);\r\n }}\r\n className=\"text-sm text-muted-foreground hover:text-primary\"\r\n >\r\n {t(\"changeUsername\", \"Change username\")}\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={() =>\r\n handleSendCode({\r\n preventDefault: () => {},\r\n } as React.FormEvent)\r\n }\r\n className=\"text-sm text-primary hover:underline\"\r\n disabled={isSubmitting}\r\n >\r\n {t(\"resendCode\", \"Resend code\")}\r\n </button>\r\n </div>\r\n </form>\r\n )}\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n}\r\n\r\nexport default VerifyEmailPage;\r\n"
27
+ },
28
+ {
29
+ "path": "verify-email-page/lang/en.json",
30
+ "type": "registry:lang",
31
+ "target": "$modules$/verify-email-page/lang/en.json",
32
+ "content": "{\r\n \"title\": \"Verify Email\",\r\n \"descriptionRequest\": \"Enter your username and we'll send you a verification code.\",\r\n \"descriptionVerify\": \"Enter the verification code sent to your email.\",\r\n \"cardTitleRequest\": \"Request Verification Code\",\r\n \"cardTitleVerify\": \"Enter Verification Code\",\r\n \"cardDescRequest\": \"Step 1 of 2: Request a verification code\",\r\n \"cardDescVerify\": \"Step 2 of 2: Enter the code to verify your email\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"Enter your username\",\r\n \"code\": \"Verification Code\",\r\n \"codePlaceholder\": \"Enter 6-digit code\",\r\n \"sendCode\": \"Send Verification Code\",\r\n \"sending\": \"Sending...\",\r\n \"verifyEmail\": \"Verify Email\",\r\n \"verifying\": \"Verifying...\",\r\n \"codeSentTitle\": \"Code Sent!\",\r\n \"codeSentDesc\": \"A verification code has been sent to your email.\",\r\n \"verifiedTitle\": \"Email Verified!\",\r\n \"verifiedDesc\": \"Your email has been successfully verified.\",\r\n \"errorTitle\": \"Error\",\r\n \"errorSendGeneric\": \"Failed to send verification code. Please try again.\",\r\n \"errorVerifyGeneric\": \"Failed to verify email. Please check your code and try again.\",\r\n \"successTitle\": \"Email Verified!\",\r\n \"successDescription\": \"Your email has been verified. You can now login to your account.\",\r\n \"goToLogin\": \"Go to Login\",\r\n \"codeFor\": \"Verification code for:\",\r\n \"changeUsername\": \"Change username\",\r\n \"resendCode\": \"Resend code\",\r\n \"backToLogin\": \"Back to Login\"\r\n}\r\n"
33
+ },
34
+ {
35
+ "path": "verify-email-page/lang/tr.json",
36
+ "type": "registry:lang",
37
+ "target": "$modules$/verify-email-page/lang/tr.json",
38
+ "content": "{\r\n \"title\": \"E-posta Doğrulama\",\r\n \"descriptionRequest\": \"Kullanıcı adınızı girin, size bir doğrulama kodu göndereceğiz.\",\r\n \"descriptionVerify\": \"E-postanıza gönderilen doğrulama kodunu girin.\",\r\n \"cardTitleRequest\": \"Doğrulama Kodu İste\",\r\n \"cardTitleVerify\": \"Doğrulama Kodunu Gir\",\r\n \"cardDescRequest\": \"Adım 1/2: Doğrulama kodu isteyin\",\r\n \"cardDescVerify\": \"Adım 2/2: E-postanızı doğrulamak için kodu girin\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"Kullanıcı adınızı girin\",\r\n \"code\": \"Doğrulama Kodu\",\r\n \"codePlaceholder\": \"6 haneli kodu girin\",\r\n \"sendCode\": \"Doğrulama Kodu Gönder\",\r\n \"sending\": \"Gönderiliyor...\",\r\n \"verifyEmail\": \"E-postayı Doğrula\",\r\n \"verifying\": \"Doğrulanıyor...\",\r\n \"codeSentTitle\": \"Kod Gönderildi!\",\r\n \"codeSentDesc\": \"E-posta adresinize bir doğrulama kodu gönderildi.\",\r\n \"verifiedTitle\": \"E-posta Doğrulandı!\",\r\n \"verifiedDesc\": \"E-postanız başarıyla doğrulandı.\",\r\n \"errorTitle\": \"Hata\",\r\n \"errorSendGeneric\": \"Doğrulama kodu gönderilemedi. Lütfen tekrar deneyin.\",\r\n \"errorVerifyGeneric\": \"E-posta doğrulanamadı. Lütfen kodunuzu kontrol edip tekrar deneyin.\",\r\n \"successTitle\": \"E-posta Doğrulandı!\",\r\n \"successDescription\": \"E-postanız doğrulandı. Artık hesabınıza giriş yapabilirsiniz.\",\r\n \"goToLogin\": \"Girişe Git\",\r\n \"codeFor\": \"Doğrulama kodu:\",\r\n \"changeUsername\": \"Kullanıcı adını değiştir\",\r\n \"resendCode\": \"Kodu tekrar gönder\",\r\n \"backToLogin\": \"Girişe Dön\"\r\n}\r\n"
39
+ }
40
+ ],
41
+ "exports": {
42
+ "types": [],
43
+ "variables": [
44
+ "VerifyEmailPage",
45
+ "default"
46
+ ]
47
+ }
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promakeai/cli",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "promake": "dist/index.js"
package/template/.env CHANGED
@@ -1,7 +1,6 @@
1
- VITE_API_PAYMENT="https://payment.promake.ai/api/v1"
2
- VITE_TENANT_UUID="YWJjeHl6MTIzT0dVWkNBTg"
1
+ VITE_TENANT_UUID=""
3
2
  VITE_MAIL_SERVICE_URL="https://mail.promake.ai/api/v1/send-mail"
4
- VITE_TENANT_MAIL="uc.erkut@gmail.com"
3
+ VITE_TENANT_MAIL=""
5
4
  VITE_ONLINE_PAYMENT_METHODS="stripe,iyzico"
6
5
  VITE_AVAILABLE_PAYMENT_METHODS="card,transfer,cash"
7
6
  VITE_PROMAKE_ENV="testb"
package/template/bun.lock CHANGED
@@ -5,8 +5,9 @@
5
5
  "name": "new",
6
6
  "dependencies": {
7
7
  "@hookform/resolvers": "^5.2.2",
8
- "@promakeai/customer-backend-client": "^1.1.0",
9
- "@promakeai/inspector": "^1.5.1",
8
+ "@promakeai/customer-backend-client": "^1.2.0",
9
+ "@promakeai/dbreact": "^1.1.1",
10
+ "@promakeai/inspector": "^1.7.4",
10
11
  "@radix-ui/react-accordion": "^1.2.12",
11
12
  "@radix-ui/react-alert-dialog": "^1.1.15",
12
13
  "@radix-ui/react-aspect-ratio": "^1.1.8",
@@ -228,11 +229,15 @@
228
229
 
229
230
  "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
230
231
 
231
- "@promakeai/customer-backend-client": ["@promakeai/customer-backend-client@1.1.0", "", { "dependencies": { "axios": "^1.7.0", "zod": "^4.1.13" }, "peerDependencies": { "@tanstack/react-query": ">=5.0.0", "react": ">=18.0.0" }, "optionalPeers": ["@tanstack/react-query", "react"] }, "sha512-Ql56YtwRQyJ9toFyfSkkn0deAdlVodNdK7d2xd9nVVAS7C2F8fxIuJ3xCtWtdLfXjponHhG2qdy9ILq8V4fpbA=="],
232
+ "@promakeai/customer-backend-client": ["@promakeai/customer-backend-client@1.2.0", "", { "dependencies": { "axios": "^1.7.0", "zod": "^4.1.13" }, "peerDependencies": { "@tanstack/react-query": ">=5.0.0", "react": ">=18.0.0" }, "optionalPeers": ["@tanstack/react-query", "react"] }, "sha512-w8uk1abno9W+HeYs0DXOCpGSO4kbdWCLkPNHy53j25qXCLk5xAnqE6wRio9BaADk5hkRC+Ghs428sce1AXWOgA=="],
232
233
 
233
- "@promakeai/inspector": ["@promakeai/inspector@1.5.1", "", { "dependencies": { "@promakeai/inspector-types": "1.5.1", "clsx": "^2.1.1", "lodash": "^4.17.21", "lucide-react": "^0.554.0", "react-colorful": "^5.6.1", "vite-plugin-component-debugger": "^2.2.0", "zustand": "^5.0.8" }, "peerDependencies": { "react": ">=18.0.0", "vite": ">=5.0.0" }, "optionalPeers": ["vite"] }, "sha512-sKclusU4D9xsTJZZ629cFFq2GXyD2l/aOKQdQ7qq4eNfYW85nmoS+D4aQ9M88LcNngO+uFmLCUBnpZHwamYS/A=="],
234
+ "@promakeai/dbreact": ["@promakeai/dbreact@1.1.1", "", { "dependencies": { "@promakeai/orm": "1.3.0" }, "peerDependencies": { "@tanstack/react-query": ">=5.0.0", "react": ">=19.0.0", "react-dom": ">=19.0.0", "sql.js": ">=1.11.0" } }, "sha512-xlnebJzy7u9ABLbJlAQ/p6arIfAFj4DbNvKWswD5PP4aEESoaBrLLk/QL/O3BXsyzLAB3GuzsMyuGkevrCybdw=="],
234
235
 
235
- "@promakeai/inspector-types": ["@promakeai/inspector-types@1.5.1", "", {}, "sha512-35xVpUTLWJ7Zf1VQZNPmg84+nSce9IX2FvB5Lwikp3EEKb4IONnxfECtBIsqjCM3EH7BvHuirZtbcp4/L1AjuA=="],
236
+ "@promakeai/inspector": ["@promakeai/inspector@1.7.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@promakeai/inspector-types": "1.7.5", "clsx": "^2.1.1", "estree-walker": "^3.0.3", "lodash": "^4.17.21", "lucide-react": "^0.554.0", "magic-string": "^0.30.21", "react-colorful": "^5.6.1", "vite-plugin-component-debugger": "^2.2.0", "zustand": "^5.0.8" }, "peerDependencies": { "react": ">=18.0.0", "vite": ">=5.0.0" }, "optionalPeers": ["vite"] }, "sha512-dudt8Yuyxrvudatr1T61qY8f0UT8klcGphnpaLbZ98sZTuth+m9X3CePz/bgf6judDCtcX4zFzjI+8e7+ryukw=="],
237
+
238
+ "@promakeai/inspector-types": ["@promakeai/inspector-types@1.7.5", "", {}, "sha512-4swpzEDymv0abrVN0KrbdtSss0OAVPzCzd7MOivSLFLlLQuKmsbyxFJkKY1qTQYCNjEjkhpnWuRsayK21I23qA=="],
239
+
240
+ "@promakeai/orm": ["@promakeai/orm@1.3.0", "", {}, "sha512-4V6/w8/M6H63tmsENYFdsX51NqbRpPyFvUSRY/U8xtp9dSq+ch7GubQBS+U7m43gW8ap7x8DX/fYoWdimgDz7g=="],
236
241
 
237
242
  "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
238
243