diff --git a/src/Mealz/MealBundle/Resources/config/routing.yml b/src/Mealz/MealBundle/Resources/config/routing.yml index 8245a5484..4457050cf 100644 --- a/src/Mealz/MealBundle/Resources/config/routing.yml +++ b/src/Mealz/MealBundle/Resources/config/routing.yml @@ -46,6 +46,13 @@ MealzMealBundle_menu: path: /menu/{week} defaults: { _controller: App\Mealz\MealBundle\Controller\FrontendController::renderIndex } +MealzMealBundle_menu_create: + path: /menu/{week}/create + defaults: + _controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController + path: /weeks + permanent: true + MealzMealBundle_weeks: path: /weeks defaults: { _controller: App\Mealz\MealBundle\Controller\FrontendController::renderIndex } diff --git a/src/Resources/src/components/menu/MenuParticipationPanel.vue b/src/Resources/src/components/menu/MenuParticipationPanel.vue index d989a45c9..a0033fa36 100644 --- a/src/Resources/src/components/menu/MenuParticipationPanel.vue +++ b/src/Resources/src/components/menu/MenuParticipationPanel.vue @@ -15,6 +15,9 @@ :meal="meal" class="max-w-[300px] px-2" /> + + {{ t('menu.noMeals') }} + @@ -24,6 +27,9 @@ import { Dictionary } from 'types/types'; import MealParticipationInput from './MealParticipationInput.vue'; import { computed } from 'vue'; import { XCircleIcon } from '@heroicons/vue/solid'; +import { useI18n } from 'vue-i18n'; + +const { t } = useI18n(); const props = defineProps<{ meals: Dictionary; @@ -34,9 +40,9 @@ const emit = defineEmits(['closePanel']); const mealList = computed(() => { const keys = Object.keys(props.meals); removeCombinedMealKey(keys); - const returnMealDTOs = []; + const returnMealDTOs: MealDTO[] = []; keys.forEach((key) => { - if (parseInt(key) > 0) { + if (props.meals[key].length > 0) { returnMealDTOs.push(...props.meals[key]); } }); @@ -46,7 +52,13 @@ const mealList = computed(() => { function removeCombinedMealKey(keys: string[]) { let indexToRemove = -1; keys.forEach((mealId) => { - if (parseInt(mealId) > 0 && props.meals[mealId][0].dishSlug === 'combined-dish') { + if ( + parseInt(mealId) > 0 && + props.meals[mealId] !== undefined && + props.meals[mealId] !== null && + props.meals[mealId].length > 0 && + props.meals[mealId][0].dishSlug === 'combined-dish' + ) { indexToRemove = keys.indexOf(mealId); } }); diff --git a/src/Resources/src/locales/de.json b/src/Resources/src/locales/de.json index 39b24191a..216bd0af8 100644 --- a/src/Resources/src/locales/de.json +++ b/src/Resources/src/locales/de.json @@ -279,7 +279,8 @@ "notFound": "Keine Profile für diese Anfrage gefunden", "shortQuery": "Min. 3 Buchstaben für Suche eingeben", "search": "Teilnehmer filtern", - "guest": "Gast" + "guest": "Gast", + "noMeals": "Noch keine Gerichte ausgewählt" }, "printList": { "title": "Teilnahmen am ", diff --git a/src/Resources/src/locales/en.json b/src/Resources/src/locales/en.json index e18ce5f16..8d76243cb 100644 --- a/src/Resources/src/locales/en.json +++ b/src/Resources/src/locales/en.json @@ -279,7 +279,8 @@ "notFound": "No profiles found for this query", "shortQuery": "Min. 3 Buchstaben für Suche eingeben", "search": "Filter participant", - "guest": "Gast" + "guest": "Gast", + "noMeals": "No dishes selected yet" }, "printList": { "title": "Participations on ", diff --git a/src/Resources/src/views/Menu.vue b/src/Resources/src/views/Menu.vue index 0fda18a28..e9c5b6076 100644 --- a/src/Resources/src/views/Menu.vue +++ b/src/Resources/src/views/Menu.vue @@ -11,7 +11,7 @@ /> { cy.get('input') .eq(12) - .should('have.value', 'Innards DE'); + .should('have.value', 'Braaaaaiiinnnzzzzzz DE'); cy.get('input') .eq(13) - .should('have.value', 'Braaaaaiiinnnzzzzzz DE'); + .should('have.value', 'Innards DE'); // Test Participations cy.get('span').contains('Teilnahmen').click(); @@ -299,7 +299,7 @@ describe('Test Creating a Menu', () => { .parent() .find('td') .eq(4) - .click() + .click(); cy.wait('@putParticipation'); @@ -327,7 +327,7 @@ describe('Test Creating a Menu', () => { .parent() .find('td') .eq(4) - .click() + .click(); cy.wait('@putParticipation'); @@ -353,7 +353,7 @@ describe('Test Creating a Menu', () => { .parent() .find('td') .eq(4) - .click() + .click(); cy.wait('@deleteParticipation'); @@ -370,6 +370,154 @@ describe('Test Creating a Menu', () => { .should('not.exist'); }); + it('should create a menu with participation limits, delete a meal in the first row of a day and be able to set it again', () => { + cy.get('span > a').contains('Mahlzeiten').click(); + + cy.wait(['@getWeeks']); + + // Go to 7th week (it should not have been created yet because of db reset) + cy.get('h4').eq(6).contains('Woche').click(); + + cy.wait(['@getDishesCount', '@getCategories', '@getDishes']); + + // create menu + // Monday + cy.get('input') + .first() + .parent() + .find('svg') + .eq(1) + .click() + .parent() + .find('input') + .click() + .type('Tasty') + .parent().parent() + .find('li').contains('Tasty Worms DE') + .click(); + + cy.get('h2').should('contain', 'Woche').click(); + + cy.get('input') + .eq(1) + .parent() + .find('svg') + .eq(1) + .click() + .parent() + .find('input') + .click() + .parent().parent() + .find('li').contains('Limbs DE') + .click(); + + cy.get('h2').should('contain', 'Woche').click(); + + // Save + cy.contains('input', 'Speichern').click(); + + cy.wait(['@postWeeks', '@getWeeks']); + + cy.get('[data-cy="msgClose"]').click(); + + // change participation limit + cy.get('input') + .first() + .parent() + .parent() + .parent() + .parent() + .find('div.col-start-1') + .first() + .find('button') + .first() + .click(); + + cy.get('[data-cy="meal-participation-limit-input"]') + .eq(1) + .clear() + .type('17'); + + cy.get('span').contains('Limit').parent().find('svg').click(); + + // Delete Meal + cy.get('h2').should('contain', 'Woche').click(); + + cy.get('input') + .first() + .parent() + .find('svg') + .eq(1) + .click(); + + cy.get('h2').should('contain', 'Woche').click(); + + // Save + cy.contains('input', 'Speichern').click(); + + cy.wait(['@putMenu', '@getWeeks']); + + cy.get('[data-cy="msgClose"]').click(); + + // Check Limbs is now set as first input + cy.get('input') + .first() + .should('have.value', 'Limbs DE'); + + // Set new second Meal + cy.get('input') + .eq(1) + .parent() + .find('svg') + .eq(1) + .click() + .parent() + .find('input') + .click() + .parent().parent() + .find('li').contains('Braaaaaiiinnnzzzzzz DE') + .click(); + + cy.get('h2').should('contain', 'Woche').click(); + + // Save + cy.contains('input', 'Speichern').click(); + + cy.wait(['@putMenu', '@getWeeks']); + + cy.get('[data-cy="msgClose"]').click(); + + // Check Meals are both saved + cy.get('input') + .first() + .should('have.value', 'Braaaaaiiinnnzzzzzz DE'); + + cy.get('input') + .eq(1) + .should('have.value', 'Limbs DE'); + + // Check participation limits + cy.get('input') + .first() + .parent() + .parent() + .parent() + .parent() + .find('div.col-start-1') + .first() + .find('button') + .first() + .click(); + + cy.get('[data-cy="meal-participation-limit-input"]') + .eq(0) + .should('have.value', 0); + + cy.get('[data-cy="meal-participation-limit-input"]') + .eq(1) + .should('have.value', 17); + }); + it('should not create a menu if the initial submission of a menu gets aborted', () => { cy.get('span > a').contains('Mahlzeiten').click();