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();