hazo_auth 1.4.2 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -19
- package/SETUP_CHECKLIST.md +779 -0
- package/dist/app/api/hazo_auth/change_password/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/change_password/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/change_password/route.js +98 -0
- package/dist/app/api/hazo_auth/forgot_password/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/forgot_password/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/forgot_password/route.js +78 -0
- package/dist/app/api/hazo_auth/get_auth/route.d.ts +10 -0
- package/dist/app/api/hazo_auth/get_auth/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/get_auth/route.js +63 -0
- package/dist/app/api/hazo_auth/invalidate_cache/route.d.ts +14 -0
- package/dist/app/api/hazo_auth/invalidate_cache/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/invalidate_cache/route.js +96 -0
- package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.js +82 -0
- package/dist/app/api/hazo_auth/library_photos/route.d.ts +22 -0
- package/dist/app/api/hazo_auth/library_photos/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/library_photos/route.js +80 -0
- package/dist/app/api/hazo_auth/login/route.d.ts +12 -0
- package/dist/app/api/hazo_auth/login/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/login/route.js +140 -0
- package/dist/app/api/hazo_auth/logout/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/logout/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/logout/route.js +71 -0
- package/dist/app/api/hazo_auth/me/route.d.ts +3 -0
- package/dist/app/api/hazo_auth/me/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/me/route.js +34 -0
- package/dist/app/api/hazo_auth/profile_picture/[filename]/route.d.ts +7 -0
- package/dist/app/api/hazo_auth/profile_picture/[filename]/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/profile_picture/[filename]/route.js +43 -0
- package/dist/app/api/hazo_auth/register/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/register/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/register/route.js +80 -0
- package/dist/app/api/hazo_auth/remove_profile_picture/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/remove_profile_picture/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/remove_profile_picture/route.js +64 -0
- package/dist/app/api/hazo_auth/resend_verification/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/resend_verification/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/resend_verification/route.js +79 -0
- package/dist/app/api/hazo_auth/reset_password/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/reset_password/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/reset_password/route.js +76 -0
- package/dist/app/api/hazo_auth/update_user/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/update_user/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/update_user/route.js +95 -0
- package/dist/app/api/hazo_auth/upload_profile_picture/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/upload_profile_picture/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/upload_profile_picture/route.js +204 -0
- package/dist/app/api/hazo_auth/validate_reset_token/route.d.ts +6 -0
- package/dist/app/api/hazo_auth/validate_reset_token/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/validate_reset_token/route.js +58 -0
- package/dist/app/api/hazo_auth/verify_email/route.d.ts +11 -0
- package/dist/app/api/hazo_auth/verify_email/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/verify_email/route.js +63 -0
- package/dist/cli/generate.d.ts +7 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +184 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +173 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +201 -0
- package/dist/cli/validate.d.ts +15 -0
- package/dist/cli/validate.d.ts.map +1 -0
- package/dist/cli/validate.js +509 -0
- package/dist/components/ui/card.d.ts +9 -0
- package/dist/components/ui/card.d.ts.map +1 -0
- package/dist/components/ui/card.js +45 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -1
- package/dist/hooks/use-mobile.js +17 -3
- package/dist/lib/services/profile_picture_service.d.ts +34 -2
- package/dist/lib/services/profile_picture_service.d.ts.map +1 -1
- package/dist/lib/services/profile_picture_service.js +157 -15
- package/dist/page_components/forgot_password.d.ts +19 -0
- package/dist/page_components/forgot_password.d.ts.map +1 -0
- package/dist/page_components/forgot_password.js +36 -0
- package/dist/page_components/index.d.ts +7 -0
- package/dist/page_components/index.d.ts.map +1 -0
- package/dist/page_components/index.js +9 -0
- package/dist/page_components/login.d.ts +26 -0
- package/dist/page_components/login.d.ts.map +1 -0
- package/dist/page_components/login.js +40 -0
- package/dist/page_components/my_settings.d.ts +64 -0
- package/dist/page_components/my_settings.d.ts.map +1 -0
- package/dist/page_components/my_settings.js +67 -0
- package/dist/page_components/register.d.ts +25 -0
- package/dist/page_components/register.d.ts.map +1 -0
- package/dist/page_components/register.js +43 -0
- package/dist/page_components/reset_password.d.ts +25 -0
- package/dist/page_components/reset_password.d.ts.map +1 -0
- package/dist/page_components/reset_password.js +43 -0
- package/dist/page_components/verify_email.d.ts +21 -0
- package/dist/page_components/verify_email.d.ts.map +1 -0
- package/dist/page_components/verify_email.js +36 -0
- package/dist/server/routes/change_password.d.ts +2 -0
- package/dist/server/routes/change_password.d.ts.map +1 -0
- package/dist/server/routes/change_password.js +2 -0
- package/dist/server/routes/forgot_password.d.ts +2 -0
- package/dist/server/routes/forgot_password.d.ts.map +1 -0
- package/dist/server/routes/forgot_password.js +2 -0
- package/dist/server/routes/get_auth.d.ts +2 -0
- package/dist/server/routes/get_auth.d.ts.map +1 -0
- package/dist/server/routes/get_auth.js +2 -0
- package/dist/server/routes/index.d.ts +19 -0
- package/dist/server/routes/index.d.ts.map +1 -0
- package/dist/server/routes/index.js +25 -0
- package/dist/server/routes/invalidate_cache.d.ts +2 -0
- package/dist/server/routes/invalidate_cache.d.ts.map +1 -0
- package/dist/server/routes/invalidate_cache.js +2 -0
- package/dist/server/routes/library_photo.d.ts +2 -0
- package/dist/server/routes/library_photo.d.ts.map +1 -0
- package/dist/server/routes/library_photo.js +3 -0
- package/dist/server/routes/library_photos.d.ts +2 -0
- package/dist/server/routes/library_photos.d.ts.map +1 -0
- package/dist/server/routes/library_photos.js +2 -0
- package/dist/server/routes/login.d.ts +2 -0
- package/dist/server/routes/login.d.ts.map +1 -0
- package/dist/server/routes/login.js +2 -0
- package/dist/server/routes/logout.d.ts +2 -0
- package/dist/server/routes/logout.d.ts.map +1 -0
- package/dist/server/routes/logout.js +2 -0
- package/dist/server/routes/me.d.ts +2 -0
- package/dist/server/routes/me.d.ts.map +1 -0
- package/dist/server/routes/me.js +2 -0
- package/dist/server/routes/profile_picture_filename.d.ts +2 -0
- package/dist/server/routes/profile_picture_filename.d.ts.map +1 -0
- package/dist/server/routes/profile_picture_filename.js +3 -0
- package/dist/server/routes/register.d.ts +2 -0
- package/dist/server/routes/register.d.ts.map +1 -0
- package/dist/server/routes/register.js +2 -0
- package/dist/server/routes/remove_profile_picture.d.ts +2 -0
- package/dist/server/routes/remove_profile_picture.d.ts.map +1 -0
- package/dist/server/routes/remove_profile_picture.js +2 -0
- package/dist/server/routes/resend_verification.d.ts +2 -0
- package/dist/server/routes/resend_verification.d.ts.map +1 -0
- package/dist/server/routes/resend_verification.js +2 -0
- package/dist/server/routes/reset_password.d.ts +2 -0
- package/dist/server/routes/reset_password.d.ts.map +1 -0
- package/dist/server/routes/reset_password.js +2 -0
- package/dist/server/routes/update_user.d.ts +2 -0
- package/dist/server/routes/update_user.d.ts.map +1 -0
- package/dist/server/routes/update_user.js +2 -0
- package/dist/server/routes/upload_profile_picture.d.ts +2 -0
- package/dist/server/routes/upload_profile_picture.d.ts.map +1 -0
- package/dist/server/routes/upload_profile_picture.js +2 -0
- package/dist/server/routes/validate_reset_token.d.ts +2 -0
- package/dist/server/routes/validate_reset_token.d.ts.map +1 -0
- package/dist/server/routes/validate_reset_token.js +2 -0
- package/dist/server/routes/verify_email.d.ts +2 -0
- package/dist/server/routes/verify_email.d.ts.map +1 -0
- package/dist/server/routes/verify_email.js +2 -0
- package/package.json +40 -17
- package/components.json +0 -22
- package/instrumentation.ts +0 -32
- package/migrations/001_add_token_type_to_refresh_tokens.sql +0 -14
- package/migrations/002_add_name_to_hazo_users.sql +0 -7
- package/migrations/003_add_url_on_logon_to_hazo_users.sql +0 -8
- package/next.config.mjs +0 -67
- package/postcss.config.mjs +0 -8
- package/public/file.svg +0 -1
- package/public/globe.svg +0 -1
- package/public/next.svg +0 -1
- package/public/vercel.svg +0 -1
- package/public/window.svg +0 -1
- package/scripts/apply_migration.ts +0 -118
- package/scripts/init_users.ts +0 -378
- package/src/app/api/hazo_auth/auth/upload_profile_picture/route.ts +0 -268
- package/src/app/api/hazo_auth/change_password/route.ts +0 -132
- package/src/app/api/hazo_auth/forgot_password/route.ts +0 -107
- package/src/app/api/hazo_auth/get_auth/route.ts +0 -89
- package/src/app/api/hazo_auth/invalidate_cache/route.ts +0 -139
- package/src/app/api/hazo_auth/library_photos/route.ts +0 -73
- package/src/app/api/hazo_auth/login/route.ts +0 -181
- package/src/app/api/hazo_auth/logout/route.ts +0 -89
- package/src/app/api/hazo_auth/me/route.ts +0 -47
- package/src/app/api/hazo_auth/profile_picture/[filename]/route.ts +0 -67
- package/src/app/api/hazo_auth/register/route.ts +0 -109
- package/src/app/api/hazo_auth/remove_profile_picture/route.ts +0 -86
- package/src/app/api/hazo_auth/resend_verification/route.ts +0 -108
- package/src/app/api/hazo_auth/reset_password/route.ts +0 -107
- package/src/app/api/hazo_auth/update_user/route.ts +0 -126
- package/src/app/api/hazo_auth/upload_profile_picture/route.ts +0 -268
- package/src/app/api/hazo_auth/user_management/permissions/route.ts +0 -367
- package/src/app/api/hazo_auth/user_management/roles/route.ts +0 -442
- package/src/app/api/hazo_auth/user_management/users/roles/route.ts +0 -367
- package/src/app/api/hazo_auth/user_management/users/route.ts +0 -239
- package/src/app/api/hazo_auth/validate_reset_token/route.ts +0 -83
- package/src/app/api/hazo_auth/verify_email/route.ts +0 -88
- package/src/app/api/migrations/apply/route.ts +0 -91
- package/src/app/favicon.ico +0 -0
- package/src/app/fonts/GeistMonoVF.woff +0 -0
- package/src/app/fonts/GeistVF.woff +0 -0
- package/src/app/globals.css +0 -89
- package/src/app/hazo_auth/forgot_password/forgot_password_page_client.tsx +0 -60
- package/src/app/hazo_auth/forgot_password/page.tsx +0 -24
- package/src/app/hazo_auth/login/login_page_client.tsx +0 -86
- package/src/app/hazo_auth/login/page.tsx +0 -38
- package/src/app/hazo_auth/my_settings/my_settings_page_client.tsx +0 -120
- package/src/app/hazo_auth/my_settings/page.tsx +0 -40
- package/src/app/hazo_auth/register/page.tsx +0 -36
- package/src/app/hazo_auth/register/register_page_client.tsx +0 -81
- package/src/app/hazo_auth/reset_password/page.tsx +0 -29
- package/src/app/hazo_auth/reset_password/reset_password_page_client.tsx +0 -81
- package/src/app/hazo_auth/user_management/page.tsx +0 -14
- package/src/app/hazo_auth/user_management/user_management_page_client.tsx +0 -16
- package/src/app/hazo_auth/verify_email/page.tsx +0 -24
- package/src/app/hazo_auth/verify_email/verify_email_page_client.tsx +0 -60
- package/src/app/hazo_connect/api/sqlite/data/route.ts +0 -203
- package/src/app/hazo_connect/api/sqlite/schema/route.ts +0 -45
- package/src/app/hazo_connect/api/sqlite/tables/route.ts +0 -36
- package/src/app/hazo_connect/sqlite_admin/page.tsx +0 -51
- package/src/app/hazo_connect/sqlite_admin/sqlite-admin-client.tsx +0 -984
- package/src/app/layout.tsx +0 -43
- package/src/app/page.tsx +0 -170
- package/src/components/index.ts +0 -7
- package/src/components/layouts/email_verification/config/email_verification_field_config.ts +0 -86
- package/src/components/layouts/email_verification/hooks/use_email_verification.ts +0 -297
- package/src/components/layouts/email_verification/index.tsx +0 -297
- package/src/components/layouts/forgot_password/config/forgot_password_field_config.ts +0 -58
- package/src/components/layouts/forgot_password/hooks/use_forgot_password_form.ts +0 -179
- package/src/components/layouts/forgot_password/index.tsx +0 -168
- package/src/components/layouts/index.ts +0 -26
- package/src/components/layouts/login/config/login_field_config.ts +0 -67
- package/src/components/layouts/login/hooks/use_login_form.ts +0 -286
- package/src/components/layouts/login/index.tsx +0 -252
- package/src/components/layouts/my_settings/components/editable_field.tsx +0 -177
- package/src/components/layouts/my_settings/components/password_change_dialog.tsx +0 -301
- package/src/components/layouts/my_settings/components/profile_picture_dialog.tsx +0 -385
- package/src/components/layouts/my_settings/components/profile_picture_display.tsx +0 -66
- package/src/components/layouts/my_settings/components/profile_picture_gravatar_tab.tsx +0 -143
- package/src/components/layouts/my_settings/components/profile_picture_library_tab.tsx +0 -311
- package/src/components/layouts/my_settings/components/profile_picture_upload_tab.tsx +0 -341
- package/src/components/layouts/my_settings/config/my_settings_field_config.ts +0 -61
- package/src/components/layouts/my_settings/hooks/use_my_settings.ts +0 -458
- package/src/components/layouts/my_settings/index.tsx +0 -351
- package/src/components/layouts/register/config/register_field_config.ts +0 -101
- package/src/components/layouts/register/hooks/use_register_form.ts +0 -275
- package/src/components/layouts/register/index.tsx +0 -226
- package/src/components/layouts/reset_password/config/reset_password_field_config.ts +0 -86
- package/src/components/layouts/reset_password/hooks/use_reset_password_form.ts +0 -276
- package/src/components/layouts/reset_password/index.tsx +0 -294
- package/src/components/layouts/shared/components/already_logged_in_guard.tsx +0 -95
- package/src/components/layouts/shared/components/auth_page_shell.tsx +0 -36
- package/src/components/layouts/shared/components/field_error_message.tsx +0 -29
- package/src/components/layouts/shared/components/form_action_buttons.tsx +0 -64
- package/src/components/layouts/shared/components/form_field_wrapper.tsx +0 -44
- package/src/components/layouts/shared/components/form_header.tsx +0 -36
- package/src/components/layouts/shared/components/logout_button.tsx +0 -76
- package/src/components/layouts/shared/components/password_field.tsx +0 -72
- package/src/components/layouts/shared/components/profile_pic_menu.tsx +0 -321
- package/src/components/layouts/shared/components/profile_pic_menu_wrapper.tsx +0 -40
- package/src/components/layouts/shared/components/sidebar_layout_wrapper.tsx +0 -214
- package/src/components/layouts/shared/components/standalone_layout_wrapper.tsx +0 -53
- package/src/components/layouts/shared/components/two_column_auth_layout.tsx +0 -44
- package/src/components/layouts/shared/components/unauthorized_guard.tsx +0 -78
- package/src/components/layouts/shared/components/visual_panel.tsx +0 -41
- package/src/components/layouts/shared/config/layout_customization.ts +0 -95
- package/src/components/layouts/shared/data/layout_data_client.ts +0 -19
- package/src/components/layouts/shared/hooks/use_auth_status.ts +0 -103
- package/src/components/layouts/shared/hooks/use_hazo_auth.ts +0 -158
- package/src/components/layouts/shared/index.ts +0 -34
- package/src/components/layouts/shared/utils/ip_address.ts +0 -37
- package/src/components/layouts/shared/utils/validation.ts +0 -66
- package/src/components/layouts/user_management/components/roles_matrix.tsx +0 -607
- package/src/components/layouts/user_management/index.tsx +0 -1295
- package/src/components/ui/alert-dialog.tsx +0 -141
- package/src/components/ui/avatar.tsx +0 -50
- package/src/components/ui/button.tsx +0 -57
- package/src/components/ui/checkbox.tsx +0 -30
- package/src/components/ui/dialog.tsx +0 -122
- package/src/components/ui/dropdown-menu.tsx +0 -201
- package/src/components/ui/hazo_ui_tooltip.tsx +0 -67
- package/src/components/ui/index.ts +0 -22
- package/src/components/ui/input.tsx +0 -22
- package/src/components/ui/label.tsx +0 -26
- package/src/components/ui/separator.tsx +0 -31
- package/src/components/ui/sheet.tsx +0 -139
- package/src/components/ui/sidebar.tsx +0 -773
- package/src/components/ui/skeleton.tsx +0 -15
- package/src/components/ui/sonner.tsx +0 -31
- package/src/components/ui/switch.tsx +0 -29
- package/src/components/ui/table.tsx +0 -120
- package/src/components/ui/tabs.tsx +0 -55
- package/src/components/ui/tooltip.tsx +0 -32
- package/src/components/ui/vertical-tabs.tsx +0 -59
- package/src/hooks/use-mobile.tsx +0 -19
- package/src/index.ts +0 -7
- package/src/lib/already_logged_in_config.server.ts +0 -46
- package/src/lib/app_logger.ts +0 -24
- package/src/lib/auth/auth_cache.ts +0 -220
- package/src/lib/auth/auth_rate_limiter.ts +0 -121
- package/src/lib/auth/auth_types.ts +0 -65
- package/src/lib/auth/auth_utils.server.ts +0 -196
- package/src/lib/auth/hazo_get_auth.server.ts +0 -333
- package/src/lib/auth/index.ts +0 -23
- package/src/lib/auth/server_auth.ts +0 -88
- package/src/lib/auth_utility_config.server.ts +0 -136
- package/src/lib/config/config_loader.server.ts +0 -164
- package/src/lib/email_verification_config.server.ts +0 -32
- package/src/lib/file_types_config.server.ts +0 -25
- package/src/lib/forgot_password_config.server.ts +0 -32
- package/src/lib/hazo_connect_instance.server.ts +0 -101
- package/src/lib/hazo_connect_setup.server.ts +0 -194
- package/src/lib/hazo_connect_setup.ts +0 -54
- package/src/lib/index.ts +0 -44
- package/src/lib/login_config.server.ts +0 -71
- package/src/lib/messages_config.server.ts +0 -45
- package/src/lib/migrations/apply_migration.ts +0 -105
- package/src/lib/my_settings_config.server.ts +0 -135
- package/src/lib/password_requirements_config.server.ts +0 -39
- package/src/lib/profile_pic_menu_config.server.ts +0 -138
- package/src/lib/profile_picture_config.server.ts +0 -56
- package/src/lib/register_config.server.ts +0 -73
- package/src/lib/reset_password_config.server.ts +0 -75
- package/src/lib/services/email_service.ts +0 -581
- package/src/lib/services/email_verification_service.ts +0 -270
- package/src/lib/services/index.ts +0 -15
- package/src/lib/services/login_service.ts +0 -134
- package/src/lib/services/password_change_service.ts +0 -154
- package/src/lib/services/password_reset_service.ts +0 -405
- package/src/lib/services/profile_picture_remove_service.ts +0 -120
- package/src/lib/services/profile_picture_service.ts +0 -215
- package/src/lib/services/profile_picture_source_mapper.ts +0 -62
- package/src/lib/services/registration_service.ts +0 -184
- package/src/lib/services/token_service.ts +0 -240
- package/src/lib/services/user_profiles_service.ts +0 -143
- package/src/lib/services/user_update_service.ts +0 -141
- package/src/lib/ui_shell_config.server.ts +0 -73
- package/src/lib/ui_sizes_config.server.ts +0 -37
- package/src/lib/user_fields_config.server.ts +0 -31
- package/src/lib/user_management_config.server.ts +0 -39
- package/src/lib/utils/api_route_helpers.ts +0 -60
- package/src/lib/utils/error_sanitizer.ts +0 -75
- package/src/lib/utils.ts +0 -11
- package/src/middleware.ts +0 -94
- package/src/routes/index.ts +0 -34
- package/src/server/config/config_loader.ts +0 -496
- package/src/server/index.ts +0 -38
- package/src/server/logging/logger_service.ts +0 -56
- package/src/server/routes/root_router.ts +0 -16
- package/src/server/server.ts +0 -28
- package/src/server/types/app_types.ts +0 -74
- package/src/server/types/express.d.ts +0 -16
- package/src/stories/email_verification_layout.stories.tsx +0 -137
- package/src/stories/forgot_password_layout.stories.tsx +0 -85
- package/src/stories/login_layout.stories.tsx +0 -85
- package/src/stories/project_overview.stories.tsx +0 -33
- package/src/stories/register_layout.stories.tsx +0 -107
- package/tailwind.config.ts +0 -77
- package/tsconfig.build.json +0 -36
- package/tsconfig.json +0 -28
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// file_description: reusable error message component for form field validation errors
|
|
2
|
-
// section: types
|
|
3
|
-
type FieldErrorMessageProps = {
|
|
4
|
-
message: string | string[];
|
|
5
|
-
className?: string;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
// section: component
|
|
9
|
-
export function FieldErrorMessage({
|
|
10
|
-
message,
|
|
11
|
-
className,
|
|
12
|
-
}: FieldErrorMessageProps) {
|
|
13
|
-
const messages = Array.isArray(message) ? message : [message];
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<div
|
|
17
|
-
className={`cls_field_error_message flex flex-col gap-1 text-sm text-red-600 ${className ?? ""}`}
|
|
18
|
-
role="alert"
|
|
19
|
-
aria-live="polite"
|
|
20
|
-
>
|
|
21
|
-
{messages.map((msg, index) => (
|
|
22
|
-
<p key={index} className="break-words leading-relaxed">
|
|
23
|
-
{msg}
|
|
24
|
-
</p>
|
|
25
|
-
))}
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
// file_description: reusable form action buttons component with submit (positive, left) and cancel (negative, right) buttons
|
|
2
|
-
// section: imports
|
|
3
|
-
import { CircleCheckBig, CircleX } from "lucide-react";
|
|
4
|
-
import { Button } from "../../../ui/button";
|
|
5
|
-
import type { ButtonPaletteDefaults } from "../config/layout_customization";
|
|
6
|
-
|
|
7
|
-
// section: types
|
|
8
|
-
type FormActionButtonsProps = {
|
|
9
|
-
submitLabel: string;
|
|
10
|
-
cancelLabel: string;
|
|
11
|
-
buttonPalette: ButtonPaletteDefaults;
|
|
12
|
-
isSubmitDisabled: boolean;
|
|
13
|
-
onCancel: () => void;
|
|
14
|
-
submitAriaLabel?: string;
|
|
15
|
-
cancelAriaLabel?: string;
|
|
16
|
-
className?: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
// section: component
|
|
20
|
-
export function FormActionButtons({
|
|
21
|
-
submitLabel,
|
|
22
|
-
cancelLabel,
|
|
23
|
-
buttonPalette,
|
|
24
|
-
isSubmitDisabled,
|
|
25
|
-
onCancel,
|
|
26
|
-
submitAriaLabel = "Submit form",
|
|
27
|
-
cancelAriaLabel = "Cancel form",
|
|
28
|
-
className,
|
|
29
|
-
}: FormActionButtonsProps) {
|
|
30
|
-
return (
|
|
31
|
-
<div
|
|
32
|
-
className={`cls_form_action_buttons mt-2 flex items-center justify-end gap-4 ${className ?? ""}`}
|
|
33
|
-
>
|
|
34
|
-
<Button
|
|
35
|
-
type="submit"
|
|
36
|
-
disabled={isSubmitDisabled}
|
|
37
|
-
className="cls_form_action_submit_button flex items-center gap-2"
|
|
38
|
-
aria-label={submitAriaLabel}
|
|
39
|
-
style={{
|
|
40
|
-
backgroundColor: buttonPalette.submitBackground,
|
|
41
|
-
color: buttonPalette.submitText,
|
|
42
|
-
}}
|
|
43
|
-
>
|
|
44
|
-
<CircleCheckBig className="h-4 w-4" aria-hidden="true" />
|
|
45
|
-
<span>{submitLabel}</span>
|
|
46
|
-
</Button>
|
|
47
|
-
<Button
|
|
48
|
-
type="button"
|
|
49
|
-
variant="outline"
|
|
50
|
-
onClick={onCancel}
|
|
51
|
-
className="cls_form_action_cancel_button flex items-center gap-2"
|
|
52
|
-
aria-label={cancelAriaLabel}
|
|
53
|
-
style={{
|
|
54
|
-
borderColor: buttonPalette.cancelBorder,
|
|
55
|
-
color: buttonPalette.cancelText,
|
|
56
|
-
}}
|
|
57
|
-
>
|
|
58
|
-
<CircleX className="h-4 w-4" aria-hidden="true" />
|
|
59
|
-
<span>{cancelLabel}</span>
|
|
60
|
-
</Button>
|
|
61
|
-
</div>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// file_description: reusable wrapper component for form fields that standardizes label, input, and error message structure
|
|
2
|
-
// section: imports
|
|
3
|
-
import { Label } from "../../../ui/label";
|
|
4
|
-
import { FieldErrorMessage } from "./field_error_message";
|
|
5
|
-
|
|
6
|
-
// section: types
|
|
7
|
-
type FormFieldWrapperProps = {
|
|
8
|
-
fieldId: string;
|
|
9
|
-
label: string;
|
|
10
|
-
input: React.ReactNode;
|
|
11
|
-
errorMessage?: string | string[];
|
|
12
|
-
className?: string;
|
|
13
|
-
labelClassName?: string;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
// section: component
|
|
17
|
-
export function FormFieldWrapper({
|
|
18
|
-
fieldId,
|
|
19
|
-
label,
|
|
20
|
-
input,
|
|
21
|
-
errorMessage,
|
|
22
|
-
className,
|
|
23
|
-
labelClassName,
|
|
24
|
-
}: FormFieldWrapperProps) {
|
|
25
|
-
return (
|
|
26
|
-
<div
|
|
27
|
-
className={`cls_form_field_wrapper flex flex-col gap-2 ${className ?? ""}`}
|
|
28
|
-
>
|
|
29
|
-
<Label
|
|
30
|
-
htmlFor={fieldId}
|
|
31
|
-
className={`cls_form_field_label text-sm font-medium text-slate-800 ${labelClassName ?? ""}`}
|
|
32
|
-
>
|
|
33
|
-
{label}
|
|
34
|
-
</Label>
|
|
35
|
-
{input}
|
|
36
|
-
{errorMessage ? (
|
|
37
|
-
<div className="mt-1 min-h-0">
|
|
38
|
-
<FieldErrorMessage message={errorMessage} />
|
|
39
|
-
</div>
|
|
40
|
-
) : null}
|
|
41
|
-
</div>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
// file_description: reusable form header component for displaying heading and subheading in authentication layouts
|
|
2
|
-
// section: types
|
|
3
|
-
type FormHeaderProps = {
|
|
4
|
-
heading: string;
|
|
5
|
-
subHeading: string;
|
|
6
|
-
className?: string;
|
|
7
|
-
headingClassName?: string;
|
|
8
|
-
subHeadingClassName?: string;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
// section: component
|
|
12
|
-
export function FormHeader({
|
|
13
|
-
heading,
|
|
14
|
-
subHeading,
|
|
15
|
-
className,
|
|
16
|
-
headingClassName,
|
|
17
|
-
subHeadingClassName,
|
|
18
|
-
}: FormHeaderProps) {
|
|
19
|
-
return (
|
|
20
|
-
<header
|
|
21
|
-
className={`cls_form_header flex flex-col gap-2 text-center md:text-left ${className ?? ""}`}
|
|
22
|
-
>
|
|
23
|
-
<h1
|
|
24
|
-
className={`cls_form_header_title text-2xl font-semibold text-slate-900 ${headingClassName ?? ""}`}
|
|
25
|
-
>
|
|
26
|
-
{heading}
|
|
27
|
-
</h1>
|
|
28
|
-
<p
|
|
29
|
-
className={`cls_form_header_subtitle text-sm text-slate-600 ${subHeadingClassName ?? ""}`}
|
|
30
|
-
>
|
|
31
|
-
{subHeading}
|
|
32
|
-
</p>
|
|
33
|
-
</header>
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
// file_description: logout button component for user logout functionality
|
|
2
|
-
// section: client_directive
|
|
3
|
-
"use client";
|
|
4
|
-
|
|
5
|
-
// section: imports
|
|
6
|
-
import { useState } from "react";
|
|
7
|
-
import { useRouter } from "next/navigation";
|
|
8
|
-
import { Button } from "../../../ui/button";
|
|
9
|
-
import { LogOut } from "lucide-react";
|
|
10
|
-
import { toast } from "sonner";
|
|
11
|
-
import { trigger_auth_status_refresh } from "../hooks/use_auth_status";
|
|
12
|
-
|
|
13
|
-
// section: types
|
|
14
|
-
export type LogoutButtonProps = {
|
|
15
|
-
className?: string;
|
|
16
|
-
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
|
|
17
|
-
size?: "default" | "sm" | "lg" | "icon";
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
// section: component
|
|
21
|
-
export function LogoutButton({
|
|
22
|
-
className,
|
|
23
|
-
variant = "outline",
|
|
24
|
-
size = "default",
|
|
25
|
-
}: LogoutButtonProps) {
|
|
26
|
-
const router = useRouter();
|
|
27
|
-
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
|
28
|
-
|
|
29
|
-
const handleLogout = async () => {
|
|
30
|
-
setIsLoggingOut(true);
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const response = await fetch("/api/hazo_auth/logout", {
|
|
34
|
-
method: "POST",
|
|
35
|
-
headers: {
|
|
36
|
-
"Content-Type": "application/json",
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const data = await response.json();
|
|
41
|
-
|
|
42
|
-
if (!response.ok || !data.success) {
|
|
43
|
-
throw new Error(data.error || "Logout failed");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
toast.success("Logged out successfully");
|
|
47
|
-
|
|
48
|
-
// Trigger auth status refresh in all components (navbar, sidebar, etc.)
|
|
49
|
-
trigger_auth_status_refresh();
|
|
50
|
-
|
|
51
|
-
// Refresh the page to update authentication state (cookies are cleared server-side)
|
|
52
|
-
router.refresh();
|
|
53
|
-
} catch (error) {
|
|
54
|
-
const errorMessage =
|
|
55
|
-
error instanceof Error ? error.message : "Logout failed. Please try again.";
|
|
56
|
-
toast.error(errorMessage);
|
|
57
|
-
} finally {
|
|
58
|
-
setIsLoggingOut(false);
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<Button
|
|
64
|
-
onClick={handleLogout}
|
|
65
|
-
disabled={isLoggingOut}
|
|
66
|
-
variant={variant}
|
|
67
|
-
size={size}
|
|
68
|
-
className={className}
|
|
69
|
-
aria-label="Logout"
|
|
70
|
-
>
|
|
71
|
-
<LogOut className="h-4 w-4 mr-2" aria-hidden="true" />
|
|
72
|
-
{isLoggingOut ? "Logging out..." : "Logout"}
|
|
73
|
-
</Button>
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
// file_description: reusable password input with visibility toggle and error messaging
|
|
2
|
-
// section: client_directive
|
|
3
|
-
"use client";
|
|
4
|
-
|
|
5
|
-
// section: imports
|
|
6
|
-
import { Eye, EyeOff } from "lucide-react";
|
|
7
|
-
import { Button } from "../../../ui/button";
|
|
8
|
-
import { Input } from "../../../ui/input";
|
|
9
|
-
import { FieldErrorMessage } from "./field_error_message";
|
|
10
|
-
|
|
11
|
-
// section: types
|
|
12
|
-
export type PasswordFieldProps = {
|
|
13
|
-
inputId: string;
|
|
14
|
-
ariaLabel: string;
|
|
15
|
-
value: string;
|
|
16
|
-
placeholder: string;
|
|
17
|
-
autoComplete?: string;
|
|
18
|
-
isVisible: boolean;
|
|
19
|
-
onChange: (value: string) => void;
|
|
20
|
-
onToggleVisibility: () => void;
|
|
21
|
-
errorMessage?: string | string[];
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// section: component
|
|
25
|
-
export function PasswordField({
|
|
26
|
-
inputId,
|
|
27
|
-
ariaLabel,
|
|
28
|
-
value,
|
|
29
|
-
placeholder,
|
|
30
|
-
autoComplete,
|
|
31
|
-
isVisible,
|
|
32
|
-
onChange,
|
|
33
|
-
onToggleVisibility,
|
|
34
|
-
errorMessage,
|
|
35
|
-
}: PasswordFieldProps) {
|
|
36
|
-
return (
|
|
37
|
-
<div className="cls_password_field_wrapper">
|
|
38
|
-
<div className="relative">
|
|
39
|
-
<Input
|
|
40
|
-
id={inputId}
|
|
41
|
-
type={isVisible ? "text" : "password"}
|
|
42
|
-
value={value}
|
|
43
|
-
onChange={(event) => onChange(event.target.value)}
|
|
44
|
-
autoComplete={autoComplete}
|
|
45
|
-
placeholder={placeholder}
|
|
46
|
-
aria-label={ariaLabel}
|
|
47
|
-
className="cls_password_field_input pr-11"
|
|
48
|
-
/>
|
|
49
|
-
<Button
|
|
50
|
-
type="button"
|
|
51
|
-
variant="ghost"
|
|
52
|
-
size="icon"
|
|
53
|
-
aria-label={`${isVisible ? "Hide" : "Show"} ${ariaLabel.toLowerCase()}`}
|
|
54
|
-
onClick={onToggleVisibility}
|
|
55
|
-
className="cls_password_field_toggle absolute right-1 top-1/2 -translate-y-1/2 text-slate-600 hover:text-slate-900"
|
|
56
|
-
>
|
|
57
|
-
{isVisible ? (
|
|
58
|
-
<EyeOff className="h-4 w-4" aria-hidden="true" />
|
|
59
|
-
) : (
|
|
60
|
-
<Eye className="h-4 w-4" aria-hidden="true" />
|
|
61
|
-
)}
|
|
62
|
-
</Button>
|
|
63
|
-
</div>
|
|
64
|
-
{errorMessage ? (
|
|
65
|
-
<div className="mt-1 min-h-0">
|
|
66
|
-
<FieldErrorMessage message={errorMessage} />
|
|
67
|
-
</div>
|
|
68
|
-
) : null}
|
|
69
|
-
</div>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
// file_description: profile picture menu component for navbar or sidebar - shows profile picture when logged in, or sign up/sign in buttons when not logged in
|
|
2
|
-
// section: client_directive
|
|
3
|
-
"use client";
|
|
4
|
-
|
|
5
|
-
// section: imports
|
|
6
|
-
import { useState, useMemo } from "react";
|
|
7
|
-
import { useRouter } from "next/navigation";
|
|
8
|
-
import Link from "next/link";
|
|
9
|
-
import { Avatar, AvatarImage, AvatarFallback } from "../../../ui/avatar";
|
|
10
|
-
import { Button } from "../../../ui/button";
|
|
11
|
-
import {
|
|
12
|
-
DropdownMenu,
|
|
13
|
-
DropdownMenuContent,
|
|
14
|
-
DropdownMenuItem,
|
|
15
|
-
DropdownMenuSeparator,
|
|
16
|
-
DropdownMenuTrigger,
|
|
17
|
-
} from "../../../ui/dropdown-menu";
|
|
18
|
-
import { Settings, LogOut } from "lucide-react";
|
|
19
|
-
import { toast } from "sonner";
|
|
20
|
-
import { use_auth_status, trigger_auth_status_refresh } from "../hooks/use_auth_status";
|
|
21
|
-
// Type-only import from server file is safe (types are erased at runtime)
|
|
22
|
-
import type { ProfilePicMenuMenuItem } from "../../../../lib/profile_pic_menu_config.server";
|
|
23
|
-
|
|
24
|
-
// section: types
|
|
25
|
-
export type ProfilePicMenuProps = {
|
|
26
|
-
show_single_button?: boolean;
|
|
27
|
-
sign_up_label?: string;
|
|
28
|
-
sign_in_label?: string;
|
|
29
|
-
register_path?: string;
|
|
30
|
-
login_path?: string;
|
|
31
|
-
settings_path?: string;
|
|
32
|
-
logout_path?: string;
|
|
33
|
-
custom_menu_items?: ProfilePicMenuMenuItem[];
|
|
34
|
-
className?: string;
|
|
35
|
-
avatar_size?: "default" | "sm" | "lg";
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
// section: component
|
|
39
|
-
/**
|
|
40
|
-
* Profile picture menu component
|
|
41
|
-
* Shows user profile picture when authenticated, or sign up/sign in buttons when not authenticated
|
|
42
|
-
* Clicking profile picture opens dropdown menu with user info and actions
|
|
43
|
-
* @param props - Component props including configuration options
|
|
44
|
-
* @returns Profile picture menu component
|
|
45
|
-
*/
|
|
46
|
-
export function ProfilePicMenu({
|
|
47
|
-
show_single_button = false,
|
|
48
|
-
sign_up_label = "Sign Up",
|
|
49
|
-
sign_in_label = "Sign In",
|
|
50
|
-
register_path = "/hazo_auth/register",
|
|
51
|
-
login_path = "/hazo_auth/login",
|
|
52
|
-
settings_path = "/hazo_auth/my_settings",
|
|
53
|
-
logout_path = "/api/hazo_auth/logout",
|
|
54
|
-
custom_menu_items = [],
|
|
55
|
-
className,
|
|
56
|
-
avatar_size = "default",
|
|
57
|
-
}: ProfilePicMenuProps) {
|
|
58
|
-
const router = useRouter();
|
|
59
|
-
const authStatus = use_auth_status();
|
|
60
|
-
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
|
61
|
-
|
|
62
|
-
// Get initials from name or email
|
|
63
|
-
const getInitials = (): string => {
|
|
64
|
-
if (authStatus.name) {
|
|
65
|
-
const parts = authStatus.name.trim().split(" ");
|
|
66
|
-
if (parts.length >= 2) {
|
|
67
|
-
return `${parts[0][0]}${parts[parts.length - 1][0]}`.toUpperCase();
|
|
68
|
-
}
|
|
69
|
-
return authStatus.name[0]?.toUpperCase() || "";
|
|
70
|
-
}
|
|
71
|
-
if (authStatus.email) {
|
|
72
|
-
return authStatus.email[0]?.toUpperCase() || "";
|
|
73
|
-
}
|
|
74
|
-
return "?";
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// Handle logout
|
|
78
|
-
const handleLogout = async () => {
|
|
79
|
-
setIsLoggingOut(true);
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
const response = await fetch(logout_path, {
|
|
83
|
-
method: "POST",
|
|
84
|
-
headers: {
|
|
85
|
-
"Content-Type": "application/json",
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const data = await response.json();
|
|
90
|
-
|
|
91
|
-
if (!response.ok || !data.success) {
|
|
92
|
-
throw new Error(data.error || "Logout failed");
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
toast.success("Logged out successfully");
|
|
96
|
-
|
|
97
|
-
// Trigger auth status refresh in all components
|
|
98
|
-
trigger_auth_status_refresh();
|
|
99
|
-
|
|
100
|
-
// Refresh the page to update authentication state
|
|
101
|
-
router.refresh();
|
|
102
|
-
} catch (error) {
|
|
103
|
-
const errorMessage =
|
|
104
|
-
error instanceof Error ? error.message : "Logout failed. Please try again.";
|
|
105
|
-
toast.error(errorMessage);
|
|
106
|
-
} finally {
|
|
107
|
-
setIsLoggingOut(false);
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
// Build menu items with default items and custom items
|
|
112
|
-
const menuItems = useMemo(() => {
|
|
113
|
-
const items: ProfilePicMenuMenuItem[] = [];
|
|
114
|
-
|
|
115
|
-
// Add default info items (only if authenticated)
|
|
116
|
-
if (authStatus.authenticated) {
|
|
117
|
-
// User name (info, order: 1)
|
|
118
|
-
if (authStatus.name) {
|
|
119
|
-
items.push({
|
|
120
|
-
type: "info",
|
|
121
|
-
value: authStatus.name,
|
|
122
|
-
order: 1,
|
|
123
|
-
id: "default_name",
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Email address (info, order: 2)
|
|
128
|
-
if (authStatus.email) {
|
|
129
|
-
items.push({
|
|
130
|
-
type: "info",
|
|
131
|
-
value: authStatus.email,
|
|
132
|
-
order: 2,
|
|
133
|
-
id: "default_email",
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Separator (order: 1)
|
|
138
|
-
items.push({
|
|
139
|
-
type: "separator",
|
|
140
|
-
order: 1,
|
|
141
|
-
id: "default_separator",
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
// Settings (link, order: 1)
|
|
145
|
-
items.push({
|
|
146
|
-
type: "link",
|
|
147
|
-
label: "Settings",
|
|
148
|
-
href: settings_path,
|
|
149
|
-
order: 1,
|
|
150
|
-
id: "default_settings",
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
// Logout (link, order: 2)
|
|
154
|
-
items.push({
|
|
155
|
-
type: "link",
|
|
156
|
-
label: "Logout",
|
|
157
|
-
href: logout_path,
|
|
158
|
-
order: 2,
|
|
159
|
-
id: "default_logout",
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Add custom menu items
|
|
164
|
-
items.push(...custom_menu_items);
|
|
165
|
-
|
|
166
|
-
// Sort items by type group and order
|
|
167
|
-
// Order: info items first, then separators, then links
|
|
168
|
-
items.sort((a, b) => {
|
|
169
|
-
// Define type priority: info = 0, separator = 1, link = 2
|
|
170
|
-
const typePriority = { info: 0, separator: 1, link: 2 };
|
|
171
|
-
const aPriority = typePriority[a.type];
|
|
172
|
-
const bPriority = typePriority[b.type];
|
|
173
|
-
|
|
174
|
-
if (aPriority !== bPriority) {
|
|
175
|
-
return aPriority - bPriority;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Within same type, sort by order
|
|
179
|
-
return a.order - b.order;
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
return items;
|
|
183
|
-
}, [authStatus.authenticated, authStatus.name, authStatus.email, settings_path, logout_path, custom_menu_items]);
|
|
184
|
-
|
|
185
|
-
// Avatar size classes
|
|
186
|
-
const avatarSizeClasses = {
|
|
187
|
-
sm: "h-8 w-8",
|
|
188
|
-
default: "h-10 w-10",
|
|
189
|
-
lg: "h-12 w-12",
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
// Show loading state
|
|
193
|
-
if (authStatus.loading) {
|
|
194
|
-
return (
|
|
195
|
-
<div className={`cls_profile_pic_menu ${className || ""}`}>
|
|
196
|
-
<div className="h-10 w-10 rounded-full bg-slate-200 animate-pulse" />
|
|
197
|
-
</div>
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Not authenticated - show sign up/sign in buttons
|
|
202
|
-
if (!authStatus.authenticated) {
|
|
203
|
-
return (
|
|
204
|
-
<div className={`cls_profile_pic_menu flex items-center gap-2 ${className || ""}`}>
|
|
205
|
-
{show_single_button ? (
|
|
206
|
-
<Button asChild variant="default" size="sm">
|
|
207
|
-
<Link href={register_path} className="cls_profile_pic_menu_sign_up">
|
|
208
|
-
{sign_up_label}
|
|
209
|
-
</Link>
|
|
210
|
-
</Button>
|
|
211
|
-
) : (
|
|
212
|
-
<>
|
|
213
|
-
<Button asChild variant="outline" size="sm">
|
|
214
|
-
<Link href={register_path} className="cls_profile_pic_menu_sign_up">
|
|
215
|
-
{sign_up_label}
|
|
216
|
-
</Link>
|
|
217
|
-
</Button>
|
|
218
|
-
<Button asChild variant="default" size="sm">
|
|
219
|
-
<Link href={login_path} className="cls_profile_pic_menu_sign_in">
|
|
220
|
-
{sign_in_label}
|
|
221
|
-
</Link>
|
|
222
|
-
</Button>
|
|
223
|
-
</>
|
|
224
|
-
)}
|
|
225
|
-
</div>
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Authenticated - show profile picture with dropdown menu
|
|
230
|
-
return (
|
|
231
|
-
<div className={`cls_profile_pic_menu ${className || ""}`}>
|
|
232
|
-
<DropdownMenu>
|
|
233
|
-
<DropdownMenuTrigger asChild>
|
|
234
|
-
<button
|
|
235
|
-
className="cls_profile_pic_menu_trigger focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary rounded-full"
|
|
236
|
-
aria-label="Profile menu"
|
|
237
|
-
>
|
|
238
|
-
<Avatar className={`cls_profile_pic_menu_avatar ${avatarSizeClasses[avatar_size]} cursor-pointer`}>
|
|
239
|
-
<AvatarImage
|
|
240
|
-
src={authStatus.profile_picture_url}
|
|
241
|
-
alt={authStatus.name ? `Profile picture of ${authStatus.name}` : "Profile picture"}
|
|
242
|
-
className="cls_profile_pic_menu_image"
|
|
243
|
-
/>
|
|
244
|
-
<AvatarFallback className="cls_profile_pic_menu_fallback bg-slate-200 text-slate-600">
|
|
245
|
-
{getInitials()}
|
|
246
|
-
</AvatarFallback>
|
|
247
|
-
</Avatar>
|
|
248
|
-
</button>
|
|
249
|
-
</DropdownMenuTrigger>
|
|
250
|
-
<DropdownMenuContent align="end" className="cls_profile_pic_menu_dropdown w-56">
|
|
251
|
-
{menuItems.map((item) => {
|
|
252
|
-
if (item.type === "separator") {
|
|
253
|
-
return <DropdownMenuSeparator key={item.id} className="cls_profile_pic_menu_separator" />;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (item.type === "info") {
|
|
257
|
-
return (
|
|
258
|
-
<div key={item.id} className="cls_profile_pic_menu_info">
|
|
259
|
-
{item.value && (
|
|
260
|
-
<div className="cls_profile_pic_menu_info_value px-2 py-1.5 text-sm text-foreground">
|
|
261
|
-
{item.value}
|
|
262
|
-
</div>
|
|
263
|
-
)}
|
|
264
|
-
</div>
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (item.type === "link") {
|
|
269
|
-
// Special handling for logout
|
|
270
|
-
if (item.id === "default_logout") {
|
|
271
|
-
return (
|
|
272
|
-
<DropdownMenuItem
|
|
273
|
-
key={item.id}
|
|
274
|
-
onClick={handleLogout}
|
|
275
|
-
disabled={isLoggingOut}
|
|
276
|
-
className="cls_profile_pic_menu_logout cursor-pointer text-destructive focus:text-destructive"
|
|
277
|
-
>
|
|
278
|
-
<LogOut className="mr-2 h-4 w-4" />
|
|
279
|
-
{isLoggingOut ? "Logging out..." : item.label}
|
|
280
|
-
</DropdownMenuItem>
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Special handling for settings
|
|
285
|
-
if (item.id === "default_settings") {
|
|
286
|
-
return (
|
|
287
|
-
<DropdownMenuItem
|
|
288
|
-
key={item.id}
|
|
289
|
-
asChild
|
|
290
|
-
className="cls_profile_pic_menu_settings cursor-pointer"
|
|
291
|
-
>
|
|
292
|
-
<Link href={item.href || settings_path}>
|
|
293
|
-
<Settings className="mr-2 h-4 w-4" />
|
|
294
|
-
{item.label}
|
|
295
|
-
</Link>
|
|
296
|
-
</DropdownMenuItem>
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Generic link handling
|
|
301
|
-
return (
|
|
302
|
-
<DropdownMenuItem
|
|
303
|
-
key={item.id}
|
|
304
|
-
asChild
|
|
305
|
-
className="cls_profile_pic_menu_link cursor-pointer"
|
|
306
|
-
>
|
|
307
|
-
<Link href={item.href || "#"}>
|
|
308
|
-
{item.label}
|
|
309
|
-
</Link>
|
|
310
|
-
</DropdownMenuItem>
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return null;
|
|
315
|
-
})}
|
|
316
|
-
</DropdownMenuContent>
|
|
317
|
-
</DropdownMenu>
|
|
318
|
-
</div>
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// file_description: server wrapper component that loads profile picture menu configuration and passes to client component
|
|
2
|
-
// section: imports
|
|
3
|
-
import { ProfilePicMenu } from "./profile_pic_menu";
|
|
4
|
-
import { get_profile_pic_menu_config } from "../../../../lib/profile_pic_menu_config.server";
|
|
5
|
-
|
|
6
|
-
// section: types
|
|
7
|
-
export type ProfilePicMenuWrapperProps = {
|
|
8
|
-
className?: string;
|
|
9
|
-
avatar_size?: "default" | "sm" | "lg";
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
// section: component
|
|
13
|
-
/**
|
|
14
|
-
* Server wrapper component that loads profile picture menu configuration from hazo_auth_config.ini
|
|
15
|
-
* and passes it to the client ProfilePicMenu component
|
|
16
|
-
* @param props - Component props including className and avatar_size
|
|
17
|
-
* @returns ProfilePicMenu component with loaded configuration
|
|
18
|
-
*/
|
|
19
|
-
export function ProfilePicMenuWrapper({
|
|
20
|
-
className,
|
|
21
|
-
avatar_size,
|
|
22
|
-
}: ProfilePicMenuWrapperProps) {
|
|
23
|
-
const config = get_profile_pic_menu_config();
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<ProfilePicMenu
|
|
27
|
-
show_single_button={config.show_single_button}
|
|
28
|
-
sign_up_label={config.sign_up_label}
|
|
29
|
-
sign_in_label={config.sign_in_label}
|
|
30
|
-
register_path={config.register_path}
|
|
31
|
-
login_path={config.login_path}
|
|
32
|
-
settings_path={config.settings_path}
|
|
33
|
-
logout_path={config.logout_path}
|
|
34
|
-
custom_menu_items={config.custom_menu_items}
|
|
35
|
-
className={className}
|
|
36
|
-
avatar_size={avatar_size}
|
|
37
|
-
/>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|