@visns-studio/visns-components 5.11.3 → 5.11.5

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/README.md CHANGED
@@ -951,6 +951,766 @@ File upload component with drag and drop support.
951
951
  />
952
952
  ```
953
953
 
954
+ ### Association Management Components
955
+
956
+ #### AssociationManager
957
+
958
+ A sophisticated component for managing entity relationships and associations within your application. The AssociationManager provides an intuitive interface for creating, viewing, and managing complex many-to-many relationships between different data entities.
959
+
960
+ ```jsx
961
+ <AssociationManager
962
+ config={{
963
+ title: "Client Associations",
964
+ description: "Manage relationships between clients and projects",
965
+ primaryEntity: {
966
+ id: "clients",
967
+ label: "Clients",
968
+ displayKey: "name",
969
+ fetchUrl: "/api/clients"
970
+ },
971
+ secondaryEntity: {
972
+ id: "projects",
973
+ label: "Projects",
974
+ displayKey: "title",
975
+ fetchUrl: "/api/projects"
976
+ },
977
+ association: {
978
+ fetchUrl: "/api/client-project-associations",
979
+ createUrl: "/api/client-project-associations",
980
+ deleteUrl: "/api/client-project-associations",
981
+ pivotTable: "client_project"
982
+ },
983
+ permissions: {
984
+ canCreate: true,
985
+ canDelete: true,
986
+ canView: true
987
+ },
988
+ ui: {
989
+ searchPlaceholder: "Search clients or projects...",
990
+ emptyStateMessage: "No associations found",
991
+ confirmDeleteMessage: "Are you sure you want to remove this association?"
992
+ }
993
+ }}
994
+ userProfile={userProfile}
995
+ onAssociationChange={(data) => console.log('Association changed:', data)}
996
+ />
997
+ ```
998
+
999
+ **Key Features:**
1000
+
1001
+ 1. **Bidirectional Relationship Management**:
1002
+ - Create associations from either entity perspective
1003
+ - Automatic relationship synchronization
1004
+ - Real-time updates across related views
1005
+
1006
+ 2. **Advanced Search and Filtering**:
1007
+ - Multi-entity search capabilities
1008
+ - Filter by entity type, status, or custom attributes
1009
+ - Debounced search to optimize performance
1010
+
1011
+ 3. **Bulk Operations**:
1012
+ - Select multiple entities for batch association
1013
+ - Bulk delete with confirmation dialogs
1014
+ - Mass import/export functionality
1015
+
1016
+ 4. **Visual Association Mapping**:
1017
+ - Interactive relationship visualization
1018
+ - Drag-and-drop association creation
1019
+ - Color-coded entity types
1020
+
1021
+ 5. **Permission-Based Access Control**:
1022
+ - Granular permissions for create, read, update, delete
1023
+ - Role-based access to specific entity types
1024
+ - Custom permission validation
1025
+
1026
+ **Configuration Options:**
1027
+
1028
+ ```jsx
1029
+ const associationConfig = {
1030
+ // Required: Basic entity configuration
1031
+ primaryEntity: {
1032
+ id: "clients", // Unique identifier
1033
+ label: "Clients", // Display name
1034
+ displayKey: "name", // Field to show in lists
1035
+ fetchUrl: "/api/clients", // API endpoint
1036
+ searchFields: ["name", "email"], // Fields to search
1037
+ icon: "Users", // Lucide icon name
1038
+ color: "#3b82f6" // Brand color
1039
+ },
1040
+
1041
+ secondaryEntity: {
1042
+ id: "projects",
1043
+ label: "Projects",
1044
+ displayKey: "title",
1045
+ fetchUrl: "/api/projects",
1046
+ searchFields: ["title", "description"],
1047
+ icon: "FolderOpen",
1048
+ color: "#10b981"
1049
+ },
1050
+
1051
+ // Association configuration
1052
+ association: {
1053
+ fetchUrl: "/api/associations", // Get existing associations
1054
+ createUrl: "/api/associations", // Create new associations
1055
+ updateUrl: "/api/associations", // Update associations (optional)
1056
+ deleteUrl: "/api/associations", // Delete associations
1057
+ pivotTable: "client_project", // Database table name
1058
+
1059
+ // Additional pivot data
1060
+ pivotFields: [
1061
+ {
1062
+ name: "role",
1063
+ label: "Role",
1064
+ type: "select",
1065
+ options: [
1066
+ { value: "manager", label: "Manager" },
1067
+ { value: "contributor", label: "Contributor" }
1068
+ ]
1069
+ },
1070
+ {
1071
+ name: "start_date",
1072
+ label: "Start Date",
1073
+ type: "date"
1074
+ }
1075
+ ]
1076
+ },
1077
+
1078
+ // UI customization
1079
+ ui: {
1080
+ layout: "split", // "split", "tabs", "cards"
1081
+ theme: "default", // "default", "compact", "detailed"
1082
+ showEntityCounts: true, // Show association counts
1083
+ showLastModified: true, // Show modification timestamps
1084
+ enableDragDrop: true, // Enable drag-and-drop
1085
+ confirmActions: true, // Show confirmation dialogs
1086
+
1087
+ // Custom labels and messages
1088
+ labels: {
1089
+ createButton: "Add Association",
1090
+ deleteButton: "Remove",
1091
+ searchPlaceholder: "Search entities...",
1092
+ noResultsMessage: "No entities found",
1093
+ loadingMessage: "Loading associations..."
1094
+ }
1095
+ },
1096
+
1097
+ // Validation rules
1098
+ validation: {
1099
+ preventDuplicates: true, // Prevent duplicate associations
1100
+ requirePivotData: false, // Require additional pivot fields
1101
+ customValidation: (primary, secondary, pivotData) => {
1102
+ // Custom validation logic
1103
+ return { valid: true, message: "" };
1104
+ }
1105
+ },
1106
+
1107
+ // Performance optimization
1108
+ performance: {
1109
+ enableVirtualization: true, // For large datasets
1110
+ pageSize: 50, // Pagination size
1111
+ debounceMs: 300, // Search debounce
1112
+ cacheResults: true // Cache API responses
1113
+ }
1114
+ };
1115
+ ```
1116
+
1117
+ **API Integration:**
1118
+
1119
+ The AssociationManager expects specific API response formats:
1120
+
1121
+ ```javascript
1122
+ // GET /api/clients (Primary Entity)
1123
+ {
1124
+ "data": [
1125
+ {
1126
+ "id": 1,
1127
+ "name": "Acme Corp",
1128
+ "email": "contact@acme.com",
1129
+ "created_at": "2023-01-01T00:00:00Z"
1130
+ }
1131
+ ],
1132
+ "total": 150,
1133
+ "page": 1,
1134
+ "per_page": 50
1135
+ }
1136
+
1137
+ // GET /api/associations (Existing Associations)
1138
+ {
1139
+ "data": [
1140
+ {
1141
+ "id": 1,
1142
+ "primary_id": 1,
1143
+ "secondary_id": 5,
1144
+ "pivot_data": {
1145
+ "role": "manager",
1146
+ "start_date": "2023-01-01"
1147
+ },
1148
+ "primary": {
1149
+ "id": 1,
1150
+ "name": "Acme Corp"
1151
+ },
1152
+ "secondary": {
1153
+ "id": 5,
1154
+ "title": "Website Redesign"
1155
+ },
1156
+ "created_at": "2023-01-01T00:00:00Z"
1157
+ }
1158
+ ]
1159
+ }
1160
+
1161
+ // POST /api/associations (Create Association)
1162
+ {
1163
+ "primary_id": 1,
1164
+ "secondary_id": 5,
1165
+ "pivot_data": {
1166
+ "role": "manager",
1167
+ "start_date": "2023-01-01"
1168
+ }
1169
+ }
1170
+
1171
+ // Response:
1172
+ {
1173
+ "success": true,
1174
+ "data": {
1175
+ "id": 1,
1176
+ "primary_id": 1,
1177
+ "secondary_id": 5,
1178
+ "created_at": "2023-01-01T00:00:00Z"
1179
+ },
1180
+ "message": "Association created successfully"
1181
+ }
1182
+ ```
1183
+
1184
+ **Event Handling:**
1185
+
1186
+ ```jsx
1187
+ <AssociationManager
1188
+ config={associationConfig}
1189
+ onAssociationChange={(event) => {
1190
+ // event.type: 'created', 'updated', 'deleted'
1191
+ // event.data: Association data
1192
+ // event.entities: Affected entities
1193
+ console.log('Association event:', event);
1194
+ }}
1195
+ onEntitySelect={(entity, type) => {
1196
+ // Handle entity selection
1197
+ console.log('Entity selected:', entity, type);
1198
+ }}
1199
+ onError={(error) => {
1200
+ // Handle errors
1201
+ console.error('Association error:', error);
1202
+ }}
1203
+ />
1204
+ ```
1205
+
1206
+ **Advanced Usage Examples:**
1207
+
1208
+ 1. **Client-Project Association with Roles**:
1209
+ ```jsx
1210
+ // Managing client assignments to projects with specific roles
1211
+ <AssociationManager
1212
+ config={{
1213
+ primaryEntity: { id: "clients", label: "Clients", ... },
1214
+ secondaryEntity: { id: "projects", label: "Projects", ... },
1215
+ association: {
1216
+ pivotFields: [
1217
+ {
1218
+ name: "role",
1219
+ label: "Role in Project",
1220
+ type: "select",
1221
+ required: true,
1222
+ options: [
1223
+ { value: "sponsor", label: "Project Sponsor" },
1224
+ { value: "stakeholder", label: "Key Stakeholder" },
1225
+ { value: "user", label: "End User" }
1226
+ ]
1227
+ }
1228
+ ]
1229
+ }
1230
+ }}
1231
+ />
1232
+ ```
1233
+
1234
+ 2. **User-Permission Association**:
1235
+ ```jsx
1236
+ // Managing user permissions with expiration dates
1237
+ <AssociationManager
1238
+ config={{
1239
+ primaryEntity: { id: "users", label: "Users", ... },
1240
+ secondaryEntity: { id: "permissions", label: "Permissions", ... },
1241
+ association: {
1242
+ pivotFields: [
1243
+ {
1244
+ name: "expires_at",
1245
+ label: "Expiration Date",
1246
+ type: "datetime",
1247
+ required: false
1248
+ },
1249
+ {
1250
+ name: "granted_by",
1251
+ label: "Granted By",
1252
+ type: "select",
1253
+ fetchUrl: "/api/users/managers"
1254
+ }
1255
+ ]
1256
+ }
1257
+ }}
1258
+ />
1259
+ ```
1260
+
1261
+ ### Business Card OCR Component
1262
+
1263
+ #### BusinessCardOcr (Enhanced v5.11.1+)
1264
+
1265
+ An advanced OCR (Optical Character Recognition) component specifically designed for scanning business cards and automatically extracting contact information. The component provides intelligent text recognition, client matching, and seamless contact management integration.
1266
+
1267
+ ```jsx
1268
+ <BusinessCardOcr
1269
+ isOpen={showScanner}
1270
+ onClose={() => setShowScanner(false)}
1271
+ onContactSaved={(contact) => {
1272
+ console.log('Contact saved:', contact);
1273
+ // Handle the saved contact data
1274
+ }}
1275
+ fields={[
1276
+ { id: 'name', label: 'Full Name', required: true },
1277
+ { id: 'email', label: 'Email', type: 'email' },
1278
+ { id: 'phone', label: 'Phone', type: 'tel' },
1279
+ { id: 'company', label: 'Company' },
1280
+ { id: 'position', label: 'Position' },
1281
+ { id: 'address', label: 'Address', type: 'textarea' }
1282
+ ]}
1283
+ fetchConfig={{
1284
+ ocrUrl: '/api/ocr/business-card',
1285
+ saveUrl: '/api/contacts',
1286
+ clientSearchUrl: '/api/clients/search',
1287
+ duplicateCheckUrl: '/api/contacts/check-duplicate'
1288
+ }}
1289
+ settings={{
1290
+ enableClientMatching: true,
1291
+ enableDuplicateCheck: true,
1292
+ autoSave: false,
1293
+ imageQuality: 0.8,
1294
+ supportedFormats: ['image/jpeg', 'image/png', 'image/webp']
1295
+ }}
1296
+ />
1297
+ ```
1298
+
1299
+ **Key Features:**
1300
+
1301
+ 1. **Advanced OCR Processing**:
1302
+ - High-accuracy text extraction from business card images
1303
+ - Intelligent field mapping and recognition
1304
+ - Support for multiple languages and formats
1305
+ - Automatic rotation and perspective correction
1306
+
1307
+ 2. **Smart Client Matching**:
1308
+ - Automatic company name recognition
1309
+ - Fuzzy matching against existing client database
1310
+ - Confidence scoring for match suggestions
1311
+ - Manual override and confirmation options
1312
+
1313
+ 3. **Duplicate Detection**:
1314
+ - Email and phone number duplicate checking
1315
+ - Visual comparison with existing contacts
1316
+ - Merge or create new contact options
1317
+ - Conflict resolution interface
1318
+
1319
+ 4. **Interactive Editing Interface**:
1320
+ - Real-time field editing and validation
1321
+ - Drag-and-drop image upload
1322
+ - Live camera capture (mobile devices)
1323
+ - Field confidence indicators
1324
+
1325
+ 5. **Contact Management Integration**:
1326
+ - Direct save to contact database
1327
+ - Custom field mapping and validation
1328
+ - Bulk import capabilities
1329
+ - Export to various formats
1330
+
1331
+ **Configuration Options:**
1332
+
1333
+ ```jsx
1334
+ const businessCardConfig = {
1335
+ // Field definitions for extracted data
1336
+ fields: [
1337
+ {
1338
+ id: 'name',
1339
+ label: 'Full Name',
1340
+ type: 'text',
1341
+ required: true,
1342
+ validation: {
1343
+ minLength: 2,
1344
+ pattern: /^[a-zA-Z\s]+$/
1345
+ },
1346
+ ocrMapping: ['name', 'full_name', 'contact_name']
1347
+ },
1348
+ {
1349
+ id: 'email',
1350
+ label: 'Email Address',
1351
+ type: 'email',
1352
+ required: false,
1353
+ validation: {
1354
+ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
1355
+ },
1356
+ ocrMapping: ['email', 'e_mail', 'email_address']
1357
+ },
1358
+ {
1359
+ id: 'phone',
1360
+ label: 'Phone Number',
1361
+ type: 'tel',
1362
+ required: false,
1363
+ formatting: {
1364
+ mask: '(000) 000-0000',
1365
+ international: true
1366
+ },
1367
+ ocrMapping: ['phone', 'mobile', 'telephone', 'cell']
1368
+ },
1369
+ {
1370
+ id: 'company',
1371
+ label: 'Company Name',
1372
+ type: 'text',
1373
+ required: false,
1374
+ clientMatching: true, // Enable client matching for this field
1375
+ ocrMapping: ['company', 'organization', 'business_name']
1376
+ },
1377
+ {
1378
+ id: 'position',
1379
+ label: 'Job Title',
1380
+ type: 'text',
1381
+ required: false,
1382
+ ocrMapping: ['title', 'position', 'job_title', 'role']
1383
+ },
1384
+ {
1385
+ id: 'address',
1386
+ label: 'Address',
1387
+ type: 'textarea',
1388
+ required: false,
1389
+ formatting: {
1390
+ multiline: true,
1391
+ rows: 3
1392
+ },
1393
+ ocrMapping: ['address', 'location', 'street_address']
1394
+ },
1395
+ {
1396
+ id: 'website',
1397
+ label: 'Website',
1398
+ type: 'url',
1399
+ required: false,
1400
+ validation: {
1401
+ pattern: /^https?:\/\/.+/
1402
+ },
1403
+ ocrMapping: ['website', 'url', 'web', 'site']
1404
+ }
1405
+ ],
1406
+
1407
+ // API endpoint configuration
1408
+ fetchConfig: {
1409
+ ocrUrl: '/api/ocr/business-card', // OCR processing endpoint
1410
+ saveUrl: '/api/contacts', // Contact save endpoint
1411
+ clientSearchUrl: '/api/clients/search', // Client matching endpoint
1412
+ duplicateCheckUrl: '/api/contacts/check', // Duplicate check endpoint
1413
+ uploadUrl: '/api/files/upload', // Image upload endpoint
1414
+
1415
+ // Request configuration
1416
+ timeout: 30000, // 30 second timeout
1417
+ retries: 3, // Retry failed requests
1418
+ headers: {
1419
+ 'Accept': 'application/json',
1420
+ 'X-Requested-With': 'XMLHttpRequest'
1421
+ }
1422
+ },
1423
+
1424
+ // Component behavior settings
1425
+ settings: {
1426
+ // OCR settings
1427
+ imageQuality: 0.8, // Image compression quality
1428
+ maxImageSize: 5242880, // 5MB max file size
1429
+ supportedFormats: [ // Accepted image formats
1430
+ 'image/jpeg',
1431
+ 'image/png',
1432
+ 'image/webp',
1433
+ 'image/bmp'
1434
+ ],
1435
+
1436
+ // Processing options
1437
+ enableClientMatching: true, // Enable company matching
1438
+ enableDuplicateCheck: true, // Check for duplicates
1439
+ autoSave: false, // Auto-save after OCR
1440
+ requireConfirmation: true, // Confirm before saving
1441
+
1442
+ // UI options
1443
+ showConfidenceScores: true, // Show OCR confidence
1444
+ enableManualEdit: true, // Allow manual editing
1445
+ showImagePreview: true, // Show uploaded image
1446
+ enableCameraCapture: true, // Enable camera on mobile
1447
+
1448
+ // Validation options
1449
+ validateOnBlur: true, // Validate fields on blur
1450
+ highlightErrors: true, // Highlight validation errors
1451
+ showTooltips: true, // Show field tooltips
1452
+
1453
+ // Performance options
1454
+ debounceMs: 500, // Debounce for auto-save
1455
+ cacheResults: true, // Cache OCR results
1456
+ enablePreprocessing: true // Image preprocessing
1457
+ },
1458
+
1459
+ // UI customization
1460
+ ui: {
1461
+ theme: 'default', // 'default', 'compact', 'minimal'
1462
+ layout: 'modal', // 'modal', 'inline', 'drawer'
1463
+ size: 'large', // 'small', 'medium', 'large'
1464
+
1465
+ // Labels and messages
1466
+ labels: {
1467
+ uploadButton: 'Upload Business Card',
1468
+ scanButton: 'Scan with Camera',
1469
+ saveButton: 'Save Contact',
1470
+ cancelButton: 'Cancel',
1471
+ editButton: 'Edit Information',
1472
+ processButton: 'Process Image'
1473
+ },
1474
+
1475
+ messages: {
1476
+ uploadPrompt: 'Drop an image here or click to upload',
1477
+ processing: 'Processing business card...',
1478
+ ocrSuccess: 'Text extracted successfully',
1479
+ ocrError: 'Failed to process image',
1480
+ saveSuccess: 'Contact saved successfully',
1481
+ duplicateFound: 'Duplicate contact detected'
1482
+ },
1483
+
1484
+ // Style customization
1485
+ styles: {
1486
+ primaryColor: '#3b82f6',
1487
+ successColor: '#10b981',
1488
+ errorColor: '#ef4444',
1489
+ borderRadius: '8px',
1490
+ boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'
1491
+ }
1492
+ }
1493
+ };
1494
+ ```
1495
+
1496
+ **API Integration:**
1497
+
1498
+ The BusinessCardOcr component expects specific API response formats:
1499
+
1500
+ ```javascript
1501
+ // POST /api/ocr/business-card (OCR Processing)
1502
+ // Request: FormData with image file
1503
+ {
1504
+ "image": File
1505
+ }
1506
+
1507
+ // Response:
1508
+ {
1509
+ "success": true,
1510
+ "data": {
1511
+ "extracted_text": "John Smith\nSenior Developer\nAcme Corp\nj.smith@acme.com\n(555) 123-4567",
1512
+ "fields": {
1513
+ "name": {
1514
+ "value": "John Smith",
1515
+ "confidence": 0.95,
1516
+ "position": { "x": 100, "y": 50, "width": 200, "height": 30 }
1517
+ },
1518
+ "email": {
1519
+ "value": "j.smith@acme.com",
1520
+ "confidence": 0.92,
1521
+ "position": { "x": 100, "y": 120, "width": 250, "height": 25 }
1522
+ },
1523
+ "company": {
1524
+ "value": "Acme Corp",
1525
+ "confidence": 0.88,
1526
+ "position": { "x": 100, "y": 80, "width": 150, "height": 25 }
1527
+ }
1528
+ },
1529
+ "processing_time": 2.3,
1530
+ "image_url": "/storage/uploads/card_123.jpg"
1531
+ }
1532
+ }
1533
+
1534
+ // GET /api/clients/search (Client Matching)
1535
+ {
1536
+ "query": "Acme Corp"
1537
+ }
1538
+
1539
+ // Response:
1540
+ {
1541
+ "data": [
1542
+ {
1543
+ "id": 5,
1544
+ "name": "Acme Corporation",
1545
+ "match_score": 0.85,
1546
+ "address": "123 Business St",
1547
+ "phone": "(555) 987-6543",
1548
+ "website": "https://acme.com"
1549
+ }
1550
+ ]
1551
+ }
1552
+
1553
+ // POST /api/contacts/check (Duplicate Check)
1554
+ {
1555
+ "email": "j.smith@acme.com",
1556
+ "phone": "(555) 123-4567"
1557
+ }
1558
+
1559
+ // Response:
1560
+ {
1561
+ "duplicates": [
1562
+ {
1563
+ "id": 10,
1564
+ "name": "John Smith",
1565
+ "email": "j.smith@acme.com",
1566
+ "match_type": "email",
1567
+ "match_score": 1.0,
1568
+ "created_at": "2023-01-01T00:00:00Z"
1569
+ }
1570
+ ]
1571
+ }
1572
+
1573
+ // POST /api/contacts (Save Contact)
1574
+ {
1575
+ "name": "John Smith",
1576
+ "email": "j.smith@acme.com",
1577
+ "phone": "(555) 123-4567",
1578
+ "company": "Acme Corp",
1579
+ "position": "Senior Developer",
1580
+ "client_id": 5,
1581
+ "source": "business_card_ocr",
1582
+ "confidence_scores": {
1583
+ "name": 0.95,
1584
+ "email": 0.92,
1585
+ "company": 0.88
1586
+ }
1587
+ }
1588
+
1589
+ // Response:
1590
+ {
1591
+ "success": true,
1592
+ "data": {
1593
+ "id": 15,
1594
+ "name": "John Smith",
1595
+ "created_at": "2023-01-01T00:00:00Z"
1596
+ },
1597
+ "message": "Contact created successfully"
1598
+ }
1599
+ ```
1600
+
1601
+ **Event Handling:**
1602
+
1603
+ ```jsx
1604
+ <BusinessCardOcr
1605
+ isOpen={showScanner}
1606
+ onClose={() => setShowScanner(false)}
1607
+ onContactSaved={(contact) => {
1608
+ // Handle successful contact save
1609
+ console.log('New contact saved:', contact);
1610
+
1611
+ // Optional: Update parent component state
1612
+ setContacts(prev => [...prev, contact]);
1613
+
1614
+ // Optional: Show success notification
1615
+ toast.success(`Contact ${contact.name} saved successfully`);
1616
+ }}
1617
+ onOcrComplete={(extractedData) => {
1618
+ // Handle OCR completion
1619
+ console.log('OCR extraction completed:', extractedData);
1620
+
1621
+ // Optional: Custom processing of extracted data
1622
+ if (extractedData.confidence < 0.7) {
1623
+ toast.warning('Low confidence OCR results. Please review carefully.');
1624
+ }
1625
+ }}
1626
+ onClientMatch={(matches) => {
1627
+ // Handle client matching results
1628
+ console.log('Client matches found:', matches);
1629
+
1630
+ // Optional: Auto-select high confidence matches
1631
+ if (matches.length === 1 && matches[0].match_score > 0.9) {
1632
+ // Auto-select the best match
1633
+ return matches[0];
1634
+ }
1635
+ }}
1636
+ onDuplicateDetected={(duplicates) => {
1637
+ // Handle duplicate detection
1638
+ console.log('Duplicate contacts found:', duplicates);
1639
+
1640
+ // Optional: Custom duplicate handling logic
1641
+ return new Promise((resolve) => {
1642
+ // Show custom duplicate resolution UI
1643
+ showDuplicateDialog(duplicates, resolve);
1644
+ });
1645
+ }}
1646
+ onError={(error) => {
1647
+ // Handle errors
1648
+ console.error('OCR error:', error);
1649
+
1650
+ // Optional: Custom error handling
1651
+ if (error.type === 'network') {
1652
+ toast.error('Network error. Please check your connection.');
1653
+ } else if (error.type === 'validation') {
1654
+ toast.error('Please correct the highlighted fields.');
1655
+ }
1656
+ }}
1657
+ />
1658
+ ```
1659
+
1660
+ **Advanced Usage Examples:**
1661
+
1662
+ 1. **Integration with Existing Contact Form**:
1663
+ ```jsx
1664
+ const ContactForm = () => {
1665
+ const [showOcr, setShowOcr] = useState(false);
1666
+ const [formData, setFormData] = useState({});
1667
+
1668
+ return (
1669
+ <div>
1670
+ <Form data={formData} onChange={setFormData}>
1671
+ {/* Regular form fields */}
1672
+ </Form>
1673
+
1674
+ <button onClick={() => setShowOcr(true)}>
1675
+ Scan Business Card
1676
+ </button>
1677
+
1678
+ <BusinessCardOcr
1679
+ isOpen={showOcr}
1680
+ onClose={() => setShowOcr(false)}
1681
+ onContactSaved={(contact) => {
1682
+ // Pre-fill form with OCR data
1683
+ setFormData(contact);
1684
+ setShowOcr(false);
1685
+ }}
1686
+ />
1687
+ </div>
1688
+ );
1689
+ };
1690
+ ```
1691
+
1692
+ 2. **Bulk Business Card Processing**:
1693
+ ```jsx
1694
+ const BulkCardProcessor = () => {
1695
+ const [queue, setQueue] = useState([]);
1696
+
1697
+ return (
1698
+ <BusinessCardOcr
1699
+ settings={{
1700
+ autoSave: true,
1701
+ enableBulkMode: true
1702
+ }}
1703
+ onContactSaved={(contact) => {
1704
+ setQueue(prev => [...prev, contact]);
1705
+ }}
1706
+ onBulkComplete={(contacts) => {
1707
+ console.log(`Processed ${contacts.length} business cards`);
1708
+ }}
1709
+ />
1710
+ );
1711
+ };
1712
+ ```
1713
+
954
1714
  ### Utility Components
955
1715
 
956
1716
  #### CustomFetch
@@ -1309,9 +2069,9 @@ Response:
1309
2069
 
1310
2070
  ### Report Builder Component
1311
2071
 
1312
- #### GenericReport
2072
+ #### GenericReport (Enhanced v5.10.11+)
1313
2073
 
1314
- A powerful report building component that allows users to create custom reports by selecting tables, columns, and configuring joins, filters, and sorting.
2074
+ A powerful and enhanced report building component that provides an intuitive wizard-based interface for creating custom reports. The component has been significantly improved with new features and better user experience.
1315
2075
 
1316
2076
  ```jsx
