<commit_before>import React from 'react';
import {
  getRunningDinnerBasicDetailsSelector,
  getRunningDinnerOptionsSelector,
  isClosedDinnerSelector,
  setNextNavigationStep,
  setPreviousNavigationStep, updateMeals,
} from "@runningdinner/shared";
import {PageTitle} from "../common/theme/typography/Tags";
import {SpacingGrid} from "../common/theme/SpacingGrid";
import WizardButtons from "./WizardButtons";
import {useTranslation} from "react-i18next";
import {useDispatch} from "react-redux";
import {
  Meal, OptionsNavigationStep, ParticipantPreviewNavigationStep, PublicRegistrationNavigationStep, useBackendIssueHandler, validateRunningDinnerOptions,
} from "@runningdinner/shared";
import {useWizardSelector} from "@runningdinner/shared";
import MealTimeEditControl from "../admin/dashboard/MealTimeEditControl";
import { cloneDeep } from 'lodash';
import {useNotificationHttpError} from "../common/NotificationHttpErrorHook";
import {FormProvider, useForm} from "react-hook-form";

export default function MealTimesStep() {

  const {t} = useTranslation(['wizard', 'common']);

  const options = useWizardSelector(getRunningDinnerOptionsSelector);
  const {date} = useWizardSelector(getRunningDinnerBasicDetailsSelector);
  const isClosedDinner = useWizardSelector(isClosedDinnerSelector);

  const {meals} = options;

  const [mealsFormState, setMealsFormState] = React.useState(cloneDeep(meals));

  const {getIssuesTranslated} = useBackendIssueHandler({
    defaultTranslationResolutionSettings: {
      namespaces: 'wizard'
    }
  });
  const {showHttpErrorDefaultNotification} = useNotificationHttpError(getIssuesTranslated);

  const dispatch = useDispatch();

  const formMethods = useForm();

  React.useEffect(() => {
    dispatch(setNextNavigationStep(isClosedDinner ? ParticipantPreviewNavigationStep : PublicRegistrationNavigationStep));
    dispatch(setPreviousNavigationStep(OptionsNavigationStep));
    // eslint-disable-next-line
  }, [dispatch]);

  const submitMealTimesAsync = async() => {
    const optionsToValidate = {...options};
    optionsToValidate.meals = mealsFormState;
    try {
      await validateRunningDinnerOptions(optionsToValidate, date);
      dispatch(updateMeals(mealsFormState));
      return true;
    } catch(e) {
      showHttpErrorDefaultNotification(e);
      return false;
    }
  };

  function handleTimeChange(meal: Meal, newTime: Date) {
    const meals = cloneDeep(mealsFormState);
    for (let i = 0; i < meals.length; i++) {
      if (meals[i].label === meal.label) {
        meals[i].time = newTime;
      }
    }
    setMealsFormState(meals);
  }

  const mealTimeFields = mealsFormState.map((meal) =>
      <SpacingGrid item key={meal.label}>
        <MealTimeEditControl {...meal} onHandleTimeChange={(newValue) => handleTimeChange(meal, newValue)} />
      </SpacingGrid>
  );

  return (
      <div>
        <PageTitle>{t('time_setup')}</PageTitle>
        <FormProvider {...formMethods}>
          <SpacingGrid container justify={"space-between"}>
            {mealTimeFields}
          </SpacingGrid>

          <WizardButtons onSubmitData={submitMealTimesAsync} />
        </FormProvider>
      </div>
  );
}<commit_msg>- Improved meal times layout<commit_after>import React from 'react';
import {
  getRunningDinnerBasicDetailsSelector,
  getRunningDinnerOptionsSelector,
  isClosedDinnerSelector,
  setNextNavigationStep,
  setPreviousNavigationStep, updateMeals,
} from "@runningdinner/shared";
import {PageTitle} from "../common/theme/typography/Tags";
import {SpacingGrid} from "../common/theme/SpacingGrid";
import WizardButtons from "./WizardButtons";
import {useTranslation} from "react-i18next";
import {useDispatch} from "react-redux";
import {
  Meal, OptionsNavigationStep, ParticipantPreviewNavigationStep, PublicRegistrationNavigationStep, useBackendIssueHandler, validateRunningDinnerOptions,
} from "@runningdinner/shared";
import {useWizardSelector} from "@runningdinner/shared";
import MealTimeEditControl from "../admin/dashboard/MealTimeEditControl";
import { cloneDeep } from 'lodash';
import {useNotificationHttpError} from "../common/NotificationHttpErrorHook";
import {FormProvider, useForm} from "react-hook-form";
import {useMediaQuery, useTheme} from "@material-ui/core";

export default function MealTimesStep() {

  const {t} = useTranslation(['wizard', 'common']);

  const options = useWizardSelector(getRunningDinnerOptionsSelector);
  const {date} = useWizardSelector(getRunningDinnerBasicDetailsSelector);
  const isClosedDinner = useWizardSelector(isClosedDinnerSelector);

  const theme = useTheme();
  const isSmallDevice = useMediaQuery(theme.breakpoints.down("sm"));

  const {meals} = options;

  const [mealsFormState, setMealsFormState] = React.useState(cloneDeep(meals));

  const {getIssuesTranslated} = useBackendIssueHandler({
    defaultTranslationResolutionSettings: {
      namespaces: 'wizard'
    }
  });
  const {showHttpErrorDefaultNotification} = useNotificationHttpError(getIssuesTranslated);

  const dispatch = useDispatch();

  const formMethods = useForm();

  React.useEffect(() => {
    dispatch(setNextNavigationStep(isClosedDinner ? ParticipantPreviewNavigationStep : PublicRegistrationNavigationStep));
    dispatch(setPreviousNavigationStep(OptionsNavigationStep));
    // eslint-disable-next-line
  }, [dispatch]);

  const submitMealTimesAsync = async() => {
    const optionsToValidate = {...options};
    optionsToValidate.meals = mealsFormState;
    try {
      await validateRunningDinnerOptions(optionsToValidate, date);
      dispatch(updateMeals(mealsFormState));
      return true;
    } catch(e) {
      showHttpErrorDefaultNotification(e);
      return false;
    }
  };

  function handleTimeChange(meal: Meal, newTime: Date) {
    const meals = cloneDeep(mealsFormState);
    for (let i = 0; i < meals.length; i++) {
      if (meals[i].label === meal.label) {
        meals[i].time = newTime;
      }
    }
    setMealsFormState(meals);
  }

  const mealTimeFields = mealsFormState.map((meal) =>
      <SpacingGrid item key={meal.label} pr={6}>
        <MealTimeEditControl {...meal} onHandleTimeChange={(newValue) => handleTimeChange(meal, newValue)} />
      </SpacingGrid>
  );

  const mealTimeFieldsDirection = isSmallDevice ? "column" : "row";

  return (
      <div>
        <PageTitle>{t('time_setup')}</PageTitle>
        <FormProvider {...formMethods}>
          <SpacingGrid container direction={mealTimeFieldsDirection}>
            {mealTimeFields}
          </SpacingGrid>

          <WizardButtons onSubmitData={submitMealTimesAsync} />
        </FormProvider>
      </div>
  );
}
{'fraction_non_alphanumeric': 0.11699248120300752, 'fraction_numerical': 0.0010526315789473684, 'mean_word_length': 4.6604255319148935, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6439856', 'n_tokens_mistral': 1933, 'n_tokens_neox': 1891, 'n_words': 371}