@digilogiclabs/create-saas-app 2.10.0 → 2.12.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.
- package/CHANGELOG.md +6 -0
- package/README.md +153 -113
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli/commands/create.d.ts.map +1 -1
- package/dist/cli/commands/create.js +2 -6
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/generators/template-generator.d.ts.map +1 -1
- package/dist/generators/template-generator.js +15 -8
- package/dist/generators/template-generator.js.map +1 -1
- package/dist/templates/shared/admin/web/src/components/admin-nav.tsx +3 -3
- package/dist/templates/shared/auth/supabase/web/src/lib/auth-session.ts +36 -16
- package/dist/templates/shared/auth/supabase/web/src/middleware.ts +6 -0
- package/dist/templates/shared/cookie-consent/web/components/cookie-consent.tsx +5 -5
- package/dist/templates/shared/design/web/src/components/ui/button.tsx +56 -0
- package/dist/templates/shared/email/web/src/lib/email/client.ts +1 -1
- package/dist/templates/shared/error-pages/web/src/app/error.tsx +13 -11
- package/dist/templates/shared/error-pages/web/src/app/global-error.tsx +2 -0
- package/dist/templates/shared/error-pages/web/src/app/not-found.tsx +6 -6
- package/dist/templates/shared/legal/web/src/app/(legal)/privacy/page.tsx +4 -4
- package/dist/templates/shared/legal/web/src/app/(legal)/terms/page.tsx +4 -4
- package/dist/templates/shared/loading/web/components/skeleton.tsx +4 -4
- package/dist/templates/shared/mock/web/.env.local +55 -0
- package/dist/templates/shared/mock/web/src/components/mock-auth-provider.tsx +72 -0
- package/dist/templates/shared/mock/web/src/components/mock-banner.tsx +29 -0
- package/dist/templates/shared/mock/web/src/lib/mock.ts +147 -0
- package/dist/templates/shared/payments/web/src/app/api/webhooks/stripe/route.ts +10 -4
- package/dist/templates/shared/redis/web/src/lib/redis.ts +1 -1
- package/dist/templates/web/ai-platform/template/src/app/api/auth/route.ts +57 -0
- package/dist/templates/web/ai-platform/template/src/app/login/page.tsx +112 -0
- package/dist/templates/web/ai-platform/template/src/app/models/page.tsx +186 -0
- package/dist/templates/web/ai-platform/template/src/app/playground/page.tsx +251 -0
- package/dist/templates/web/ai-platform/template/src/app/settings/page.tsx +190 -0
- package/dist/templates/web/ai-platform/template/src/app/signup/page.tsx +133 -0
- package/dist/templates/web/ai-platform/template/src/lib/auth-session.ts +52 -0
- package/dist/templates/web/base/template/eslint.config.mjs +14 -0
- package/dist/templates/web/base/template/src/app/auth/callback/route.ts +1 -1
- package/dist/templates/web/base/template/src/app/checkout/page.tsx +76 -103
- package/dist/templates/web/base/template/src/app/dashboard/page.tsx +145 -329
- package/dist/templates/web/base/template/src/app/layout.tsx +40 -38
- package/dist/templates/web/base/template/src/app/login/page.tsx +116 -66
- package/dist/templates/web/base/template/src/app/page.tsx +97 -193
- package/dist/templates/web/base/template/src/app/settings/page.tsx +154 -0
- package/dist/templates/web/base/template/src/app/signup/page.tsx +117 -66
- package/dist/templates/web/base/template/src/components/providers/app-providers.tsx +8 -3
- package/dist/templates/web/base/template/src/components/shared/header.tsx +229 -63
- package/dist/templates/web/iot-dashboard/template/src/app/alerts/page.tsx +157 -0
- package/dist/templates/web/iot-dashboard/template/src/app/api/auth/route.ts +57 -0
- package/dist/templates/web/iot-dashboard/template/src/app/devices/[id]/page.tsx +204 -0
- package/dist/templates/web/iot-dashboard/template/src/app/devices/new/page.tsx +139 -0
- package/dist/templates/web/iot-dashboard/template/src/app/devices/page.tsx +171 -0
- package/dist/templates/web/iot-dashboard/template/src/app/login/page.tsx +112 -0
- package/dist/templates/web/iot-dashboard/template/src/app/settings/page.tsx +186 -0
- package/dist/templates/web/iot-dashboard/template/src/app/signup/page.tsx +133 -0
- package/dist/templates/web/iot-dashboard/template/src/lib/auth-session.ts +52 -0
- package/dist/templates/web/marketplace/template/src/app/api/auth/route.ts +57 -0
- package/dist/templates/web/marketplace/template/src/app/login/page.tsx +112 -0
- package/dist/templates/web/marketplace/template/src/app/orders/page.tsx +160 -0
- package/dist/templates/web/marketplace/template/src/app/products/[id]/page.tsx +218 -0
- package/dist/templates/web/marketplace/template/src/app/settings/page.tsx +150 -0
- package/dist/templates/web/marketplace/template/src/app/signup/page.tsx +133 -0
- package/dist/templates/web/marketplace/template/src/lib/auth-session.ts +52 -0
- package/dist/templates/web/micro-saas/template/src/app/api/auth/route.ts +57 -0
- package/dist/templates/web/micro-saas/template/src/app/login/page.tsx +14 -3
- package/dist/templates/web/micro-saas/template/src/app/signup/page.tsx +15 -4
- package/dist/templates/web/micro-saas/template/src/lib/auth-session.ts +52 -0
- package/dist/templates/web/ui-auth/template/eslint.config.mjs +14 -0
- package/dist/templates/web/ui-auth/template/src/app/checkout/page.tsx +3 -3
- package/dist/templates/web/ui-auth/template/src/app/dev-setup/page.tsx +81 -91
- package/dist/templates/web/ui-auth/template/src/app/layout.tsx +38 -36
- package/dist/templates/web/ui-auth/template/src/app/login/page.tsx +22 -45
- package/dist/templates/web/ui-auth/template/src/app/page.tsx +106 -306
- package/dist/templates/web/ui-auth/template/src/app/setup/page.tsx +387 -402
- package/dist/templates/web/ui-auth/template/src/app/signup/page.tsx +24 -47
- package/dist/templates/web/ui-auth/template/src/components/providers/app-providers.tsx +8 -3
- package/dist/templates/web/ui-auth/template/src/components/shared/header.tsx +229 -94
- package/dist/templates/web/ui-auth-ai/template/src/app/layout.tsx +38 -45
- package/dist/templates/web/ui-auth-ai/template/src/app/login/page.tsx +86 -0
- package/dist/templates/web/ui-auth-ai/template/src/app/page.tsx +107 -193
- package/dist/templates/web/ui-auth-ai/template/src/app/signup/page.tsx +105 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/ai/audio-generator.tsx +144 -140
- package/dist/templates/web/ui-auth-ai/template/src/components/ai/video-generator.tsx +156 -157
- package/dist/templates/web/ui-auth-ai/template/src/components/auth/login-form.tsx +7 -3
- package/dist/templates/web/ui-auth-ai/template/src/components/providers/app-providers.tsx +25 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/shared/footer.tsx +36 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/shared/header.tsx +228 -0
- package/dist/templates/web/ui-auth-ai/template/src/components/ui/button.tsx +5 -5
- package/dist/templates/web/ui-auth-ai/template/src/components/ui/input.tsx +1 -1
- package/dist/templates/web/ui-auth-ai/template/src/components/ui/select.tsx +1 -1
- package/dist/templates/web/ui-auth-ai/template/src/components/ui/textarea.tsx +1 -1
- package/dist/templates/web/ui-auth-ai/template/src/components/ui/theme-toggle.tsx +34 -0
- package/dist/templates/web/ui-auth-ai/template/src/lib/supabase.ts +6 -4
- package/dist/templates/web/ui-auth-ai/template/src/providers/auth-provider.tsx +7 -5
- package/dist/templates/web/ui-auth-payments/template/src/app/billing/page.tsx +63 -192
- package/dist/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +104 -296
- package/dist/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +27 -27
- package/dist/templates/web/ui-auth-payments/template/src/app/dev-setup/page.tsx +70 -81
- package/dist/templates/web/ui-auth-payments/template/src/app/layout.tsx +38 -36
- package/dist/templates/web/ui-auth-payments/template/src/app/login/loading.tsx +9 -9
- package/dist/templates/web/ui-auth-payments/template/src/app/login/page.tsx +4 -104
- package/dist/templates/web/ui-auth-payments/template/src/app/page.tsx +69 -337
- package/dist/templates/web/ui-auth-payments/template/src/app/setup/page.tsx +55 -68
- package/dist/templates/web/ui-auth-payments/template/src/app/signup/loading.tsx +13 -13
- package/dist/templates/web/ui-auth-payments/template/src/app/signup/page.tsx +4 -123
- package/dist/templates/web/ui-auth-payments/template/src/components/client/auth-status.tsx +37 -52
- package/dist/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +49 -103
- package/dist/templates/web/ui-auth-payments/template/src/components/client/newsletter-signup.tsx +4 -4
- package/dist/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +60 -140
- package/dist/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +25 -28
- package/dist/templates/web/ui-auth-payments/template/src/components/shared/header.tsx +229 -230
- package/dist/templates/web/ui-auth-payments/template/src/lib/actions/auth.ts +245 -245
- package/dist/templates/web/ui-auth-payments/template/src/lib/actions/index.ts +339 -339
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/ai/page.tsx +305 -309
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +62 -312
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/checkout/page.tsx +109 -125
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +27 -27
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/dev-setup/page.tsx +68 -83
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/layout.tsx +40 -38
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +20 -20
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/page.tsx +140 -394
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +28 -27
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/setup/page.tsx +51 -66
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/auth-status.tsx +37 -52
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +50 -79
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +58 -111
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/providers/app-providers.tsx +8 -3
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/shared/header.tsx +229 -252
- package/dist/templates/web/ui-auth-payments-ai/template/src/lib/actions/auth.ts +245 -245
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/billing/page.tsx +63 -192
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/checkout/page.tsx +109 -125
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +27 -27
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/layout.tsx +40 -38
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +122 -385
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/setup/page.tsx +340 -344
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/auth-status.tsx +37 -52
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/login-form.tsx +49 -103
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/client/signup-form.tsx +60 -140
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/providers/app-providers.tsx +8 -3
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +229 -252
- package/dist/templates/web/ui-auth-payments-audio/template/src/lib/actions/auth.ts +3 -3
- package/dist/templates/web/ui-auth-payments-video/template/src/app/billing/page.tsx +63 -192
- package/dist/templates/web/ui-auth-payments-video/template/src/app/checkout/page.tsx +109 -125
- package/dist/templates/web/ui-auth-payments-video/template/src/app/layout.tsx +38 -36
- package/dist/templates/web/ui-auth-payments-video/template/src/app/login/page.tsx +9 -109
- package/dist/templates/web/ui-auth-payments-video/template/src/app/page.tsx +132 -392
- package/dist/templates/web/ui-auth-payments-video/template/src/app/setup/page.tsx +346 -350
- package/dist/templates/web/ui-auth-payments-video/template/src/app/signup/page.tsx +9 -128
- package/dist/templates/web/ui-auth-payments-video/template/src/components/client/login-form.tsx +90 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/components/client/signup-form.tsx +105 -0
- package/dist/templates/web/ui-auth-payments-video/template/src/components/providers/app-providers.tsx +8 -3
- package/dist/templates/web/ui-auth-payments-video/template/src/components/shared/header.tsx +229 -246
- package/dist/templates/web/ui-only/template/eslint.config.mjs +14 -0
- package/dist/templates/web/ui-only/template/src/app/checkout/page.tsx +2 -2
- package/dist/templates/web/ui-only/template/src/app/login/page.tsx +69 -63
- package/dist/templates/web/ui-only/template/src/app/page.tsx +69 -91
- package/dist/templates/web/ui-only/template/src/app/signup/page.tsx +94 -79
- package/dist/templates/web/ui-only/template/src/components/providers/app-providers.tsx +1 -6
- package/dist/templates/web/ui-only/template/src/components/shared/header.tsx +90 -53
- package/dist/templates/web/ui-package-test/template/package.json +19 -23
- package/dist/templates/web/ui-package-test/template/postcss.config.mjs +8 -0
- package/dist/templates/web/ui-package-test/template/src/app/globals.css +88 -0
- package/dist/templates/web/ui-package-test/template/src/app/layout.tsx +27 -0
- package/dist/templates/web/ui-package-test/template/src/app/page.tsx +46 -106
- package/package.json +1 -1
- package/src/templates/shared/admin/web/src/components/admin-nav.tsx +3 -3
- package/src/templates/shared/auth/supabase/web/src/lib/auth-session.ts +36 -16
- package/src/templates/shared/auth/supabase/web/src/middleware.ts +6 -0
- package/src/templates/shared/cookie-consent/web/components/cookie-consent.tsx +5 -5
- package/src/templates/shared/design/web/src/components/ui/button.tsx +56 -0
- package/src/templates/shared/email/web/src/lib/email/client.ts +1 -1
- package/src/templates/shared/error-pages/web/src/app/error.tsx +13 -11
- package/src/templates/shared/error-pages/web/src/app/global-error.tsx +2 -0
- package/src/templates/shared/error-pages/web/src/app/not-found.tsx +6 -6
- package/src/templates/shared/legal/web/src/app/(legal)/privacy/page.tsx +4 -4
- package/src/templates/shared/legal/web/src/app/(legal)/terms/page.tsx +4 -4
- package/src/templates/shared/loading/web/components/skeleton.tsx +4 -4
- package/src/templates/shared/mock/web/.env.local +55 -0
- package/src/templates/shared/mock/web/src/components/mock-auth-provider.tsx +72 -0
- package/src/templates/shared/mock/web/src/components/mock-banner.tsx +29 -0
- package/src/templates/shared/mock/web/src/lib/mock.ts +147 -0
- package/src/templates/shared/payments/web/src/app/api/webhooks/stripe/route.ts +10 -4
- package/src/templates/shared/redis/web/src/lib/redis.ts +1 -1
- package/src/templates/web/ai-platform/template/src/app/api/auth/route.ts +57 -0
- package/src/templates/web/ai-platform/template/src/app/login/page.tsx +112 -0
- package/src/templates/web/ai-platform/template/src/app/models/page.tsx +186 -0
- package/src/templates/web/ai-platform/template/src/app/playground/page.tsx +251 -0
- package/src/templates/web/ai-platform/template/src/app/settings/page.tsx +190 -0
- package/src/templates/web/ai-platform/template/src/app/signup/page.tsx +133 -0
- package/src/templates/web/ai-platform/template/src/lib/auth-session.ts +52 -0
- package/src/templates/web/base/template/eslint.config.mjs +14 -0
- package/src/templates/web/base/template/src/app/auth/callback/route.ts +1 -1
- package/src/templates/web/base/template/src/app/checkout/page.tsx +76 -103
- package/src/templates/web/base/template/src/app/dashboard/page.tsx +145 -329
- package/src/templates/web/base/template/src/app/layout.tsx +40 -38
- package/src/templates/web/base/template/src/app/login/page.tsx +116 -66
- package/src/templates/web/base/template/src/app/page.tsx +97 -193
- package/src/templates/web/base/template/src/app/settings/page.tsx +154 -0
- package/src/templates/web/base/template/src/app/signup/page.tsx +117 -66
- package/src/templates/web/base/template/src/components/providers/app-providers.tsx +8 -3
- package/src/templates/web/base/template/src/components/shared/header.tsx +229 -63
- package/src/templates/web/iot-dashboard/template/src/app/alerts/page.tsx +157 -0
- package/src/templates/web/iot-dashboard/template/src/app/api/auth/route.ts +57 -0
- package/src/templates/web/iot-dashboard/template/src/app/devices/[id]/page.tsx +204 -0
- package/src/templates/web/iot-dashboard/template/src/app/devices/new/page.tsx +139 -0
- package/src/templates/web/iot-dashboard/template/src/app/devices/page.tsx +171 -0
- package/src/templates/web/iot-dashboard/template/src/app/login/page.tsx +112 -0
- package/src/templates/web/iot-dashboard/template/src/app/settings/page.tsx +186 -0
- package/src/templates/web/iot-dashboard/template/src/app/signup/page.tsx +133 -0
- package/src/templates/web/iot-dashboard/template/src/lib/auth-session.ts +52 -0
- package/src/templates/web/marketplace/template/src/app/api/auth/route.ts +57 -0
- package/src/templates/web/marketplace/template/src/app/login/page.tsx +112 -0
- package/src/templates/web/marketplace/template/src/app/orders/page.tsx +160 -0
- package/src/templates/web/marketplace/template/src/app/products/[id]/page.tsx +218 -0
- package/src/templates/web/marketplace/template/src/app/settings/page.tsx +150 -0
- package/src/templates/web/marketplace/template/src/app/signup/page.tsx +133 -0
- package/src/templates/web/marketplace/template/src/lib/auth-session.ts +52 -0
- package/src/templates/web/micro-saas/template/src/app/api/auth/route.ts +57 -0
- package/src/templates/web/micro-saas/template/src/app/login/page.tsx +14 -3
- package/src/templates/web/micro-saas/template/src/app/signup/page.tsx +15 -4
- package/src/templates/web/micro-saas/template/src/lib/auth-session.ts +52 -0
- package/src/templates/web/ui-auth/template/eslint.config.mjs +14 -0
- package/src/templates/web/ui-auth/template/src/app/checkout/page.tsx +3 -3
- package/src/templates/web/ui-auth/template/src/app/dev-setup/page.tsx +81 -91
- package/src/templates/web/ui-auth/template/src/app/layout.tsx +38 -36
- package/src/templates/web/ui-auth/template/src/app/login/page.tsx +22 -45
- package/src/templates/web/ui-auth/template/src/app/page.tsx +106 -306
- package/src/templates/web/ui-auth/template/src/app/setup/page.tsx +387 -402
- package/src/templates/web/ui-auth/template/src/app/signup/page.tsx +24 -47
- package/src/templates/web/ui-auth/template/src/components/providers/app-providers.tsx +8 -3
- package/src/templates/web/ui-auth/template/src/components/shared/header.tsx +229 -94
- package/src/templates/web/ui-auth-ai/template/src/app/layout.tsx +38 -45
- package/src/templates/web/ui-auth-ai/template/src/app/login/page.tsx +86 -0
- package/src/templates/web/ui-auth-ai/template/src/app/page.tsx +107 -193
- package/src/templates/web/ui-auth-ai/template/src/app/signup/page.tsx +105 -0
- package/src/templates/web/ui-auth-ai/template/src/components/ai/audio-generator.tsx +144 -140
- package/src/templates/web/ui-auth-ai/template/src/components/ai/video-generator.tsx +156 -157
- package/src/templates/web/ui-auth-ai/template/src/components/auth/login-form.tsx +7 -3
- package/src/templates/web/ui-auth-ai/template/src/components/providers/app-providers.tsx +25 -0
- package/src/templates/web/ui-auth-ai/template/src/components/shared/footer.tsx +36 -0
- package/src/templates/web/ui-auth-ai/template/src/components/shared/header.tsx +228 -0
- package/src/templates/web/ui-auth-ai/template/src/components/ui/button.tsx +5 -5
- package/src/templates/web/ui-auth-ai/template/src/components/ui/input.tsx +1 -1
- package/src/templates/web/ui-auth-ai/template/src/components/ui/select.tsx +1 -1
- package/src/templates/web/ui-auth-ai/template/src/components/ui/textarea.tsx +1 -1
- package/src/templates/web/ui-auth-ai/template/src/components/ui/theme-toggle.tsx +34 -0
- package/src/templates/web/ui-auth-ai/template/src/lib/supabase.ts +6 -4
- package/src/templates/web/ui-auth-ai/template/src/providers/auth-provider.tsx +7 -5
- package/src/templates/web/ui-auth-payments/template/src/app/billing/page.tsx +63 -192
- package/src/templates/web/ui-auth-payments/template/src/app/checkout/page.tsx +104 -296
- package/src/templates/web/ui-auth-payments/template/src/app/dashboard/page.tsx +27 -27
- package/src/templates/web/ui-auth-payments/template/src/app/dev-setup/page.tsx +70 -81
- package/src/templates/web/ui-auth-payments/template/src/app/layout.tsx +38 -36
- package/src/templates/web/ui-auth-payments/template/src/app/login/loading.tsx +9 -9
- package/src/templates/web/ui-auth-payments/template/src/app/login/page.tsx +4 -104
- package/src/templates/web/ui-auth-payments/template/src/app/page.tsx +69 -337
- package/src/templates/web/ui-auth-payments/template/src/app/setup/page.tsx +55 -68
- package/src/templates/web/ui-auth-payments/template/src/app/signup/loading.tsx +13 -13
- package/src/templates/web/ui-auth-payments/template/src/app/signup/page.tsx +4 -123
- package/src/templates/web/ui-auth-payments/template/src/components/client/auth-status.tsx +37 -52
- package/src/templates/web/ui-auth-payments/template/src/components/client/login-form.tsx +49 -103
- package/src/templates/web/ui-auth-payments/template/src/components/client/newsletter-signup.tsx +4 -4
- package/src/templates/web/ui-auth-payments/template/src/components/client/signup-form.tsx +60 -140
- package/src/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +25 -28
- package/src/templates/web/ui-auth-payments/template/src/components/shared/header.tsx +229 -230
- package/src/templates/web/ui-auth-payments/template/src/lib/actions/auth.ts +245 -245
- package/src/templates/web/ui-auth-payments/template/src/lib/actions/index.ts +339 -339
- package/src/templates/web/ui-auth-payments-ai/template/src/app/ai/page.tsx +305 -309
- package/src/templates/web/ui-auth-payments-ai/template/src/app/billing/page.tsx +62 -312
- package/src/templates/web/ui-auth-payments-ai/template/src/app/checkout/page.tsx +109 -125
- package/src/templates/web/ui-auth-payments-ai/template/src/app/dashboard/page.tsx +27 -27
- package/src/templates/web/ui-auth-payments-ai/template/src/app/dev-setup/page.tsx +68 -83
- package/src/templates/web/ui-auth-payments-ai/template/src/app/layout.tsx +40 -38
- package/src/templates/web/ui-auth-payments-ai/template/src/app/onboarding/page.tsx +20 -20
- package/src/templates/web/ui-auth-payments-ai/template/src/app/page.tsx +140 -394
- package/src/templates/web/ui-auth-payments-ai/template/src/app/settings/page.tsx +28 -27
- package/src/templates/web/ui-auth-payments-ai/template/src/app/setup/page.tsx +51 -66
- package/src/templates/web/ui-auth-payments-ai/template/src/components/client/auth-status.tsx +37 -52
- package/src/templates/web/ui-auth-payments-ai/template/src/components/client/login-form.tsx +50 -79
- package/src/templates/web/ui-auth-payments-ai/template/src/components/client/signup-form.tsx +58 -111
- package/src/templates/web/ui-auth-payments-ai/template/src/components/providers/app-providers.tsx +8 -3
- package/src/templates/web/ui-auth-payments-ai/template/src/components/shared/header.tsx +229 -252
- package/src/templates/web/ui-auth-payments-ai/template/src/lib/actions/auth.ts +245 -245
- package/src/templates/web/ui-auth-payments-audio/template/src/app/billing/page.tsx +63 -192
- package/src/templates/web/ui-auth-payments-audio/template/src/app/checkout/page.tsx +109 -125
- package/src/templates/web/ui-auth-payments-audio/template/src/app/dashboard/page.tsx +27 -27
- package/src/templates/web/ui-auth-payments-audio/template/src/app/layout.tsx +40 -38
- package/src/templates/web/ui-auth-payments-audio/template/src/app/page.tsx +122 -385
- package/src/templates/web/ui-auth-payments-audio/template/src/app/setup/page.tsx +340 -344
- package/src/templates/web/ui-auth-payments-audio/template/src/components/client/auth-status.tsx +37 -52
- package/src/templates/web/ui-auth-payments-audio/template/src/components/client/login-form.tsx +49 -103
- package/src/templates/web/ui-auth-payments-audio/template/src/components/client/signup-form.tsx +60 -140
- package/src/templates/web/ui-auth-payments-audio/template/src/components/providers/app-providers.tsx +8 -3
- package/src/templates/web/ui-auth-payments-audio/template/src/components/shared/header.tsx +229 -252
- package/src/templates/web/ui-auth-payments-audio/template/src/lib/actions/auth.ts +3 -3
- package/src/templates/web/ui-auth-payments-video/template/src/app/billing/page.tsx +63 -192
- package/src/templates/web/ui-auth-payments-video/template/src/app/checkout/page.tsx +109 -125
- package/src/templates/web/ui-auth-payments-video/template/src/app/layout.tsx +38 -36
- package/src/templates/web/ui-auth-payments-video/template/src/app/login/page.tsx +9 -109
- package/src/templates/web/ui-auth-payments-video/template/src/app/page.tsx +132 -392
- package/src/templates/web/ui-auth-payments-video/template/src/app/setup/page.tsx +346 -350
- package/src/templates/web/ui-auth-payments-video/template/src/app/signup/page.tsx +9 -128
- package/src/templates/web/ui-auth-payments-video/template/src/components/client/login-form.tsx +90 -0
- package/src/templates/web/ui-auth-payments-video/template/src/components/client/signup-form.tsx +105 -0
- package/src/templates/web/ui-auth-payments-video/template/src/components/providers/app-providers.tsx +8 -3
- package/src/templates/web/ui-auth-payments-video/template/src/components/shared/header.tsx +229 -246
- package/src/templates/web/ui-only/template/eslint.config.mjs +14 -0
- package/src/templates/web/ui-only/template/src/app/checkout/page.tsx +2 -2
- package/src/templates/web/ui-only/template/src/app/login/page.tsx +69 -63
- package/src/templates/web/ui-only/template/src/app/page.tsx +69 -91
- package/src/templates/web/ui-only/template/src/app/signup/page.tsx +94 -79
- package/src/templates/web/ui-only/template/src/components/providers/app-providers.tsx +1 -6
- package/src/templates/web/ui-only/template/src/components/shared/header.tsx +90 -53
- package/src/templates/web/ui-package-test/template/package.json +19 -23
- package/src/templates/web/ui-package-test/template/postcss.config.mjs +8 -0
- package/src/templates/web/ui-package-test/template/src/app/globals.css +88 -0
- package/src/templates/web/ui-package-test/template/src/app/layout.tsx +27 -0
- package/src/templates/web/ui-package-test/template/src/app/page.tsx +46 -106
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/README.md +0 -655
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/app/(tabs)/ai.tsx +0 -683
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/app/_layout.tsx +0 -124
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/app.json +0 -74
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/babel.config.js +0 -25
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/docs/MOBILE-SETUP.md +0 -787
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/eas.json +0 -25
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/expo-env.d.ts +0 -3
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -346
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/jest-setup.ts +0 -37
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -180
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/metro.config.js +0 -11
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/package.json +0 -122
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -599
- package/dist/templates/mobile/ui-auth-payments-ai-rag/template/tsconfig.json +0 -32
- package/dist/templates/web/base/template/.eslintrc.js +0 -8
- package/dist/templates/web/base/template/src/components/__tests__/example.test.tsx +0 -49
- package/dist/templates/web/base/template/src/test/setup.ts +0 -74
- package/dist/templates/web/base/template/vitest.config.ts +0 -17
- package/dist/templates/web/ui-auth/template/.eslintrc.js +0 -8
- package/dist/templates/web/ui-auth/template/src/components/__tests__/example.test.tsx +0 -49
- package/dist/templates/web/ui-auth/template/src/test/setup.ts +0 -74
- package/dist/templates/web/ui-auth/template/vitest.config.ts +0 -17
- package/dist/templates/web/ui-auth-payments/template/src/components/__tests__/example.test.tsx +0 -49
- package/dist/templates/web/ui-auth-payments/template/src/test/setup.ts +0 -74
- package/dist/templates/web/ui-auth-payments/template/vitest.config.ts +0 -17
- package/dist/templates/web/ui-auth-payments-ai/template/src/components/__tests__/example.test.tsx +0 -49
- package/dist/templates/web/ui-auth-payments-ai/template/src/test/setup.ts +0 -74
- package/dist/templates/web/ui-auth-payments-ai/template/vitest.config.ts +0 -17
- package/dist/templates/web/ui-auth-payments-ai-rag/template/README.md +0 -434
- package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/KnowledgeManager.tsx +0 -642
- package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGAnalytics.tsx +0 -466
- package/dist/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGChatInterface.tsx +0 -393
- package/dist/templates/web/ui-auth-payments-ai-rag/template/docs/GETTING-STARTED.md +0 -457
- package/dist/templates/web/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -478
- package/dist/templates/web/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -250
- package/dist/templates/web/ui-auth-payments-ai-rag/template/package.json +0 -73
- package/dist/templates/web/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -622
- package/dist/templates/web/ui-auth-payments-ai-rag/template/src/app/ai/page.tsx +0 -396
- package/dist/templates/web/ui-auth-payments-audio/template/src/components/__tests__/example.test.tsx +0 -49
- package/dist/templates/web/ui-auth-payments-audio/template/src/test/setup.ts +0 -74
- package/dist/templates/web/ui-auth-payments-audio/template/vitest.config.ts +0 -17
- package/dist/templates/web/ui-auth-payments-video/template/src/components/__tests__/example.test.tsx +0 -49
- package/dist/templates/web/ui-auth-payments-video/template/src/test/setup.ts +0 -74
- package/dist/templates/web/ui-auth-payments-video/template/vitest.config.ts +0 -17
- package/dist/templates/web/ui-only/template/.eslintrc.js +0 -8
- package/dist/templates/web/ui-only/template/src/components/__tests__/example.test.tsx +0 -49
- package/dist/templates/web/ui-only/template/src/test/setup.ts +0 -74
- package/dist/templates/web/ui-only/template/vitest.config.ts +0 -17
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/README.md +0 -655
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/app/(tabs)/ai.tsx +0 -683
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/app/_layout.tsx +0 -124
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/app.json +0 -74
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/babel.config.js +0 -25
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/docs/MOBILE-SETUP.md +0 -787
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/eas.json +0 -25
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/expo-env.d.ts +0 -3
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -346
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/jest-setup.ts +0 -37
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -180
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/metro.config.js +0 -11
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/package.json +0 -122
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -599
- package/src/templates/mobile/ui-auth-payments-ai-rag/template/tsconfig.json +0 -32
- package/src/templates/web/base/template/.eslintrc.js +0 -8
- package/src/templates/web/base/template/src/components/__tests__/example.test.tsx +0 -49
- package/src/templates/web/base/template/src/test/setup.ts +0 -74
- package/src/templates/web/base/template/vitest.config.ts +0 -17
- package/src/templates/web/ui-auth/template/.eslintrc.js +0 -8
- package/src/templates/web/ui-auth/template/src/components/__tests__/example.test.tsx +0 -49
- package/src/templates/web/ui-auth/template/src/test/setup.ts +0 -74
- package/src/templates/web/ui-auth/template/vitest.config.ts +0 -17
- package/src/templates/web/ui-auth-payments/template/src/components/__tests__/example.test.tsx +0 -49
- package/src/templates/web/ui-auth-payments/template/src/test/setup.ts +0 -74
- package/src/templates/web/ui-auth-payments/template/vitest.config.ts +0 -17
- package/src/templates/web/ui-auth-payments-ai/template/src/components/__tests__/example.test.tsx +0 -49
- package/src/templates/web/ui-auth-payments-ai/template/src/test/setup.ts +0 -74
- package/src/templates/web/ui-auth-payments-ai/template/vitest.config.ts +0 -17
- package/src/templates/web/ui-auth-payments-ai-rag/template/README.md +0 -434
- package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/KnowledgeManager.tsx +0 -642
- package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGAnalytics.tsx +0 -466
- package/src/templates/web/ui-auth-payments-ai-rag/template/components/rag/RAGChatInterface.tsx +0 -393
- package/src/templates/web/ui-auth-payments-ai-rag/template/docs/GETTING-STARTED.md +0 -457
- package/src/templates/web/ui-auth-payments-ai-rag/template/hooks/useRAGSystem.ts +0 -478
- package/src/templates/web/ui-auth-payments-ai-rag/template/lib/rag/config.ts +0 -250
- package/src/templates/web/ui-auth-payments-ai-rag/template/package.json +0 -73
- package/src/templates/web/ui-auth-payments-ai-rag/template/scripts/setup-rag.js +0 -622
- package/src/templates/web/ui-auth-payments-ai-rag/template/src/app/ai/page.tsx +0 -396
- package/src/templates/web/ui-auth-payments-audio/template/src/components/__tests__/example.test.tsx +0 -49
- package/src/templates/web/ui-auth-payments-audio/template/src/test/setup.ts +0 -74
- package/src/templates/web/ui-auth-payments-audio/template/vitest.config.ts +0 -17
- package/src/templates/web/ui-auth-payments-video/template/src/components/__tests__/example.test.tsx +0 -49
- package/src/templates/web/ui-auth-payments-video/template/src/test/setup.ts +0 -74
- package/src/templates/web/ui-auth-payments-video/template/vitest.config.ts +0 -17
- package/src/templates/web/ui-only/template/.eslintrc.js +0 -8
- package/src/templates/web/ui-only/template/src/components/__tests__/example.test.tsx +0 -49
- package/src/templates/web/ui-only/template/src/test/setup.ts +0 -74
- package/src/templates/web/ui-only/template/vitest.config.ts +0 -17
|
@@ -1,340 +1,340 @@
|
|
|
1
|
-
'use server'
|
|
2
|
-
|
|
3
|
-
import { after } from 'next/server'
|
|
4
|
-
import { revalidateTag, revalidatePath } from 'next/cache'
|
|
5
|
-
import { getCurrentUser } from '@/lib/auth-server'
|
|
6
|
-
import { z } from 'zod'
|
|
7
|
-
|
|
8
|
-
// Common response type
|
|
9
|
-
export type ActionResponse<T = any> = {
|
|
10
|
-
success: boolean
|
|
11
|
-
data?: T
|
|
12
|
-
error?: string
|
|
13
|
-
fieldErrors?: Record<string, string[]>
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Example server action for contact form
|
|
18
|
-
*/
|
|
19
|
-
export async function submitContactForm(prevState: any, formData: FormData): Promise<ActionResponse> {
|
|
20
|
-
try {
|
|
21
|
-
const contactSchema = z.object({
|
|
22
|
-
name: z.string().min(2, 'Name must be at least 2 characters'),
|
|
23
|
-
email: z.string().email('Invalid email address'),
|
|
24
|
-
subject: z.string().min(5, 'Subject must be at least 5 characters'),
|
|
25
|
-
message: z.string().min(10, 'Message must be at least 10 characters'),
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
const rawData = {
|
|
29
|
-
name: formData.get('name') as string,
|
|
30
|
-
email: formData.get('email') as string,
|
|
31
|
-
subject: formData.get('subject') as string,
|
|
32
|
-
message: formData.get('message') as string,
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const validationResult = contactSchema.safeParse(rawData)
|
|
36
|
-
|
|
37
|
-
if (!validationResult.success) {
|
|
38
|
-
return {
|
|
39
|
-
success: false,
|
|
40
|
-
error: 'Please check your input',
|
|
41
|
-
fieldErrors: validationResult.error.
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const { name, email, subject, message } = validationResult.data
|
|
46
|
-
|
|
47
|
-
// Process contact form submission
|
|
48
|
-
// This could involve:
|
|
49
|
-
// - Sending email to admin
|
|
50
|
-
// - Saving to database
|
|
51
|
-
// - Sending auto-reply to user
|
|
52
|
-
|
|
53
|
-
// Use after() for non-blocking operations (Next.js 15.3 feature)
|
|
54
|
-
after(async () => {
|
|
55
|
-
// Send notification email to admin (non-blocking)
|
|
56
|
-
console.log('Sending notification email for contact form submission')
|
|
57
|
-
|
|
58
|
-
// Log analytics event (non-blocking)
|
|
59
|
-
console.log('Logging contact form submission analytics')
|
|
60
|
-
|
|
61
|
-
// Update dashboard statistics (non-blocking)
|
|
62
|
-
console.log('Updating contact form statistics')
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
success: true,
|
|
67
|
-
data: { message: 'Thank you for your message. We\'ll get back to you soon!' }
|
|
68
|
-
}
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error('Contact form error:', error)
|
|
71
|
-
return {
|
|
72
|
-
success: false,
|
|
73
|
-
error: 'An unexpected error occurred. Please try again.',
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Example server action for newsletter signup
|
|
80
|
-
*/
|
|
81
|
-
export async function subscribeToNewsletter(prevState: any, formData: FormData): Promise<ActionResponse> {
|
|
82
|
-
try {
|
|
83
|
-
const email = formData.get('email') as string
|
|
84
|
-
|
|
85
|
-
const emailSchema = z.string().email('Invalid email address')
|
|
86
|
-
const validationResult = emailSchema.safeParse(email)
|
|
87
|
-
|
|
88
|
-
if (!validationResult.success) {
|
|
89
|
-
return {
|
|
90
|
-
success: false,
|
|
91
|
-
error: 'Please enter a valid email address',
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Add to newsletter list
|
|
96
|
-
// This could involve:
|
|
97
|
-
// - Adding to email service provider (Mailchimp, ConvertKit, etc.)
|
|
98
|
-
// - Saving to database
|
|
99
|
-
// - Sending welcome email
|
|
100
|
-
|
|
101
|
-
after(async () => {
|
|
102
|
-
// Send welcome email (non-blocking)
|
|
103
|
-
console.log(`Sending welcome email to ${email}`)
|
|
104
|
-
|
|
105
|
-
// Add to email marketing platform (non-blocking)
|
|
106
|
-
console.log(`Adding ${email} to newsletter list`)
|
|
107
|
-
|
|
108
|
-
// Track conversion (non-blocking)
|
|
109
|
-
console.log('Tracking newsletter signup conversion')
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
success: true,
|
|
114
|
-
data: { message: 'Successfully subscribed to newsletter!' }
|
|
115
|
-
}
|
|
116
|
-
} catch (error) {
|
|
117
|
-
console.error('Newsletter subscription error:', error)
|
|
118
|
-
return {
|
|
119
|
-
success: false,
|
|
120
|
-
error: 'An unexpected error occurred. Please try again.',
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Example authenticated server action
|
|
127
|
-
*/
|
|
128
|
-
export async function createPost(prevState: any, formData: FormData): Promise<ActionResponse> {
|
|
129
|
-
try {
|
|
130
|
-
// Require authentication
|
|
131
|
-
const user = await getCurrentUser()
|
|
132
|
-
if (!user) {
|
|
133
|
-
return {
|
|
134
|
-
success: false,
|
|
135
|
-
error: 'Authentication required',
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const postSchema = z.object({
|
|
140
|
-
title: z.string().min(3, 'Title must be at least 3 characters'),
|
|
141
|
-
content: z.string().min(10, 'Content must be at least 10 characters'),
|
|
142
|
-
published: z.boolean().default(false),
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
const rawData = {
|
|
146
|
-
title: formData.get('title') as string,
|
|
147
|
-
content: formData.get('content') as string,
|
|
148
|
-
published: formData.get('published') === 'true',
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const validationResult = postSchema.safeParse(rawData)
|
|
152
|
-
|
|
153
|
-
if (!validationResult.success) {
|
|
154
|
-
return {
|
|
155
|
-
success: false,
|
|
156
|
-
error: 'Please check your input',
|
|
157
|
-
fieldErrors: validationResult.error.
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const { title, content, published } = validationResult.data
|
|
162
|
-
|
|
163
|
-
// Create post in database
|
|
164
|
-
const post = {
|
|
165
|
-
id: Math.random().toString(36).substr(2, 9),
|
|
166
|
-
title,
|
|
167
|
-
content,
|
|
168
|
-
published,
|
|
169
|
-
authorId: user.id,
|
|
170
|
-
createdAt: new Date().toISOString(),
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Revalidate relevant paths and tags
|
|
174
|
-
revalidateTag('posts')
|
|
175
|
-
revalidatePath('/posts')
|
|
176
|
-
if (published) {
|
|
177
|
-
revalidatePath('/')
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Non-blocking operations
|
|
181
|
-
after(async () => {
|
|
182
|
-
// Send notifications to subscribers (non-blocking)
|
|
183
|
-
if (published) {
|
|
184
|
-
console.log('Notifying subscribers of new post')
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Update search index (non-blocking)
|
|
188
|
-
console.log('Updating search index')
|
|
189
|
-
|
|
190
|
-
// Track content creation analytics (non-blocking)
|
|
191
|
-
console.log('Tracking post creation analytics')
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
return {
|
|
195
|
-
success: true,
|
|
196
|
-
data: { post, message: published ? 'Post published successfully!' : 'Post saved as draft!' }
|
|
197
|
-
}
|
|
198
|
-
} catch (error) {
|
|
199
|
-
console.error('Create post error:', error)
|
|
200
|
-
return {
|
|
201
|
-
success: false,
|
|
202
|
-
error: 'An unexpected error occurred. Please try again.',
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Example action for updating user preferences
|
|
209
|
-
*/
|
|
210
|
-
export async function updatePreferences(prevState: any, formData: FormData): Promise<ActionResponse> {
|
|
211
|
-
try {
|
|
212
|
-
const user = await getCurrentUser()
|
|
213
|
-
if (!user) {
|
|
214
|
-
return {
|
|
215
|
-
success: false,
|
|
216
|
-
error: 'Authentication required',
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const preferencesSchema = z.object({
|
|
221
|
-
emailNotifications: z.boolean().default(true),
|
|
222
|
-
pushNotifications: z.boolean().default(false),
|
|
223
|
-
marketingEmails: z.boolean().default(false),
|
|
224
|
-
theme: z.enum(['light', 'dark', 'system']).default('system'),
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
const rawData = {
|
|
228
|
-
emailNotifications: formData.get('emailNotifications') === 'true',
|
|
229
|
-
pushNotifications: formData.get('pushNotifications') === 'true',
|
|
230
|
-
marketingEmails: formData.get('marketingEmails') === 'true',
|
|
231
|
-
theme: formData.get('theme') as 'light' | 'dark' | 'system' | null || 'system',
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const validationResult = preferencesSchema.safeParse(rawData)
|
|
235
|
-
|
|
236
|
-
if (!validationResult.success) {
|
|
237
|
-
return {
|
|
238
|
-
success: false,
|
|
239
|
-
error: 'Please check your input',
|
|
240
|
-
fieldErrors: validationResult.error.
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const preferences = validationResult.data
|
|
245
|
-
|
|
246
|
-
// Update user preferences in database
|
|
247
|
-
// This would typically involve a database update
|
|
248
|
-
|
|
249
|
-
after(async () => {
|
|
250
|
-
// Update notification service settings (non-blocking)
|
|
251
|
-
console.log('Updating notification service settings')
|
|
252
|
-
|
|
253
|
-
// Log preference changes for analytics (non-blocking)
|
|
254
|
-
console.log('Logging preference changes')
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
return {
|
|
258
|
-
success: true,
|
|
259
|
-
data: { preferences, message: 'Preferences updated successfully!' }
|
|
260
|
-
}
|
|
261
|
-
} catch (error) {
|
|
262
|
-
console.error('Update preferences error:', error)
|
|
263
|
-
return {
|
|
264
|
-
success: false,
|
|
265
|
-
error: 'An unexpected error occurred. Please try again.',
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Example action with file upload
|
|
272
|
-
*/
|
|
273
|
-
export async function uploadAvatar(prevState: any, formData: FormData): Promise<ActionResponse> {
|
|
274
|
-
try {
|
|
275
|
-
const user = await getCurrentUser()
|
|
276
|
-
if (!user) {
|
|
277
|
-
return {
|
|
278
|
-
success: false,
|
|
279
|
-
error: 'Authentication required',
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const file = formData.get('avatar') as File
|
|
284
|
-
|
|
285
|
-
if (!file || file.size === 0) {
|
|
286
|
-
return {
|
|
287
|
-
success: false,
|
|
288
|
-
error: 'Please select a file to upload',
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Validate file type and size
|
|
293
|
-
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
|
|
294
|
-
const maxSize = 5 * 1024 * 1024 // 5MB
|
|
295
|
-
|
|
296
|
-
if (!allowedTypes.includes(file.type)) {
|
|
297
|
-
return {
|
|
298
|
-
success: false,
|
|
299
|
-
error: 'Please upload a valid image file (JPEG, PNG, GIF, or WebP)',
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if (file.size > maxSize) {
|
|
304
|
-
return {
|
|
305
|
-
success: false,
|
|
306
|
-
error: 'File size must be less than 5MB',
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Process file upload
|
|
311
|
-
// This would typically involve:
|
|
312
|
-
// - Uploading to cloud storage (AWS S3, Cloudinary, etc.)
|
|
313
|
-
// - Resizing/optimizing the image
|
|
314
|
-
// - Updating user record in database
|
|
315
|
-
|
|
316
|
-
const avatarUrl = `https://example.com/avatars/${user.id}-${Date.now()}.${file.type.split('/')[1]}`
|
|
317
|
-
|
|
318
|
-
after(async () => {
|
|
319
|
-
// Generate different image sizes (non-blocking)
|
|
320
|
-
console.log('Generating avatar thumbnails')
|
|
321
|
-
|
|
322
|
-
// Update CDN cache (non-blocking)
|
|
323
|
-
console.log('Updating CDN cache')
|
|
324
|
-
|
|
325
|
-
// Log upload event (non-blocking)
|
|
326
|
-
console.log('Logging avatar upload event')
|
|
327
|
-
})
|
|
328
|
-
|
|
329
|
-
return {
|
|
330
|
-
success: true,
|
|
331
|
-
data: { avatarUrl, message: 'Avatar uploaded successfully!' }
|
|
332
|
-
}
|
|
333
|
-
} catch (error) {
|
|
334
|
-
console.error('Upload avatar error:', error)
|
|
335
|
-
return {
|
|
336
|
-
success: false,
|
|
337
|
-
error: 'An unexpected error occurred. Please try again.',
|
|
338
|
-
}
|
|
339
|
-
}
|
|
1
|
+
'use server'
|
|
2
|
+
|
|
3
|
+
import { after } from 'next/server'
|
|
4
|
+
import { revalidateTag, revalidatePath } from 'next/cache'
|
|
5
|
+
import { getCurrentUser } from '@/lib/auth-server'
|
|
6
|
+
import { z } from 'zod'
|
|
7
|
+
|
|
8
|
+
// Common response type
|
|
9
|
+
export type ActionResponse<T = any> = {
|
|
10
|
+
success: boolean
|
|
11
|
+
data?: T
|
|
12
|
+
error?: string
|
|
13
|
+
fieldErrors?: Record<string, string[]>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Example server action for contact form
|
|
18
|
+
*/
|
|
19
|
+
export async function submitContactForm(prevState: any, formData: FormData): Promise<ActionResponse> {
|
|
20
|
+
try {
|
|
21
|
+
const contactSchema = z.object({
|
|
22
|
+
name: z.string().min(2, 'Name must be at least 2 characters'),
|
|
23
|
+
email: z.string().email('Invalid email address'),
|
|
24
|
+
subject: z.string().min(5, 'Subject must be at least 5 characters'),
|
|
25
|
+
message: z.string().min(10, 'Message must be at least 10 characters'),
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const rawData = {
|
|
29
|
+
name: formData.get('name') as string,
|
|
30
|
+
email: formData.get('email') as string,
|
|
31
|
+
subject: formData.get('subject') as string,
|
|
32
|
+
message: formData.get('message') as string,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const validationResult = contactSchema.safeParse(rawData)
|
|
36
|
+
|
|
37
|
+
if (!validationResult.success) {
|
|
38
|
+
return {
|
|
39
|
+
success: false,
|
|
40
|
+
error: 'Please check your input',
|
|
41
|
+
fieldErrors: validationResult.error.flatten().fieldErrors,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const { name, email, subject, message } = validationResult.data
|
|
46
|
+
|
|
47
|
+
// Process contact form submission
|
|
48
|
+
// This could involve:
|
|
49
|
+
// - Sending email to admin
|
|
50
|
+
// - Saving to database
|
|
51
|
+
// - Sending auto-reply to user
|
|
52
|
+
|
|
53
|
+
// Use after() for non-blocking operations (Next.js 15.3 feature)
|
|
54
|
+
after(async () => {
|
|
55
|
+
// Send notification email to admin (non-blocking)
|
|
56
|
+
console.log('Sending notification email for contact form submission')
|
|
57
|
+
|
|
58
|
+
// Log analytics event (non-blocking)
|
|
59
|
+
console.log('Logging contact form submission analytics')
|
|
60
|
+
|
|
61
|
+
// Update dashboard statistics (non-blocking)
|
|
62
|
+
console.log('Updating contact form statistics')
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
success: true,
|
|
67
|
+
data: { message: 'Thank you for your message. We\'ll get back to you soon!' }
|
|
68
|
+
}
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error('Contact form error:', error)
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
error: 'An unexpected error occurred. Please try again.',
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Example server action for newsletter signup
|
|
80
|
+
*/
|
|
81
|
+
export async function subscribeToNewsletter(prevState: any, formData: FormData): Promise<ActionResponse> {
|
|
82
|
+
try {
|
|
83
|
+
const email = formData.get('email') as string
|
|
84
|
+
|
|
85
|
+
const emailSchema = z.string().email('Invalid email address')
|
|
86
|
+
const validationResult = emailSchema.safeParse(email)
|
|
87
|
+
|
|
88
|
+
if (!validationResult.success) {
|
|
89
|
+
return {
|
|
90
|
+
success: false,
|
|
91
|
+
error: 'Please enter a valid email address',
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Add to newsletter list
|
|
96
|
+
// This could involve:
|
|
97
|
+
// - Adding to email service provider (Mailchimp, ConvertKit, etc.)
|
|
98
|
+
// - Saving to database
|
|
99
|
+
// - Sending welcome email
|
|
100
|
+
|
|
101
|
+
after(async () => {
|
|
102
|
+
// Send welcome email (non-blocking)
|
|
103
|
+
console.log(`Sending welcome email to ${email}`)
|
|
104
|
+
|
|
105
|
+
// Add to email marketing platform (non-blocking)
|
|
106
|
+
console.log(`Adding ${email} to newsletter list`)
|
|
107
|
+
|
|
108
|
+
// Track conversion (non-blocking)
|
|
109
|
+
console.log('Tracking newsletter signup conversion')
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
success: true,
|
|
114
|
+
data: { message: 'Successfully subscribed to newsletter!' }
|
|
115
|
+
}
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error('Newsletter subscription error:', error)
|
|
118
|
+
return {
|
|
119
|
+
success: false,
|
|
120
|
+
error: 'An unexpected error occurred. Please try again.',
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Example authenticated server action
|
|
127
|
+
*/
|
|
128
|
+
export async function createPost(prevState: any, formData: FormData): Promise<ActionResponse> {
|
|
129
|
+
try {
|
|
130
|
+
// Require authentication
|
|
131
|
+
const user = await getCurrentUser()
|
|
132
|
+
if (!user) {
|
|
133
|
+
return {
|
|
134
|
+
success: false,
|
|
135
|
+
error: 'Authentication required',
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const postSchema = z.object({
|
|
140
|
+
title: z.string().min(3, 'Title must be at least 3 characters'),
|
|
141
|
+
content: z.string().min(10, 'Content must be at least 10 characters'),
|
|
142
|
+
published: z.boolean().default(false),
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
const rawData = {
|
|
146
|
+
title: formData.get('title') as string,
|
|
147
|
+
content: formData.get('content') as string,
|
|
148
|
+
published: formData.get('published') === 'true',
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const validationResult = postSchema.safeParse(rawData)
|
|
152
|
+
|
|
153
|
+
if (!validationResult.success) {
|
|
154
|
+
return {
|
|
155
|
+
success: false,
|
|
156
|
+
error: 'Please check your input',
|
|
157
|
+
fieldErrors: validationResult.error.flatten().fieldErrors,
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const { title, content, published } = validationResult.data
|
|
162
|
+
|
|
163
|
+
// Create post in database
|
|
164
|
+
const post = {
|
|
165
|
+
id: Math.random().toString(36).substr(2, 9),
|
|
166
|
+
title,
|
|
167
|
+
content,
|
|
168
|
+
published,
|
|
169
|
+
authorId: user.id,
|
|
170
|
+
createdAt: new Date().toISOString(),
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Revalidate relevant paths and tags
|
|
174
|
+
revalidateTag('posts')
|
|
175
|
+
revalidatePath('/posts')
|
|
176
|
+
if (published) {
|
|
177
|
+
revalidatePath('/')
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Non-blocking operations
|
|
181
|
+
after(async () => {
|
|
182
|
+
// Send notifications to subscribers (non-blocking)
|
|
183
|
+
if (published) {
|
|
184
|
+
console.log('Notifying subscribers of new post')
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Update search index (non-blocking)
|
|
188
|
+
console.log('Updating search index')
|
|
189
|
+
|
|
190
|
+
// Track content creation analytics (non-blocking)
|
|
191
|
+
console.log('Tracking post creation analytics')
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
success: true,
|
|
196
|
+
data: { post, message: published ? 'Post published successfully!' : 'Post saved as draft!' }
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error('Create post error:', error)
|
|
200
|
+
return {
|
|
201
|
+
success: false,
|
|
202
|
+
error: 'An unexpected error occurred. Please try again.',
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Example action for updating user preferences
|
|
209
|
+
*/
|
|
210
|
+
export async function updatePreferences(prevState: any, formData: FormData): Promise<ActionResponse> {
|
|
211
|
+
try {
|
|
212
|
+
const user = await getCurrentUser()
|
|
213
|
+
if (!user) {
|
|
214
|
+
return {
|
|
215
|
+
success: false,
|
|
216
|
+
error: 'Authentication required',
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const preferencesSchema = z.object({
|
|
221
|
+
emailNotifications: z.boolean().default(true),
|
|
222
|
+
pushNotifications: z.boolean().default(false),
|
|
223
|
+
marketingEmails: z.boolean().default(false),
|
|
224
|
+
theme: z.enum(['light', 'dark', 'system']).default('system'),
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
const rawData = {
|
|
228
|
+
emailNotifications: formData.get('emailNotifications') === 'true',
|
|
229
|
+
pushNotifications: formData.get('pushNotifications') === 'true',
|
|
230
|
+
marketingEmails: formData.get('marketingEmails') === 'true',
|
|
231
|
+
theme: formData.get('theme') as 'light' | 'dark' | 'system' | null || 'system',
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const validationResult = preferencesSchema.safeParse(rawData)
|
|
235
|
+
|
|
236
|
+
if (!validationResult.success) {
|
|
237
|
+
return {
|
|
238
|
+
success: false,
|
|
239
|
+
error: 'Please check your input',
|
|
240
|
+
fieldErrors: validationResult.error.flatten().fieldErrors,
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const preferences = validationResult.data
|
|
245
|
+
|
|
246
|
+
// Update user preferences in database
|
|
247
|
+
// This would typically involve a database update
|
|
248
|
+
|
|
249
|
+
after(async () => {
|
|
250
|
+
// Update notification service settings (non-blocking)
|
|
251
|
+
console.log('Updating notification service settings')
|
|
252
|
+
|
|
253
|
+
// Log preference changes for analytics (non-blocking)
|
|
254
|
+
console.log('Logging preference changes')
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
success: true,
|
|
259
|
+
data: { preferences, message: 'Preferences updated successfully!' }
|
|
260
|
+
}
|
|
261
|
+
} catch (error) {
|
|
262
|
+
console.error('Update preferences error:', error)
|
|
263
|
+
return {
|
|
264
|
+
success: false,
|
|
265
|
+
error: 'An unexpected error occurred. Please try again.',
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Example action with file upload
|
|
272
|
+
*/
|
|
273
|
+
export async function uploadAvatar(prevState: any, formData: FormData): Promise<ActionResponse> {
|
|
274
|
+
try {
|
|
275
|
+
const user = await getCurrentUser()
|
|
276
|
+
if (!user) {
|
|
277
|
+
return {
|
|
278
|
+
success: false,
|
|
279
|
+
error: 'Authentication required',
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const file = formData.get('avatar') as File
|
|
284
|
+
|
|
285
|
+
if (!file || file.size === 0) {
|
|
286
|
+
return {
|
|
287
|
+
success: false,
|
|
288
|
+
error: 'Please select a file to upload',
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Validate file type and size
|
|
293
|
+
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
|
|
294
|
+
const maxSize = 5 * 1024 * 1024 // 5MB
|
|
295
|
+
|
|
296
|
+
if (!allowedTypes.includes(file.type)) {
|
|
297
|
+
return {
|
|
298
|
+
success: false,
|
|
299
|
+
error: 'Please upload a valid image file (JPEG, PNG, GIF, or WebP)',
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (file.size > maxSize) {
|
|
304
|
+
return {
|
|
305
|
+
success: false,
|
|
306
|
+
error: 'File size must be less than 5MB',
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Process file upload
|
|
311
|
+
// This would typically involve:
|
|
312
|
+
// - Uploading to cloud storage (AWS S3, Cloudinary, etc.)
|
|
313
|
+
// - Resizing/optimizing the image
|
|
314
|
+
// - Updating user record in database
|
|
315
|
+
|
|
316
|
+
const avatarUrl = `https://example.com/avatars/${user.id}-${Date.now()}.${file.type.split('/')[1]}`
|
|
317
|
+
|
|
318
|
+
after(async () => {
|
|
319
|
+
// Generate different image sizes (non-blocking)
|
|
320
|
+
console.log('Generating avatar thumbnails')
|
|
321
|
+
|
|
322
|
+
// Update CDN cache (non-blocking)
|
|
323
|
+
console.log('Updating CDN cache')
|
|
324
|
+
|
|
325
|
+
// Log upload event (non-blocking)
|
|
326
|
+
console.log('Logging avatar upload event')
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
success: true,
|
|
331
|
+
data: { avatarUrl, message: 'Avatar uploaded successfully!' }
|
|
332
|
+
}
|
|
333
|
+
} catch (error) {
|
|
334
|
+
console.error('Upload avatar error:', error)
|
|
335
|
+
return {
|
|
336
|
+
success: false,
|
|
337
|
+
error: 'An unexpected error occurred. Please try again.',
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
340
|
}
|