@payez/next-mvp 3.0.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/README.md +782 -0
- package/dist/api/auth-handler.d.ts +67 -0
- package/dist/api/auth-handler.js +397 -0
- package/dist/api/index.d.ts +10 -0
- package/dist/api/index.js +19 -0
- package/dist/api-handlers/account/change-password.d.ts +9 -0
- package/dist/api-handlers/account/change-password.js +112 -0
- package/dist/api-handlers/account/masked-info.d.ts +2 -0
- package/dist/api-handlers/account/masked-info.js +41 -0
- package/dist/api-handlers/account/profile.d.ts +3 -0
- package/dist/api-handlers/account/profile.js +63 -0
- package/dist/api-handlers/account/recovery/initiate.d.ts +2 -0
- package/dist/api-handlers/account/recovery/initiate.js +26 -0
- package/dist/api-handlers/account/recovery/send-code.d.ts +2 -0
- package/dist/api-handlers/account/recovery/send-code.js +28 -0
- package/dist/api-handlers/account/recovery/verify-code.d.ts +2 -0
- package/dist/api-handlers/account/recovery/verify-code.js +28 -0
- package/dist/api-handlers/account/reset-password.d.ts +2 -0
- package/dist/api-handlers/account/reset-password.js +26 -0
- package/dist/api-handlers/account/send-code.d.ts +24 -0
- package/dist/api-handlers/account/send-code.js +60 -0
- package/dist/api-handlers/account/update-phone.d.ts +27 -0
- package/dist/api-handlers/account/update-phone.js +64 -0
- package/dist/api-handlers/account/validate-password.d.ts +17 -0
- package/dist/api-handlers/account/validate-password.js +81 -0
- package/dist/api-handlers/account/verify-email.d.ts +26 -0
- package/dist/api-handlers/account/verify-email.js +106 -0
- package/dist/api-handlers/account/verify-sms.d.ts +26 -0
- package/dist/api-handlers/account/verify-sms.js +106 -0
- package/dist/api-handlers/admin/analytics.d.ts +20 -0
- package/dist/api-handlers/admin/analytics.js +379 -0
- package/dist/api-handlers/admin/audit.d.ts +20 -0
- package/dist/api-handlers/admin/audit.js +214 -0
- package/dist/api-handlers/admin/index.d.ts +21 -0
- package/dist/api-handlers/admin/index.js +41 -0
- package/dist/api-handlers/admin/redis-sessions.d.ts +36 -0
- package/dist/api-handlers/admin/redis-sessions.js +204 -0
- package/dist/api-handlers/admin/sessions.d.ts +21 -0
- package/dist/api-handlers/admin/sessions.js +284 -0
- package/dist/api-handlers/admin/site-logs.d.ts +46 -0
- package/dist/api-handlers/admin/site-logs.js +318 -0
- package/dist/api-handlers/admin/users.d.ts +20 -0
- package/dist/api-handlers/admin/users.js +222 -0
- package/dist/api-handlers/admin/vibe-data.d.ts +80 -0
- package/dist/api-handlers/admin/vibe-data.js +268 -0
- package/dist/api-handlers/anon/preferences.d.ts +37 -0
- package/dist/api-handlers/anon/preferences.js +96 -0
- package/dist/api-handlers/auth/jwks.d.ts +2 -0
- package/dist/api-handlers/auth/jwks.js +24 -0
- package/dist/api-handlers/auth/login.d.ts +42 -0
- package/dist/api-handlers/auth/login.js +178 -0
- package/dist/api-handlers/auth/refresh.d.ts +74 -0
- package/dist/api-handlers/auth/refresh.js +635 -0
- package/dist/api-handlers/auth/signout.d.ts +37 -0
- package/dist/api-handlers/auth/signout.js +187 -0
- package/dist/api-handlers/auth/status.d.ts +8 -0
- package/dist/api-handlers/auth/status.js +26 -0
- package/dist/api-handlers/auth/update-session.d.ts +37 -0
- package/dist/api-handlers/auth/update-session.js +95 -0
- package/dist/api-handlers/auth/validate.d.ts +6 -0
- package/dist/api-handlers/auth/validate.js +43 -0
- package/dist/api-handlers/auth/verify-code.d.ts +43 -0
- package/dist/api-handlers/auth/verify-code.js +94 -0
- package/dist/api-handlers/session/refresh-viability.d.ts +14 -0
- package/dist/api-handlers/session/refresh-viability.js +39 -0
- package/dist/api-handlers/session/viability.d.ts +13 -0
- package/dist/api-handlers/session/viability.js +146 -0
- package/dist/api-handlers/test/force-expire.d.ts +23 -0
- package/dist/api-handlers/test/force-expire.js +65 -0
- package/dist/auth/auth-decision.d.ts +39 -0
- package/dist/auth/auth-decision.js +182 -0
- package/dist/auth/auth-options.d.ts +57 -0
- package/dist/auth/auth-options.js +213 -0
- package/dist/auth/callbacks/index.d.ts +6 -0
- package/dist/auth/callbacks/index.js +12 -0
- package/dist/auth/callbacks/jwt.d.ts +45 -0
- package/dist/auth/callbacks/jwt.js +305 -0
- package/dist/auth/callbacks/session.d.ts +60 -0
- package/dist/auth/callbacks/session.js +170 -0
- package/dist/auth/callbacks/signin.d.ts +23 -0
- package/dist/auth/callbacks/signin.js +44 -0
- package/dist/auth/events/index.d.ts +4 -0
- package/dist/auth/events/index.js +8 -0
- package/dist/auth/events/signout.d.ts +17 -0
- package/dist/auth/events/signout.js +32 -0
- package/dist/auth/providers/credentials.d.ts +32 -0
- package/dist/auth/providers/credentials.js +223 -0
- package/dist/auth/providers/index.d.ts +5 -0
- package/dist/auth/providers/index.js +21 -0
- package/dist/auth/providers/oauth.d.ts +26 -0
- package/dist/auth/providers/oauth.js +105 -0
- package/dist/auth/route-config.d.ts +66 -0
- package/dist/auth/route-config.js +190 -0
- package/dist/auth/types/auth-types.d.ts +417 -0
- package/dist/auth/types/auth-types.js +53 -0
- package/dist/auth/types/index.d.ts +6 -0
- package/dist/auth/types/index.js +22 -0
- package/dist/auth/unauthenticated-routes.d.ts +1 -0
- package/dist/auth/unauthenticated-routes.js +19 -0
- package/dist/auth/utils/idp-client.d.ts +94 -0
- package/dist/auth/utils/idp-client.js +383 -0
- package/dist/auth/utils/index.d.ts +5 -0
- package/dist/auth/utils/index.js +21 -0
- package/dist/auth/utils/token-utils.d.ts +84 -0
- package/dist/auth/utils/token-utils.js +219 -0
- package/dist/client/AuthContext.d.ts +19 -0
- package/dist/client/AuthContext.js +112 -0
- package/dist/client/fetch-with-auth.d.ts +11 -0
- package/dist/client/fetch-with-auth.js +44 -0
- package/dist/client/fetchWithSession.d.ts +3 -0
- package/dist/client/fetchWithSession.js +24 -0
- package/dist/client/index.d.ts +9 -0
- package/dist/client/index.js +20 -0
- package/dist/client/useAnonSession.d.ts +36 -0
- package/dist/client/useAnonSession.js +99 -0
- package/dist/components/SessionSync.d.ts +13 -0
- package/dist/components/SessionSync.js +119 -0
- package/dist/components/SignalRHealthCheck.d.ts +10 -0
- package/dist/components/SignalRHealthCheck.js +97 -0
- package/dist/components/account/UserAvatarMenu.d.ts +20 -0
- package/dist/components/account/UserAvatarMenu.js +80 -0
- package/dist/components/account/index.d.ts +7 -0
- package/dist/components/account/index.js +10 -0
- package/dist/components/admin/AlertSettingsTab.d.ts +48 -0
- package/dist/components/admin/AlertSettingsTab.js +351 -0
- package/dist/components/admin/AnalyticsTab.d.ts +22 -0
- package/dist/components/admin/AnalyticsTab.js +167 -0
- package/dist/components/admin/DataBrowserTab.d.ts +19 -0
- package/dist/components/admin/DataBrowserTab.js +252 -0
- package/dist/components/admin/LoggingSettingsTab.d.ts +73 -0
- package/dist/components/admin/LoggingSettingsTab.js +339 -0
- package/dist/components/admin/SessionsTab.d.ts +37 -0
- package/dist/components/admin/SessionsTab.js +165 -0
- package/dist/components/admin/StatsTab.d.ts +53 -0
- package/dist/components/admin/StatsTab.js +161 -0
- package/dist/components/admin/VibeAdminContext.d.ts +32 -0
- package/dist/components/admin/VibeAdminContext.js +38 -0
- package/dist/components/admin/VibeAdminLayout.d.ts +11 -0
- package/dist/components/admin/VibeAdminLayout.js +69 -0
- package/dist/components/admin/index.d.ts +29 -0
- package/dist/components/admin/index.js +44 -0
- package/dist/components/auth/FederatedAuthSection.d.ts +8 -0
- package/dist/components/auth/FederatedAuthSection.js +45 -0
- package/dist/components/auth/ModeAwareLoginPage.d.ts +10 -0
- package/dist/components/auth/ModeAwareLoginPage.js +42 -0
- package/dist/components/auth/ModeAwareSignupPage.d.ts +9 -0
- package/dist/components/auth/ModeAwareSignupPage.js +78 -0
- package/dist/components/auth/TraditionalAuthSection.d.ts +14 -0
- package/dist/components/auth/TraditionalAuthSection.js +20 -0
- package/dist/components/recovery/CompleteStep.d.ts +5 -0
- package/dist/components/recovery/CompleteStep.js +8 -0
- package/dist/components/recovery/InitiateRecoveryStep.d.ts +8 -0
- package/dist/components/recovery/InitiateRecoveryStep.js +20 -0
- package/dist/components/recovery/SelectMethodStep.d.ts +8 -0
- package/dist/components/recovery/SelectMethodStep.js +8 -0
- package/dist/components/recovery/SetPasswordStep.d.ts +6 -0
- package/dist/components/recovery/SetPasswordStep.js +20 -0
- package/dist/components/recovery/VerifyCodeStep.d.ts +10 -0
- package/dist/components/recovery/VerifyCodeStep.js +24 -0
- package/dist/components/reserved/ReservedRecoveryWarning.d.ts +38 -0
- package/dist/components/reserved/ReservedRecoveryWarning.js +92 -0
- package/dist/components/reserved/ReservedStatusBox.d.ts +30 -0
- package/dist/components/reserved/ReservedStatusBox.js +71 -0
- package/dist/components/ui/BetaBadge.d.ts +29 -0
- package/dist/components/ui/BetaBadge.js +38 -0
- package/dist/components/ui/Footer.d.ts +37 -0
- package/dist/components/ui/Footer.js +41 -0
- package/dist/config/env.d.ts +66 -0
- package/dist/config/env.js +57 -0
- package/dist/config/logger.d.ts +57 -0
- package/dist/config/logger.js +73 -0
- package/dist/config/logging-config.d.ts +30 -0
- package/dist/config/logging-config.js +122 -0
- package/dist/config/unauthenticated-routes.d.ts +17 -0
- package/dist/config/unauthenticated-routes.js +24 -0
- package/dist/config/vibe-log-transport.d.ts +79 -0
- package/dist/config/vibe-log-transport.js +203 -0
- package/dist/edge/internal-api-url.d.ts +53 -0
- package/dist/edge/internal-api-url.js +63 -0
- package/dist/edge/middleware.d.ts +14 -0
- package/dist/edge/middleware.js +32 -0
- package/dist/hooks/useAuth.d.ts +23 -0
- package/dist/hooks/useAuth.js +81 -0
- package/dist/hooks/useAuthSettings.d.ts +59 -0
- package/dist/hooks/useAuthSettings.js +93 -0
- package/dist/hooks/useAvailableProviders.d.ts +45 -0
- package/dist/hooks/useAvailableProviders.js +108 -0
- package/dist/hooks/usePasswordValidation.d.ts +27 -0
- package/dist/hooks/usePasswordValidation.js +102 -0
- package/dist/hooks/useProfile.d.ts +15 -0
- package/dist/hooks/useProfile.js +59 -0
- package/dist/hooks/usePublicAuthSettings.d.ts +56 -0
- package/dist/hooks/usePublicAuthSettings.js +131 -0
- package/dist/hooks/useSessionExpiration.d.ts +57 -0
- package/dist/hooks/useSessionExpiration.js +72 -0
- package/dist/hooks/useViabilitySession.d.ts +75 -0
- package/dist/hooks/useViabilitySession.js +268 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +54 -0
- package/dist/lib/anon-session.d.ts +74 -0
- package/dist/lib/anon-session.js +169 -0
- package/dist/lib/api-handler.d.ts +123 -0
- package/dist/lib/api-handler.js +478 -0
- package/dist/lib/app-slug.d.ts +95 -0
- package/dist/lib/app-slug.js +172 -0
- package/dist/lib/demo-mode.d.ts +6 -0
- package/dist/lib/demo-mode.js +16 -0
- package/dist/lib/geolocation.d.ts +64 -0
- package/dist/lib/geolocation.js +235 -0
- package/dist/lib/idp-client-config.d.ts +75 -0
- package/dist/lib/idp-client-config.js +351 -0
- package/dist/lib/idp-fetch.d.ts +14 -0
- package/dist/lib/idp-fetch.js +91 -0
- package/dist/lib/internal-api.d.ts +87 -0
- package/dist/lib/internal-api.js +122 -0
- package/dist/lib/jwt-decode-client.d.ts +10 -0
- package/dist/lib/jwt-decode-client.js +46 -0
- package/dist/lib/jwt-decode.d.ts +48 -0
- package/dist/lib/jwt-decode.js +57 -0
- package/dist/lib/nextauth-secret.d.ts +10 -0
- package/dist/lib/nextauth-secret.js +104 -0
- package/dist/lib/rate-limit-service.d.ts +23 -0
- package/dist/lib/rate-limit-service.js +6 -0
- package/dist/lib/redis.d.ts +5 -0
- package/dist/lib/redis.js +28 -0
- package/dist/lib/refresh-token-validator.d.ts +13 -0
- package/dist/lib/refresh-token-validator.js +117 -0
- package/dist/lib/roles.d.ts +145 -0
- package/dist/lib/roles.js +168 -0
- package/dist/lib/secret-validation.d.ts +4 -0
- package/dist/lib/secret-validation.js +14 -0
- package/dist/lib/session-store.d.ts +166 -0
- package/dist/lib/session-store.js +537 -0
- package/dist/lib/session.d.ts +21 -0
- package/dist/lib/session.js +26 -0
- package/dist/lib/site-logger.d.ts +214 -0
- package/dist/lib/site-logger.js +210 -0
- package/dist/lib/standardized-client-api.d.ts +161 -0
- package/dist/lib/standardized-client-api.js +786 -0
- package/dist/lib/startup-init.d.ts +40 -0
- package/dist/lib/startup-init.js +261 -0
- package/dist/lib/test-aware-get-token.d.ts +2 -0
- package/dist/lib/test-aware-get-token.js +81 -0
- package/dist/lib/token-expiry.d.ts +14 -0
- package/dist/lib/token-expiry.js +39 -0
- package/dist/lib/token-lifecycle.d.ts +52 -0
- package/dist/lib/token-lifecycle.js +398 -0
- package/dist/lib/types/api-responses.d.ts +128 -0
- package/dist/lib/types/api-responses.js +171 -0
- package/dist/lib/user-agent-parser.d.ts +50 -0
- package/dist/lib/user-agent-parser.js +220 -0
- package/dist/logging/api/admin-analytics.d.ts +3 -0
- package/dist/logging/api/admin-analytics.js +45 -0
- package/dist/logging/api/audit-log.d.ts +3 -0
- package/dist/logging/api/audit-log.js +52 -0
- package/dist/logging/components/AdminAnalyticsLayout.d.ts +10 -0
- package/dist/logging/components/AdminAnalyticsLayout.js +11 -0
- package/dist/logging/components/AuditLogViewer.d.ts +7 -0
- package/dist/logging/components/AuditLogViewer.js +51 -0
- package/dist/logging/components/ErrorMetricsCard.d.ts +7 -0
- package/dist/logging/components/ErrorMetricsCard.js +16 -0
- package/dist/logging/components/HealthMetricsCard.d.ts +7 -0
- package/dist/logging/components/HealthMetricsCard.js +19 -0
- package/dist/logging/hooks/useAdminAnalytics.d.ts +24 -0
- package/dist/logging/hooks/useAdminAnalytics.js +22 -0
- package/dist/logging/hooks/useAuditLog.d.ts +6 -0
- package/dist/logging/hooks/useAuditLog.js +25 -0
- package/dist/logging/hooks/useErrorMetrics.d.ts +6 -0
- package/dist/logging/hooks/useErrorMetrics.js +38 -0
- package/dist/logging/hooks/useHealthMetrics.d.ts +6 -0
- package/dist/logging/hooks/useHealthMetrics.js +41 -0
- package/dist/logging/index.d.ts +11 -0
- package/dist/logging/index.js +40 -0
- package/dist/logging/types/analytics.d.ts +68 -0
- package/dist/logging/types/analytics.js +3 -0
- package/dist/logging/types/audit.d.ts +29 -0
- package/dist/logging/types/audit.js +2 -0
- package/dist/logging/types/index.d.ts +2 -0
- package/dist/logging/types/index.js +19 -0
- package/dist/middleware/auth-decision.d.ts +33 -0
- package/dist/middleware/auth-decision.js +65 -0
- package/dist/middleware/create-middleware.d.ts +100 -0
- package/dist/middleware/create-middleware.js +445 -0
- package/dist/middleware/rbac-check.d.ts +44 -0
- package/dist/middleware/rbac-check.js +191 -0
- package/dist/middleware/twofa-presets.d.ts +134 -0
- package/dist/middleware/twofa-presets.js +175 -0
- package/dist/models/DecodedAccessToken.d.ts +17 -0
- package/dist/models/DecodedAccessToken.js +2 -0
- package/dist/models/SessionModel.d.ts +122 -0
- package/dist/models/SessionModel.js +136 -0
- package/dist/pages/admin-login/page.d.ts +31 -0
- package/dist/pages/admin-login/page.js +83 -0
- package/dist/pages/admin-roles/RolesAdminPage.d.ts +15 -0
- package/dist/pages/admin-roles/RolesAdminPage.js +78 -0
- package/dist/pages/admin-roles/index.d.ts +8 -0
- package/dist/pages/admin-roles/index.js +15 -0
- package/dist/pages/admin-roles/modals.d.ts +72 -0
- package/dist/pages/admin-roles/modals.js +154 -0
- package/dist/pages/client-admin/ClientSiteAdminPage.d.ts +79 -0
- package/dist/pages/client-admin/ClientSiteAdminPage.js +177 -0
- package/dist/pages/client-admin/index.d.ts +32 -0
- package/dist/pages/client-admin/index.js +37 -0
- package/dist/pages/login/page.d.ts +22 -0
- package/dist/pages/login/page.js +239 -0
- package/dist/pages/profile/EnhancedProfilePage.d.ts +13 -0
- package/dist/pages/profile/EnhancedProfilePage.js +150 -0
- package/dist/pages/profile/index.d.ts +8 -0
- package/dist/pages/profile/index.js +16 -0
- package/dist/pages/profile/page.d.ts +19 -0
- package/dist/pages/profile/page.js +47 -0
- package/dist/pages/profile/profile-patch.d.ts +1 -0
- package/dist/pages/profile/profile-patch.js +281 -0
- package/dist/pages/recovery/page.d.ts +1 -0
- package/dist/pages/recovery/page.js +142 -0
- package/dist/pages/roles/MyRolesPage.d.ts +24 -0
- package/dist/pages/roles/MyRolesPage.js +71 -0
- package/dist/pages/roles/components.d.ts +63 -0
- package/dist/pages/roles/components.js +108 -0
- package/dist/pages/roles/index.d.ts +8 -0
- package/dist/pages/roles/index.js +19 -0
- package/dist/pages/security/EnhancedSecurityPage.d.ts +14 -0
- package/dist/pages/security/EnhancedSecurityPage.js +248 -0
- package/dist/pages/security/index.d.ts +8 -0
- package/dist/pages/security/index.js +16 -0
- package/dist/pages/security/page.d.ts +21 -0
- package/dist/pages/security/page.js +212 -0
- package/dist/pages/security/security-patch.d.ts +1 -0
- package/dist/pages/security/security-patch.js +302 -0
- package/dist/pages/settings/EnhancedSettingsPage.d.ts +46 -0
- package/dist/pages/settings/EnhancedSettingsPage.js +231 -0
- package/dist/pages/settings/index.d.ts +8 -0
- package/dist/pages/settings/index.js +16 -0
- package/dist/pages/settings/page.d.ts +7 -0
- package/dist/pages/settings/page.js +26 -0
- package/dist/pages/showcase/ShowcasePage.d.ts +13 -0
- package/dist/pages/showcase/ShowcasePage.js +140 -0
- package/dist/pages/showcase/index.d.ts +12 -0
- package/dist/pages/showcase/index.js +17 -0
- package/dist/pages/test-env/EmergencyLogoutPage.d.ts +14 -0
- package/dist/pages/test-env/EmergencyLogoutPage.js +98 -0
- package/dist/pages/test-env/JwtInspectPage.d.ts +14 -0
- package/dist/pages/test-env/JwtInspectPage.js +114 -0
- package/dist/pages/test-env/RefreshTokenPage.d.ts +15 -0
- package/dist/pages/test-env/RefreshTokenPage.js +91 -0
- package/dist/pages/test-env/TestEnvPage.d.ts +13 -0
- package/dist/pages/test-env/TestEnvPage.js +49 -0
- package/dist/pages/test-env/index.d.ts +24 -0
- package/dist/pages/test-env/index.js +32 -0
- package/dist/pages/verify-code/page.d.ts +30 -0
- package/dist/pages/verify-code/page.js +408 -0
- package/dist/routes/account/index.d.ts +28 -0
- package/dist/routes/account/index.js +71 -0
- package/dist/routes/account/masked-info.d.ts +33 -0
- package/dist/routes/account/masked-info.js +39 -0
- package/dist/routes/account/send-code.d.ts +37 -0
- package/dist/routes/account/send-code.js +42 -0
- package/dist/routes/account/update-phone.d.ts +13 -0
- package/dist/routes/account/update-phone.js +17 -0
- package/dist/routes/account/verify-email.d.ts +38 -0
- package/dist/routes/account/verify-email.js +43 -0
- package/dist/routes/account/verify-sms.d.ts +38 -0
- package/dist/routes/account/verify-sms.js +43 -0
- package/dist/routes/auth/index.d.ts +19 -0
- package/dist/routes/auth/index.js +64 -0
- package/dist/routes/auth/logout.d.ts +31 -0
- package/dist/routes/auth/logout.js +113 -0
- package/dist/routes/auth/nextauth.d.ts +19 -0
- package/dist/routes/auth/nextauth.js +72 -0
- package/dist/routes/auth/refresh.d.ts +30 -0
- package/dist/routes/auth/refresh.js +51 -0
- package/dist/routes/auth/session.d.ts +72 -0
- package/dist/routes/auth/session.js +180 -0
- package/dist/routes/auth/settings.d.ts +25 -0
- package/dist/routes/auth/settings.js +55 -0
- package/dist/routes/auth/viability.d.ts +52 -0
- package/dist/routes/auth/viability.js +201 -0
- package/dist/routes/index.d.ts +12 -0
- package/dist/routes/index.js +54 -0
- package/dist/routes/session/index.d.ts +6 -0
- package/dist/routes/session/index.js +10 -0
- package/dist/routes/session/refresh-viability.d.ts +16 -0
- package/dist/routes/session/refresh-viability.js +20 -0
- package/dist/services/signalrActivityService.d.ts +44 -0
- package/dist/services/signalrActivityService.js +257 -0
- package/dist/stores/authStore.d.ts +154 -0
- package/dist/stores/authStore.js +1531 -0
- package/dist/theme/ThemeProvider.d.ts +14 -0
- package/dist/theme/ThemeProvider.js +28 -0
- package/dist/theme/default.d.ts +8 -0
- package/dist/theme/default.js +33 -0
- package/dist/theme/index.d.ts +15 -0
- package/dist/theme/index.js +25 -0
- package/dist/theme/types.d.ts +56 -0
- package/dist/theme/types.js +8 -0
- package/dist/theme/useTheme.d.ts +60 -0
- package/dist/theme/useTheme.js +63 -0
- package/dist/theme/utils.d.ts +13 -0
- package/dist/theme/utils.js +39 -0
- package/dist/types/api.d.ts +134 -0
- package/dist/types/api.js +44 -0
- package/dist/types/auth.d.ts +19 -0
- package/dist/types/auth.js +2 -0
- package/dist/types/logging.d.ts +42 -0
- package/dist/types/logging.js +2 -0
- package/dist/types/recovery.d.ts +48 -0
- package/dist/types/recovery.js +2 -0
- package/dist/types/security.d.ts +1 -0
- package/dist/types/security.js +2 -0
- package/dist/utils/api.d.ts +85 -0
- package/dist/utils/api.js +287 -0
- package/dist/utils/circuitBreaker.d.ts +43 -0
- package/dist/utils/circuitBreaker.js +91 -0
- package/dist/utils/error-message.d.ts +1 -0
- package/dist/utils/error-message.js +103 -0
- package/dist/utils/layout/reservedSpace.d.ts +59 -0
- package/dist/utils/layout/reservedSpace.js +102 -0
- package/dist/utils/logout.d.ts +14 -0
- package/dist/utils/logout.js +32 -0
- package/dist/vibe/client.d.ts +261 -0
- package/dist/vibe/client.js +445 -0
- package/dist/vibe/errors.d.ts +83 -0
- package/dist/vibe/errors.js +146 -0
- package/dist/vibe/generic.d.ts +234 -0
- package/dist/vibe/generic.js +369 -0
- package/dist/vibe/hooks/index.d.ts +169 -0
- package/dist/vibe/hooks/index.js +252 -0
- package/dist/vibe/index.d.ts +23 -0
- package/dist/vibe/index.js +67 -0
- package/dist/vibe/sessions.d.ts +161 -0
- package/dist/vibe/sessions.js +391 -0
- package/dist/vibe/types.d.ts +353 -0
- package/dist/vibe/types.js +315 -0
- package/package.json +855 -0
- package/scripts/check-internal-url-usage.sh +73 -0
- package/scripts/dev-broker.ps1 +35 -0
- package/scripts/dev-local.ps1 +45 -0
- package/src/api/auth-handler.ts +550 -0
- package/src/api/index.ts +18 -0
- package/src/api-handlers/account/change-password.ts +145 -0
- package/src/api-handlers/account/masked-info.ts +45 -0
- package/src/api-handlers/account/profile.ts +80 -0
- package/src/api-handlers/account/recovery/initiate.ts +23 -0
- package/src/api-handlers/account/recovery/send-code.ts +25 -0
- package/src/api-handlers/account/recovery/verify-code.ts +25 -0
- package/src/api-handlers/account/reset-password.ts +23 -0
- package/src/api-handlers/account/send-code.ts +76 -0
- package/src/api-handlers/account/update-phone.ts +79 -0
- package/src/api-handlers/account/validate-password.ts +118 -0
- package/src/api-handlers/account/verify-email.ts +125 -0
- package/src/api-handlers/account/verify-sms.ts +125 -0
- package/src/api-handlers/admin/analytics.ts +445 -0
- package/src/api-handlers/admin/audit.ts +225 -0
- package/src/api-handlers/admin/index.ts +59 -0
- package/src/api-handlers/admin/redis-sessions.ts +253 -0
- package/src/api-handlers/admin/sessions.ts +320 -0
- package/src/api-handlers/admin/site-logs.ts +367 -0
- package/src/api-handlers/admin/users.ts +244 -0
- package/src/api-handlers/admin/vibe-data.ts +326 -0
- package/src/api-handlers/anon/preferences.ts +123 -0
- package/src/api-handlers/auth/jwks.ts +20 -0
- package/src/api-handlers/auth/login.ts +240 -0
- package/src/api-handlers/auth/refresh.ts +687 -0
- package/src/api-handlers/auth/signout.ts +212 -0
- package/src/api-handlers/auth/status.ts +23 -0
- package/src/api-handlers/auth/update-session.ts +125 -0
- package/src/api-handlers/auth/validate.ts +44 -0
- package/src/api-handlers/auth/verify-code.ts +129 -0
- package/src/api-handlers/session/refresh-viability.ts +36 -0
- package/src/api-handlers/session/viability.ts +166 -0
- package/src/api-handlers/test/force-expire.ts +67 -0
- package/src/auth/auth-decision.ts +230 -0
- package/src/auth/auth-options.ts +237 -0
- package/src/auth/callbacks/index.ts +7 -0
- package/src/auth/callbacks/jwt.ts +382 -0
- package/src/auth/callbacks/session.ts +243 -0
- package/src/auth/callbacks/signin.ts +56 -0
- package/src/auth/events/index.ts +5 -0
- package/src/auth/events/signout.ts +33 -0
- package/src/auth/providers/credentials.ts +256 -0
- package/src/auth/providers/index.ts +6 -0
- package/src/auth/providers/oauth.ts +114 -0
- package/src/auth/route-config.ts +220 -0
- package/src/auth/types/auth-types.ts +555 -0
- package/src/auth/types/index.ts +7 -0
- package/src/auth/unauthenticated-routes.ts +3 -0
- package/src/auth/utils/idp-client.ts +444 -0
- package/src/auth/utils/index.ts +6 -0
- package/src/auth/utils/token-utils.ts +244 -0
- package/src/client/AuthContext.tsx +140 -0
- package/src/client/fetch-with-auth.ts +48 -0
- package/src/client/fetchWithSession.ts +21 -0
- package/src/client/index.ts +13 -0
- package/src/client/useAnonSession.ts +131 -0
- package/src/components/SessionSync.tsx +137 -0
- package/src/components/SignalRHealthCheck.tsx +131 -0
- package/src/components/account/UserAvatarMenu.tsx +217 -0
- package/src/components/account/index.ts +8 -0
- package/src/components/admin/AlertSettingsTab.tsx +728 -0
- package/src/components/admin/AnalyticsTab.tsx +703 -0
- package/src/components/admin/DataBrowserTab.tsx +505 -0
- package/src/components/admin/LoggingSettingsTab.tsx +665 -0
- package/src/components/admin/SessionsTab.tsx +414 -0
- package/src/components/admin/StatsTab.tsx +379 -0
- package/src/components/admin/VibeAdminContext.tsx +87 -0
- package/src/components/admin/VibeAdminLayout.tsx +185 -0
- package/src/components/admin/index.ts +59 -0
- package/src/components/auth/FederatedAuthSection.tsx +95 -0
- package/src/components/auth/ModeAwareLoginPage.tsx +135 -0
- package/src/components/auth/ModeAwareSignupPage.tsx +267 -0
- package/src/components/auth/TraditionalAuthSection.tsx +99 -0
- package/src/components/recovery/CompleteStep.tsx +36 -0
- package/src/components/recovery/InitiateRecoveryStep.tsx +68 -0
- package/src/components/recovery/SelectMethodStep.tsx +73 -0
- package/src/components/recovery/SetPasswordStep.tsx +97 -0
- package/src/components/recovery/VerifyCodeStep.tsx +90 -0
- package/src/components/reserved/ReservedRecoveryWarning.tsx +160 -0
- package/src/components/reserved/ReservedStatusBox.tsx +118 -0
- package/src/components/ui/BetaBadge.tsx +58 -0
- package/src/components/ui/Footer.tsx +93 -0
- package/src/config/env.ts +57 -0
- package/src/config/logger.ts +62 -0
- package/src/config/logging-config.ts +82 -0
- package/src/config/unauthenticated-routes.ts +19 -0
- package/src/config/vibe-log-transport.ts +250 -0
- package/src/edge/internal-api-url.ts +65 -0
- package/src/edge/middleware.ts +42 -0
- package/src/hooks/useAuth.ts +115 -0
- package/src/hooks/useAuthSettings.ts +97 -0
- package/src/hooks/useAvailableProviders.ts +118 -0
- package/src/hooks/usePasswordValidation.ts +127 -0
- package/src/hooks/useProfile.ts +75 -0
- package/src/hooks/usePublicAuthSettings.ts +149 -0
- package/src/hooks/useSessionExpiration.ts +102 -0
- package/src/hooks/useViabilitySession.ts +335 -0
- package/src/index.ts +63 -0
- package/src/lib/anon-session.ts +213 -0
- package/src/lib/api-handler.ts +625 -0
- package/src/lib/app-slug.ts +178 -0
- package/src/lib/demo-mode.ts +13 -0
- package/src/lib/geolocation.ts +265 -0
- package/src/lib/idp-client-config.ts +442 -0
- package/src/lib/idp-fetch.ts +101 -0
- package/src/lib/internal-api.ts +171 -0
- package/src/lib/jwt-decode-client.ts +45 -0
- package/src/lib/jwt-decode.ts +83 -0
- package/src/lib/nextauth-secret.ts +126 -0
- package/src/lib/rate-limit-service.ts +9 -0
- package/src/lib/redis.ts +27 -0
- package/src/lib/refresh-token-validator.ts +64 -0
- package/src/lib/roles.ts +177 -0
- package/src/lib/secret-validation.ts +8 -0
- package/src/lib/session-store.ts +637 -0
- package/src/lib/session.ts +34 -0
- package/src/lib/site-logger.ts +245 -0
- package/src/lib/standardized-client-api.ts +896 -0
- package/src/lib/startup-init.ts +247 -0
- package/src/lib/test-aware-get-token.ts +30 -0
- package/src/lib/token-expiry.ts +40 -0
- package/src/lib/token-lifecycle.ts +477 -0
- package/src/lib/types/api-responses.ts +336 -0
- package/src/lib/user-agent-parser.ts +252 -0
- package/src/logging/api/admin-analytics.ts +51 -0
- package/src/logging/api/audit-log.ts +53 -0
- package/src/logging/components/AdminAnalyticsLayout.tsx +49 -0
- package/src/logging/components/AuditLogViewer.tsx +125 -0
- package/src/logging/components/ErrorMetricsCard.tsx +98 -0
- package/src/logging/components/HealthMetricsCard.tsx +70 -0
- package/src/logging/hooks/useAdminAnalytics.ts +22 -0
- package/src/logging/hooks/useAuditLog.ts +24 -0
- package/src/logging/hooks/useErrorMetrics.ts +40 -0
- package/src/logging/hooks/useHealthMetrics.ts +44 -0
- package/src/logging/index.ts +18 -0
- package/src/logging/types/analytics.ts +81 -0
- package/src/logging/types/audit.ts +31 -0
- package/src/logging/types/index.ts +3 -0
- package/src/middleware/auth-decision.ts +43 -0
- package/src/middleware/create-middleware.ts +626 -0
- package/src/middleware/rbac-check.ts +244 -0
- package/src/middleware/twofa-presets.ts +224 -0
- package/src/models/DecodedAccessToken.ts +17 -0
- package/src/models/SessionModel.ts +258 -0
- package/src/pages/admin-login/page.tsx +229 -0
- package/src/pages/admin-roles/RolesAdminPage.tsx +357 -0
- package/src/pages/admin-roles/index.ts +9 -0
- package/src/pages/admin-roles/modals.tsx +469 -0
- package/src/pages/client-admin/ClientSiteAdminPage.tsx +380 -0
- package/src/pages/client-admin/index.ts +33 -0
- package/src/pages/login/page.tsx +463 -0
- package/src/pages/profile/EnhancedProfilePage.tsx +479 -0
- package/src/pages/profile/index.ts +9 -0
- package/src/pages/profile/page.tsx +166 -0
- package/src/pages/recovery/page.tsx +234 -0
- package/src/pages/roles/MyRolesPage.tsx +211 -0
- package/src/pages/roles/components.tsx +294 -0
- package/src/pages/roles/index.ts +17 -0
- package/src/pages/security/EnhancedSecurityPage.tsx +574 -0
- package/src/pages/security/index.ts +9 -0
- package/src/pages/security/page.tsx +507 -0
- package/src/pages/settings/EnhancedSettingsPage.tsx +642 -0
- package/src/pages/settings/index.ts +9 -0
- package/src/pages/settings/page.tsx +47 -0
- package/src/pages/showcase/ShowcasePage.tsx +530 -0
- package/src/pages/showcase/index.ts +13 -0
- package/src/pages/test-env/EmergencyLogoutPage.tsx +179 -0
- package/src/pages/test-env/JwtInspectPage.tsx +418 -0
- package/src/pages/test-env/RefreshTokenPage.tsx +155 -0
- package/src/pages/test-env/TestEnvPage.tsx +116 -0
- package/src/pages/test-env/index.ts +25 -0
- package/src/pages/verify-code/page.tsx +648 -0
- package/src/routes/account/index.ts +32 -0
- package/src/routes/account/masked-info.ts +37 -0
- package/src/routes/account/send-code.ts +40 -0
- package/src/routes/account/update-phone.ts +13 -0
- package/src/routes/account/verify-email.ts +41 -0
- package/src/routes/account/verify-sms.ts +41 -0
- package/src/routes/auth/index.ts +23 -0
- package/src/routes/auth/logout.ts +127 -0
- package/src/routes/auth/nextauth.ts +71 -0
- package/src/routes/auth/refresh.ts +54 -0
- package/src/routes/auth/session.ts +193 -0
- package/src/routes/auth/settings.ts +75 -0
- package/src/routes/auth/viability.ts +220 -0
- package/src/routes/index.ts +18 -0
- package/src/routes/session/index.ts +7 -0
- package/src/routes/session/refresh-viability.ts +17 -0
- package/src/services/signalrActivityService.ts +258 -0
- package/src/stores/authStore.ts +1904 -0
- package/src/templates/instrumentation.ts +41 -0
- package/src/theme/ThemeProvider.tsx +39 -0
- package/src/theme/default.ts +33 -0
- package/src/theme/index.ts +31 -0
- package/src/theme/types.ts +69 -0
- package/src/theme/useTheme.ts +57 -0
- package/src/theme/utils.ts +40 -0
- package/src/types/api.ts +13 -0
- package/src/types/auth.d.ts +15 -0
- package/src/types/auth.ts +22 -0
- package/src/types/logging.ts +11 -0
- package/src/types/next-auth.d.ts +15 -0
- package/src/types/recovery.ts +54 -0
- package/src/types/security.ts +1 -0
- package/src/utils/api.ts +353 -0
- package/src/utils/circuitBreaker.ts +40 -0
- package/src/utils/error-message.ts +108 -0
- package/src/utils/layout/reservedSpace.ts +124 -0
- package/src/utils/logout.ts +30 -0
- package/src/vibe/client.ts +590 -0
- package/src/vibe/errors.ts +185 -0
- package/src/vibe/generic.ts +429 -0
- package/src/vibe/hooks/index.ts +367 -0
- package/src/vibe/index.ts +121 -0
- package/src/vibe/sessions.ts +551 -0
- package/src/vibe/types.ts +577 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Patch script to add re-authentication to security page
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = 'E:/Repos/PayEz-Next-MVP/packages/next-mvp/src/pages/security/EnhancedSecurityPage.tsx';
|
|
5
|
+
let content = fs.readFileSync(path, 'utf8');
|
|
6
|
+
// 1. Add ReAuthModal component after StatusBadge
|
|
7
|
+
const statusBadgeEnd = `// Status Badge Component
|
|
8
|
+
function StatusBadge({ enabled, label, isDark }: { enabled: boolean; label?: string; isDark: boolean }) {
|
|
9
|
+
const bgClass = enabled
|
|
10
|
+
? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400'
|
|
11
|
+
: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400';
|
|
12
|
+
return (
|
|
13
|
+
<span className={\`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium \${bgClass}\`}>
|
|
14
|
+
{label || (enabled ? 'Enabled' : 'Not Active')}
|
|
15
|
+
</span>
|
|
16
|
+
);
|
|
17
|
+
}`;
|
|
18
|
+
const reAuthModal = `// Status Badge Component
|
|
19
|
+
function StatusBadge({ enabled, label, isDark }: { enabled: boolean; label?: string; isDark: boolean }) {
|
|
20
|
+
const bgClass = enabled
|
|
21
|
+
? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400'
|
|
22
|
+
: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400';
|
|
23
|
+
return (
|
|
24
|
+
<span className={\`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium \${bgClass}\`}>
|
|
25
|
+
{label || (enabled ? 'Enabled' : 'Not Active')}
|
|
26
|
+
</span>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Re-Authentication Modal Component (Security Addendum)
|
|
31
|
+
type ReAuthAction = 'enable_2fa' | 'disable_2fa' | 'export_data' | 'delete_account' | null;
|
|
32
|
+
|
|
33
|
+
function ReAuthModal({
|
|
34
|
+
isOpen,
|
|
35
|
+
action,
|
|
36
|
+
require2FA,
|
|
37
|
+
onConfirm,
|
|
38
|
+
onCancel,
|
|
39
|
+
isDark,
|
|
40
|
+
}: {
|
|
41
|
+
isOpen: boolean;
|
|
42
|
+
action: ReAuthAction;
|
|
43
|
+
require2FA: boolean;
|
|
44
|
+
onConfirm: (password: string, twoFactorCode?: string) => void;
|
|
45
|
+
onCancel: () => void;
|
|
46
|
+
isDark: boolean;
|
|
47
|
+
}) {
|
|
48
|
+
const [password, setPassword] = React.useState('');
|
|
49
|
+
const [twoFactorCode, setTwoFactorCode] = React.useState('');
|
|
50
|
+
const [showPassword, setShowPassword] = React.useState(false);
|
|
51
|
+
const [error, setError] = React.useState('');
|
|
52
|
+
|
|
53
|
+
if (!isOpen) return null;
|
|
54
|
+
|
|
55
|
+
const getTitle = () => {
|
|
56
|
+
switch (action) {
|
|
57
|
+
case 'enable_2fa': return 'Enable Two-Factor Authentication';
|
|
58
|
+
case 'disable_2fa': return 'Disable Two-Factor Authentication';
|
|
59
|
+
case 'export_data': return 'Export Your Data';
|
|
60
|
+
case 'delete_account': return 'Delete Account';
|
|
61
|
+
default: return 'Confirm Action';
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const getDescription = () => {
|
|
66
|
+
switch (action) {
|
|
67
|
+
case 'enable_2fa': return 'Enter your password to enable 2FA.';
|
|
68
|
+
case 'disable_2fa': return 'Enter your password to disable 2FA. This will make your account less secure.';
|
|
69
|
+
case 'export_data': return require2FA
|
|
70
|
+
? 'Enter your password or 2FA code to request a data export.'
|
|
71
|
+
: 'Enter your password to request a data export.';
|
|
72
|
+
case 'delete_account': return require2FA
|
|
73
|
+
? 'Enter your password AND 2FA code to permanently delete your account.'
|
|
74
|
+
: 'Enter your password to permanently delete your account.';
|
|
75
|
+
default: return 'Please re-authenticate to continue.';
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
setError('');
|
|
82
|
+
if (!password && !(action === 'export_data' && twoFactorCode)) {
|
|
83
|
+
setError('Password is required');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (action === 'delete_account' && require2FA && !twoFactorCode) {
|
|
87
|
+
setError('2FA code is required for account deletion');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
onConfirm(password, twoFactorCode || undefined);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const bgOverlay = 'bg-black/50';
|
|
94
|
+
const modalBg = isDark ? 'bg-slate-800' : 'bg-white';
|
|
95
|
+
const borderColor = isDark ? 'border-slate-700' : 'border-gray-200';
|
|
96
|
+
const textPrimary = isDark ? 'text-white' : 'text-gray-900';
|
|
97
|
+
const textMuted = isDark ? 'text-slate-400' : 'text-gray-500';
|
|
98
|
+
const inputBg = isDark ? 'bg-slate-700' : 'bg-white';
|
|
99
|
+
const inputBorder = isDark ? 'border-slate-600' : 'border-gray-300';
|
|
100
|
+
|
|
101
|
+
const isDestructive = action === 'disable_2fa' || action === 'delete_account';
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<div className={\`fixed inset-0 z-50 flex items-center justify-center \${bgOverlay}\`}>
|
|
105
|
+
<div className={\`w-full max-w-md mx-4 rounded-lg shadow-xl \${modalBg} border \${borderColor}\`}>
|
|
106
|
+
<div className={\`px-6 py-4 border-b \${borderColor}\`}>
|
|
107
|
+
<h3 className={\`text-lg font-semibold \${textPrimary}\`}>{getTitle()}</h3>
|
|
108
|
+
<p className={\`text-sm mt-1 \${textMuted}\`}>{getDescription()}</p>
|
|
109
|
+
</div>
|
|
110
|
+
<form onSubmit={handleSubmit} className="px-6 py-4 space-y-4">
|
|
111
|
+
<div>
|
|
112
|
+
<label className={\`block text-sm font-medium mb-1 \${textMuted}\`}>Password</label>
|
|
113
|
+
<div className="relative">
|
|
114
|
+
<input
|
|
115
|
+
type={showPassword ? 'text' : 'password'}
|
|
116
|
+
value={password}
|
|
117
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
118
|
+
className={\`w-full px-3 py-2 rounded-md border \${inputBorder} \${inputBg} \${textPrimary} focus:ring-2 focus:ring-blue-500 focus:border-transparent\`}
|
|
119
|
+
placeholder="Enter your password"
|
|
120
|
+
autoFocus
|
|
121
|
+
/>
|
|
122
|
+
<button
|
|
123
|
+
type="button"
|
|
124
|
+
onClick={() => setShowPassword(!showPassword)}
|
|
125
|
+
className={\`absolute right-2 top-1/2 -translate-y-1/2 text-xs \${textMuted}\`}
|
|
126
|
+
>
|
|
127
|
+
{showPassword ? 'Hide' : 'Show'}
|
|
128
|
+
</button>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
{(require2FA || action === 'export_data') && (
|
|
133
|
+
<div>
|
|
134
|
+
<label className={\`block text-sm font-medium mb-1 \${textMuted}\`}>
|
|
135
|
+
{action === 'export_data' ? '2FA Code (optional if password provided)' : '2FA Code'}
|
|
136
|
+
</label>
|
|
137
|
+
<input
|
|
138
|
+
type="text"
|
|
139
|
+
value={twoFactorCode}
|
|
140
|
+
onChange={(e) => setTwoFactorCode(e.target.value.replace(/\\D/g, '').slice(0, 6))}
|
|
141
|
+
className={\`w-full px-3 py-2 rounded-md border \${inputBorder} \${inputBg} \${textPrimary} focus:ring-2 focus:ring-blue-500 focus:border-transparent font-mono text-center tracking-widest\`}
|
|
142
|
+
placeholder="000000"
|
|
143
|
+
maxLength={6}
|
|
144
|
+
/>
|
|
145
|
+
</div>
|
|
146
|
+
)}
|
|
147
|
+
|
|
148
|
+
{error && (
|
|
149
|
+
<div className="bg-red-900/30 border border-red-600 rounded-lg p-2">
|
|
150
|
+
<p className="text-red-400 text-sm">{error}</p>
|
|
151
|
+
</div>
|
|
152
|
+
)}
|
|
153
|
+
|
|
154
|
+
<div className="flex gap-3 pt-2">
|
|
155
|
+
<button
|
|
156
|
+
type="button"
|
|
157
|
+
onClick={onCancel}
|
|
158
|
+
className={\`flex-1 px-4 py-2 rounded-md border \${borderColor} \${textMuted} hover:bg-slate-700/20\`}
|
|
159
|
+
>
|
|
160
|
+
Cancel
|
|
161
|
+
</button>
|
|
162
|
+
<button
|
|
163
|
+
type="submit"
|
|
164
|
+
className={\`flex-1 px-4 py-2 rounded-md text-white \${
|
|
165
|
+
isDestructive ? 'bg-red-600 hover:bg-red-700' : 'bg-blue-600 hover:bg-blue-700'
|
|
166
|
+
}\`}
|
|
167
|
+
>
|
|
168
|
+
Confirm
|
|
169
|
+
</button>
|
|
170
|
+
</div>
|
|
171
|
+
</form>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
);
|
|
175
|
+
}`;
|
|
176
|
+
content = content.replace(statusBadgeEnd, reAuthModal);
|
|
177
|
+
// 2. Add state for re-auth modal after the showPasswords state
|
|
178
|
+
const stateLocation = `const [showPasswords, setShowPasswords] = useState({ current: false, new: false, confirm: false });`;
|
|
179
|
+
const newState = `const [showPasswords, setShowPasswords] = useState({ current: false, new: false, confirm: false });
|
|
180
|
+
|
|
181
|
+
// Re-authentication modal state (Security Addendum)
|
|
182
|
+
const [reAuthModal, setReAuthModal] = useState<{
|
|
183
|
+
isOpen: boolean;
|
|
184
|
+
action: ReAuthAction;
|
|
185
|
+
}>({ isOpen: false, action: null });`;
|
|
186
|
+
content = content.replace(stateLocation, newState);
|
|
187
|
+
// 3. Add handler functions after useEffect for security data fetch
|
|
188
|
+
const fetchEffectEnd = `useEffect(() => {
|
|
189
|
+
if (profileData) fetchSecurityData();
|
|
190
|
+
}, [profileData, fetchSecurityData]);`;
|
|
191
|
+
const handlersAddition = `useEffect(() => {
|
|
192
|
+
if (profileData) fetchSecurityData();
|
|
193
|
+
}, [profileData, fetchSecurityData]);
|
|
194
|
+
|
|
195
|
+
// Re-auth handlers (Security Addendum)
|
|
196
|
+
const handleReAuthConfirm = async (password: string, twoFactorCode?: string) => {
|
|
197
|
+
const action = reAuthModal.action;
|
|
198
|
+
setReAuthModal({ isOpen: false, action: null });
|
|
199
|
+
|
|
200
|
+
// In production, these would call the appropriate API endpoints
|
|
201
|
+
switch (action) {
|
|
202
|
+
case 'enable_2fa':
|
|
203
|
+
console.log('Enable 2FA with password confirmation');
|
|
204
|
+
// POST /api/account/2fa/enable with { password }
|
|
205
|
+
break;
|
|
206
|
+
case 'disable_2fa':
|
|
207
|
+
console.log('Disable 2FA with password confirmation');
|
|
208
|
+
// POST /api/account/2fa/disable with { password }
|
|
209
|
+
break;
|
|
210
|
+
case 'export_data':
|
|
211
|
+
console.log('Export data with password/2FA confirmation');
|
|
212
|
+
// POST /api/account/export-data with { password?, two_factor_code? }
|
|
213
|
+
break;
|
|
214
|
+
case 'delete_account':
|
|
215
|
+
console.log('Delete account with password + 2FA confirmation');
|
|
216
|
+
// POST /api/account/delete with { password, two_factor_code }
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
const openReAuthModal = (action: ReAuthAction) => {
|
|
222
|
+
setReAuthModal({ isOpen: true, action });
|
|
223
|
+
};`;
|
|
224
|
+
content = content.replace(fetchEffectEnd, handlersAddition);
|
|
225
|
+
// 4. Update Enable 2FA button
|
|
226
|
+
const oldEnable2FA = `<button className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
|
|
227
|
+
Enable 2FA
|
|
228
|
+
</button>`;
|
|
229
|
+
const newEnable2FA = `<button
|
|
230
|
+
onClick={() => openReAuthModal('enable_2fa')}
|
|
231
|
+
className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
|
|
232
|
+
>
|
|
233
|
+
Enable 2FA
|
|
234
|
+
</button>`;
|
|
235
|
+
content = content.replace(oldEnable2FA, newEnable2FA);
|
|
236
|
+
// 5. Update Disable 2FA button
|
|
237
|
+
const oldDisable2FA = `<button className="px-3 py-1.5 text-sm rounded border border-red-500 text-red-500 hover:bg-red-500/10">
|
|
238
|
+
Disable 2FA
|
|
239
|
+
</button>`;
|
|
240
|
+
const newDisable2FA = `<button
|
|
241
|
+
onClick={() => openReAuthModal('disable_2fa')}
|
|
242
|
+
className="px-3 py-1.5 text-sm rounded border border-red-500 text-red-500 hover:bg-red-500/10"
|
|
243
|
+
>
|
|
244
|
+
Disable 2FA
|
|
245
|
+
</button>`;
|
|
246
|
+
content = content.replace(oldDisable2FA, newDisable2FA);
|
|
247
|
+
// 6. Update Export Data button
|
|
248
|
+
const oldExport = `<button className="px-4 py-2 text-sm rounded border border-yellow-500 text-yellow-500 hover:bg-yellow-500/10">
|
|
249
|
+
Request Export
|
|
250
|
+
</button>`;
|
|
251
|
+
const newExport = `<button
|
|
252
|
+
onClick={() => openReAuthModal('export_data')}
|
|
253
|
+
className="px-4 py-2 text-sm rounded border border-yellow-500 text-yellow-500 hover:bg-yellow-500/10"
|
|
254
|
+
>
|
|
255
|
+
Request Export
|
|
256
|
+
</button>`;
|
|
257
|
+
content = content.replace(oldExport, newExport);
|
|
258
|
+
// 7. Update Delete Account button
|
|
259
|
+
const oldDelete = `<button className="px-4 py-2 text-sm rounded border border-red-500 text-red-500 hover:bg-red-500/10">
|
|
260
|
+
Delete Account
|
|
261
|
+
</button>`;
|
|
262
|
+
const newDelete = `<button
|
|
263
|
+
onClick={() => openReAuthModal('delete_account')}
|
|
264
|
+
className="px-4 py-2 text-sm rounded border border-red-500 text-red-500 hover:bg-red-500/10"
|
|
265
|
+
>
|
|
266
|
+
Delete Account
|
|
267
|
+
</button>`;
|
|
268
|
+
content = content.replace(oldDelete, newDelete);
|
|
269
|
+
// 8. Add ReAuthModal component to JSX before closing div
|
|
270
|
+
const closingDiv = `{/* Back to Profile link */}
|
|
271
|
+
<div className="text-center">
|
|
272
|
+
<a href="/account/profile" className={\`text-sm hover:underline \${textMuted}\`}>
|
|
273
|
+
Back to Profile
|
|
274
|
+
</a>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
);
|
|
279
|
+
}`;
|
|
280
|
+
const withModal = `{/* Re-Authentication Modal */}
|
|
281
|
+
<ReAuthModal
|
|
282
|
+
isOpen={reAuthModal.isOpen}
|
|
283
|
+
action={reAuthModal.action}
|
|
284
|
+
require2FA={twoFactorEnabled}
|
|
285
|
+
onConfirm={handleReAuthConfirm}
|
|
286
|
+
onCancel={() => setReAuthModal({ isOpen: false, action: null })}
|
|
287
|
+
isDark={isDark}
|
|
288
|
+
/>
|
|
289
|
+
|
|
290
|
+
{/* Back to Profile link */}
|
|
291
|
+
<div className="text-center">
|
|
292
|
+
<a href="/account/profile" className={\`text-sm hover:underline \${textMuted}\`}>
|
|
293
|
+
Back to Profile
|
|
294
|
+
</a>
|
|
295
|
+
</div>
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
298
|
+
);
|
|
299
|
+
}`;
|
|
300
|
+
content = content.replace(closingDiv, withModal);
|
|
301
|
+
fs.writeFileSync(path, content);
|
|
302
|
+
console.log('Security page patched with re-authentication modals');
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Settings Page for @payez/next-mvp
|
|
3
|
+
*
|
|
4
|
+
* Implements BAPert's Member Self-Service spec with:
|
|
5
|
+
* - Appearance section (theme, compact mode)
|
|
6
|
+
* - Localization section (language, timezone, date format)
|
|
7
|
+
* - Notifications section (email and SMS preferences)
|
|
8
|
+
* - Privacy section (profile visibility, activity status)
|
|
9
|
+
*
|
|
10
|
+
* @see docs/specs/MEMBER_SELF_SERVICE_SPEC.md
|
|
11
|
+
*/
|
|
12
|
+
interface PreferencesData {
|
|
13
|
+
appearance?: {
|
|
14
|
+
theme?: 'light' | 'dark' | 'system';
|
|
15
|
+
compact_mode?: boolean;
|
|
16
|
+
};
|
|
17
|
+
localization?: {
|
|
18
|
+
language?: string;
|
|
19
|
+
timezone?: string;
|
|
20
|
+
timezone_display?: string;
|
|
21
|
+
date_format?: string;
|
|
22
|
+
};
|
|
23
|
+
notifications?: {
|
|
24
|
+
email_enabled?: boolean;
|
|
25
|
+
email_security_alerts?: boolean;
|
|
26
|
+
email_account_updates?: boolean;
|
|
27
|
+
email_product_news?: boolean;
|
|
28
|
+
email_marketing?: boolean;
|
|
29
|
+
sms_enabled?: boolean;
|
|
30
|
+
sms_security_alerts?: boolean;
|
|
31
|
+
};
|
|
32
|
+
privacy?: {
|
|
33
|
+
profile_visibility?: 'private' | 'team' | 'public';
|
|
34
|
+
show_activity_status?: boolean;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
interface EnhancedSettingsPageProps {
|
|
38
|
+
initialPreferences?: PreferencesData;
|
|
39
|
+
preferencesEndpoint?: string;
|
|
40
|
+
languagesEndpoint?: string;
|
|
41
|
+
timezonesEndpoint?: string;
|
|
42
|
+
onSave?: (preferences: PreferencesData) => Promise<void>;
|
|
43
|
+
onThemeChange?: (theme: 'light' | 'dark' | 'system') => void;
|
|
44
|
+
}
|
|
45
|
+
export default function EnhancedSettingsPage({ initialPreferences, preferencesEndpoint, languagesEndpoint, timezonesEndpoint, onSave, onThemeChange, }: EnhancedSettingsPageProps): import("react/jsx-runtime").JSX.Element;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Enhanced Settings Page for @payez/next-mvp
|
|
4
|
+
*
|
|
5
|
+
* Implements BAPert's Member Self-Service spec with:
|
|
6
|
+
* - Appearance section (theme, compact mode)
|
|
7
|
+
* - Localization section (language, timezone, date format)
|
|
8
|
+
* - Notifications section (email and SMS preferences)
|
|
9
|
+
* - Privacy section (profile visibility, activity status)
|
|
10
|
+
*
|
|
11
|
+
* @see docs/specs/MEMBER_SELF_SERVICE_SPEC.md
|
|
12
|
+
*/
|
|
13
|
+
'use client';
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.default = EnhancedSettingsPage;
|
|
16
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
17
|
+
const react_1 = require("react");
|
|
18
|
+
const useTheme_1 = require("../../theme/useTheme");
|
|
19
|
+
// Common languages for fallback
|
|
20
|
+
const DEFAULT_LANGUAGES = [
|
|
21
|
+
{ code: 'en', name: 'English (US)' },
|
|
22
|
+
{ code: 'en-GB', name: 'English (UK)' },
|
|
23
|
+
{ code: 'es', name: 'Spanish' },
|
|
24
|
+
{ code: 'fr', name: 'French' },
|
|
25
|
+
{ code: 'de', name: 'German' },
|
|
26
|
+
{ code: 'ja', name: 'Japanese' },
|
|
27
|
+
{ code: 'zh', name: 'Chinese (Simplified)' },
|
|
28
|
+
];
|
|
29
|
+
// Common timezones for fallback
|
|
30
|
+
const DEFAULT_TIMEZONES = [
|
|
31
|
+
{ id: 'America/Los_Angeles', display: 'Pacific Time (US)', offset: '-08:00' },
|
|
32
|
+
{ id: 'America/Denver', display: 'Mountain Time (US)', offset: '-07:00' },
|
|
33
|
+
{ id: 'America/Chicago', display: 'Central Time (US)', offset: '-06:00' },
|
|
34
|
+
{ id: 'America/New_York', display: 'Eastern Time (US)', offset: '-05:00' },
|
|
35
|
+
{ id: 'Europe/London', display: 'London', offset: '+00:00' },
|
|
36
|
+
{ id: 'Europe/Paris', display: 'Paris', offset: '+01:00' },
|
|
37
|
+
{ id: 'Europe/Berlin', display: 'Berlin', offset: '+01:00' },
|
|
38
|
+
{ id: 'Asia/Tokyo', display: 'Tokyo', offset: '+09:00' },
|
|
39
|
+
{ id: 'Asia/Shanghai', display: 'Shanghai', offset: '+08:00' },
|
|
40
|
+
{ id: 'Australia/Sydney', display: 'Sydney', offset: '+11:00' },
|
|
41
|
+
];
|
|
42
|
+
// Date format options
|
|
43
|
+
const DATE_FORMATS = [
|
|
44
|
+
{ value: 'MM/DD/YYYY', label: 'MM/DD/YYYY', example: '01/09/2026' },
|
|
45
|
+
{ value: 'DD/MM/YYYY', label: 'DD/MM/YYYY', example: '09/01/2026' },
|
|
46
|
+
{ value: 'YYYY-MM-DD', label: 'YYYY-MM-DD', example: '2026-01-09' },
|
|
47
|
+
];
|
|
48
|
+
// Toggle component
|
|
49
|
+
function Toggle({ enabled, onChange, disabled = false, isDark = true, }) {
|
|
50
|
+
return ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => !disabled && onChange(!enabled), disabled: disabled, className: `
|
|
51
|
+
relative inline-flex h-6 w-11 items-center rounded-full transition-colors
|
|
52
|
+
${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
|
|
53
|
+
${enabled ? 'bg-blue-600' : isDark ? 'bg-slate-600' : 'bg-gray-300'}
|
|
54
|
+
`, children: (0, jsx_runtime_1.jsx)("span", { className: `
|
|
55
|
+
inline-block h-4 w-4 transform rounded-full bg-white transition-transform
|
|
56
|
+
${enabled ? 'translate-x-6' : 'translate-x-1'}
|
|
57
|
+
` }) }));
|
|
58
|
+
}
|
|
59
|
+
// Section wrapper component
|
|
60
|
+
function SettingsSection({ title, children, isDark, }) {
|
|
61
|
+
const borderColor = isDark ? 'border-slate-700' : 'border-gray-200';
|
|
62
|
+
const titleColor = isDark ? 'text-gray-400' : 'text-gray-500';
|
|
63
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: `border-b ${borderColor} pb-6 mb-6 last:border-b-0`, children: [(0, jsx_runtime_1.jsx)("h2", { className: `text-sm font-semibold uppercase tracking-wider ${titleColor} mb-4`, children: title }), children] }));
|
|
64
|
+
}
|
|
65
|
+
// Setting row component
|
|
66
|
+
function SettingRow({ label, description, children, isDark, }) {
|
|
67
|
+
const textPrimary = isDark ? 'text-white' : 'text-gray-900';
|
|
68
|
+
const textMuted = isDark ? 'text-gray-400' : 'text-gray-500';
|
|
69
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between py-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex-1", children: [(0, jsx_runtime_1.jsx)("p", { className: `font-medium ${textPrimary}`, children: label }), description && (0, jsx_runtime_1.jsx)("p", { className: `text-sm ${textMuted}`, children: description })] }), (0, jsx_runtime_1.jsx)("div", { className: "ml-4", children: children })] }));
|
|
70
|
+
}
|
|
71
|
+
// Select dropdown component
|
|
72
|
+
function Select({ value, onChange, options, isDark, }) {
|
|
73
|
+
const bgColor = isDark ? 'bg-slate-700' : 'bg-white';
|
|
74
|
+
const borderColor = isDark ? 'border-slate-600' : 'border-gray-300';
|
|
75
|
+
const textColor = isDark ? 'text-white' : 'text-gray-900';
|
|
76
|
+
return ((0, jsx_runtime_1.jsx)("select", { value: value, onChange: (e) => onChange(e.target.value), className: `
|
|
77
|
+
px-3 py-2 rounded-md border ${borderColor} ${bgColor} ${textColor}
|
|
78
|
+
focus:outline-none focus:ring-2 focus:ring-blue-500 min-w-[200px]
|
|
79
|
+
`, children: options.map((opt) => ((0, jsx_runtime_1.jsx)("option", { value: opt.value, children: opt.label }, opt.value))) }));
|
|
80
|
+
}
|
|
81
|
+
function EnhancedSettingsPage({ initialPreferences, preferencesEndpoint = '/api/v1/user/preferences', languagesEndpoint = '/api/v1/lookup/languages', timezonesEndpoint = '/api/v1/lookup/timezones', onSave, onThemeChange, }) {
|
|
82
|
+
const layout = (0, useTheme_1.useLayout)();
|
|
83
|
+
const colors = (0, useTheme_1.useColors)();
|
|
84
|
+
// Determine dark mode from theme colors
|
|
85
|
+
const isDark = colors?.background?.includes('slate-9') ||
|
|
86
|
+
colors?.background?.includes('gray-9') ||
|
|
87
|
+
colors?.card?.includes('slate-8');
|
|
88
|
+
// State
|
|
89
|
+
const [preferences, setPreferences] = (0, react_1.useState)(initialPreferences || {});
|
|
90
|
+
const [languages, setLanguages] = (0, react_1.useState)(DEFAULT_LANGUAGES);
|
|
91
|
+
const [timezones, setTimezones] = (0, react_1.useState)(DEFAULT_TIMEZONES);
|
|
92
|
+
const [loading, setLoading] = (0, react_1.useState)(!initialPreferences);
|
|
93
|
+
const [saving, setSaving] = (0, react_1.useState)(false);
|
|
94
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
95
|
+
const [successMessage, setSuccessMessage] = (0, react_1.useState)(null);
|
|
96
|
+
// Theme colors
|
|
97
|
+
const bgColor = isDark ? 'bg-slate-900' : 'bg-gray-50';
|
|
98
|
+
const cardBg = isDark ? 'bg-slate-800' : 'bg-white';
|
|
99
|
+
const borderColor = isDark ? 'border-slate-700' : 'border-gray-200';
|
|
100
|
+
const textPrimary = isDark ? 'text-white' : 'text-gray-900';
|
|
101
|
+
const textMuted = isDark ? 'text-gray-400' : 'text-gray-500';
|
|
102
|
+
// Fetch preferences and lookups
|
|
103
|
+
(0, react_1.useEffect)(() => {
|
|
104
|
+
async function fetchData() {
|
|
105
|
+
try {
|
|
106
|
+
setLoading(true);
|
|
107
|
+
setError(null);
|
|
108
|
+
// Fetch preferences
|
|
109
|
+
const prefResponse = await fetch(preferencesEndpoint, { credentials: 'include' });
|
|
110
|
+
if (prefResponse.ok) {
|
|
111
|
+
const prefData = await prefResponse.json();
|
|
112
|
+
setPreferences(prefData);
|
|
113
|
+
}
|
|
114
|
+
// Fetch languages (optional)
|
|
115
|
+
try {
|
|
116
|
+
const langResponse = await fetch(languagesEndpoint, { credentials: 'include' });
|
|
117
|
+
if (langResponse.ok) {
|
|
118
|
+
const langData = await langResponse.json();
|
|
119
|
+
if (langData.languages)
|
|
120
|
+
setLanguages(langData.languages);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Use defaults
|
|
125
|
+
}
|
|
126
|
+
// Fetch timezones (optional)
|
|
127
|
+
try {
|
|
128
|
+
const tzResponse = await fetch(timezonesEndpoint, { credentials: 'include' });
|
|
129
|
+
if (tzResponse.ok) {
|
|
130
|
+
const tzData = await tzResponse.json();
|
|
131
|
+
if (tzData.timezones)
|
|
132
|
+
setTimezones(tzData.timezones);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// Use defaults
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
setError('Failed to load settings');
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
setLoading(false);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!initialPreferences) {
|
|
147
|
+
fetchData();
|
|
148
|
+
}
|
|
149
|
+
}, [preferencesEndpoint, languagesEndpoint, timezonesEndpoint, initialPreferences]);
|
|
150
|
+
// Update preference value
|
|
151
|
+
const updatePreference = (0, react_1.useCallback)((section, key, value) => {
|
|
152
|
+
setPreferences((prev) => ({
|
|
153
|
+
...prev,
|
|
154
|
+
[section]: {
|
|
155
|
+
...prev[section],
|
|
156
|
+
[key]: value,
|
|
157
|
+
},
|
|
158
|
+
}));
|
|
159
|
+
}, []);
|
|
160
|
+
// Save preferences
|
|
161
|
+
const handleSave = (0, react_1.useCallback)(async () => {
|
|
162
|
+
try {
|
|
163
|
+
setSaving(true);
|
|
164
|
+
setError(null);
|
|
165
|
+
setSuccessMessage(null);
|
|
166
|
+
if (onSave) {
|
|
167
|
+
await onSave(preferences);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
const response = await fetch(preferencesEndpoint, {
|
|
171
|
+
method: 'PUT',
|
|
172
|
+
headers: { 'Content-Type': 'application/json' },
|
|
173
|
+
credentials: 'include',
|
|
174
|
+
body: JSON.stringify(preferences),
|
|
175
|
+
});
|
|
176
|
+
if (!response.ok) {
|
|
177
|
+
const data = await response.json();
|
|
178
|
+
throw new Error(data.message || 'Failed to save settings');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
setSuccessMessage('Settings saved successfully');
|
|
182
|
+
setTimeout(() => setSuccessMessage(null), 3000);
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
setError(err instanceof Error ? err.message : 'Failed to save settings');
|
|
186
|
+
}
|
|
187
|
+
finally {
|
|
188
|
+
setSaving(false);
|
|
189
|
+
}
|
|
190
|
+
}, [preferences, preferencesEndpoint, onSave]);
|
|
191
|
+
// Handle theme change
|
|
192
|
+
const handleThemeChange = (0, react_1.useCallback)((theme) => {
|
|
193
|
+
updatePreference('appearance', 'theme', theme);
|
|
194
|
+
onThemeChange?.(theme);
|
|
195
|
+
}, [updatePreference, onThemeChange]);
|
|
196
|
+
// Loading state
|
|
197
|
+
if (loading) {
|
|
198
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: `min-h-screen ${bgColor} flex items-center justify-center`, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center space-y-4", children: [(0, jsx_runtime_1.jsxs)("svg", { className: "animate-spin h-8 w-8 text-blue-500", viewBox: "0 0 24 24", fill: "none", children: [(0, jsx_runtime_1.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), (0, jsx_runtime_1.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" })] }), (0, jsx_runtime_1.jsx)("p", { className: textMuted, children: "Loading settings..." })] }) }));
|
|
199
|
+
}
|
|
200
|
+
const currentTheme = preferences.appearance?.theme || 'system';
|
|
201
|
+
const compactMode = preferences.appearance?.compact_mode || false;
|
|
202
|
+
const currentLanguage = preferences.localization?.language || 'en';
|
|
203
|
+
const currentTimezone = preferences.localization?.timezone || 'America/Los_Angeles';
|
|
204
|
+
const currentDateFormat = preferences.localization?.date_format || 'MM/DD/YYYY';
|
|
205
|
+
const emailEnabled = preferences.notifications?.email_enabled ?? true;
|
|
206
|
+
const smsEnabled = preferences.notifications?.sms_enabled ?? false;
|
|
207
|
+
const profileVisibility = preferences.privacy?.profile_visibility || 'team';
|
|
208
|
+
const showActivityStatus = preferences.privacy?.show_activity_status ?? true;
|
|
209
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: `min-h-screen ${bgColor}`, children: (0, jsx_runtime_1.jsxs)("div", { className: `max-w-2xl mx-auto ${layout?.padding || 'p-6'}`, children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-6", children: [(0, jsx_runtime_1.jsx)("h1", { className: `text-3xl font-bold ${textPrimary}`, children: "Settings" }), (0, jsx_runtime_1.jsx)("button", { onClick: handleSave, disabled: saving, className: `
|
|
210
|
+
px-4 py-2 rounded-md font-medium transition-colors
|
|
211
|
+
${saving ? 'opacity-50 cursor-not-allowed' : ''}
|
|
212
|
+
bg-blue-600 text-white hover:bg-blue-700
|
|
213
|
+
`, children: saving ? 'Saving...' : 'Save Changes' })] }), error && ((0, jsx_runtime_1.jsx)("div", { className: "mb-4 p-3 rounded-md bg-red-500/10 border border-red-500/50 text-red-500", children: error })), successMessage && ((0, jsx_runtime_1.jsx)("div", { className: "mb-4 p-3 rounded-md bg-green-500/10 border border-green-500/50 text-green-500", children: successMessage })), (0, jsx_runtime_1.jsxs)("div", { className: `${cardBg} rounded-lg shadow-lg border ${borderColor} p-6`, children: [(0, jsx_runtime_1.jsxs)(SettingsSection, { title: "Appearance", isDark: isDark, children: [(0, jsx_runtime_1.jsxs)("div", { className: "mb-4", children: [(0, jsx_runtime_1.jsx)("label", { className: `block text-sm font-medium ${textMuted} mb-2`, children: "Theme" }), (0, jsx_runtime_1.jsx)("div", { className: "flex gap-2", children: ['light', 'dark', 'system'].map((theme) => ((0, jsx_runtime_1.jsx)("button", { onClick: () => handleThemeChange(theme), className: `
|
|
214
|
+
px-4 py-2 rounded-md capitalize transition-colors
|
|
215
|
+
${currentTheme === theme
|
|
216
|
+
? 'bg-blue-600 text-white'
|
|
217
|
+
: isDark
|
|
218
|
+
? 'bg-slate-700 text-gray-300 hover:bg-slate-600'
|
|
219
|
+
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'}
|
|
220
|
+
`, children: theme }, theme))) })] }), (0, jsx_runtime_1.jsx)(SettingRow, { label: "Compact Mode", description: "Reduce spacing and padding for denser layouts", isDark: isDark, children: (0, jsx_runtime_1.jsx)(Toggle, { enabled: compactMode, onChange: (value) => updatePreference('appearance', 'compact_mode', value), isDark: isDark }) })] }), (0, jsx_runtime_1.jsx)(SettingsSection, { title: "Localization", isDark: isDark, children: (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { className: `block text-sm font-medium ${textMuted} mb-2`, children: "Language" }), (0, jsx_runtime_1.jsx)(Select, { value: currentLanguage, onChange: (value) => updatePreference('localization', 'language', value), options: languages.map((l) => ({ value: l.code, label: l.name })), isDark: isDark })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { className: `block text-sm font-medium ${textMuted} mb-2`, children: "Timezone" }), (0, jsx_runtime_1.jsx)(Select, { value: currentTimezone, onChange: (value) => updatePreference('localization', 'timezone', value), options: timezones.map((tz) => ({ value: tz.id, label: `${tz.display} (${tz.offset})` })), isDark: isDark }), preferences.localization?.timezone_display && ((0, jsx_runtime_1.jsxs)("p", { className: `mt-1 text-sm ${textMuted}`, children: ["Currently: ", preferences.localization.timezone_display] }))] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { className: `block text-sm font-medium ${textMuted} mb-2`, children: "Date Format" }), (0, jsx_runtime_1.jsx)(Select, { value: currentDateFormat, onChange: (value) => updatePreference('localization', 'date_format', value), options: DATE_FORMATS.map((df) => ({ value: df.value, label: df.label })), isDark: isDark }), (0, jsx_runtime_1.jsxs)("p", { className: `mt-1 text-sm ${textMuted}`, children: ["Example: ", DATE_FORMATS.find((df) => df.value === currentDateFormat)?.example] })] })] }) }), (0, jsx_runtime_1.jsxs)(SettingsSection, { title: "Notifications", isDark: isDark, children: [(0, jsx_runtime_1.jsx)(SettingRow, { label: "Email Notifications", description: "Receive updates and alerts via email", isDark: isDark, children: (0, jsx_runtime_1.jsx)(Toggle, { enabled: emailEnabled, onChange: (value) => updatePreference('notifications', 'email_enabled', value), isDark: isDark }) }), emailEnabled && ((0, jsx_runtime_1.jsxs)("div", { className: `ml-6 border-l-2 ${borderColor} pl-4 space-y-2`, children: [(0, jsx_runtime_1.jsx)(SettingRow, { label: "Security alerts", description: "Login from new device, etc.", isDark: isDark, children: (0, jsx_runtime_1.jsx)(Toggle, { enabled: preferences.notifications?.email_security_alerts ?? true, onChange: (value) => updatePreference('notifications', 'email_security_alerts', value), isDark: isDark }) }), (0, jsx_runtime_1.jsx)(SettingRow, { label: "Account updates", description: "Password expiry, etc.", isDark: isDark, children: (0, jsx_runtime_1.jsx)(Toggle, { enabled: preferences.notifications?.email_account_updates ?? true, onChange: (value) => updatePreference('notifications', 'email_account_updates', value), isDark: isDark }) }), (0, jsx_runtime_1.jsx)(SettingRow, { label: "Product news and tips", isDark: isDark, children: (0, jsx_runtime_1.jsx)(Toggle, { enabled: preferences.notifications?.email_product_news ?? false, onChange: (value) => updatePreference('notifications', 'email_product_news', value), isDark: isDark }) }), (0, jsx_runtime_1.jsx)(SettingRow, { label: "Marketing and promotions", isDark: isDark, children: (0, jsx_runtime_1.jsx)(Toggle, { enabled: preferences.notifications?.email_marketing ?? false, onChange: (value) => updatePreference('notifications', 'email_marketing', value), isDark: isDark }) })] })), (0, jsx_runtime_1.jsx)(SettingRow, { label: "SMS Notifications", description: "Receive urgent alerts via text message", isDark: isDark, children: (0, jsx_runtime_1.jsx)(Toggle, { enabled: smsEnabled, onChange: (value) => updatePreference('notifications', 'sms_enabled', value), isDark: isDark }) }), smsEnabled && ((0, jsx_runtime_1.jsx)("div", { className: `ml-6 border-l-2 ${borderColor} pl-4`, children: (0, jsx_runtime_1.jsx)(SettingRow, { label: "Security alerts only", isDark: isDark, children: (0, jsx_runtime_1.jsx)(Toggle, { enabled: preferences.notifications?.sms_security_alerts ?? true, onChange: (value) => updatePreference('notifications', 'sms_security_alerts', value), isDark: isDark }) }) }))] }), (0, jsx_runtime_1.jsxs)(SettingsSection, { title: "Privacy", isDark: isDark, children: [(0, jsx_runtime_1.jsxs)("div", { className: "mb-4", children: [(0, jsx_runtime_1.jsx)("label", { className: `block text-sm font-medium ${textMuted} mb-2`, children: "Profile Visibility" }), (0, jsx_runtime_1.jsx)("div", { className: "space-y-2", children: [
|
|
221
|
+
{ value: 'private', label: 'Private', description: 'Only you can see your profile' },
|
|
222
|
+
{ value: 'team', label: 'Team', description: 'Team members can see your profile' },
|
|
223
|
+
{ value: 'public', label: 'Public', description: 'Anyone can see your profile' },
|
|
224
|
+
].map((option) => ((0, jsx_runtime_1.jsxs)("label", { className: `flex items-center p-3 rounded-md cursor-pointer transition-colors ${profileVisibility === option.value
|
|
225
|
+
? isDark
|
|
226
|
+
? 'bg-blue-600/20 border border-blue-500'
|
|
227
|
+
: 'bg-blue-50 border border-blue-500'
|
|
228
|
+
: isDark
|
|
229
|
+
? 'bg-slate-700 hover:bg-slate-600'
|
|
230
|
+
: 'bg-gray-50 hover:bg-gray-100'}`, children: [(0, jsx_runtime_1.jsx)("input", { type: "radio", name: "profileVisibility", value: option.value, checked: profileVisibility === option.value, onChange: (e) => updatePreference('privacy', 'profile_visibility', e.target.value), className: "mr-3" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: `font-medium ${textPrimary}`, children: option.label }), (0, jsx_runtime_1.jsx)("p", { className: `text-sm ${textMuted}`, children: option.description })] })] }, option.value))) })] }), (0, jsx_runtime_1.jsx)(SettingRow, { label: "Activity Status", description: "Show when you're active to team members", isDark: isDark, children: (0, jsx_runtime_1.jsx)(Toggle, { enabled: showActivityStatus, onChange: (value) => updatePreference('privacy', 'show_activity_status', value), isDark: isDark }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-6 flex justify-between", children: [(0, jsx_runtime_1.jsx)("a", { href: "/account/security", className: `text-sm hover:underline ${textMuted}`, children: "\u2190 Security Settings" }), (0, jsx_runtime_1.jsx)("a", { href: "/account/profile", className: `text-sm hover:underline ${textMuted}`, children: "Back to Profile \u2192" })] })] }) }));
|
|
231
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Page exports
|
|
3
|
+
*
|
|
4
|
+
* - SettingsPage: Basic settings display (legacy)
|
|
5
|
+
* - EnhancedSettingsPage: Full-featured settings with appearance, localization, notifications, privacy
|
|
6
|
+
*/
|
|
7
|
+
export { default as SettingsPage } from './page';
|
|
8
|
+
export { default as EnhancedSettingsPage } from './EnhancedSettingsPage';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Settings Page exports
|
|
4
|
+
*
|
|
5
|
+
* - SettingsPage: Basic settings display (legacy)
|
|
6
|
+
* - EnhancedSettingsPage: Full-featured settings with appearance, localization, notifications, privacy
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EnhancedSettingsPage = exports.SettingsPage = void 0;
|
|
13
|
+
var page_1 = require("./page");
|
|
14
|
+
Object.defineProperty(exports, "SettingsPage", { enumerable: true, get: function () { return __importDefault(page_1).default; } });
|
|
15
|
+
var EnhancedSettingsPage_1 = require("./EnhancedSettingsPage");
|
|
16
|
+
Object.defineProperty(exports, "EnhancedSettingsPage", { enumerable: true, get: function () { return __importDefault(EnhancedSettingsPage_1).default; } });
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Basic Settings Page
|
|
4
|
+
*
|
|
5
|
+
* A simpler settings page that can be customized.
|
|
6
|
+
* For the full-featured version, use EnhancedSettingsPage.
|
|
7
|
+
*/
|
|
8
|
+
'use client';
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.default = SettingsPage;
|
|
11
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
12
|
+
const useTheme_1 = require("../../theme/useTheme");
|
|
13
|
+
function SettingsPage() {
|
|
14
|
+
const layout = (0, useTheme_1.useLayout)();
|
|
15
|
+
const colors = (0, useTheme_1.useColors)();
|
|
16
|
+
// Determine dark mode from theme colors
|
|
17
|
+
const isDark = colors?.background?.includes('slate-9') ||
|
|
18
|
+
colors?.background?.includes('gray-9') ||
|
|
19
|
+
colors?.card?.includes('slate-8');
|
|
20
|
+
const bgColor = isDark ? 'bg-slate-900' : 'bg-gray-50';
|
|
21
|
+
const cardBg = isDark ? 'bg-slate-800' : 'bg-white';
|
|
22
|
+
const borderColor = isDark ? 'border-slate-700' : 'border-gray-200';
|
|
23
|
+
const textPrimary = isDark ? 'text-white' : 'text-gray-900';
|
|
24
|
+
const textMuted = isDark ? 'text-gray-400' : 'text-gray-500';
|
|
25
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: `min-h-screen ${bgColor}`, children: (0, jsx_runtime_1.jsxs)("div", { className: `max-w-2xl mx-auto ${layout?.padding || 'p-6'}`, children: [(0, jsx_runtime_1.jsx)("h1", { className: `text-3xl font-bold ${textPrimary} mb-6`, children: "Settings" }), (0, jsx_runtime_1.jsx)("div", { className: `${cardBg} rounded-lg shadow-lg border ${borderColor} p-6`, children: (0, jsx_runtime_1.jsx)("p", { className: textMuted, children: "Settings page content goes here. Use EnhancedSettingsPage for a full-featured implementation." }) }), (0, jsx_runtime_1.jsx)("div", { className: "mt-6 text-center", children: (0, jsx_runtime_1.jsx)("a", { href: "/account/profile", className: `text-sm hover:underline ${textMuted}`, children: "Back to Profile" }) })] }) }));
|
|
26
|
+
}
|