All files / src/hooks useFlyerSelection.ts

100% Statements 22/22
100% Branches 17/17
100% Functions 5/5
100% Lines 21/21

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                                                                      2x       96x 96x     96x 96x   96x 46x       96x 80x 36x 28x   36x         96x 80x 14x 30x 14x 5x 3x         5x         96x            
// src/hooks/useFlyerSelection.ts
import { useState, useCallback, useEffect } from 'react';
import { useLocation, matchPath } from 'react-router-dom';
import { logger } from '../services/logger.client';
import type { Flyer } from '../types';
 
interface UseFlyerSelectionOptions {
  flyers: Flyer[];
  debugLogging?: boolean;
}
 
interface UseFlyerSelectionReturn {
  selectedFlyer: Flyer | null;
  handleFlyerSelect: (flyer: Flyer) => void;
  flyerIdFromUrl: string | undefined;
}
 
/**
 * A custom hook to manage flyer selection state, including:
 * - Manual flyer selection via handleFlyerSelect
 * - URL-based flyer selection (e.g., /flyers/:flyerId)
 * - Auto-selection of the first flyer when none is selected
 *
 * @param options.flyers - Array of available flyers
 * @param options.debugLogging - Enable debug logging (default: false, enabled in test env)
 * @returns Object with selectedFlyer, handleFlyerSelect callback, and flyerIdFromUrl
 *
 * @example
 * ```tsx
 * const { selectedFlyer, handleFlyerSelect, flyerIdFromUrl } = useFlyerSelection({
 *   flyers,
 *   debugLogging: process.env.NODE_ENV === 'test',
 * });
 * ```
 */
export const useFlyerSelection = ({
  flyers,
  debugLogging = process.env.NODE_ENV === 'test',
}: UseFlyerSelectionOptions): UseFlyerSelectionReturn => {
  const [selectedFlyer, setSelectedFlyer] = useState<Flyer | null>(null);
  const location = useLocation();
 
  // Extract flyerId from URL if present
  const match = matchPath('/flyers/:flyerId', location.pathname);
  const flyerIdFromUrl = match?.params.flyerId;
 
  const handleFlyerSelect = useCallback((flyer: Flyer) => {
    setSelectedFlyer(flyer);
  }, []);
 
  // Auto-select first flyer when none is selected and flyers are available
  useEffect(() => {
    if (!selectedFlyer && flyers.length > 0) {
      if (debugLogging) {
        logger.debug('[useFlyerSelection] Auto-selecting first flyer');
      }
      handleFlyerSelect(flyers[0]);
    }
  }, [flyers, selectedFlyer, handleFlyerSelect, debugLogging]);
 
  // Handle URL-based flyer selection
  useEffect(() => {
    if (flyerIdFromUrl && flyers.length > 0) {
      const flyerId = parseInt(flyerIdFromUrl, 10);
      const flyerToSelect = flyers.find((f) => f.flyer_id === flyerId);
      if (flyerToSelect && flyerToSelect.flyer_id !== selectedFlyer?.flyer_id) {
        if (debugLogging) {
          logger.debug(
            { flyerId, flyerToSelect: flyerToSelect.flyer_id },
            '[useFlyerSelection] Selecting flyer from URL',
          );
        }
        handleFlyerSelect(flyerToSelect);
      }
    }
  }, [flyers, handleFlyerSelect, selectedFlyer, flyerIdFromUrl, debugLogging]);
 
  return {
    selectedFlyer,
    handleFlyerSelect,
    flyerIdFromUrl,
  };
};