@pwc-rr/platform-kit
v1.0.46
Published
PwC RR platform kit
Readme
OneConsole Platform Kit
Shared React component library and service layer (@pwc-rr/platform-kit) for OneConsole product frontends. Provides PageHeader, layout components, HTTP client, Keycloak integration, and permission utilities.
Build & Dev
npm install
npm run build # Rollup → dist/ (CJS + ESM + types)
npm run dev # Rollup watch mode
npm run test # Vitest single run
npm run test:watch # Vitest watch modeInstallation
npm install @pwc-rr/platform-kitPeer Dependencies
npm install react react-dom antd @ant-design/icons axios keycloak-js react-router-domKey Exports (src/index.ts)
| Category | Exports | |----------|---------| | Components | PageHeader, PageHeaderProvider, Sidebar, Breadcrumb, MainLayout | | Services | keycloak, http, userService, productMenuService | | Hooks | usePermission, usePageHeader | | State | PageHeaderState (global state object) | | Types | User, Product, Tenant |
Usage
Basic Setup
import React, { useState } from 'react';
import { Layout } from 'antd';
import { PageHeader, PageHeaderProvider } from '@pwc-rr/platform-kit';
const App: React.FC = () => {
const [collapsed, setCollapsed] = useState(false);
return (
<Layout style={{ minHeight: '100vh' }}>
<PageHeader
collapsed={collapsed}
onCollapse={() => setCollapsed(!collapsed)}
/>
<Layout.Content style={{ marginTop: 64, padding: 24 }}>
{/* Page content */}
</Layout.Content>
</Layout>
);
};Product Switch Callback
<PageHeader
collapsed={collapsed}
onCollapse={() => setCollapsed(!collapsed)}
onProductChange={(productId: string) => {
console.log(`Switched to product: ${productId}`);
}}
/>Accessing Global State
PageHeader exposes global state accessible anywhere in the app:
import React from 'react';
import { PageHeaderState } from '@pwc-rr/platform-kit';
const UserInfo: React.FC = () => {
const currentUser = PageHeaderState.getCurrentUser();
const selectedTenant = PageHeaderState.getSelectedTenant();
React.useEffect(() => {
const unsubscribe = PageHeaderState.subscribe((state) => {
console.log('State updated:', state);
});
return unsubscribe;
}, []);
return (
<div>
<h2>Current user: {currentUser?.username}</h2>
<h3>Current tenant: {selectedTenant?.name}</h3>
</div>
);
};Component API
PageHeader
| Prop | Description | Type | Default | | --- | --- | --- | --- | | collapsed | Whether the sidebar is collapsed | boolean | - | | onCollapse | Callback when sidebar collapse state changes | () => void | - | | onProductChange | Callback when product is switched | (productId: string) => void | - | | extra | Custom content displayed on the right side of the header | ReactNode | - |
PageHeaderProvider
Context Provider for user info, tenant info, and other global state. Usually not used directly — PageHeader includes it internally.
usePageHeader
Custom hook to access PageHeader context in components:
const {
currentUser, // Current user info
loading, // Loading state
error, // Error message
selectedTenant, // Currently selected tenant
setSelectedTenant, // Set current tenant
logout // Logout function
} = usePageHeader();PageHeaderState
Global state object accessible anywhere in the app:
| Method | Description | Parameters | Return | | --- | --- | --- | --- | | getCurrentUser | Get current user info | - | User | null | | getSelectedTenant | Get currently selected tenant | - | { id: string; code: string; name: string; } | null | | isLoading | Get loading state | - | boolean | | getError | Get error message | - | string | null | | subscribe | Subscribe to state changes | (state: GlobalPageHeaderState) => void | () => void |
MainLayout
| Prop | Description | Type | Default | | --- | --- | --- | --- | | menuItems | Sidebar menu item config | MenuItem[] | - | | productName | Product name | string | - | | productIcon | Product icon | ReactNode | - | | children | Content area | ReactNode | - | | breadcrumb | Breadcrumb component | ReactNode | - | | defaultCollapsed | Initial sidebar collapsed state | boolean | false | | contentStyle | Custom content area style | CSSProperties | - | | contentWrapperStyle | Custom content wrapper style | CSSProperties | - | | className | Custom class name | string | - | | headerExtra | Custom header extra content | ReactNode | - |
Type Definitions
User
interface User {
id: string;
username: string;
email: string;
tenants: Array<{
id: string;
code: string;
name: string;
}>;
}Product
interface Product {
id: string;
name: string;
url: string;
icon?: string;
category?: string;
order?: number;
}HTTP Client (src/services/http.ts)
- Axios wrapper, auto-adds
/apiprefix to all requests - Auto key transformation: requests →
snake_case, responses →camelCase(configurable viatransformKeysoption) - Adds
Authorizationheader (Bearer token) andX-Tenant-Codeheader - Token refresh when < 60s remaining (
MIN_TOKEN_VALIDITY = 60) - On 401 → auto-redirect to org login, stores redirect URL in sessionStorage
http.getAuthHeaders()for native fetch/WebSocket/SSE scenarios
Keycloak Service (src/services/keycloak.ts)
- Org code stored in localStorage key
oneconsole-org-code - Set via
/org/:orgCode/*URL before Keycloak init - Each org maps to its own Keycloak realm
Permission Utilities
usePermission()hook provides:can(),hasResourceAccess(),hasModuleAccess()
Notes
- PageHeader requires a Keycloak auth service. By default it fetches config from
/api/public/keycloak-config. - Product menu data is fetched from
/api/public/product-menu(provided by the gateway). - User info is fetched from
/auth/users/me(provided by the auth service). - Components use Ant Design styles — ensure Ant Design is properly configured in your project.
App Template Generator
The library includes a template generator for quickly scaffolding a React app with MainLayout, Sidebar, Breadcrumb, and PageHeader pre-integrated.
# Using npx
npx @pwc-rr/platform-kit/templates/create-ra-app my-app
# In a project with @pwc-rr/platform-kit installed
npx ./node_modules/@pwc-rr/platform-kit/templates/create-ra-app my-appCLI Options
--use-npm: Use npm instead of yarn for dependency installation--skip-install: Skip dependency installation
See template generator docs for more details.