1317
2077
  <GenericReport
@@ -1322,19 +2082,108 @@ A powerful report building component that allows users to create custom reports
1322
2082
  executeUrl: '/ajax/reportBuilder/execute',
1323
2083
  suggestedJoinsUrl: '/ajax/reportBuilder/getSuggestedJoins',
1324
2084
  }}
2085
+ userProfile={userProfile}
2086
+ businessTemplates={businessTemplates} // Optional pre-built templates
1325
2087
  />
1326
2088
  ```
1327
2089
 
1328
- The GenericReport component provides these features:
2090
+ **Major Enhancements:**
2091
+
2092
+ - **5-Step Wizard Interface**: Guided workflow with visual progress indicators
2093
+ - **Business Templates**: Pre-built report templates for common business scenarios
2094
+ - **Calculated Fields**: Create custom formulas and calculations within reports
2095
+ - **Smart Column Selection**: Automatic suggestions based on table relationships
2096
+ - **Enhanced Filtering**: Advanced filter options with AND/OR logic and grouping
2097
+ - **Live Preview**: Real-time preview of report data as you build
2098
+ - **Intelligent Currency Formatting**: Automatic detection and formatting of monetary fields
2099
+ - **Expandable Field Summary**: View selected fields in a collapsible overview
2100
+ - **Template Management**: Save, load, and share report templates
2101
+ - **Multiple Export Formats**: Export to Excel, CSV, PDF with formatting options
2102
+
2103
+ **New Features in Recent Updates:**
2104
+
2105
+ 1. **Calculated Fields (v5.10.12+)**:
2106
+ ```jsx
2107
+ // Users can create custom calculated fields
2108
+ {
2109
+ id: 'profit_margin',
2110
+ displayName: 'Profit Margin %',
2111
+ formula: 'ROUND(((revenue - cost) / revenue) * 100, 2)',
2112
+ type: 'decimal'
2113
+ }
2114
+ ```
2115
+
2116
+ 2. **Business Templates (v5.11.0+)**:
2117
+ ```jsx
2118
+ // Pre-built templates for common scenarios
2119
+ const businessTemplates = [
2120
+ {
2121
+ id: 'utilization_planning',
2122
+ name: 'Utilization Planning',
2123
+ description: 'Weekly resource allocation and laydown utilization',
2124
+ icon: 'Calendar',
2125
+ mainTable: 'leads',
2126
+ defaultColumns: [...],
2127
+ calculatedFields: [...]
2128
+ }
2129
+ ];
2130
+ ```
2131
+
2132
+ 3. **Smart Currency Detection**:
2133
+ - Automatically formats fields containing 'value', 'price', 'cost', 'amount', etc.
2134
+ - Supports Australian Dollar (AUD) formatting by default
2135
+ - Configurable currency formatting options
2136
+
2137
+ 4. **Enhanced UI/UX**:
2138
+ - Lucide React icons throughout for consistency
2139
+ - Larger calculated field display for better visibility
2140
+ - Expandable selected fields summary
2141
+ - Step-by-step guidance with tooltips and help text
2142
+
2143
+ **The 5-Step Wizard Process:**
2144
+
2145
+ 1. **Select Data Source**: Choose main table and review business templates
2146
+ 2. **Choose Columns**: Select specific data fields with drag-and-drop reordering
2147
+ 3. **Add Relationships**: Connect related tables with automatic join suggestions
2148
+ 4. **Apply Filters**: Set conditions and date ranges with advanced logic
2149
+ 5. **Generate & Export**: Preview results and export in multiple formats
2150
+
2151
+ **API Integration:**
2152
+
2153
+ The component expects these endpoint responses:
1329
2154
 
1330
- - **Table Selection**: Choose a main table for the report
1331
- - **Column Selection**: Select columns to include in the report
1332
- - **Table Joins**: Add related tables with automatic relationship detection
1333
- - **Filtering**: Apply filters to the report data
1334
- - **Sorting**: Sort the report results
1335
- - **Report Preview**: View a preview of the report data
1336
- - **Save/Load Reports**: Save reports for future use and load saved reports
1337
- - **Export**: Export reports in various formats
2155
+ ```javascript
2156
+ // Tables endpoint
2157
+ {
2158
+ "tables": [
2159
+ {
2160
+ "id": "clients",
2161
+ "label": "Clients",
2162
+ "description": "Customer information"
2163
+ }
2164
+ ]
2165
+ }
2166
+
2167
+ // Columns endpoint
2168
+ {
2169
+ "columns": [
2170
+ {
2171
+ "name": "id",
2172
+ "type": "integer",
2173
+ "nullable": false,
2174
+ "key": "primary"
2175
+ }
2176
+ ]
2177
+ }
2178
+
2179
+ // Execute endpoint
2180
+ {
2181
+ "success": true,
2182
+ "data": [...],
2183
+ "total": 150,
2184
+ "query": "SELECT ... FROM ..."
2185
+ }
2186
+ ```
1338
2187
 
1339
2188
  ### Sketch Field Component
1340
2189
 
@@ -1650,6 +2499,61 @@ Modal components support vertical alignment configuration with the `verticalAlig
1650
2499
 
