Skip to main content

Stock Count Components Integration Guide

Overview

This guide explains how to integrate the new stock count components into your existing application. The components provide a complete mobile-first, offline-capable stock counting workflow.

Components Added

1. StockCountScannerForm - Mobile Scanner Interface

  • Location: apps/frontend-pwa/src/components/forms/stock-count-entry/StockCountScannerForm.tsx
  • Purpose: Mobile-first barcode scanning interface with offline support
  • Features:
    • Barcode scanning (camera + manual input)
    • Offline storage with IndexedDB
    • Quick quantity buttons (+1, +10, etc.)
    • Batch/serial number support
    • Bulk entry submission
    • Online/offline status handling

2. StockCountMyTasksPage - Mobile Task Management

  • Location: apps/frontend-pwa/src/components/forms/stock-count-task/StockCountMyTasksPage.tsx
  • Purpose: Mobile view for counters to manage their assigned tasks
  • Features:
    • Task grouping by status (pending, in progress, submitted)
    • Task acceptance workflow
    • Navigation to scanner interface
    • Mobile-optimized UI

3. StockCountSessionStartForm - Session Lifecycle Management

  • Location: apps/frontend-pwa/src/components/forms/stock-count-session/StockCountSessionStartForm.tsx
  • Purpose: Complete session lifecycle management
  • Features:
    • Start session functionality
    • Snapshot creation
    • Freeze/unfreeze operations
    • Session approval and posting

4. StockCountVarianceReviewForm - Enhanced Variance Review

  • Location: apps/frontend-pwa/src/components/forms/stock-count-variance/StockCountVarianceReviewForm.tsx
  • Purpose: Advanced variance review with task approval/recount
  • Features:
    • Per-task approval/recount actions
    • Threshold-based filtering
    • Task status management
    • Variance grouping by task

5. useOfflineStorage - Offline Storage Hook

  • Location: apps/frontend-pwa/src/hooks/useOfflineStorage.ts
  • Purpose: IndexedDB-based offline storage for stock count entries
  • Features:
    • Task-based entry storage
    • Submission queuing
    • Data persistence and retrieval
    • Clear operations

6. useScanner - Scanner Functionality Hook

  • Location: apps/frontend-pwa/src/hooks/useScanner.ts
  • Purpose: Barcode scanning functionality
  • Features:
    • Camera support detection
    • Manual input fallback
    • Scan sound feedback
    • Barcode processing

Integration Steps

Step 1: Install Dependencies

Add barcode scanning library to your project:

cd apps/frontend-pwa
pnpm add @zxing/library @zxing/browser

Step 2: Update Service Methods

The following service methods have been added to stockCountService.ts:

// Device management
export const getDeviceId = (): string
export const generateDeviceId = (): string

// Location freeze/unfreeze
export const freezeLocation = async (token: string, locationId: string, reason: string, sessionId?: string)
export const unfreezeLocation = async (token: string, locationId: string)

// Offline sync
export const getPendingOfflineSubmissions = async (token: string)
export const syncOfflineSubmissions = async (token: string, submissions: StockCountBulkEntrySubmission[])

Step 3: Add Translation Keys

All required translation keys have been added to apps/frontend-pwa/src/i18n/locales/en.json:

  • stockCount.scanner.* - Scanner interface translations
  • stockCount.tasks.* - Task management translations
  • stockCount.session.* - Session lifecycle translations
  • stockCount.variance.* - Variance review translations
  • stockCount.taskStatus.* - Task status translations

Step 4: Update Routes

The following routes have been added to MainPage.tsx:

case "/forms/StockCountSessionStartForm":
case "/forms/StockCountMyTasksPage":
case "/forms/StockCountVarianceReviewForm":
case "/forms/StockCountScannerForm":

Step 5: Update Menu Configuration

Add the new menu items to your Firebase Remote Config (pwaMenu.json):

{
"name": "menu.stockCountMyTasks",
"module": "stock-count",
"icon": "assignment",
"order": 3,
"path": "/forms/StockCountMyTasksPage",
"roles": ["counter", "manager"]
}

Usage Examples

1. Navigating to Scanner Form

import { useNavigate } from 'react-router-dom';

const navigate = useNavigate();

// Navigate to scanner with task data
navigate('/main', {
state: {
selectedForm: '/forms/StockCountScannerForm',
task: taskData,
products: productsList,
onTaskComplete: () => {
// Handle task completion
console.log('Task completed');
}
}
});

2. Opening Session Start Form

navigate('/main', {
state: {
selectedForm: '/forms/StockCountSessionStartForm',
session: sessionData,
onSessionUpdated: (updatedSession) => {
// Handle session update
console.log('Session updated:', updatedSession);
},
onComplete: () => {
// Handle completion
console.log('Session completed');
}
}
});

