@attabot/complaint-app
v1.0.7
Published
Complaint Management UI package — atomic React components that run on the parent app's auth and API
Readme
@attabot/complaint-app
Complaint Management UI as an npm package. Built with atomic design (atoms → molecules → organisms) so the parent app can mount a ready dashboard that uses the parent’s auth token and API base URL.
Installation
npm install @attabot/complaint-appPeer dependencies:
npm install react react-dom react-redux @reduxjs/toolkitUsage
import ComplaintApp from '@attabot/complaint-app';
import '@attabot/complaint-app/style.css';
import brandTheme from './brandTheme.json'; // static theme file
function App() {
const [darkMode, setDarkMode] = useState(false); // owned by parent
return (
<ComplaintApp
apiUrl="https://your-api.example.com"
authToken={sessionToken}
theme={brandTheme}
darkMode={darkMode}
systemsEndpoint="/api/v1/complaint-systems"
onCreateForm={() => navigate('/forms/new')}
onConfigure={(system) => navigate(`/systems/${system.id}`)}
/>
);
}Theme & dark mode (parent-controlled)
Pass a static theme file (JSON/JS) and toggle darkMode from the parent. The package applies CSS variables across the whole UI.
import brandTheme from './brandTheme.json';
<ComplaintApp theme={brandTheme} darkMode={isDark} />Theme file shape:
{
"light": { "colors": { "primary": "#2D64B8", "background": "#F5F5F5" } },
"dark": { "colors": { "primary": "#5B8DEF", "background": "#0F1115" } }
}Or pass flat overrides (merged into both modes):
<ComplaintApp theme={{ colors: { primary: '#0F766E' } }} darkMode={false} />Helpers / defaults are exported: lightTheme, darkTheme, defaultThemeFile, useTheme.
Pass data from the parent (no fetch)
<ComplaintApp
apiUrl={apiUrl}
authToken={authToken}
useDemoData={false}
systems={[
{
id: 'qms',
title: 'QMS - Query Management System',
status: 'active',
description: 'Description of the template',
departments: 3,
workflows: 12,
fields: 55,
formsFilled: 234,
updatedOn: '12 Mar 2024',
titleAsLink: true,
},
]}
onCreateForm={handleCreate}
onConfigure={handleConfigure}
/>Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| apiUrl | string | env VITE_API_URL | Base URL for axios requests |
| authToken | string | — | Bearer token stored for API calls |
| theme | object | built-in light/dark | Static theme file or token overrides |
| darkMode | boolean | false | Parent-controlled dark mode |
| basePath | string | '/' | React Router basename when nested |
| systems | array | — | Parent-controlled system list |
| systemsEndpoint | string | — | GET path relative to apiUrl |
| useDemoData | boolean | true | Show design demo cards when no data |
| title | string | 'Complaint Management' | Page title |
| description | string | lorem placeholder | Page subtitle |
| createLabel | string | 'Create New Form' | Primary CTA label |
| onCreateForm | fn | — | Create button handler |
| onConfigure | fn(system) | — | Configure button handler |
| onTitleClick | fn(system) | — | Title link click |
| onDescriptionClick | fn | — | Description link click |
| onSearch | fn(query) | — | Search change callback |
| onPublish | fn | — | Review & Publish handler |
| onStepChange | fn | — | Settings step change callback |
Atomic structure
src/components/
atoms/ Button, Input, Typography, StatusBadge, Divider, Icons, Loading
molecules/ SearchBar, DataPoint, CardHeader, CardFooter
organisms/ PageHeader, SystemCard, SystemCardGridNamed exports are available for reuse in the parent:
import { Button, SearchBar, SystemCard, api } from '@attabot/complaint-app';Auth & API
- Parent passes
apiUrl+authTokenintoComplaintApp/ApiProvider. - Package axios client (
api) keeps the passed token in memory and attachesAuthorization: Bearer …immediately before every request. It does not overwrite the parent app's auth cookie. - Optional token refresh against
POST /api/v1/auth/refreshwhen arefreshTokencookie exists. - No product/business APIs are hardcoded — provide
systemsorsystemsEndpoint.
Redux and router integration
When mounted inside a parent react-redux Provider, ComplaintApp automatically
reuses that Provider instead of adding a second competing Redux context. When used
standalone it falls back to its own store. Pass the store prop only when you
explicitly want an isolated store.
The same rule applies to React Router: an existing parent router is reused; a
BrowserRouter is only created for standalone use.
Development
npm install
npm run dev # preview Complaint Management UI
npm run build # emit dist/ for publishingLicense
MIT
