@docon/staff-portal
v1.0.1
Published
Standalone Thyrocare Staff Portal Component - Drop-in booking and ULC flow
Downloads
268
Maintainers
Readme
Staff Portal - Standalone Component
🚀 Quick Start (30 seconds)
import StaffPortal from './staff';
<StaffPortal
authToken="your-jwt-token"
apiKey="your-api-key"
userCode="user123"
/>Done! Staff portal is now embedded.
📦 What is this?
A completely standalone staff portal component that you can drop into any React app. No complex setup, no shared stores, just works.
Features
- ✅ Prop-driven or storage-driven auth
- ✅ Self-contained Redux store (no conflicts)
- ✅ Works with any React app
- ✅ Zero configuration needed
- ✅ Booking flow + ULC flow
- ✅ TypeScript support
🎯 Three Ways to Use
1. Props (Simplest - Recommended)
Parent app passes auth as props:
import StaffPortal from './staff';
function App() {
const { authToken, apiKey } = useYourAuth();
return (
<StaffPortal
authToken={authToken}
apiKey={apiKey}
userCode="user123"
onLogout={() => handleLogout()}
/>
);
}2. Shared Storage
Parent app writes to storage, staff portal reads:
// Parent app: Write to storage
localStorage.setItem('AUTH_DATA', JSON.stringify({
accessToken: 'token',
apiKey: 'key',
}));
// Staff portal: Read from storage
<StaffPortal
useSharedStorage={true}
storageKey="AUTH_DATA"
/>3. IndexedDB
For persistent storage across sessions:
import { storageService } from 'services';
// Parent app: Write to IndexedDB
await storageService.set('AUTH_DATA', {
accessToken: 'token',
apiKey: 'key',
});
// Staff portal: Read from IndexedDB
<StaffPortal
useSharedStorage={true}
storageKey="AUTH_DATA"
storageType="indexedDB"
/>📖 Props API
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| authToken | string | - | JWT access token |
| apiKey | string | - | Staff API key |
| userCode | string | - | User code/ID |
| user | object | - | User object |
| useSharedStorage | boolean | false | Read auth from storage |
| storageKey | string | 'AUTH_DATA' | Storage key name |
| storageType | 'localStorage' | 'indexedDB' | 'localStorage' | Storage type |
| onLogout | function | - | Logout callback |
| onError | function | - | Error callback |
| onAuthChange | function | - | Auth change callback |
| basePath | string | '/staff' | Base route path |
| showHeader | boolean | true | Show header |
| headerTitle | string | 'Staff Portal' | Header title |
| debug | boolean | false | Enable debug logs |
🎨 Examples
Basic Usage
<StaffPortal
authToken="token"
apiKey="key"
/>With Callbacks
<StaffPortal
authToken="token"
apiKey="key"
onLogout={() => {
console.log('User logged out');
navigate('/login');
}}
onError={(err) => {
console.error('Error:', err);
}}
/>With React Router
import { Routes, Route } from 'react-router-dom';
<Routes>
<Route path="/staff/*" element={
<StaffPortal
authToken={token}
apiKey={key}
basePath="/staff" // Must match route
/>
} />
</Routes>Custom Styling
<StaffPortal
authToken="token"
apiKey="key"
headerTitle="My Custom Portal"
showHeader={true}
/>Without Header
<div>
<YourCustomHeader />
<StaffPortal
authToken="token"
apiKey="key"
showHeader={false}
/>
</div>📂 File Structure
src/staff/
├── StaffPortalStandalone.tsx # Main component
├── StaffPortalExamples.tsx # 13 usage examples
├── index.ts # Package exports
├── pages/
│ ├── Dashboard.tsx # Dashboard page
│ ├── BookingForm.tsx # Booking flow
│ └── ThankYou.tsx # Confirmation page
├── redux/
│ └── reducer/
│ ├── auth.ts # Auth state
│ └── booking.ts # Booking state
└── ...other staff files🔧 Integration Guide
Step 1: Import
import StaffPortal from './staff';
// or
import { StaffPortalStandalone } from './staff';Step 2: Add to your app
<StaffPortal
authToken={yourAuthToken}
apiKey={yourApiKey}
/>Step 3: Done! 🎉
That's literally it.
🚦 Routes
When you embed the staff portal, it provides these routes:
/staff/dashboard- Main dashboard/staff/booking- Booking form/staff/thank-you- Order confirmation
All routes are prefixed with basePath prop (default: /staff).
🐛 Troubleshooting
Issue: "Auth not working"
Check: Are you passing auth props?
console.log({ authToken, apiKey }); // Should not be undefinedIssue: "Routes not found"
Check: Does basePath match your route?
// Parent route
<Route path="/staff/*" ... />
// Staff portal basePath
<StaffPortal basePath="/staff" /> // Must match!Issue: "Styles missing"
Check: Is UI library installed?
npm install @docon/docon-ui-libraryIssue: "Storage not syncing"
Check: Are you using the same storage key?
// Parent writes
localStorage.setItem('AUTH_DATA', ...);
// Staff reads
<StaffPortal storageKey="AUTH_DATA" /> // Must match!🧪 Testing
// Test with hardcoded auth
<StaffPortal
authToken="test-token"
apiKey="test-key"
userCode="test-user"
debug={true} // Enable logging
/>Check browser console for debug logs.
📚 More Examples
See StaffPortalExamples.tsx for 13 detailed examples including:
- ✅ Simplest prop-driven
- ✅ With callbacks
- ✅ Storage-driven
- ✅ React Router integration
- ✅ Conditional rendering
- ✅ Custom styling
- ✅ Without header
- ✅ Debug mode
- ✅ IndexedDB storage
- ✅ Complete app integration
- ✅ Multiple instances
- ✅ Lazy loading
- ✅ Iframe alternative
🎁 Bonus: Custom Hook
import { useStaffPortal } from './staff/StaffPortalExamples';
function App() {
const { isOpen, openStaffPortal, StaffPortalComponent } = useStaffPortal({
authToken: 'token',
apiKey: 'key',
});
return (
<div>
<button onClick={openStaffPortal}>Open Staff Portal</button>
{StaffPortalComponent}
</div>
);
}⏱️ Performance
- Bundle size: ~200KB (with dependencies)
- First load: < 2 seconds
- Hot reload: < 500ms
🔐 Security
- ✅ Auth passed via props (not in URL)
- ✅ Isolated Redux store (no state leaks)
- ✅ Token validation before API calls
- ✅ HTTPS only in production
📦 Making it a Package (Optional)
To reuse across multiple apps:
1. Create package.json
{
"name": "@thyrocare/staff-portal",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"peerDependencies": {
"react": "^18.0.0",
"react-router-dom": "^6.0.0",
"@reduxjs/toolkit": "^1.9.0"
}
}2. Build
npm run build3. Use in other apps
npm install @thyrocare/staff-portalimport StaffPortal from '@thyrocare/staff-portal';🚀 Quick Implementation Timeline
Day 1 (4 hours)
- ✅ Files already created
- Import in parent app
- Pass auth props
- Test basic flow
Day 2 (4 hours)
- Test booking flow end-to-end
- Test ULC flow end-to-end
- Handle edge cases
Day 3 (4 hours)
- Add error handling
- Add loading states
- Polish UI
Day 4 (4 hours)
- Full testing
- Deploy to staging
- Deploy to production
Total: 16 hours (4 days)
✅ Checklist
- [ ] Import StaffPortal component
- [ ] Pass auth props (token, apiKey, userCode)
- [ ] Test dashboard loads
- [ ] Test booking flow works
- [ ] Test ULC flow works
- [ ] Add onLogout callback
- [ ] Add error handling
- [ ] Test in production
📞 Support
- Check StaffPortalExamples.tsx for examples
- Enable
debug={true}to see logs - Check browser console for errors
🎯 Summary
Before:
- Complex setup
- Shared stores
- Cross-app sync
- 6 weeks implementation
Now:
- One component
- Pass props
- Works immediately
- 4 days implementation
Just import and use. It's that simple. 🚀
Staff Portal Standalone v1.0
Ready to use - No configuration needed
