@jmruthers/pace-core 0.5.76 → 0.5.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/{RBACService-C4udt_Zp.d.ts → AuthService-Df3IozMG.d.ts} +10 -118
- package/dist/{DataTable-ntgmhO2W.d.ts → DataTable-BE0OXZKQ.d.ts} +9 -2
- package/dist/{DataTable-4GAVPIEG.js → DataTable-ETGVF4Y5.js} +50 -13
- package/dist/{PublicLoadingSpinner-BiNER8F5.d.ts → PublicLoadingSpinner-CnUaz0vG.d.ts} +5 -2
- package/dist/{UnifiedAuthProvider-Bj6YCf7c.d.ts → UnifiedAuthProvider-B391Aqum.d.ts} +42 -45
- package/dist/{UnifiedAuthProvider-3NKDOSOK.js → UnifiedAuthProvider-P5SOJAQ6.js} +4 -5
- package/dist/{api-DDMUKIUD.js → api-KG4A2X7P.js} +9 -3
- package/dist/{audit-6TOCAMKO.js → audit-65VNHEV2.js} +2 -2
- package/dist/{chunk-K34IM5CT.js → chunk-2OGV6IRV.js} +196 -626
- package/dist/chunk-2OGV6IRV.js.map +1 -0
- package/dist/{chunk-NTNILOBC.js → chunk-5BO3MI5Y.js} +4 -4
- package/dist/{chunk-XLZ7U46Z.js → chunk-CVMVPYAL.js} +9 -60
- package/dist/chunk-CVMVPYAL.js.map +1 -0
- package/dist/{chunk-URUTVZ7N.js → chunk-FL4ZCQLD.js} +2 -2
- package/dist/{chunk-LW7MMEAQ.js → chunk-FT2M4R4F.js} +2 -2
- package/dist/{chunk-5BSLGBYI.js → chunk-JCQZ6LA7.js} +2 -8
- package/dist/{chunk-5BSLGBYI.js.map → chunk-JCQZ6LA7.js.map} +1 -1
- package/dist/{chunk-KHJS6VIA.js → chunk-LRQ6RBJC.js} +157 -112
- package/dist/chunk-LRQ6RBJC.js.map +1 -0
- package/dist/{chunk-WN6XJWOS.js → chunk-MNJXXD6C.js} +274 -743
- package/dist/chunk-MNJXXD6C.js.map +1 -0
- package/dist/{chunk-KK73ZB4E.js → chunk-PTR5PMPE.js} +153 -132
- package/dist/chunk-PTR5PMPE.js.map +1 -0
- package/dist/{chunk-B2WTCLCV.js → chunk-Q7APDV6H.js} +18 -8
- package/dist/chunk-Q7APDV6H.js.map +1 -0
- package/dist/{chunk-A4FUBC7B.js → chunk-QGVSOUJ2.js} +2 -4
- package/dist/{chunk-A4FUBC7B.js.map → chunk-QGVSOUJ2.js.map} +1 -1
- package/dist/{chunk-FGMFQSHX.js → chunk-S63MFSY6.js} +500 -551
- package/dist/chunk-S63MFSY6.js.map +1 -0
- package/dist/{chunk-AFGTSUAD.js → chunk-VSOKOFRF.js} +4 -4
- package/dist/chunk-WUXCWRL6.js +20 -0
- package/dist/chunk-WUXCWRL6.js.map +1 -0
- package/dist/{chunk-Y6TXWPJO.js → chunk-YVVGHRGI.js} +105 -31
- package/dist/chunk-YVVGHRGI.js.map +1 -0
- package/dist/{chunk-M5IWZRBT.js → chunk-ZMNXIJP4.js} +2187 -981
- package/dist/chunk-ZMNXIJP4.js.map +1 -0
- package/dist/components.d.ts +6 -6
- package/dist/components.js +14 -18
- package/dist/components.js.map +1 -1
- package/dist/{database-C3Szpi5J.d.ts → database-BXAfr2Y_.d.ts} +18 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +8 -9
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +19 -27
- package/dist/index.js +21 -29
- package/dist/index.js.map +1 -1
- package/dist/{organisation-BtshODVF.d.ts → organisation-D6qRDtbF.d.ts} +1 -1
- package/dist/providers.d.ts +7 -21
- package/dist/providers.js +3 -10
- package/dist/rbac/index.d.ts +71 -221
- package/dist/rbac/index.js +15 -16
- package/dist/{types-CGX9Vyf5.d.ts → types-BDg1mAGG.d.ts} +36 -6
- package/dist/types.d.ts +3 -3
- package/dist/types.js +61 -18
- package/dist/types.js.map +1 -1
- package/dist/{unified-CM7T0aTK.d.ts → unified-DQ4VcT7H.d.ts} +1 -1
- package/dist/{usePublicRouteParams-B-CumWRc.d.ts → usePublicRouteParams-BlgwXweB.d.ts} +3 -3
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +52 -9
- package/dist/utils.js.map +1 -1
- package/docs/CONTENT_AUDIT_REPORT.md +253 -0
- package/docs/DOCUMENTATION_AUDIT.md +172 -0
- package/docs/README.md +142 -147
- package/docs/STYLE_GUIDE.md +37 -0
- package/docs/api/classes/ColumnFactory.md +17 -17
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +4 -4
- package/docs/api/classes/MissingUserContextError.md +4 -4
- package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
- package/docs/api/classes/PermissionDeniedError.md +5 -5
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +8 -8
- package/docs/api/classes/RBACCache.md +35 -5
- package/docs/api/classes/RBACEngine.md +49 -20
- package/docs/api/classes/RBACError.md +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +11 -0
- package/docs/api/interfaces/DataTableAction.md +65 -29
- package/docs/api/interfaces/DataTableColumn.md +36 -23
- package/docs/api/interfaces/DataTableProps.md +80 -38
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +11 -11
- package/docs/api/interfaces/NavigationContextType.md +9 -9
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +7 -7
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +16 -3
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +2 -2
- package/docs/api/interfaces/RouteConfig.md +2 -2
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +94 -521
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +16 -16
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +11 -11
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +251 -269
- package/docs/api-reference/components.md +193 -0
- package/docs/api-reference/hooks.md +265 -0
- package/docs/api-reference/providers.md +6 -0
- package/docs/api-reference/types.md +6 -0
- package/docs/api-reference/utilities.md +207 -0
- package/docs/architecture/README.md +6 -0
- package/docs/{database-schema-requirements.md → architecture/database-schema-requirements.md} +6 -0
- package/docs/architecture/rbac-security-architecture.md +258 -0
- package/docs/architecture/services.md +9 -1
- package/docs/best-practices/README.md +6 -0
- package/docs/best-practices/accessibility.md +6 -0
- package/docs/{common-patterns.md → best-practices/common-patterns.md} +6 -0
- package/docs/best-practices/deployment.md +6 -0
- package/docs/best-practices/performance.md +475 -2
- package/docs/best-practices/security.md +6 -0
- package/docs/best-practices/testing.md +6 -0
- package/docs/core-concepts/authentication.md +6 -0
- package/docs/core-concepts/events.md +6 -0
- package/docs/core-concepts/organisations.md +6 -0
- package/docs/core-concepts/permissions.md +6 -0
- package/docs/core-concepts/rbac-system.md +8 -0
- package/docs/documentation-index.md +121 -182
- package/docs/{consuming-app-vite-config.md → getting-started/consuming-app-vite-config.md} +6 -0
- package/docs/getting-started/documentation-index.md +40 -0
- package/docs/getting-started/examples/README.md +878 -35
- package/docs/{faq.md → getting-started/faq.md} +7 -1
- package/docs/getting-started/installation-guide.md +6 -0
- package/docs/{quick-reference.md → getting-started/quick-reference.md} +6 -0
- package/docs/implementation-guides/app-layout.md +6 -0
- package/docs/implementation-guides/authentication.md +1021 -0
- package/docs/implementation-guides/component-styling.md +6 -0
- package/docs/implementation-guides/data-tables.md +1264 -2076
- package/docs/implementation-guides/dynamic-colors.md +6 -0
- package/docs/implementation-guides/event-theming-summary.md +6 -0
- package/docs/{file-reference-system.md → implementation-guides/file-reference-system.md} +6 -0
- package/docs/implementation-guides/file-upload-storage.md +6 -0
- package/docs/implementation-guides/forms.md +6 -0
- package/docs/implementation-guides/inactivity-tracking.md +6 -0
- package/docs/implementation-guides/navigation.md +6 -0
- package/docs/implementation-guides/organisation-security.md +6 -0
- package/docs/implementation-guides/permission-enforcement.md +6 -0
- package/docs/implementation-guides/public-pages-advanced.md +6 -0
- package/docs/implementation-guides/public-pages.md +6 -0
- package/docs/migration/MIGRATION_GUIDE.md +827 -351
- package/docs/migration/README.md +7 -1
- package/docs/migration/organisation-context-timing-fix.md +6 -0
- package/docs/migration/rbac-migration.md +44 -1
- package/docs/migration/service-architecture.md +6 -0
- package/docs/migration/v0.4.15-tailwind-scanning.md +6 -0
- package/docs/migration/v0.4.16-css-first-approach.md +6 -0
- package/docs/migration/v0.4.17-source-path-fix.md +6 -0
- package/docs/rbac/README-rbac-rls-integration.md +6 -0
- package/docs/rbac/README.md +6 -0
- package/docs/rbac/advanced-patterns.md +6 -0
- package/docs/rbac/api-reference.md +7 -1
- package/docs/rbac/breaking-changes-v3.md +222 -0
- package/docs/rbac/examples/rbac-rls-integration-example.md +6 -0
- package/docs/rbac/examples.md +6 -0
- package/docs/rbac/getting-started.md +6 -0
- package/docs/rbac/migration-guide.md +260 -0
- package/docs/rbac/quick-start.md +70 -13
- package/docs/rbac/rbac-rls-integration.md +6 -0
- package/docs/rbac/super-admin-guide.md +6 -0
- package/docs/rbac/troubleshooting.md +6 -0
- package/docs/security/README.md +6 -0
- package/docs/security/checklist.md +6 -0
- package/docs/styles/README.md +7 -1
- package/docs/{usage.md → styles/usage.md} +6 -0
- package/docs/testing/README.md +6 -0
- package/docs/{visual-testing.md → testing/visual-testing.md} +6 -0
- package/docs/troubleshooting/README.md +387 -5
- package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +6 -0
- package/docs/troubleshooting/common-issues.md +6 -0
- package/docs/troubleshooting/database-view-compatibility.md +6 -0
- package/docs/troubleshooting/organisation-context-setup.md +6 -0
- package/docs/troubleshooting/react-hooks-issue-analysis.md +6 -0
- package/docs/troubleshooting/styling-issues.md +6 -0
- package/docs/troubleshooting/tailwind-content-scanning.md +6 -0
- package/package.json +1 -1
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -1
- package/src/__tests__/helpers/test-providers.tsx +3 -53
- package/src/components/DataTable/DataTable.test.tsx +319 -0
- package/src/components/DataTable/DataTable.tsx +32 -11
- package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx.skip} +6 -4
- package/src/components/DataTable/__tests__/{DataTable.test.tsx → DataTable.test.tsx.skip} +6 -4
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +31 -9
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +601 -0
- package/src/components/DataTable/__tests__/keyboard.test.tsx +615 -0
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +639 -0
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx.skip +330 -0
- package/src/components/DataTable/components/AccessDeniedPage.tsx +2 -2
- package/src/components/DataTable/components/ActionButtons.tsx +88 -104
- package/src/components/DataTable/components/DataTableCore.tsx +309 -337
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +4 -2
- package/src/components/DataTable/components/DataTableModals.tsx +22 -1
- package/src/components/DataTable/components/EditableRow.tsx +69 -84
- package/src/components/DataTable/components/EmptyState.tsx +5 -1
- package/src/components/DataTable/components/ImportModal.tsx +65 -36
- package/src/components/DataTable/components/PaginationControls.tsx +40 -100
- package/src/components/DataTable/components/UnifiedTableBody.tsx +125 -148
- package/src/components/DataTable/context/DataTableContext.tsx +1 -1
- package/src/components/DataTable/core/ColumnFactory.ts +5 -0
- package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +12 -10
- package/src/components/DataTable/examples/HierarchicalExample.tsx +1 -1
- package/src/components/DataTable/examples/InitialPageSizeExample.tsx +1 -0
- package/src/components/DataTable/examples/PerformanceExample.tsx +1 -0
- package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +1 -5
- package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +167 -0
- package/src/components/DataTable/hooks/index.ts +7 -0
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +32 -15
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +102 -0
- package/src/components/DataTable/hooks/useDataTableConfiguration.ts +89 -0
- package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +117 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +71 -27
- package/src/components/DataTable/hooks/useDataTableState.ts +39 -11
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +33 -0
- package/src/components/DataTable/hooks/useHierarchicalState.ts +15 -1
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +447 -0
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +94 -0
- package/src/components/DataTable/hooks/useTableColumns.ts +10 -7
- package/src/components/DataTable/hooks/useTableHandlers.ts +174 -0
- package/src/components/DataTable/index.ts +12 -3
- package/src/components/DataTable/types.ts +129 -9
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +159 -22
- package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +111 -0
- package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +15 -29
- package/src/components/DataTable/utils/a11yUtils.ts +244 -0
- package/src/components/DataTable/utils/debugTools.ts +609 -0
- package/src/components/DataTable/utils/exportUtils.ts +114 -16
- package/src/components/DataTable/utils/flexibleImport.ts +202 -32
- package/src/components/DataTable/utils/hierarchicalUtils.ts +1 -1
- package/src/components/DataTable/utils/index.ts +2 -0
- package/src/components/DataTable/utils/paginationUtils.ts +350 -0
- package/src/components/DataTable/utils/rowUtils.ts +6 -5
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -24
- package/src/components/NavigationMenu/NavigationMenu.tsx +19 -8
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +1 -23
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +56 -6
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +137 -13
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +1 -1
- package/src/components/Select/Select.tsx +1 -0
- package/src/components/examples/PermissionExample.tsx +173 -0
- package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
- package/src/examples/PublicEventPage.tsx +274 -0
- package/src/examples/PublicPageApp.tsx +308 -0
- package/src/examples/PublicPageUsageExample.tsx +216 -0
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +12 -1
- package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +129 -17
- package/src/hooks/__tests__/useRBAC.unit.test.ts +151 -846
- package/src/hooks/useOrganisationPermissions.test.ts +42 -18
- package/src/hooks/useOrganisationPermissions.ts +12 -6
- package/src/hooks/useOrganisationSecurity.test.ts +138 -85
- package/src/hooks/useOrganisationSecurity.ts +41 -10
- package/src/index.ts +0 -1
- package/src/providers/AuthProvider.simplified.tsx +880 -0
- package/src/providers/UnifiedAuthProvider.test.simple.tsx +8 -8
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +29 -19
- package/src/providers/index.ts +0 -1
- package/src/providers/services/EventServiceProvider.tsx +19 -15
- package/src/providers/services/InactivityServiceProvider.tsx +19 -15
- package/src/providers/services/OrganisationServiceProvider.tsx +19 -15
- package/src/providers/services/UnifiedAuthProvider.tsx +156 -127
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +1 -1
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -3
- package/src/rbac/README.md +1 -1
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +25 -27
- package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +313 -0
- package/src/rbac/__tests__/engine.comprehensive.test.ts +114 -348
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +28 -110
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +33 -85
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +2 -2
- package/src/rbac/adapters.tsx +26 -69
- package/src/rbac/api.test.ts +90 -27
- package/src/rbac/api.ts +61 -10
- package/src/rbac/audit.test.ts +33 -38
- package/src/rbac/audit.ts +21 -6
- package/src/rbac/cache.ts +33 -1
- package/src/rbac/components/NavigationGuard.tsx +11 -11
- package/src/rbac/components/NavigationProvider.test.tsx +11 -5
- package/src/rbac/components/NavigationProvider.tsx +37 -13
- package/src/rbac/components/PagePermissionGuard.tsx +111 -50
- package/src/rbac/components/PagePermissionProvider.tsx +5 -5
- package/src/rbac/components/PermissionEnforcer.tsx +11 -11
- package/src/rbac/components/RoleBasedRouter.tsx +5 -5
- package/src/rbac/components/SecureDataProvider.tsx +5 -5
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +8 -8
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +14 -14
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +12 -12
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +6 -6
- package/src/rbac/engine.test.simple.ts +19 -13
- package/src/rbac/engine.test.ts +1 -0
- package/src/rbac/engine.ts +330 -766
- package/src/rbac/errors.ts +156 -0
- package/src/rbac/hooks/usePermissions.ts +32 -10
- package/src/rbac/hooks/useRBAC.test.ts +126 -512
- package/src/rbac/hooks/useRBAC.ts +147 -193
- package/src/rbac/hooks/useResolvedScope.ts +12 -0
- package/src/rbac/index.ts +7 -4
- package/src/rbac/security.ts +109 -18
- package/src/rbac/types.ts +12 -1
- package/src/services/AuthService.ts +2 -15
- package/src/services/EventService.ts +43 -46
- package/src/services/OrganisationService.ts +51 -31
- package/src/services/__tests__/AuthService.test.ts +1 -1
- package/src/services/__tests__/EventService.test.ts +1 -1
- package/src/services/__tests__/OrganisationService.test.ts +1 -1
- package/src/services/base/BaseService.ts +8 -0
- package/src/styles/base.css +208 -0
- package/src/styles/semantic.css +24 -0
- package/src/types/database.generated.ts +7347 -0
- package/src/types/database.ts +20 -0
- package/src/utils/logger.ts +179 -0
- package/src/utils/organisationContext.ts +11 -4
- package/src/utils/storage/__tests__/helpers.unit.test.ts +6 -2
- package/dist/appNameResolver-UURKN7NF.js +0 -22
- package/dist/audit-6TOCAMKO.js.map +0 -1
- package/dist/chunk-B2WTCLCV.js.map +0 -1
- package/dist/chunk-FGMFQSHX.js.map +0 -1
- package/dist/chunk-K34IM5CT.js.map +0 -1
- package/dist/chunk-KHJS6VIA.js.map +0 -1
- package/dist/chunk-KK73ZB4E.js.map +0 -1
- package/dist/chunk-M5IWZRBT.js.map +0 -1
- package/dist/chunk-ULBI5JGB.js +0 -109
- package/dist/chunk-ULBI5JGB.js.map +0 -1
- package/dist/chunk-WN6XJWOS.js.map +0 -1
- package/dist/chunk-XLZ7U46Z.js.map +0 -1
- package/dist/chunk-Y6TXWPJO.js.map +0 -1
- package/docs/DOCUMENTATION_CHECKLIST.md +0 -281
- package/docs/TERMINOLOGY.md +0 -231
- package/docs/api/interfaces/RBACContextType.md +0 -468
- package/docs/api/interfaces/RBACProviderProps.md +0 -107
- package/docs/best-practices/performance-expansion.md +0 -473
- package/docs/breaking-changes.md +0 -179
- package/docs/consuming-app-example.md +0 -290
- package/docs/documentation-templates.md +0 -539
- package/docs/examples/navigation-menu-auth-fix.md +0 -344
- package/docs/getting-started/examples/basic-auth-app.md +0 -520
- package/docs/getting-started/examples/full-featured-app.md +0 -616
- package/docs/getting-started/quick-start.md +0 -376
- package/docs/implementation-guides/datatable-filtering.md +0 -313
- package/docs/implementation-guides/datatable-rbac-usage.md +0 -317
- package/docs/implementation-guides/hierarchical-datatable.md +0 -850
- package/docs/implementation-guides/large-datasets.md +0 -281
- package/docs/implementation-guides/performance.md +0 -403
- package/docs/migration/quick-migration-guide.md +0 -320
- package/docs/migration-guide.md +0 -193
- package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +0 -226
- package/docs/performance/README.md +0 -551
- package/docs/style-guide.md +0 -964
- package/docs/troubleshooting/authentication-issues.md +0 -334
- package/docs/troubleshooting/debugging.md +0 -1117
- package/docs/troubleshooting/migration.md +0 -918
- package/src/__tests__/hooks/usePermissions.test.ts +0 -261
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +0 -574
- package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -613
- package/src/hooks/services/__tests__/useServiceHooks.test.tsx +0 -137
- package/src/hooks/services/usePermissions.ts +0 -70
- package/src/hooks/services/useRBACService.ts +0 -30
- package/src/hooks/usePermissionCheck.ts +0 -150
- package/src/providers/__tests__/ServiceProviders.test.tsx +0 -477
- package/src/providers/services/RBACServiceProvider.tsx +0 -79
- package/src/rbac/__tests__/integration.authflow.test.tsx +0 -119
- package/src/rbac/__tests__/integration.navigation.test.tsx +0 -69
- package/src/rbac/__tests__/integration.securedata.test.tsx +0 -92
- package/src/rbac/__tests__/integration.smoke.test.tsx +0 -73
- package/src/rbac/providers/RBACProvider.tsx +0 -645
- package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +0 -688
- package/src/rbac/providers/__tests__/RBACProvider.test.tsx +0 -1186
- package/src/rbac/providers/index.ts +0 -11
- package/src/services/RBACService.ts +0 -522
- package/src/services/__tests__/RBACService.test.ts +0 -492
- package/src/services/interfaces/IRBACService.ts +0 -62
- package/src/utils/appNameResolver.test 2.ts +0 -494
- /package/dist/{DataTable-4GAVPIEG.js.map → DataTable-ETGVF4Y5.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-3NKDOSOK.js.map → UnifiedAuthProvider-P5SOJAQ6.js.map} +0 -0
- /package/dist/{api-DDMUKIUD.js.map → api-KG4A2X7P.js.map} +0 -0
- /package/dist/{appNameResolver-UURKN7NF.js.map → audit-65VNHEV2.js.map} +0 -0
- /package/dist/{chunk-NTNILOBC.js.map → chunk-5BO3MI5Y.js.map} +0 -0
- /package/dist/{chunk-URUTVZ7N.js.map → chunk-FL4ZCQLD.js.map} +0 -0
- /package/dist/{chunk-LW7MMEAQ.js.map → chunk-FT2M4R4F.js.map} +0 -0
- /package/dist/{chunk-AFGTSUAD.js.map → chunk-VSOKOFRF.js.map} +0 -0
- /package/docs/{app.css.example → styles/app.css.example} +0 -0
|
@@ -1,51 +1,887 @@
|
|
|
1
|
+
---
|
|
2
|
+
lastUpdated: 2025-10-29T22:43:00+11:00
|
|
3
|
+
version: 0.5.76
|
|
4
|
+
reviewedBy: content-audit
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Examples & Starter Projects
|
|
2
8
|
|
|
3
|
-
Complete
|
|
9
|
+
> **🚀 Complete Working Examples** | [← Back to Documentation](../README.md) | [Installation Guide](./installation-guide.md)
|
|
4
10
|
|
|
5
|
-
|
|
11
|
+
Complete working examples to help you get started with PACE Core, from basic authentication to full-featured applications.
|
|
6
12
|
|
|
7
|
-
|
|
8
|
-
A minimal application showing just authentication and basic UI components.
|
|
13
|
+
## Overview
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
- User login/logout
|
|
12
|
-
- Basic dashboard
|
|
13
|
-
- Simple navigation
|
|
14
|
-
- Responsive design
|
|
15
|
+
This guide provides comprehensive examples demonstrating all PACE Core features:
|
|
15
16
|
|
|
16
|
-
**
|
|
17
|
+
- **Basic Authentication App** - Minimal setup with login/logout
|
|
18
|
+
- **Full-Featured Application** - Complete meal management app with all features
|
|
19
|
+
- **Component Examples** - Individual component usage patterns
|
|
20
|
+
- **Starter Projects** - Downloadable templates for different frameworks
|
|
21
|
+
|
|
22
|
+
## 🚀 Quick Examples
|
|
17
23
|
|
|
18
|
-
|
|
24
|
+
### Basic Authentication App
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
A detailed example showing how to fix NavigationMenu authentication context issues.
|
|
26
|
+
A minimal application showing just authentication and basic UI components.
|
|
22
27
|
|
|
23
28
|
**Features:**
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
+
- User login/logout with Supabase
|
|
30
|
+
- Basic dashboard with user info
|
|
31
|
+
- Simple navigation with permission-based filtering
|
|
32
|
+
- Responsive design with Tailwind CSS
|
|
33
|
+
- Permission-based content display
|
|
29
34
|
|
|
30
|
-
**Perfect for:**
|
|
35
|
+
**Perfect for:** Learning the basics, simple apps, prototypes
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
#### Project Setup
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Create new React app
|
|
41
|
+
npx create-react-app basic-auth-app --template typescript
|
|
42
|
+
cd basic-auth-app
|
|
43
|
+
|
|
44
|
+
# Install PACE Core
|
|
45
|
+
npm install @jmruthers/pace-core
|
|
46
|
+
|
|
47
|
+
# Install additional dependencies
|
|
48
|
+
npm install @supabase/supabase-js react-router-dom
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Environment Configuration
|
|
52
|
+
|
|
53
|
+
Create `.env.local`:
|
|
54
|
+
```env
|
|
55
|
+
VITE_SUPABASE_URL=your_supabase_url
|
|
56
|
+
VITE_SUPABASE_ANON_KEY=your_supabase_anon_key
|
|
57
|
+
VITE_APP_NAME=Basic Auth App
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### Supabase Setup
|
|
61
|
+
|
|
62
|
+
Create a new Supabase project and set up the database:
|
|
63
|
+
|
|
64
|
+
```sql
|
|
65
|
+
-- Create users table
|
|
66
|
+
CREATE TABLE users (
|
|
67
|
+
id UUID REFERENCES auth.users(id) PRIMARY KEY,
|
|
68
|
+
email TEXT UNIQUE NOT NULL,
|
|
69
|
+
name TEXT,
|
|
70
|
+
role TEXT DEFAULT 'user',
|
|
71
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
-- Enable RLS
|
|
75
|
+
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
|
|
76
|
+
|
|
77
|
+
-- Create policy
|
|
78
|
+
CREATE POLICY "Users can view their own data" ON users
|
|
79
|
+
FOR SELECT USING (auth.uid() = id);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### App Structure
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
src/
|
|
86
|
+
├── components/
|
|
87
|
+
│ ├── Dashboard.tsx
|
|
88
|
+
│ ├── LoginForm.tsx
|
|
89
|
+
│ └── Navigation.tsx
|
|
90
|
+
├── hooks/
|
|
91
|
+
│ └── useSupabase.ts
|
|
92
|
+
├── types/
|
|
93
|
+
│ └── index.ts
|
|
94
|
+
├── App.tsx
|
|
95
|
+
├── main.tsx
|
|
96
|
+
└── index.css
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Supabase Client Setup
|
|
100
|
+
|
|
101
|
+
`src/hooks/useSupabase.ts`:
|
|
102
|
+
```tsx
|
|
103
|
+
import { createClient } from '@supabase/supabase-js';
|
|
104
|
+
|
|
105
|
+
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
|
|
106
|
+
const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
|
|
107
|
+
|
|
108
|
+
export const supabase = createClient(supabaseUrl, supabaseKey);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Types Definition
|
|
112
|
+
|
|
113
|
+
`src/types/index.ts`:
|
|
114
|
+
```tsx
|
|
115
|
+
export interface User {
|
|
116
|
+
id: string;
|
|
117
|
+
email: string;
|
|
118
|
+
name: string;
|
|
119
|
+
role: 'admin' | 'user';
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface AuthState {
|
|
123
|
+
user: User | null;
|
|
124
|
+
loading: boolean;
|
|
125
|
+
error: string | null;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Main App Component
|
|
130
|
+
|
|
131
|
+
`src/App.tsx`:
|
|
132
|
+
```tsx
|
|
133
|
+
import React from 'react';
|
|
134
|
+
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
|
|
135
|
+
import { UnifiedAuthProvider } from '@jmruthers/pace-core';
|
|
136
|
+
import { supabase } from './hooks/useSupabase';
|
|
137
|
+
import LoginForm from './components/LoginForm';
|
|
138
|
+
import Dashboard from './components/Dashboard';
|
|
139
|
+
import '@jmruthers/pace-core/src/styles/core.css';
|
|
140
|
+
|
|
141
|
+
function App() {
|
|
142
|
+
return (
|
|
143
|
+
<UnifiedAuthProvider
|
|
144
|
+
supabaseClient={supabase}
|
|
145
|
+
appName="Basic Auth App"
|
|
146
|
+
idleTimeoutMs={30 * 60 * 1000}
|
|
147
|
+
warnBeforeMs={5 * 60 * 1000}
|
|
148
|
+
onIdleLogout={() => window.location.href = '/login'}
|
|
149
|
+
>
|
|
150
|
+
<Router>
|
|
151
|
+
<div className="min-h-screen bg-sec-50">
|
|
152
|
+
<Routes>
|
|
153
|
+
<Route path="/login" element={<LoginForm />} />
|
|
154
|
+
<Route path="/" element={<Dashboard />} />
|
|
155
|
+
<Route path="/dashboard" element={<Dashboard />} />
|
|
156
|
+
</Routes>
|
|
157
|
+
</div>
|
|
158
|
+
</Router>
|
|
159
|
+
</UnifiedAuthProvider>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export default App;
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
#### Login Form Component
|
|
167
|
+
|
|
168
|
+
`src/components/LoginForm.tsx`:
|
|
169
|
+
```tsx
|
|
170
|
+
import React, { useState } from 'react';
|
|
171
|
+
import { useNavigate } from 'react-router-dom';
|
|
172
|
+
import { Button, Card, Input, Alert } from '@jmruthers/pace-core';
|
|
173
|
+
import { useUnifiedAuth } from '@jmruthers/pace-core';
|
|
174
|
+
|
|
175
|
+
const LoginForm: React.FC = () => {
|
|
176
|
+
const [email, setEmail] = useState('');
|
|
177
|
+
const [password, setPassword] = useState('');
|
|
178
|
+
const [loading, setLoading] = useState(false);
|
|
179
|
+
const [error, setError] = useState('');
|
|
180
|
+
const navigate = useNavigate();
|
|
181
|
+
const { signIn } = useUnifiedAuth();
|
|
182
|
+
|
|
183
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
184
|
+
e.preventDefault();
|
|
185
|
+
setLoading(true);
|
|
186
|
+
setError('');
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
await signIn({ email, password });
|
|
190
|
+
navigate('/dashboard');
|
|
191
|
+
} catch (err) {
|
|
192
|
+
setError(err instanceof Error ? err.message : 'Login failed');
|
|
193
|
+
} finally {
|
|
194
|
+
setLoading(false);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<div className="min-h-screen flex items-center justify-center bg-sec-50 py-12 px-4 sm:px-6 lg:px-8">
|
|
200
|
+
<div className="max-w-md w-full space-y-8">
|
|
201
|
+
<div>
|
|
202
|
+
<h2 className="mt-6 text-center text-3xl font-extrabold text-sec-900">
|
|
203
|
+
Sign in to your account
|
|
204
|
+
</h2>
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<Card className="mt-8 space-y-6 p-8">
|
|
208
|
+
<form onSubmit={handleSubmit} className="space-y-6">
|
|
209
|
+
{error && (
|
|
210
|
+
<Alert variant="destructive">
|
|
211
|
+
{error}
|
|
212
|
+
</Alert>
|
|
213
|
+
)}
|
|
214
|
+
|
|
215
|
+
<div>
|
|
216
|
+
<Input
|
|
217
|
+
label="Email address"
|
|
218
|
+
type="email"
|
|
219
|
+
value={email}
|
|
220
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
221
|
+
required
|
|
222
|
+
placeholder="Enter your email"
|
|
223
|
+
/>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<div>
|
|
227
|
+
<Input
|
|
228
|
+
label="Password"
|
|
229
|
+
type="password"
|
|
230
|
+
value={password}
|
|
231
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
232
|
+
required
|
|
233
|
+
placeholder="Enter your password"
|
|
234
|
+
/>
|
|
235
|
+
</div>
|
|
236
|
+
|
|
237
|
+
<Button
|
|
238
|
+
type="submit"
|
|
239
|
+
className="w-full"
|
|
240
|
+
disabled={loading}
|
|
241
|
+
>
|
|
242
|
+
{loading ? 'Signing in...' : 'Sign in'}
|
|
243
|
+
</Button>
|
|
244
|
+
</form>
|
|
245
|
+
</Card>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
);
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
export default LoginForm;
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### Dashboard Component
|
|
255
|
+
|
|
256
|
+
`src/components/Dashboard.tsx`:
|
|
257
|
+
```tsx
|
|
258
|
+
import React from 'react';
|
|
259
|
+
import { useNavigate } from 'react-router-dom';
|
|
260
|
+
import {
|
|
261
|
+
Card,
|
|
262
|
+
Button,
|
|
263
|
+
Alert,
|
|
264
|
+
PaceAppLayout,
|
|
265
|
+
Header,
|
|
266
|
+
UserMenu
|
|
267
|
+
} from '@jmruthers/pace-core';
|
|
268
|
+
import { useUnifiedAuth } from '@jmruthers/pace-core';
|
|
269
|
+
|
|
270
|
+
const Dashboard: React.FC = () => {
|
|
271
|
+
const { user, signOut, loading } = useUnifiedAuth();
|
|
272
|
+
const navigate = useNavigate();
|
|
273
|
+
|
|
274
|
+
if (loading) {
|
|
275
|
+
return (
|
|
276
|
+
<div className="min-h-screen flex items-center justify-center">
|
|
277
|
+
<div className="text-center">
|
|
278
|
+
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-main-600 mx-auto"></div>
|
|
279
|
+
<p className="mt-4 text-sec-600">Loading...</p>
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (!user) {
|
|
286
|
+
navigate('/login');
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const handleLogout = async () => {
|
|
291
|
+
await signOut();
|
|
292
|
+
navigate('/login');
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const navigationItems = [
|
|
296
|
+
{ label: 'Dashboard', href: '/dashboard', icon: 'Home' },
|
|
297
|
+
{ label: 'Profile', href: '/profile', icon: 'User' },
|
|
298
|
+
{ label: 'Settings', href: '/settings', icon: 'Settings' }
|
|
299
|
+
];
|
|
300
|
+
|
|
301
|
+
return (
|
|
302
|
+
<PaceAppLayout
|
|
303
|
+
title="Basic Auth App"
|
|
304
|
+
user={user}
|
|
305
|
+
onLogout={handleLogout}
|
|
306
|
+
navigation={navigationItems}
|
|
307
|
+
>
|
|
308
|
+
<div className="p-6">
|
|
309
|
+
<div className="mb-6">
|
|
310
|
+
<h1 className="text-3xl font-bold text-sec-900">Welcome, {user.name || user.email}!</h1>
|
|
311
|
+
<p className="text-sec-600">This is your basic dashboard.</p>
|
|
312
|
+
</div>
|
|
313
|
+
|
|
314
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
315
|
+
<Card>
|
|
316
|
+
<div className="p-6">
|
|
317
|
+
<h3 className="text-lg font-semibold text-sec-900 mb-2">User Info</h3>
|
|
318
|
+
<p className="text-sec-600 mb-4">Your account details</p>
|
|
319
|
+
<div className="space-y-2">
|
|
320
|
+
<p><strong>Email:</strong> {user.email}</p>
|
|
321
|
+
<p><strong>Role:</strong> {user.role}</p>
|
|
322
|
+
<p><strong>ID:</strong> {user.id}</p>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</Card>
|
|
326
|
+
|
|
327
|
+
<Card>
|
|
328
|
+
<div className="p-6">
|
|
329
|
+
<h3 className="text-lg font-semibold text-sec-900 mb-2">Quick Actions</h3>
|
|
330
|
+
<p className="text-sec-600 mb-4">Common tasks</p>
|
|
331
|
+
<div className="space-y-2">
|
|
332
|
+
<Button variant="outline" className="w-full justify-start">
|
|
333
|
+
Edit Profile
|
|
334
|
+
</Button>
|
|
335
|
+
<Button variant="outline" className="w-full justify-start">
|
|
336
|
+
Change Password
|
|
337
|
+
</Button>
|
|
338
|
+
<Button variant="outline" className="w-full justify-start">
|
|
339
|
+
View Settings
|
|
340
|
+
</Button>
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
</Card>
|
|
344
|
+
|
|
345
|
+
<Card>
|
|
346
|
+
<div className="p-6">
|
|
347
|
+
<h3 className="text-lg font-semibold text-sec-900 mb-2">System Status</h3>
|
|
348
|
+
<p className="text-sec-600 mb-4">Application health</p>
|
|
349
|
+
<Alert>
|
|
350
|
+
<div className="flex items-center">
|
|
351
|
+
<div className="w-2 h-2 bg-main-500 rounded-full mr-2"></div>
|
|
352
|
+
All systems operational
|
|
353
|
+
</div>
|
|
354
|
+
</Alert>
|
|
355
|
+
</div>
|
|
356
|
+
</Card>
|
|
357
|
+
</div>
|
|
358
|
+
|
|
359
|
+
<div className="mt-8">
|
|
360
|
+
<Card>
|
|
361
|
+
<div className="p-6">
|
|
362
|
+
<h3 className="text-lg font-semibold text-sec-900 mb-4">Recent Activity</h3>
|
|
363
|
+
<div className="space-y-3">
|
|
364
|
+
<div className="flex items-center justify-between py-2 border-b border-sec-200">
|
|
365
|
+
<span className="text-sec-600">Logged in successfully</span>
|
|
366
|
+
<span className="text-sm text-sec-500">Just now</span>
|
|
367
|
+
</div>
|
|
368
|
+
<div className="flex items-center justify-between py-2 border-b border-sec-200">
|
|
369
|
+
<span className="text-sec-600">Account created</span>
|
|
370
|
+
<span className="text-sm text-sec-500">2 days ago</span>
|
|
371
|
+
</div>
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
</Card>
|
|
375
|
+
</div>
|
|
376
|
+
</div>
|
|
377
|
+
</PaceAppLayout>
|
|
378
|
+
);
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
export default Dashboard;
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
#### Navigation Component
|
|
385
|
+
|
|
386
|
+
`src/components/Navigation.tsx`:
|
|
387
|
+
```tsx
|
|
388
|
+
import React from 'react';
|
|
389
|
+
import { Link, useLocation } from 'react-router-dom';
|
|
390
|
+
import { NavigationMenu } from '@jmruthers/pace-core';
|
|
391
|
+
|
|
392
|
+
const Navigation: React.FC = () => {
|
|
393
|
+
const location = useLocation();
|
|
394
|
+
|
|
395
|
+
const navigationItems = [
|
|
396
|
+
{ label: 'Dashboard', href: '/dashboard', icon: 'Home' },
|
|
397
|
+
{ label: 'Profile', href: '/profile', icon: 'User' },
|
|
398
|
+
{ label: 'Settings', href: '/settings', icon: 'Settings' }
|
|
399
|
+
];
|
|
400
|
+
|
|
401
|
+
return (
|
|
402
|
+
<NavigationMenu
|
|
403
|
+
items={navigationItems}
|
|
404
|
+
currentPath={location.pathname}
|
|
405
|
+
onNavigate={(href) => {
|
|
406
|
+
// Navigation is handled by React Router
|
|
407
|
+
window.location.href = href;
|
|
408
|
+
}}
|
|
409
|
+
/>
|
|
410
|
+
);
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
export default Navigation;
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
#### Vite Configuration
|
|
417
|
+
|
|
418
|
+
`vite.config.ts`:
|
|
419
|
+
```ts
|
|
420
|
+
import { defineConfig } from 'vite';
|
|
421
|
+
import react from '@vitejs/plugin-react';
|
|
422
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
423
|
+
|
|
424
|
+
export default defineConfig({
|
|
425
|
+
plugins: [
|
|
426
|
+
react(),
|
|
427
|
+
tailwindcss({
|
|
428
|
+
content: [
|
|
429
|
+
'./src/**/*.{js,ts,jsx,tsx}',
|
|
430
|
+
'./node_modules/@jmruthers/pace-core/**/*.{js,ts,jsx,tsx}'
|
|
431
|
+
]
|
|
432
|
+
})
|
|
433
|
+
],
|
|
434
|
+
server: {
|
|
435
|
+
port: 3000,
|
|
436
|
+
open: true
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
#### Package.json Scripts
|
|
442
|
+
|
|
443
|
+
```json
|
|
444
|
+
{
|
|
445
|
+
"scripts": {
|
|
446
|
+
"dev": "vite",
|
|
447
|
+
"build": "tsc && vite build",
|
|
448
|
+
"preview": "vite preview",
|
|
449
|
+
"type-check": "tsc --noEmit"
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
#### Running the App
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
# Start development server
|
|
458
|
+
npm run dev
|
|
459
|
+
|
|
460
|
+
# Build for production
|
|
461
|
+
npm run build
|
|
462
|
+
|
|
463
|
+
# Preview production build
|
|
464
|
+
npm run preview
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
#### Features Demonstrated
|
|
468
|
+
|
|
469
|
+
**Authentication:**
|
|
470
|
+
- ✅ User login with email/password
|
|
471
|
+
- ✅ Session management
|
|
472
|
+
- ✅ Automatic redirects
|
|
473
|
+
- ✅ Loading states
|
|
474
|
+
- ✅ Error handling
|
|
475
|
+
|
|
476
|
+
**UI Components:**
|
|
477
|
+
- ✅ Card layouts
|
|
478
|
+
- ✅ Form inputs
|
|
479
|
+
- ✅ Buttons with variants
|
|
480
|
+
- ✅ Alerts and notifications
|
|
481
|
+
- ✅ Responsive design
|
|
482
|
+
|
|
483
|
+
**Layout:**
|
|
484
|
+
- ✅ App layout with header
|
|
485
|
+
- ✅ Navigation menu
|
|
486
|
+
- ✅ User menu
|
|
487
|
+
- ✅ Responsive sidebar
|
|
488
|
+
|
|
489
|
+
**State Management:**
|
|
490
|
+
- ✅ Authentication state
|
|
491
|
+
- ✅ User data
|
|
492
|
+
- ✅ Loading states
|
|
493
|
+
- ✅ Error states
|
|
33
494
|
|
|
34
495
|
### Full-Featured Application
|
|
35
|
-
|
|
496
|
+
|
|
497
|
+
A complete meal management application demonstrating all PACE Core features including authentication, RBAC, data tables, forms, and permission enforcement.
|
|
36
498
|
|
|
37
499
|
**Features:**
|
|
38
|
-
-
|
|
39
|
-
- Role-based access control
|
|
40
|
-
- Data tables with CRUD operations
|
|
41
|
-
- Form validation
|
|
42
|
-
- Permission enforcement
|
|
43
|
-
- Event management
|
|
500
|
+
- Complete authentication flow with RBAC
|
|
44
501
|
- Multi-tenant organisation support
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
502
|
+
- Event management and selection
|
|
503
|
+
- Advanced DataTable with CRUD operations
|
|
504
|
+
- Form validation and error handling
|
|
505
|
+
- Permission enforcement at page and component level
|
|
506
|
+
- Responsive layout with navigation
|
|
507
|
+
- Production-ready patterns
|
|
508
|
+
|
|
509
|
+
#### Project Structure
|
|
510
|
+
|
|
511
|
+
```
|
|
512
|
+
src/
|
|
513
|
+
├── App.tsx # Main app with all providers
|
|
514
|
+
├── lib/
|
|
515
|
+
│ └── supabase.ts # Supabase client
|
|
516
|
+
├── components/
|
|
517
|
+
│ ├── auth/
|
|
518
|
+
│ │ ├── LoginPage.tsx # Login form
|
|
519
|
+
│ │ └── ProtectedRoute.tsx # Route protection
|
|
520
|
+
│ ├── layout/
|
|
521
|
+
│ │ ├── AppLayout.tsx # Main layout
|
|
522
|
+
│ │ └── Navigation.tsx # Navigation menu
|
|
523
|
+
│ ├── dashboard/
|
|
524
|
+
│ │ └── DashboardPage.tsx # Dashboard with metrics
|
|
525
|
+
│ ├── meals/
|
|
526
|
+
│ │ ├── MealsPage.tsx # Meals list with DataTable
|
|
527
|
+
│ │ ├── MealForm.tsx # Add/edit meal form
|
|
528
|
+
│ │ └── MealModal.tsx # Modal for meal operations
|
|
529
|
+
│ ├── users/
|
|
530
|
+
│ │ ├── UsersPage.tsx # User management
|
|
531
|
+
│ │ └── UserForm.tsx # User creation/editing
|
|
532
|
+
│ └── shared/
|
|
533
|
+
│ ├── LoadingSpinner.tsx # Loading states
|
|
534
|
+
│ └── ErrorBoundary.tsx # Error handling
|
|
535
|
+
├── hooks/
|
|
536
|
+
│ ├── useMeals.ts # Meals data management
|
|
537
|
+
│ └── useUsers.ts # Users data management
|
|
538
|
+
├── types/
|
|
539
|
+
│ ├── meal.ts # Meal type definitions
|
|
540
|
+
│ └── user.ts # User type definitions
|
|
541
|
+
└── utils/
|
|
542
|
+
├── permissions.ts # Permission checking
|
|
543
|
+
└── validation.ts # Form validation schemas
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
#### App.tsx - Complete Application Setup
|
|
547
|
+
|
|
548
|
+
```tsx
|
|
549
|
+
import {
|
|
550
|
+
UnifiedAuthProvider,
|
|
551
|
+
OrganisationProvider,
|
|
552
|
+
EventProvider,
|
|
553
|
+
ErrorBoundary
|
|
554
|
+
} from '@jmruthers/pace-core';
|
|
555
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
556
|
+
import { supabase } from './lib/supabase';
|
|
557
|
+
import { AppRoutes } from './components/AppRoutes';
|
|
558
|
+
|
|
559
|
+
function App() {
|
|
560
|
+
return (
|
|
561
|
+
<ErrorBoundary>
|
|
562
|
+
<UnifiedAuthProvider
|
|
563
|
+
supabaseClient={supabase}
|
|
564
|
+
appName="meal-manager"
|
|
565
|
+
enableRBAC={true}
|
|
566
|
+
requireOrganisationContext={true}
|
|
567
|
+
idleTimeoutMs={30 * 60 * 1000}
|
|
568
|
+
warnBeforeMs={5 * 60 * 1000}
|
|
569
|
+
onIdleLogout={() => window.location.href = '/login'}
|
|
570
|
+
>
|
|
571
|
+
<OrganisationProvider>
|
|
572
|
+
<EventProvider>
|
|
573
|
+
<BrowserRouter>
|
|
574
|
+
<AppRoutes />
|
|
575
|
+
</BrowserRouter>
|
|
576
|
+
</EventProvider>
|
|
577
|
+
</OrganisationProvider>
|
|
578
|
+
</UnifiedAuthProvider>
|
|
579
|
+
</ErrorBoundary>
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
export default App;
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
#### AppRoutes.tsx - Route Configuration
|
|
587
|
+
|
|
588
|
+
```tsx
|
|
589
|
+
import { Routes, Route } from 'react-router-dom';
|
|
590
|
+
import { LoginPage } from './components/auth/LoginPage';
|
|
591
|
+
import { ProtectedRoute } from './components/auth/ProtectedRoute';
|
|
592
|
+
import { AppLayout } from './components/layout/AppLayout';
|
|
593
|
+
import { DashboardPage } from './components/dashboard/DashboardPage';
|
|
594
|
+
import { MealsPage } from './components/meals/MealsPage';
|
|
595
|
+
import { UsersPage } from './components/users/UsersPage';
|
|
596
|
+
|
|
597
|
+
export function AppRoutes() {
|
|
598
|
+
return (
|
|
599
|
+
<Routes>
|
|
600
|
+
<Route path="/login" element={<LoginPage />} />
|
|
601
|
+
<Route path="/" element={
|
|
602
|
+
<ProtectedRoute>
|
|
603
|
+
<AppLayout>
|
|
604
|
+
<DashboardPage />
|
|
605
|
+
</AppLayout>
|
|
606
|
+
</ProtectedRoute>
|
|
607
|
+
} />
|
|
608
|
+
<Route path="/meals" element={
|
|
609
|
+
<ProtectedRoute>
|
|
610
|
+
<AppLayout>
|
|
611
|
+
<MealsPage />
|
|
612
|
+
</AppLayout>
|
|
613
|
+
</ProtectedRoute>
|
|
614
|
+
} />
|
|
615
|
+
<Route path="/users" element={
|
|
616
|
+
<ProtectedRoute>
|
|
617
|
+
<AppLayout>
|
|
618
|
+
<UsersPage />
|
|
619
|
+
</AppLayout>
|
|
620
|
+
</ProtectedRoute>
|
|
621
|
+
} />
|
|
622
|
+
</Routes>
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
#### MealsPage.tsx - Advanced DataTable Implementation
|
|
628
|
+
|
|
629
|
+
```tsx
|
|
630
|
+
import { DataTable, type DataTableColumn } from '@jmruthers/pace-core';
|
|
631
|
+
import { useState } from 'react';
|
|
632
|
+
import { useMeals } from '../../hooks/useMeals';
|
|
633
|
+
|
|
634
|
+
interface Meal {
|
|
635
|
+
id: string;
|
|
636
|
+
name: string;
|
|
637
|
+
category: string;
|
|
638
|
+
calories: number;
|
|
639
|
+
date: string;
|
|
640
|
+
description?: string;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
const columns: DataTableColumn<Meal>[] = [
|
|
644
|
+
{
|
|
645
|
+
accessorKey: 'name',
|
|
646
|
+
header: 'Meal Name',
|
|
647
|
+
sortable: true,
|
|
648
|
+
features: { search: true },
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
accessorKey: 'category',
|
|
652
|
+
header: 'Category',
|
|
653
|
+
sortable: true,
|
|
654
|
+
enableGrouping: true,
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
accessorKey: 'calories',
|
|
658
|
+
header: 'Calories',
|
|
659
|
+
sortable: true,
|
|
660
|
+
cell: ({ row }) => (
|
|
661
|
+
<span className="font-mono">
|
|
662
|
+
{row.original.calories.toLocaleString()}
|
|
663
|
+
</span>
|
|
664
|
+
),
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
accessorKey: 'date',
|
|
668
|
+
header: 'Date',
|
|
669
|
+
sortable: true,
|
|
670
|
+
cell: ({ row }) => (
|
|
671
|
+
<span>
|
|
672
|
+
{new Date(row.original.date).toLocaleDateString()}
|
|
673
|
+
</span>
|
|
674
|
+
),
|
|
675
|
+
},
|
|
676
|
+
];
|
|
677
|
+
|
|
678
|
+
export function MealsPage() {
|
|
679
|
+
const { meals, loading, error, addMeal, updateMeal, deleteMeal } = useMeals();
|
|
680
|
+
|
|
681
|
+
const handleAddMeal = () => {
|
|
682
|
+
// Open add meal modal
|
|
683
|
+
console.log('Add meal');
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
const handleEditMeal = (meal: Meal) => {
|
|
687
|
+
// Open edit meal modal
|
|
688
|
+
console.log('Edit meal:', meal);
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
const handleDeleteMeal = async (meal: Meal) => {
|
|
692
|
+
if (confirm(`Delete ${meal.name}?`)) {
|
|
693
|
+
await deleteMeal(meal.id);
|
|
694
|
+
}
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
if (loading) return <div>Loading meals...</div>;
|
|
698
|
+
if (error) return <div>Error: {error}</div>;
|
|
699
|
+
|
|
700
|
+
return (
|
|
701
|
+
<div className="p-6">
|
|
702
|
+
<div className="mb-6">
|
|
703
|
+
<h1 className="text-2xl font-bold text-sec-900">Meals</h1>
|
|
704
|
+
<p className="text-sec-600">Manage your meal planning and tracking</p>
|
|
705
|
+
</div>
|
|
706
|
+
|
|
707
|
+
<DataTable
|
|
708
|
+
data={meals}
|
|
709
|
+
columns={columns}
|
|
710
|
+
rbac={{
|
|
711
|
+
resource: 'meals',
|
|
712
|
+
pageId: 'meals-management'
|
|
713
|
+
}}
|
|
714
|
+
title="Meals"
|
|
715
|
+
description="Track and manage your meals"
|
|
716
|
+
features={{
|
|
717
|
+
search: true,
|
|
718
|
+
pagination: true,
|
|
719
|
+
sorting: true,
|
|
720
|
+
filtering: true,
|
|
721
|
+
columnVisibility: true,
|
|
722
|
+
rowActions: true,
|
|
723
|
+
creation: true,
|
|
724
|
+
editing: true,
|
|
725
|
+
deletion: true,
|
|
726
|
+
export: true,
|
|
727
|
+
import: true,
|
|
728
|
+
}}
|
|
729
|
+
onRowClick={(row) => console.log('Row clicked:', row)}
|
|
730
|
+
onAddRow={handleAddMeal}
|
|
731
|
+
onEditRow={handleEditMeal}
|
|
732
|
+
onDeleteRow={handleDeleteMeal}
|
|
733
|
+
onExport={() => console.log('Export meals')}
|
|
734
|
+
onImport={() => console.log('Import meals')}
|
|
735
|
+
getRowId={(row) => row.id}
|
|
736
|
+
/>
|
|
737
|
+
</div>
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
#### DashboardPage.tsx - Metrics and Overview
|
|
743
|
+
|
|
744
|
+
```tsx
|
|
745
|
+
import { Card, CardHeader, CardTitle, CardContent } from '@jmruthers/pace-core';
|
|
746
|
+
import { useMeals } from '../../hooks/useMeals';
|
|
747
|
+
import { useUsers } from '../../hooks/useUsers';
|
|
748
|
+
|
|
749
|
+
export function DashboardPage() {
|
|
750
|
+
const { meals } = useMeals();
|
|
751
|
+
const { users } = useUsers();
|
|
752
|
+
|
|
753
|
+
const totalMeals = meals.length;
|
|
754
|
+
const totalCalories = meals.reduce((sum, meal) => sum + meal.calories, 0);
|
|
755
|
+
const averageCalories = totalMeals > 0 ? Math.round(totalCalories / totalMeals) : 0;
|
|
756
|
+
const totalUsers = users.length;
|
|
757
|
+
|
|
758
|
+
return (
|
|
759
|
+
<div className="p-6">
|
|
760
|
+
<div className="mb-6">
|
|
761
|
+
<h1 className="text-2xl font-bold text-sec-900">Dashboard</h1>
|
|
762
|
+
<p className="text-sec-600">Overview of your meal management system</p>
|
|
763
|
+
</div>
|
|
764
|
+
|
|
765
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
|
766
|
+
<Card>
|
|
767
|
+
<CardHeader>
|
|
768
|
+
<CardTitle>Total Meals</CardTitle>
|
|
769
|
+
</CardHeader>
|
|
770
|
+
<CardContent>
|
|
771
|
+
<p className="text-3xl font-bold text-main-600">{totalMeals}</p>
|
|
772
|
+
<p className="text-sm text-sec-600">All time</p>
|
|
773
|
+
</CardContent>
|
|
774
|
+
</Card>
|
|
775
|
+
|
|
776
|
+
<Card>
|
|
777
|
+
<CardHeader>
|
|
778
|
+
<CardTitle>Total Calories</CardTitle>
|
|
779
|
+
</CardHeader>
|
|
780
|
+
<CardContent>
|
|
781
|
+
<p className="text-3xl font-bold text-main-600">{totalCalories.toLocaleString()}</p>
|
|
782
|
+
<p className="text-sm text-sec-600">All time</p>
|
|
783
|
+
</CardContent>
|
|
784
|
+
</Card>
|
|
785
|
+
|
|
786
|
+
<Card>
|
|
787
|
+
<CardHeader>
|
|
788
|
+
<CardTitle>Average Calories</CardTitle>
|
|
789
|
+
</CardHeader>
|
|
790
|
+
<CardContent>
|
|
791
|
+
<p className="text-3xl font-bold text-main-600">{averageCalories}</p>
|
|
792
|
+
<p className="text-sm text-sec-600">Per meal</p>
|
|
793
|
+
</CardContent>
|
|
794
|
+
</Card>
|
|
795
|
+
|
|
796
|
+
<Card>
|
|
797
|
+
<CardHeader>
|
|
798
|
+
<CardTitle>Total Users</CardTitle>
|
|
799
|
+
</CardHeader>
|
|
800
|
+
<CardContent>
|
|
801
|
+
<p className="text-3xl font-bold text-main-600">{totalUsers}</p>
|
|
802
|
+
<p className="text-sm text-sec-600">Registered</p>
|
|
803
|
+
</CardContent>
|
|
804
|
+
</Card>
|
|
805
|
+
</div>
|
|
806
|
+
|
|
807
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
808
|
+
<Card>
|
|
809
|
+
<CardHeader>
|
|
810
|
+
<CardTitle>Recent Meals</CardTitle>
|
|
811
|
+
</CardHeader>
|
|
812
|
+
<CardContent>
|
|
813
|
+
<div className="space-y-3">
|
|
814
|
+
{meals.slice(0, 5).map((meal) => (
|
|
815
|
+
<div key={meal.id} className="flex justify-between items-center py-2 border-b border-sec-200">
|
|
816
|
+
<div>
|
|
817
|
+
<p className="font-medium">{meal.name}</p>
|
|
818
|
+
<p className="text-sm text-sec-600">{meal.category}</p>
|
|
819
|
+
</div>
|
|
820
|
+
<div className="text-right">
|
|
821
|
+
<p className="font-mono">{meal.calories}</p>
|
|
822
|
+
<p className="text-sm text-sec-600">{new Date(meal.date).toLocaleDateString()}</p>
|
|
823
|
+
</div>
|
|
824
|
+
</div>
|
|
825
|
+
))}
|
|
826
|
+
</div>
|
|
827
|
+
</CardContent>
|
|
828
|
+
</Card>
|
|
829
|
+
|
|
830
|
+
<Card>
|
|
831
|
+
<CardHeader>
|
|
832
|
+
<CardTitle>Meal Categories</CardTitle>
|
|
833
|
+
</CardHeader>
|
|
834
|
+
<CardContent>
|
|
835
|
+
<div className="space-y-3">
|
|
836
|
+
{Object.entries(
|
|
837
|
+
meals.reduce((acc, meal) => {
|
|
838
|
+
acc[meal.category] = (acc[meal.category] || 0) + 1;
|
|
839
|
+
return acc;
|
|
840
|
+
}, {} as Record<string, number>)
|
|
841
|
+
).map(([category, count]) => (
|
|
842
|
+
<div key={category} className="flex justify-between items-center py-2 border-b border-sec-200">
|
|
843
|
+
<span className="font-medium">{category}</span>
|
|
844
|
+
<span className="text-main-600 font-semibold">{count}</span>
|
|
845
|
+
</div>
|
|
846
|
+
))}
|
|
847
|
+
</div>
|
|
848
|
+
</CardContent>
|
|
849
|
+
</Card>
|
|
850
|
+
</div>
|
|
851
|
+
</div>
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
#### Features Demonstrated
|
|
857
|
+
|
|
858
|
+
**Authentication & RBAC:**
|
|
859
|
+
- ✅ Complete authentication flow
|
|
860
|
+
- ✅ Role-based access control
|
|
861
|
+
- ✅ Permission enforcement
|
|
862
|
+
- ✅ Multi-tenant organisation support
|
|
863
|
+
- ✅ Event management
|
|
864
|
+
|
|
865
|
+
**Data Management:**
|
|
866
|
+
- ✅ Advanced DataTable with all features
|
|
867
|
+
- ✅ CRUD operations
|
|
868
|
+
- ✅ Sorting, filtering, pagination
|
|
869
|
+
- ✅ Search functionality
|
|
870
|
+
- ✅ Export/import capabilities
|
|
871
|
+
|
|
872
|
+
**UI Components:**
|
|
873
|
+
- ✅ Complete component library usage
|
|
874
|
+
- ✅ Responsive design
|
|
875
|
+
- ✅ Form validation
|
|
876
|
+
- ✅ Error handling
|
|
877
|
+
- ✅ Loading states
|
|
878
|
+
|
|
879
|
+
**Production Patterns:**
|
|
880
|
+
- ✅ Error boundaries
|
|
881
|
+
- ✅ Custom hooks
|
|
882
|
+
- ✅ Type safety
|
|
883
|
+
- ✅ Performance optimization
|
|
884
|
+
- ✅ Accessibility
|
|
49
885
|
|
|
50
886
|
## 📁 Code Samples
|
|
51
887
|
|
|
@@ -70,10 +906,10 @@ See individual components in action:
|
|
|
70
906
|
## 🎯 Choose Your Path
|
|
71
907
|
|
|
72
908
|
### I'm New to PACE Core
|
|
73
|
-
Start with the [Basic Authentication App](
|
|
909
|
+
Start with the [Basic Authentication App](#basic-authentication-app) to learn the fundamentals.
|
|
74
910
|
|
|
75
911
|
### I Want to Build Something Real
|
|
76
|
-
Use the [Full-Featured Application](
|
|
912
|
+
Use the [Full-Featured Application](#full-featured-application) as your foundation.
|
|
77
913
|
|
|
78
914
|
### I Need Specific Examples
|
|
79
915
|
Browse the [API Reference](../api-reference/) for component-specific examples.
|
|
@@ -92,8 +928,8 @@ All examples are designed to be easily customizable:
|
|
|
92
928
|
|
|
93
929
|
## 📚 Learning Path
|
|
94
930
|
|
|
95
|
-
1. **Start Here** → [Installation](
|
|
96
|
-
2. **Quick Start** → [
|
|
931
|
+
1. **Start Here** → [Installation Guide](./installation-guide.md)
|
|
932
|
+
2. **Quick Start** → [Authentication Guide](../implementation-guides/authentication.md)
|
|
97
933
|
3. **Examples** → Choose an example above
|
|
98
934
|
4. **Core Concepts** → [Understand the Fundamentals](../core-concepts/)
|
|
99
935
|
5. **Implementation** → [Advanced Patterns](../implementation-guides/)
|
|
@@ -104,3 +940,10 @@ All examples are designed to be easily customizable:
|
|
|
104
940
|
- **Stuck on an example?** Check [Common Issues](../troubleshooting/common-issues.md)
|
|
105
941
|
- **Want to contribute?** Add your own examples to our community section
|
|
106
942
|
- **Have questions?** Review our [Troubleshooting](../troubleshooting/) guides
|
|
943
|
+
|
|
944
|
+
## Related Documentation
|
|
945
|
+
|
|
946
|
+
- [Authentication Implementation Guide](../implementation-guides/authentication.md) - Complete authentication setup
|
|
947
|
+
- [Data Tables Guide](../implementation-guides/data-tables.md) - Advanced data management
|
|
948
|
+
- [API Reference](../api-reference/) - Complete component documentation
|
|
949
|
+
- [Best Practices](../best-practices/) - Production guidelines
|