All files / src/components/SearchForm helper.ts

100% Statements 45/45
77.77% Branches 7/9
100% Functions 4/4
100% Lines 45/45

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  1x               1x     1x                         1x 3x 3x 3x 3x 3x   3x 3x             1x 44x 44x 44x 44x 8x 8x   8x 8x 44x 44x 44x               1x 3x 3x 3x 3x   3x 3x   1x 5x 5x 5x   5x 3x     3x   3x   3x   3x 3x 3x   3x 3x 5x  
// Types
import {
  ActionGroup,
  ActionItemType,
  ActionKind,
  ActivityType,
} from '@shared/types';
 
// Stores
import { useSetChatResetFlag } from '@/stores';
 
// Constants
import { ROUTES } from '@/constants';
 
interface HandleActionClickParams {
  item: ActionItemType;
  onClose?: () => void;
}
 
/**
 * Determines if the search dialog should be closed based on the action item
 *
 * @param item The action item that was clicked
 * @returns boolean indicating whether the dialog should be closed
 */
export const shouldCloseDialog = (item: ActionItemType): boolean => {
  const closableTypes = [
    ActivityType.VIEW_MENU,
    ActivityType.VIEW_STATISTIC,
    ActivityType.COMPARE_STATISTIC,
  ];
 
  return closableTypes.includes(item.type);
};
 
/**
 * Groups options by their group property
 * @param options Array of action items to be grouped
 * @returns Object with group names as keys and arrays of matching options as values
 */
export const groupOptionsByGroup = (
  options: ActionItemType[],
): Record<string, ActionItemType[]> => {
  return options.reduce(
    (acc, option) => {
      const groupKey = String(option.group);
      (acc[groupKey] ??= []).push(option);
 
      return acc;
    },
    {} as Record<string, ActionItemType[]>,
  );
};
 
/**
 * Determines the redirect path for an action item based on keywords in its label
 *
 * @param item The action item containing label and payload information
 * @returns The matching route path if keywords are found in the label
 */
export const getRedirectPath = (item: ActionItemType) => {
  const redirectMap: Partial<Record<ActionGroup, string>> = {
    [ActionGroup.MENU]: ROUTES.HOME,
    [ActionGroup.STATISTIC]: ROUTES.STATISTICS,
  };
 
  return redirectMap[item.group] ?? '/';
};
 
export const handleActionClick = async ({
  item,
  onClose,
}: HandleActionClickParams) => {
  // For REDIRECT actions from keyboard, trigger click to let Link handle navigation
  if (item.kind === ActionKind.REDIRECT) {
    const pathname = getRedirectPath(item) || '';
 
    // Reset chat before navigation
    useSetChatResetFlag(true);
    // Normalize to absolute URL
    const absoluteUrl = new URL(pathname, window.location.origin).toString();
 
    window.location.href = absoluteUrl;
 
    if (shouldCloseDialog(item)) {
      onClose?.();
    }
 
    return;
  }
};