@pagamio/frontend-commons-lib
v0.8.201
Published
Pagamio library for Frontend reusable components like the form engine and table container
Downloads
2,502
Maintainers
Readme
pagamio-frontend-commons-library
A reusable React component library styled with Tailwind CSS, designed to streamline your frontend development process.
:rocket: Features
- A Form Engine: A package with all possible input components that can be used to build a form. This helps render forms in your project.
- Reusable Components: A collection of customizable components like DateInput, TextInput, and more.
- Tailwind CSS: Utility-first CSS framework for rapid UI development.
- TypeScript Support: Fully typed components for enhanced developer experience.
- Flexible Imports: Import components individually or collectively.
- Peer Dependencies: Ensures compatibility with React and React DOM versions.
- API Client: Robust API integration with authentication support, SWR data fetching, and mocking capabilities.
:package: Installation
Install the library via Yarn:
yarn add pagamio-frontend-commons-lib:art: Usage
Importing Styles
Import the compiled Tailwind CSS styles into your application's entry point (e.g., index.js or App.js):
import 'pagamio-frontend-commons-lib/lib/styles.css';Importing Components
You can import components individually or collectively.
a. Named Imports
Import multiple components from the main entry point:
import { DateInput, TextInput } from 'pagamio-frontend-commons-lib';
:gear: Environment Variables
Some utilities (for example the useImageUpload hook and ImageUploader component) require an API endpoint that issues presigned upload URLs. Make sure your host application exposes the following public environment variable before using those helpers:
| Variable | Description |
| --- | --- |
| NEXT_PUBLIC_UPLOAD_URL_ENDPOINT | HTTP endpoint that returns presigned URLs for file uploads. |
# .env (per app)
NEXT_PUBLIC_UPLOAD_URL_ENDPOINT=https://<your-upload-service>/upload-urlThis value is resolved at runtime;
:shield: RBAC Module
The Role-Based Access Control (RBAC) module provides a flexible system for implementing permission-based access control in your applications.
Features
- Generic TypeScript implementation that works with any permission system
- Flexible configuration that can be initialized once at application startup
- Pure utility functions that can be used anywhere in your application
- React hooks for convenient use in components
- Support for role-based and permission-based access control
- Type-safe API with generics for custom user and permission types
Core Components
Initialization
Initialize the RBAC system with your application-specific configuration:
import { initializeRBAC } from 'pagamio-frontend-commons-lib/rbac';
import { Permissions } from './permissions';
// Define your permission enum
enum Permissions {
ALL = 'ALL',
VIEW_DASHBOARD = 'VIEW_DASHBOARD',
MANAGE_USERS = 'MANAGE_USERS',
// ... other permissions
}
// Define your RBAC configuration
const rbacConfig = {
'ADMIN': [Permissions.ALL],
'MANAGER': [Permissions.VIEW_DASHBOARD, Permissions.MANAGE_USERS],
'USER': [Permissions.VIEW_DASHBOARD],
};
// Initialize RBAC with your configuration
initializeRBAC({
rbacConfig,
allPermissionValue: Permissions.ALL,
allPermissions: Object.values(Permissions),
roleKey: 'roleName' // The property in your user object that contains the role
});Utility Functions
Use the RBAC utility functions to check permissions and roles:
import { hasPermission, hasRole, getUserPermissions } from 'pagamio-frontend-commons-lib/rbac';
import { Permissions } from './permissions';
// Check if a user has a specific permission
const canViewDashboard = hasPermission(user, Permissions.VIEW_DASHBOARD);
// Check if a user has a specific role
const isAdmin = hasRole(user, 'ADMIN');
// Get all permissions for a user
const userPermissions = getUserPermissions(user);React Hooks
Use the RBAC hooks in your React components:
import { useHasPermission, useHasRole } from 'pagamio-frontend-commons-lib/rbac';
import { useAuth } from 'pagamio-frontend-commons-lib/auth';
import { Permissions } from './permissions';
function Dashboard() {
const { user } = useAuth();
const canManageUsers = useHasPermission(user, Permissions.MANAGE_USERS);
return (
<div>
<h1>Dashboard</h1>
{canManageUsers && <UserManagement />}
</div>
);
}:globe_with_meridians: API Module
The API module provides a robust system for making API requests with built-in authentication, caching, and error handling capabilities.
Features
- TypeScript support with generic types for type-safe API operations
- Authentication integration with token management
- SWR integration for data fetching, caching, and revalidation
- Support for RESTful operations (GET, POST, PUT, PATCH, DELETE)
- Pagination support for large datasets
- Configurable retry logic and timeout handling
- Request and response interceptors
- Error handling and logging
- Mock API support for testing and development
Core Components
ApiClient
The ApiClient class provides a flexible HTTP client with authentication support, retry logic, and error handling.
import { ApiClient, createApiClient } from 'pagamio-frontend-commons-lib';
// Create a client with your custom auth configuration
const apiClient = createApiClient<MyAuthConfig>({
baseURL: 'https://api.example.com',
tokenManager: tokenManager,
defaultHeaders: {
'Content-Type': 'application/json',
},
timeout: 5000,
retries: 2,
});
// Making API calls
const data = await apiClient.get<MyResponseType>('/users');
const newUser = await apiClient.post<UserResponse>('/users', { name: 'John', email: '[email protected]' });SWR Integration
The API module includes SWR hooks for efficient data fetching with caching, revalidation, and focus refetching.
import { useApiSWR, usePaginatedApiSWR } from 'pagamio-frontend-commons-lib';
// Basic data fetching with SWR
function UserProfile({ userId }) {
const { data, error, isLoading } = useApiSWR<UserData>(`/users/${userId}`);
if (isLoading) return <div>Loading
...
</div>;
if (error) return <div>Error
loading
user
data < /div>;
return <div>Hello, { data.name }! < /div>;
}
// Paginated data fetching
function UserList() {
const { data, error, isLoading } = usePaginatedApiSWR<User>('/users', {
params: { page: 0, size: 10 }
});
if (isLoading) return <div>Loading
users
...
</div>;
return (
<div>
<h2>Users({ data.totalElements }) < /h2>
< ul >
{
data.content.map(user => <li key = { user.id } > { user.name } < /li>)}
< /ul>
< /div>
);
}API Context Provider
The ApiProvider component makes the API client available throughout your application.
import { ApiProvider, createApiClient } from 'pagamio-frontend-commons-lib';
// Create API client
const apiClient = createApiClient<MyAuthConfig>({
baseURL: 'https://api.example.com',
tokenManager: tokenManager,
});
// Wrap your application with the provider
function App() {
return (
<ApiProvider apiClient = { apiClient } >
<YourApplication / >
</ApiProvider>
);
}API Mutations
The API module provides hooks for performing mutations (create, update, delete operations).
import { useApiMutation, useApiSWRWithMutation } from 'pagamio-frontend-commons-lib';
// Using the mutation hook
function CreateUserForm() {
const mutation = useApiMutation<UserResponse>();
const handleSubmit = async (userData) => {
try {
const newUser = await mutation.post('/users', userData);
alert(`User ${newUser.name} created successfully!`);
} catch (error) {
console.error('Failed to create user:', error);
}
};
return <form onSubmit = { handleSubmit } > {/* form fields */ } < /form>;
}
// Combined SWR and mutation hook
function EditUserProfile({ userId }) {
const { data, error, isLoading, mutate } = useApiSWRWithMutation<UserData>(
`/users/${userId}`
);
const handleUpdate = async (updatedData) => {
try {
await mutate.patch(`/users/${userId}`, updatedData);
alert('Profile updated successfully!');
} catch (error) {
console.error('Failed to update profile:', error);
}
};
if (isLoading) return <div>Loading
...
</div>;
return <ProfileForm user = { data }
onSubmit = { handleUpdate }
/>;
}Mocking API Requests
The API module supports mocking API requests for testing and development.
import { ApiProvider, createApiClient, MockConfig } from 'pagamio-frontend-commons-lib';
// Define mock configurations
const mockConfig: MockConfig[] = [
{
path: '/users',
method: 'GET',
response: [
{ id: 1, name: 'John Doe', email: '[email protected]' },
{ id: 2, name: 'Jane Smith', email: '[email protected]' }
]
},
{
path: '/users',
method: 'POST',
params: { name: 'Alice', email: '[email protected]' },
response: { id: 3, name: 'Alice', email: '[email protected]' }
}
];
// Enable mocking in the provider
function TestApp() {
return (
<ApiProvider
apiClient = { apiClient }
mocked = { true }
mockConfig = { mockConfig } >
<YourApplication / >
</ApiProvider>
)
;
}Authentication Integration
The API client integrates with the token manager for authentication.
import { createApiClient, createTokenManager } from 'pagamio-frontend-commons-lib';
// Create a token manager
const tokenManager = createTokenManager<MyAuthConfig>({
baseUrl: 'https://api.example.com',
refreshEndpoint: '/auth/refresh',
cookieOptions: {
secure: true,
sameSite: 'strict'
}
});
// Create API client with authentication
const apiClient = createApiClient<MyAuthConfig>({
baseURL: 'https://api.example.com',
tokenManager: tokenManager,
onUnauthorized: () => {
// Handle unauthorized access (e.g., redirect to login)
window.location.href = '/login';
}
});Advanced Configuration
Custom Request/Response Handling
const apiClient = createApiClient<MyAuthConfig>({
baseURL: 'https://api.example.com',
tokenManager: tokenManager,
onRequest: async (config) => {
// Add custom headers or modify request configuration
config.headers = {
...config.headers,
'X-Custom-Header': 'CustomValue'
};
return config;
},
onResponse: async (response, data) => {
// Transform or process response data
return data.results || data;
},
onError: async (error) => {
// Log or handle errors
console.error(`API Error (${error.status}):`, error.message);
}
});Pagination and Filtering
// Custom pagination params
const { data } = useApiSWR<UserListResponse>('/users', {
params: {
page: 0,
size: 25,
sortBy: 'createdAt',
sortDir: 'desc',
name: 'John'
}
});TypeScript Integration
The API module is fully typed with TypeScript, providing type safety and better developer experience.
// Define your auth configuration
interface MyAuthConfig extends CustomAuthConfig {
UserInfo: {
id: string;
username: string;
email: string;
roles: string[];
};
TokenInfo: {
token: string;
expiresIn: number;
};
Credentials: {
username: string;
password: string;
};
}
// Use your custom types with the API client
const apiClient = createApiClient<MyAuthConfig>({
baseURL: 'https://api.example.com',
tokenManager: tokenManager
});
// Type-safe API calls
interface Product {
id: string;
name: string;
price: number;
}
const { data: products } = useApiSWR<Product[]>('/products');Best Practices
Centralize API Configuration: Create a central API configuration file that sets up the API client and exports hooks for use throughout your application.
Use TypeScript: Leverage TypeScript definitions for type-safe API calls and better developer experience.
Handle Loading and Error States: Always handle loading and error states in your components when using API hooks.
Implement Proper Error Handling: Configure error handling with the
onErrorcallback and handle errors appropriately in your UI.Use Mocking for Development: Enable mocking during development to work without a backend or to test specific scenarios.
Optimize Cache Invalidation: Use SWR's
mutatefunction to keep your data fresh and update the UI after mutations.Set Appropriate Timeouts: Configure request timeouts based on the expected response time of your API endpoints.
:globe_with_meridians: Translations
The library provides a complete translation system that supports internationalization for your applications.
Languages Currently Supported
The library comes with built-in support for the following languages:
- English (en)
- Spanish (es)
- French (fr)
- Portuguese (pt)
Implementation Guide
Follow these steps to implement translations in your project:
1. Setup Translation Provider
Wrap your application with the TranslationProvider:
import { TranslationProvider } from 'pagamio-frontend-commons-lib';
function App() {
return (
<TranslationProvider
defaultLocale="en"
loadPath="/translations" // Path to your translation files
>
<YourApplicationComponents />
</TranslationProvider>
);
}Alternatively, if you're using the AppLayout component:
import { AppLayout } from 'pagamio-frontend-commons-lib';
function App() {
return (
<AppLayout
// other props...
enableTranslations={true}
translationConfig={{
defaultLocale: 'en',
loadPath: '/translations',
}}
>
{/* Your content */}
</AppLayout>
);
}2. Create Translation Files
Create JSON files for each language in your project:
/public
/translations
en.json
es.json
fr.json
pt.jsonExample of a translation file (en.json):
{
"common": {
"save": "Save",
"cancel": "Cancel",
"submit": "Submit"
},
"auth": {
"login": "Login",
"register": "Register",
"forgotPassword": "Forgot Password?"
}
}3. Add i18next-scanner Config
Create an i18next-scanner.config.js in your project root:
module.exports = {
input: ['src/**/*.{js,jsx,ts,tsx}', '!src/**/*.test.{js,jsx,ts,tsx}', '!**/node_modules/**'],
output: './public/translations/',
options: {
debug: true,
func: {
list: ['t', 'tLib'],
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
lngs: ['en', 'es', 'fr', 'pt'],
defaultLng: 'en',
defaultValue: function(lng, ns, key) {
return key;
},
resource: {
loadPath: 'public/translations/{{lng}}.json',
savePath: '{{lng}}.json',
jsonIndent: 2,
lineEnding: '\n',
},
removeUnusedKeys: false,
nsSeparator: false,
keySeparator: '.',
},
};4. Add Extraction Script to package.json
"scripts": {
"extract-translations": "i18next-scanner --config i18next-scanner.config.js 'src/**/*.{js,jsx,ts,tsx}'"
}5. Install Required Dependencies
Install the necessary dev dependencies:
yarn add -D i18next-scannerOr if you're using npm:
npm install --save-dev i18next-scanner6. Use Translations in Components
import { useTranslation } from 'pagamio-frontend-commons-lib';
function YourComponent() {
const { t } = useTranslation();
return (
<div>
<h1>{t('common.title', 'Default Title')}</h1>
<p>{t('common.description', 'This is a default description')}</p>
<button>{t('common.save', 'Save')}</button>
</div>
);
}7. Use Library Translations
The library provides common translations for frequently used UI elements:
import { useLibTranslations } from 'pagamio-frontend-commons-lib';
function YourComponent() {
const { tLib } = useLibTranslations();
return (
<div>
<button>{tLib('save')}</button>
<button>{tLib('cancel')}</button>
<button>{tLib('submit')}</button>
</div>
);
}8. Add Locale Switcher
Add a language switcher to allow users to change the application language:
import { LocaleSwitcher } from 'pagamio-frontend-commons-lib';
function Header() {
return (
<header>
<nav>
{/* Your other navigation elements */}
<LocaleSwitcher />
</nav>
</header>
);
}You can customize language display names:
<LocaleSwitcher
localeNames={{
en: 'English',
es: 'Español',
fr: 'Français',
pt: 'Português'
}}
/>9. Run the Extraction Script
Extract all translation keys from your application:
yarn extract-translationsThis will scan your code for translation keys and update your translation files.
Advanced Configuration
Custom Locale Detector
You can configure the translation system to detect the browser's locale:
import { TranslationProvider, detectBrowserLocale } from 'pagamio-frontend-commons-lib';
function App() {
const browserLocale = detectBrowserLocale(); // Returns 'en', 'es', etc.
return (
<TranslationProvider
defaultLocale={browserLocale}
loadPath="/translations"
>
<YourApplicationComponents />
</TranslationProvider>
);
}Direct Loading of Translation Data
Instead of loading translations from files, you can provide them directly:
import { TranslationProvider } from 'pagamio-frontend-commons-lib';
const translations = [
{
locale: 'en',
messages: {
common: {
save: 'Save',
cancel: 'Cancel'
}
}
},
{
locale: 'es',
messages: {
common: {
save: 'Guardar',
cancel: 'Cancelar'
}
}
}
];
function App() {
return (
<TranslationProvider
defaultLocale="en"
localeData={translations}
>
<YourApplicationComponents />
</TranslationProvider>
);
}