3. Opening Variance Review

navigate('/main', {
state: {
selectedForm: '/forms/StockCountVarianceReviewForm',
sessionId: 'session-id',
onTaskUpdated: () => {
// Handle task updates
console.log('Task updated');
}
}
});

4. Using Offline Storage

import { useOfflineStorage } from '@/hooks/useOfflineStorage';

const { saveOfflineEntries, getOfflineEntries, clearOfflineEntries } = useOfflineStorage();

// Save entries for a task
await saveOfflineEntries(taskId, entries);

// Get entries for a task
const entries = await getOfflineEntries(taskId);

// Clear entries for a task
await clearOfflineEntries(taskId);

5. Using Scanner Hook

import { useScanner } from '@/hooks/useScanner';

const { startScanning, stopScanning, isScanning, simulateScan } = useScanner();

// Start scanning
startScanning((barcode) => {
console.log('Scanned:', barcode);
// Handle barcode
});

// Stop scanning
stopScanning();

// Simulate scan (for testing)
simulateScan('123456789');

Mobile Navigation

For mobile-specific navigation, you can create dedicated mobile routes:

// In your routing configuration
const mobileRoutes = [
{
path: '/stock-count/my-tasks',
component: StockCountMyTasksPage,
mobile: true
},
{
path: '/stock-count/scanner/:taskId',
component: StockCountScannerForm,
mobile: true
}
];

Offline Functionality

IndexedDB Schema

The offline storage uses the following IndexedDB structure:

  • Database: StockCountOfflineDB
  • Stores:
    • entries - Task-based entry storage
    • submissions - Pending submission queue

Sync Process

  1. Online: Entries are submitted immediately
  2. Offline: Entries are stored locally and queued for sync
  3. Reconnect: Queued submissions are automatically synced

Device Management

Each device gets a unique ID stored in localStorage:

const deviceId = getDeviceId(); // Gets or creates device ID

Testing

Unit Tests

Create tests for the new components:

// __tests__/StockCountScannerForm.test.tsx
import { render, screen } from '@testing-library/react';
import { StockCountScannerForm } from '../StockCountScannerForm';

test('renders scanner form', () => {
render(<StockCountScannerForm task={mockTask} products={mockProducts} />);
expect(screen.getByText('Stock Count Scanner')).toBeInTheDocument();
});

Integration Tests

Test the complete workflow:

// __tests__/stockCountWorkflow.test.tsx
test('complete stock count workflow', async () => {
// 1. Create session
// 2. Generate tasks
// 3. Start session
// 4. Count items
// 5. Review variances
// 6. Post session
});

Manual Testing

  1. Barcode Scanning: Test with real barcodes on mobile devices
  2. Offline Functionality: Test with network disconnected
  3. Mobile UI: Test on various mobile screen sizes
  4. Performance: Test with large datasets

Troubleshooting

Common Issues

  1. Camera Not Working

    • Ensure HTTPS is used (required for camera access)
    • Check browser permissions
    • Test with manual input fallback
  2. Offline Storage Not Working

    • Check IndexedDB support
    • Verify database initialization
    • Check for storage quota issues
  3. Sync Issues

    • Verify network connectivity
    • Check API endpoints
    • Review error logs

Debug Tools

// Enable debug logging
localStorage.setItem('debug', 'stock-count:*');

// Check offline storage
const { getPendingSubmissions } = useOfflineStorage();
const pending = await getPendingSubmissions();
console.log('Pending submissions:', pending);

Performance Considerations

  1. Large Datasets: Implement pagination for large task lists
  2. Offline Storage: Monitor IndexedDB size and implement cleanup
  3. Camera Performance: Optimize camera resolution for scanning
  4. Sync Frequency: Implement background sync with reasonable intervals

Security Considerations

  1. Device ID: Ensure device IDs are unique and secure
  2. Offline Data: Encrypt sensitive data in IndexedDB
  3. API Security: Validate all API calls and implement proper authentication
  4. Data Integrity: Implement checksums for offline data validation

Future Enhancements

  1. Photo Capture: Add product photo capture functionality
  2. Advanced Sync: Implement conflict resolution for offline changes
  3. Background Sync: Add service worker for background synchronization
  4. Analytics: Add usage analytics and performance monitoring
  5. Multi-language: Add support for additional languages

Support

For issues or questions:

  1. Check the troubleshooting section above
  2. Review the component documentation
  3. Check the console for error messages
  4. Test with the debug tools provided
  5. Contact the development team with specific error details