Source: app/util/filterConfig.js

import uniq from 'lodash/uniq';
import flatten from 'lodash/flatten';
import camelCase from 'lodash/camelCase';
import Cuisine from 'common/src/app/data/enum/Cuisine';
import FilterType from 'common/src/app/data/enum/FilterType';
import FoodOptimising from 'common/src/app/data/enum/FoodOptimising';
import Seasonal from 'common/src/app/data/enum/Seasonal';
import MealType from 'common/src/app/data/enum/MealType';
import RecipeTime from 'common/src/app/data/enum/RecipeTime';
import CookingType from 'common/src/app/data/enum/CookingType';
import StoriesType from 'common/src/app/data/enum/StoriesType';
import { GenderType } from 'common/src/app/data/enum/Gender';
import WeightLossType from 'common/src/app/data/enum/WeightLossType';
import AgeType from 'common/src/app/data/enum/AgeType';
import FeaturesType from 'common/src/app/data/enum/FeaturesType';
import SeasonalType from 'common/src/app/data/enum/SeasonalType';

// define filter types, sections and items
// to add a new filter section (or type) just add here
export const filterSections = {
  [FilterType.SUCCESS_STORY]: {
    stories: StoriesType,
    gender: GenderType,
    weightLoss: WeightLossType,
    age: AgeType,
  },

  [FilterType.RECIPES]: {
    useFoodPreferences: {
      0: 'useFoodPreferences',
    },
    foodOptimising: FoodOptimising,
    cuisine: Cuisine,
    mealType: MealType,
    seasonal: Seasonal,
    cookingType: CookingType,
    time: RecipeTime,
  },

  [FilterType.FEATURES]: {
    features: FeaturesType,
    seasonal: SeasonalType,
  },

  [FilterType.COMMUNITY]: {},
};

/**
 * You are now able to pass an optional formatter
 *
 * example:
 *
 * {
 *   0: 'value 1',
 *   1: 'value 2',
 *   2: 'value 3',
 *   3: 'value 4',
 *   4: 'value 5',
 *   formatter: object,
 * }
 *
 * note: when using the formatter it will not use the objectKeys as values anymore
 *
 * @param filterType
 * @param currentSection
 * @returns {{name: string, filters: {formatter: *, name: string, filters: {description: string, value: (*), key: *}[], key: string}[]}}
 */
export const filterGenerator = (filterType, currentSection) => ({
  name: `searchFilter.${filterType}.name`,
  filters: [
    ...Object.keys(currentSection).map(section => {
      const formatter = currentSection[section]?.formatter;
      const currentFilterSection = currentSection[section];
      const rawDescription = currentSection[section]?.rawDescription;
      delete currentFilterSection?.formatter;
      delete currentFilterSection?.rawDescription;
      return {
        name: `searchFilter.${filterType}.${section}.name`,
        key: section,
        formatter,
        rawDescription,
        filters: [
          ...Object.keys(currentFilterSection).map(value =>
            typeof currentFilterSection[value] === 'object'
              ? {
                  description: currentFilterSection[value].title,
                  key: currentFilterSection[value].title,
                  value: formatter ? currentFilterSection[value].slug : parseInt(value, 10),
                }
              : {
                  description: `searchFilter.${filterType}.${section}.${camelCase(
                    currentFilterSection[value],
                  )}`,
                  key: currentFilterSection[value],
                  value: formatter ? currentFilterSection[value] : parseInt(value, 10),
                },
          ),
        ],
      };
    }),
  ],
});

// create the config based of the definitions and the generator
const filterConfig = () =>
  Object.keys(filterSections).reduce(
    (acc, cur) => ({
      ...acc,
      [cur]: filterGenerator(cur, filterSections[cur]),
    }),
    {},
  );

/**
 * Array of all filter keys. Used to build collection parameters
 * @type {string[]}
 */
export const allFilterKeys = uniq(
  flatten(Object.values(filterConfig()).map(f => f.filters.map(subFilter => subFilter.key))),
).sort(); // we do a sort on the end to make sure the order is deterministic

export default filterConfig;