1651
2500
  The ReactDataGrid's `defaultGroupBy` prop enables internal grouping functionality that creates collapsible group headers within the table structure. It does NOT create any external UI elements that need relocation, as all grouping controls are internal to the table component.
1652
2501
 
2502
+ ### Navigation Component Icon Visibility Issues
2503
+
2504
+ #### Browser Rendering Optimization Fix
2505
+
2506
+ **Problem:** Navigation action icons (specifically anchor/Link elements) would disappear during page scroll in production environments. The issue only affected anchor tags while button elements remained visible. Notably, the problem disappeared when browser dev tools were open, indicating a browser rendering optimization conflict.
2507
+
2508
+ **Root Cause:** Firefox and other browsers apply aggressive rendering optimizations that can incorrectly cull elements from the paint tree. The combination of CSS `contain: layout` property with sticky positioning was causing anchor elements to be optimized out of view during scroll events.
2509
+
2510
+ **Solution Applied:**
2511
+
2512
+ 1. **Removed problematic containment properties:**
2513
+ - Removed `contain: layout` from `.content-header` and action elements
2514
+ - This property was causing layout optimization conflicts
2515
+
2516
+ 2. **Enhanced compositor layer creation:**
2517
+ - Changed `transform: translateZ(0)` to `transform: translateZ(0) translateX(0) translateY(0)`
2518
+ - Added `isolation: isolate` to force elements onto their own render layers
2519
+ - Added `backface-visibility: hidden` to prevent rendering glitches
2520
+
2521
+ 3. **Improved z-index stacking:**
2522
+ - Elevated z-index values from 100-103 range to 1000-1003 range
2523
+ - Ensures action icons stay above sticky header's stacking context
2524
+
2525
+ **Files Modified:**
2526
+ - `src/components/crm/styles/Navigation.module.scss` (content-header and action styling)
2527
+ - Enhanced both regular and alternate theme action containers
2528
+
2529
+ #### Navigation Component Debug Mode
2530
+
2531
+ The Navigation component now includes optional debugging capabilities to help diagnose rendering issues:
2532
+
2533
+ **Enable Debug Mode:**
2534
+ ```jsx
2535
+ <Navigation debugIcons={true} {...otherProps} />
2536
+ ```
2537
+
2538
+ **Debug Features:**
2539
+ - **Visual indicators:** Red borders around anchor elements with 'A' labels, blue borders around buttons with 'B' labels
2540
+ - **Console logging:** Detailed scroll event logs showing element positions, visibility, z-index, transforms, and containment properties
2541
+ - **Real-time monitoring:** Tracks icon visibility changes during scroll events
2542
+
2543
+ **Debug CSS Classes:**
2544
+ The component includes `.debug-icons` styles that can be applied for visual debugging:
2545
+ ```scss
2546
+ .debug-icons {
2547
+ a, button {
2548
+ border: 2px solid red !important;
2549
+ background: rgba(255, 0, 0, 0.1) !important;
2550
+ // Additional debug styling...
2551
+ }
2552
+ }
2553
+ ```
2554
+
2555
+ This fix ensures navigation icons remain visible during scroll across all browser environments and rendering contexts.
2556
+
1653
2557
  ## Support
1654
2558
 
1655
2559
  For support, please contact the VISNS Studio team or open an issue on GitHub.