feat(router): wire portal/register pages, portal-context guard carve-out, lint cleanup
Routing wiring (Phase D of WS-3 PR-B1):
- apps/app/src/plugins/1.router/guards.ts: add a single early-return
carve-out before the org-selection redirect — `if (to.meta.context
=== 'portal') return`. Per ARCH-CONSOLIDATION-2026-04 §4.3,
meta.context is the canonical contract; PR-B2 evolves the guards
from this key to full context-aware logic (post-login landing,
context-switcher, role checks).
- apps/app/env.d.ts: extend RouteMeta with the new layout names
('OrganizerLayout' | 'PortalLayout' | 'PublicLayout'), context,
requiresAuth, requiresToken, navMode, navTitle.
- apps/app/typed-router.d.ts: regenerated by unplugin-vue-router to
pick up portal/* and register/* route names.
- Page meta finalisation: portal pages have layout: 'PortalLayout',
context: 'portal', preserving original requiresAuth + nav fields;
register pages have layout: 'PublicLayout' + public: true (the
apps/app guard convention for public routes, since meta.public is
what the existing guard recognises).
Form-types restructure (boundaries cleanup):
- apps/app/src/composables/forms/types/formBuilder.ts → src/types/forms/
- apps/app/src/composables/forms/utils/{formValidation,validators}.ts
→ src/utils/forms/
- All `@/composables/forms/{types,utils}/*` imports rewritten across
pages, components, composables, tests.
- This avoids a `types → composables` boundaries violation at
src/types/formSchema.ts which re-exports primitives from the
inlined form-schema. types/formSchema.ts now imports from
@/types/forms/formBuilder which is in the same boundaries zone.
Lint cleanup for moved portal sources (apps/portal had no
.eslintrc.cjs; the migrated code now has to pass apps/app's stricter
config):
- axios.isAxiosError → named import { isAxiosError }
(ClaimenTab, RoosterTab, profiel.vue)
- void schemaQuery.refetch() → schemaQuery.refetch()
(register/[public_token].vue)
- if-then-else collapsed to single boolean return (formatFieldValue)
- :delay-on-touch-only="true" → delay-on-touch-only shorthand
(FieldSectionPriority)
- ml-2 class → ms-2 (FieldAvailabilityPicker)
- multi-statement-per-line splits in profiel.vue + spec files
- unused emailConfigured ref removed (profiel.vue)
- one-component-per-file disabled with TODO TECH-WS3-PORTAL-LINT-CLEANUP
ref (FieldOptionsLocale.spec.ts — multi-Wrapper test pattern)
- restored `import Draggable from 'vuedraggable'` after lint:fix
removed it (template-only usage; the import IS needed)
- camelcase param renamed in FieldOptionsLocale harness factory
- typecheck nudge: spec state.data typed via PublicFormSectionOption[] /
PublicFormTimeSlot[] aliases instead of Record<string, unknown>
- PortalLayout.vue: explicit `import { useRoute, useRouter }` so the
vitest mock can intercept (the trimmed AutoImport set doesn't pull
vue-router's auto-imports)
Vitest: 23 / 162 passing. Lint: 0 errors / 0 new warnings (only the
pre-existing boundaries v5→v6 deprecation warnings remain). Typecheck:
clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
31
apps/app/components.d.ts
vendored
31
apps/app/components.d.ts
vendored
@@ -33,6 +33,7 @@ declare module 'vue' {
|
||||
CardStatisticsHorizontal: typeof import('./src/@core/components/cards/CardStatisticsHorizontal.vue')['default']
|
||||
CardStatisticsVertical: typeof import('./src/@core/components/cards/CardStatisticsVertical.vue')['default']
|
||||
CardStatisticsVerticalSimple: typeof import('./src/@core/components/CardStatisticsVerticalSimple.vue')['default']
|
||||
ClaimenTab: typeof import('./src/components/portal/event/ClaimenTab.vue')['default']
|
||||
CompanyDialog: typeof import('./src/components/organisation/CompanyDialog.vue')['default']
|
||||
ConfirmDialog: typeof import('./src/components/dialogs/ConfirmDialog.vue')['default']
|
||||
CreateAppDialog: typeof import('./src/components/dialogs/CreateAppDialog.vue')['default']
|
||||
@@ -57,6 +58,7 @@ declare module 'vue' {
|
||||
DialogCloseBtn: typeof import('./src/@core/components/DialogCloseBtn.vue')['default']
|
||||
DismissFailureDialog: typeof import('./src/components/form-failures/DismissFailureDialog.vue')['default']
|
||||
DropZone: typeof import('./src/@core/components/DropZone.vue')['default']
|
||||
DuplicateSubmissionHint: typeof import('./src/components/shared/public-form/DuplicateSubmissionHint.vue')['default']
|
||||
EditEventDialog: typeof import('./src/components/events/EditEventDialog.vue')['default']
|
||||
EditOrganisationDialog: typeof import('./src/components/organisations/EditOrganisationDialog.vue')['default']
|
||||
EditPersonDialog: typeof import('./src/components/persons/EditPersonDialog.vue')['default']
|
||||
@@ -66,15 +68,39 @@ declare module 'vue' {
|
||||
EmailTemplatesTab: typeof import('./src/components/organisation/EmailTemplatesTab.vue')['default']
|
||||
EnableOneTimePasswordDialog: typeof import('./src/components/dialogs/EnableOneTimePasswordDialog.vue')['default']
|
||||
ErrorHeader: typeof import('./src/components/ErrorHeader.vue')['default']
|
||||
EventCard: typeof import('./src/components/portal/EventCard.vue')['default']
|
||||
EventMetricCards: typeof import('./src/components/events/EventMetricCards.vue')['default']
|
||||
EventTabsNav: typeof import('./src/components/events/EventTabsNav.vue')['default']
|
||||
FieldAvailabilityPicker: typeof import('./src/components/shared/public-form/FieldAvailabilityPicker.vue')['default']
|
||||
FieldBoolean: typeof import('./src/components/shared/public-form/FieldBoolean.vue')['default']
|
||||
FieldCheckboxList: typeof import('./src/components/shared/public-form/FieldCheckboxList.vue')['default']
|
||||
FieldDate: typeof import('./src/components/shared/public-form/FieldDate.vue')['default']
|
||||
FieldEmail: typeof import('./src/components/shared/public-form/FieldEmail.vue')['default']
|
||||
FieldHeading: typeof import('./src/components/shared/public-form/FieldHeading.vue')['default']
|
||||
FieldMultiselect: typeof import('./src/components/shared/public-form/FieldMultiselect.vue')['default']
|
||||
FieldNumber: typeof import('./src/components/shared/public-form/FieldNumber.vue')['default']
|
||||
FieldParagraph: typeof import('./src/components/shared/public-form/FieldParagraph.vue')['default']
|
||||
FieldPhone: typeof import('./src/components/shared/public-form/FieldPhone.vue')['default']
|
||||
FieldRadio: typeof import('./src/components/shared/public-form/FieldRadio.vue')['default']
|
||||
FieldRenderer: typeof import('./src/components/shared/public-form/FieldRenderer.vue')['default']
|
||||
FieldSectionPriority: typeof import('./src/components/shared/public-form/FieldSectionPriority.vue')['default']
|
||||
FieldSelect: typeof import('./src/components/shared/public-form/FieldSelect.vue')['default']
|
||||
FieldTagPicker: typeof import('./src/components/shared/public-form/FieldTagPicker.vue')['default']
|
||||
FieldText: typeof import('./src/components/shared/public-form/FieldText.vue')['default']
|
||||
FieldTextarea: typeof import('./src/components/shared/public-form/FieldTextarea.vue')['default']
|
||||
FieldUrl: typeof import('./src/components/shared/public-form/FieldUrl.vue')['default']
|
||||
FormConfirmation: typeof import('./src/components/shared/public-form/FormConfirmation.vue')['default']
|
||||
FormErrorState: typeof import('./src/components/shared/public-form/FormErrorState.vue')['default']
|
||||
FormFailureDetail: typeof import('./src/components/form-failures/FormFailureDetail.vue')['default']
|
||||
FormFailuresTable: typeof import('./src/components/form-failures/FormFailuresTable.vue')['default']
|
||||
FormStepper: typeof import('./src/components/shared/public-form/FormStepper.vue')['default']
|
||||
I18n: typeof import('./src/@core/components/I18n.vue')['default']
|
||||
IdentityMatchBanner: typeof import('./src/components/shared/public-form/IdentityMatchBanner.vue')['default']
|
||||
ImageUploadField: typeof import('./src/components/common/ImageUploadField.vue')['default']
|
||||
ImpersonateDialog: typeof import('./src/components/platform/ImpersonateDialog.vue')['default']
|
||||
ImpersonationBanner: typeof import('./src/components/platform/ImpersonationBanner.vue')['default']
|
||||
ImportFromEventDialog: typeof import('./src/components/event/ImportFromEventDialog.vue')['default']
|
||||
InformatieTab: typeof import('./src/components/portal/event/InformatieTab.vue')['default']
|
||||
InfoTooltip: typeof import('./src/components/common/InfoTooltip.vue')['default']
|
||||
InviteMemberDialog: typeof import('./src/components/members/InviteMemberDialog.vue')['default']
|
||||
MfaChallengeCard: typeof import('./src/components/auth/MfaChallengeCard.vue')['default']
|
||||
@@ -85,6 +111,7 @@ declare module 'vue' {
|
||||
Notifications: typeof import('./src/@core/components/Notifications.vue')['default']
|
||||
NotificationsTab: typeof import('./src/components/account-settings/NotificationsTab.vue')['default']
|
||||
OrganisationSwitcher: typeof import('./src/components/layout/OrganisationSwitcher.vue')['default']
|
||||
OverzichtTab: typeof import('./src/components/portal/event/OverzichtTab.vue')['default']
|
||||
PasswordRequirements: typeof import('./src/components/auth/PasswordRequirements.vue')['default']
|
||||
PaymentProvidersDialog: typeof import('./src/components/dialogs/PaymentProvidersDialog.vue')['default']
|
||||
PersonDetailPanel: typeof import('./src/components/persons/PersonDetailPanel.vue')['default']
|
||||
@@ -95,6 +122,7 @@ declare module 'vue' {
|
||||
RegistrationFieldTemplatesTab: typeof import('./src/components/organisation/RegistrationFieldTemplatesTab.vue')['default']
|
||||
ResolveFailureDialog: typeof import('./src/components/form-failures/ResolveFailureDialog.vue')['default']
|
||||
RetryFailureDialog: typeof import('./src/components/form-failures/RetryFailureDialog.vue')['default']
|
||||
RoosterTab: typeof import('./src/components/portal/event/RoosterTab.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
ScrollToTop: typeof import('./src/@core/components/ScrollToTop.vue')['default']
|
||||
@@ -109,11 +137,14 @@ declare module 'vue' {
|
||||
ShareProjectDialog: typeof import('./src/components/dialogs/ShareProjectDialog.vue')['default']
|
||||
ShiftDetailPanel: typeof import('./src/components/shifts/ShiftDetailPanel.vue')['default']
|
||||
Shortcuts: typeof import('./src/@core/components/Shortcuts.vue')['default']
|
||||
StatusCard: typeof import('./src/components/portal/StatusCard.vue')['default']
|
||||
SubmitterDetails: typeof import('./src/components/shared/public-form/SubmitterDetails.vue')['default']
|
||||
TablePagination: typeof import('./src/@core/components/TablePagination.vue')['default']
|
||||
TemplatePickerDialog: typeof import('./src/components/event/TemplatePickerDialog.vue')['default']
|
||||
ThemeSwitcher: typeof import('./src/@core/components/ThemeSwitcher.vue')['default']
|
||||
TiptapEditor: typeof import('./src/@core/components/TiptapEditor.vue')['default']
|
||||
TwoFactorAuthDialog: typeof import('./src/components/dialogs/TwoFactorAuthDialog.vue')['default']
|
||||
UserAvatarMenu: typeof import('./src/components/portal/UserAvatarMenu.vue')['default']
|
||||
UserInfoEditDialog: typeof import('./src/components/dialogs/UserInfoEditDialog.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user