All files / src/pages/inventory/dialogs/DeleteItemDialog deleteItemErrorHandler.ts

100% Statements 98/98
100% Branches 11/11
100% Functions 1/1
100% Lines 98/98

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 991x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 6x 6x 6x 6x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 6x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 6x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 6x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x  
/**
 * @file deleteItemErrorHandler.ts
 * @description
 * Error handling logic for delete item operations.
 * Maps backend errors to user-friendly messages.
 * Separated from hook to keep logic testable and reusable.
 */
 
import type { TFunction } from 'i18next';
 
/**
 * Categorized error response from deleteItem API
 */
export interface DeleteErrorResult {
  /** User-facing error message */
  message: string;
  /** Error severity: warning, error, info */
  severity: 'error' | 'warning' | 'info';
}
 
/**
 * Process API error response and return user-friendly message.
 *
 * Handles specific business rules:
 * - Quantity must be 0 before deletion
 * - Only admins can delete items
 * - Item not found scenarios
 *
 * @param errorText - Error text from API
 * @param t - i18n translation function
 * @returns Categorized error result with message and severity
 *
 * @example
 * ```ts
 * const error = handleDeleteError('You still have merchandise', t);
 * // Returns: { message: '...translated message...', severity: 'error' }
 * ```
 */
export function handleDeleteError(
  errorText: string | undefined,
  t: TFunction
): DeleteErrorResult {
  if (!errorText) {
    return {
      message: t('errors:inventory.requests.failedToDeleteItem', 'Failed to delete item. Please try again.'),
      severity: 'error',
    };
  }
 
  const lowerError = errorText.toLowerCase();
 
  // ============================================
  // Business Rule: Quantity must be zero
  // ============================================
  if (lowerError.includes('still have') || lowerError.includes('merchandise') || lowerError.includes('stock')) {
    return {
      message: t(
        'errors:inventory.businessRules.quantityMustBeZero',
        'You still have merchandise in stock. You need to first remove items from stock by changing quantity.'
      ),
      severity: 'error',
    };
  }
 
  // ============================================
  // Authorization: Admin only
  // ============================================
  if (lowerError.includes('admin') || lowerError.includes('access denied')) {
    return {
      message: t(
        'errors:inventory.businessRules.adminOnly',
        'Only administrators can delete items.'
      ),
      severity: 'warning',
    };
  }
 
  // ============================================
  // Not Found: Item no longer exists
  // ============================================
  if (lowerError.includes('404') || lowerError.includes('not found')) {
    return {
      message: t(
        'errors:inventory.businessRules.itemNotFound',
        'Item not found. It may have been deleted by another user.'
      ),
      severity: 'warning',
    };
  }
 
  // ============================================
  // Generic error fallback
  // ============================================
  return {
    message: t('errors:inventory.requests.failedToDeleteItem', 'Failed to delete item. Please try again.'),
    severity: 'error',
  };
}