From 28d71c878a9af3bef73685f14687428a1f79acf1 Mon Sep 17 00:00:00 2001 From: MalibusParty <76796838+MalibusParty@users.noreply.github.com> Date: Tue, 27 Feb 2024 13:29:05 +0100 Subject: [PATCH 01/20] #262673: fixed a bug, that prevented offered meals to be taken over after the locktime --- src/Resources/src/components/dashboard/MealCheckbox.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Resources/src/components/dashboard/MealCheckbox.vue b/src/Resources/src/components/dashboard/MealCheckbox.vue index ebef2b7a9..c8e41ec0f 100644 --- a/src/Resources/src/components/dashboard/MealCheckbox.vue +++ b/src/Resources/src/components/dashboard/MealCheckbox.vue @@ -123,7 +123,10 @@ const checkboxCSS = computed(() => { async function handle() { // Meal is not locked - if (mealOrVariation.value.isLocked === false && isLocked(String(props.dayID)) === false) { + if ( + (mealOrVariation.value.isLocked === false || mealOrVariation.value.mealState === 'tradeable') && + isLocked(String(props.dayID)) === false + ) { addLock(String(props.dayID)); // User is participating if (isParticipating.value) { @@ -138,6 +141,7 @@ async function handle() { } removeLock(String(props.dayID)); } else if (isLocked(String(props.dayID)) === false) { + console.log(`Attemting accept offer: mealstate: ${mealOrVariation.value.mealState}`); addLock(String(props.dayID)); if (mealOrVariation.value.mealState === 'offerable') { addLock(String(props.dayID)); From 20307a046f07cd7c36bf83c9ef57b81f8299a2e2 Mon Sep 17 00:00:00 2001 From: MalibusParty <76796838+MalibusParty@users.noreply.github.com> Date: Tue, 27 Feb 2024 13:36:09 +0100 Subject: [PATCH 02/20] #262674: fixed a bug that prevented guests from participating --- config/packages/security.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/packages/security.yaml b/config/packages/security.yaml index c7e149e78..eeceab4f7 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -78,6 +78,7 @@ security: - { path: ^/api/print/participations, roles: [IS_AUTHENTICATED_ANONYMOUSLY] } - { path: ^/api/dashboard, roles: [IS_AUTHENTICATED_ANONYMOUSLY] } - { path: ^/api/guest-invitation, roles: [IS_AUTHENTICATED_ANONYMOUSLY] } + - { path: ^/api/guest/meal/participation, roles: [IS_AUTHENTICATED_ANONYMOUSLY] } - { path: ^/api/environmentals, roles: [IS_AUTHENTICATED_ANONYMOUSLY] } - { path: ^/api/user, roles: [IS_AUTHENTICATED_ANONYMOUSLY] } - { path: ^/api/event/invitation/\S*, roles: [IS_AUTHENTICATED_ANONYMOUSLY] } From 6135dc9f0e1f09fcbf17fd810aaeb8ba98fb75a1 Mon Sep 17 00:00:00 2001 From: MalibusParty <76796838+MalibusParty@users.noreply.github.com> Date: Tue, 27 Feb 2024 13:57:57 +0100 Subject: [PATCH 03/20] #262683: fixed a bug, that prevented deleted dishvariations to vanish --- src/Mealz/MealBundle/Controller/DishController.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Mealz/MealBundle/Controller/DishController.php b/src/Mealz/MealBundle/Controller/DishController.php index befbf9174..f6a004374 100644 --- a/src/Mealz/MealBundle/Controller/DishController.php +++ b/src/Mealz/MealBundle/Controller/DishController.php @@ -5,6 +5,7 @@ namespace App\Mealz\MealBundle\Controller; use App\Mealz\MealBundle\Entity\Dish; +use App\Mealz\MealBundle\Entity\DishCollection; use App\Mealz\MealBundle\Repository\CategoryRepository; use App\Mealz\MealBundle\Repository\CategoryRepositoryInterface; use App\Mealz\MealBundle\Repository\DishRepository; @@ -60,6 +61,15 @@ public function getDishes(): JsonResponse $dishes[] = $combiDish[0]; } + /** @var Dish $dish */ + foreach ($dishes as $dish) { + $variations = array_filter( + $dish->getVariations()->toArray(), + fn ($variation) => $variation->isEnabled() + ); + $dish->setVariations(new DishCollection($variations)); + } + return new JsonResponse($dishes, 200); } From 38a073885d4f6984d103ed945a4e7ba787463c16 Mon Sep 17 00:00:00 2001 From: MalibusParty <76796838+MalibusParty@users.noreply.github.com> Date: Tue, 27 Feb 2024 15:59:21 +0100 Subject: [PATCH 04/20] fixed a bug that made some dishvariation collections not be returned as an array --- src/Mealz/MealBundle/Controller/DishController.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Mealz/MealBundle/Controller/DishController.php b/src/Mealz/MealBundle/Controller/DishController.php index f6a004374..421050aaa 100644 --- a/src/Mealz/MealBundle/Controller/DishController.php +++ b/src/Mealz/MealBundle/Controller/DishController.php @@ -63,11 +63,13 @@ public function getDishes(): JsonResponse /** @var Dish $dish */ foreach ($dishes as $dish) { - $variations = array_filter( - $dish->getVariations()->toArray(), - fn ($variation) => $variation->isEnabled() - ); - $dish->setVariations(new DishCollection($variations)); + if (count($dish->getVariations()) > 0) { + $variations = array_values(array_filter( + $dish->getVariations()->toArray(), + fn ($variation) => $variation->isEnabled() + )); + $dish->setVariations(new DishCollection($variations)); + } } return new JsonResponse($dishes, 200); From 08b7e07d3cfb1dc2ea2021c2497075eb64d9237d Mon Sep 17 00:00:00 2001 From: MalibusParty <76796838+MalibusParty@users.noreply.github.com> Date: Tue, 27 Feb 2024 16:30:36 +0100 Subject: [PATCH 05/20] added functionality to close popups where applicable --- .../src/components/categories/CategoriesCreationPanel.vue | 3 +++ src/Resources/src/components/dishes/DishActions.vue | 6 +++++- .../src/components/dishes/DishVariationActions.vue | 1 + .../src/components/dishes/DishVariationCreationPanel.vue | 4 ++++ src/Resources/src/components/dishes/DishesCreationPanel.vue | 3 +++ src/Resources/src/components/dishes/DishesHeader.vue | 4 +++- .../src/components/eventParticipation/EventPopup.vue | 2 +- src/Resources/src/components/events/EventCreationPanel.vue | 4 ++++ src/Resources/src/components/events/EventsActions.vue | 1 + src/Resources/src/components/events/EventsHeader.vue | 4 +++- .../src/components/timeslots/SlotCreationPanel.vue | 3 +++ 11 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/Resources/src/components/categories/CategoriesCreationPanel.vue b/src/Resources/src/components/categories/CategoriesCreationPanel.vue index 3dbe3b954..a5e1402ab 100644 --- a/src/Resources/src/components/categories/CategoriesCreationPanel.vue +++ b/src/Resources/src/components/categories/CategoriesCreationPanel.vue @@ -46,6 +46,8 @@ const props = withDefaults( } ); +const emit = defineEmits(['closePanel']); + const titleDeInput = ref(props.titleDe); const titleEnInput = ref(props.titleEn); const required = ref(false); @@ -66,5 +68,6 @@ async function onSubmit() { }; await createCategory(category); } + emit('closePanel'); } diff --git a/src/Resources/src/components/dishes/DishActions.vue b/src/Resources/src/components/dishes/DishActions.vue index c260c5669..2cef25c46 100644 --- a/src/Resources/src/components/dishes/DishActions.vue +++ b/src/Resources/src/components/dishes/DishActions.vue @@ -13,7 +13,10 @@ /> diff --git a/src/Resources/src/components/dishes/DishVariationActions.vue b/src/Resources/src/components/dishes/DishVariationActions.vue index cfd982efa..3ae81aa72 100644 --- a/src/Resources/src/components/dishes/DishVariationActions.vue +++ b/src/Resources/src/components/dishes/DishVariationActions.vue @@ -15,6 +15,7 @@ :title-en="variation.titleEn" :slug="variation.slug" :edit="true" + @close-panel="close()" /> diff --git a/src/Resources/src/components/dishes/DishVariationCreationPanel.vue b/src/Resources/src/components/dishes/DishVariationCreationPanel.vue index 8776479c5..bfaf8ad37 100644 --- a/src/Resources/src/components/dishes/DishVariationCreationPanel.vue +++ b/src/Resources/src/components/dishes/DishVariationCreationPanel.vue @@ -47,6 +47,8 @@ const props = withDefaults( } ); +const emit = defineEmits(['closePanel']); + const titleDeInput = ref(props.titleDe); const titleEnInput = ref(props.titleEn); const required = ref(false); @@ -57,8 +59,10 @@ async function onSubmit() { return; } else if (props.edit === true && typeof props.slug === 'string') { await updateDishVariation(props.slug, createDishVariationDtoObject()); + emit('closePanel'); } else if (props.edit === false) { await createDishVariation(createDishVariationDtoObject(), props.parentSlug); + emit('closePanel'); } } diff --git a/src/Resources/src/components/dishes/DishesCreationPanel.vue b/src/Resources/src/components/dishes/DishesCreationPanel.vue index 1f5bacdc5..b5fb61ce3 100644 --- a/src/Resources/src/components/dishes/DishesCreationPanel.vue +++ b/src/Resources/src/components/dishes/DishesCreationPanel.vue @@ -91,6 +91,8 @@ const props = withDefaults( } ); +const emit = defineEmits(['closePanel']); + onMounted(async () => { await fetchCategories(); }); @@ -113,6 +115,7 @@ async function onSubmit() { } else { await createDish(createDishDtoObject()); } + emit('closePanel'); } function createDishDtoObject() { diff --git a/src/Resources/src/components/dishes/DishesHeader.vue b/src/Resources/src/components/dishes/DishesHeader.vue index 050957854..2209159c3 100644 --- a/src/Resources/src/components/dishes/DishesHeader.vue +++ b/src/Resources/src/components/dishes/DishesHeader.vue @@ -17,7 +17,9 @@ /> diff --git a/src/Resources/src/components/eventParticipation/EventPopup.vue b/src/Resources/src/components/eventParticipation/EventPopup.vue index ed75d3c84..3100b86a7 100644 --- a/src/Resources/src/components/eventParticipation/EventPopup.vue +++ b/src/Resources/src/components/eventParticipation/EventPopup.vue @@ -71,7 +71,7 @@ const props = withDefaults( ); const showParticipations = ref(false); -const participations = ref([]); +const participations = ref([]); const isLoading = ref(false); watch(showParticipations, async () => { diff --git a/src/Resources/src/components/events/EventCreationPanel.vue b/src/Resources/src/components/events/EventCreationPanel.vue index f3fc0f9d3..4f83faef1 100644 --- a/src/Resources/src/components/events/EventCreationPanel.vue +++ b/src/Resources/src/components/events/EventCreationPanel.vue @@ -59,6 +59,8 @@ const props = withDefaults( } ); +const emit = defineEmits(['closePanel']); + const eventTitle = ref(props.title); const isEventPublic = ref(props.isPublic); @@ -68,8 +70,10 @@ async function onSubmit() { required.value = true; if (eventTitle.value !== '' && props.edit === false) { await createEvent(eventTitle.value, isEventPublic.value); + emit('closePanel'); } else if (eventTitle.value !== '' && props.slug !== '') { await updateEvent(props.slug, eventTitle.value, isEventPublic.value); + emit('closePanel'); } } diff --git a/src/Resources/src/components/events/EventsActions.vue b/src/Resources/src/components/events/EventsActions.vue index 8459d5256..e25281ab4 100644 --- a/src/Resources/src/components/events/EventsActions.vue +++ b/src/Resources/src/components/events/EventsActions.vue @@ -18,6 +18,7 @@ :is-public="event.public" :edit="true" :slug="event.slug" + @close-panel="close()" /> diff --git a/src/Resources/src/components/events/EventsHeader.vue b/src/Resources/src/components/events/EventsHeader.vue index 1c8d72d92..6fc05fb27 100644 --- a/src/Resources/src/components/events/EventsHeader.vue +++ b/src/Resources/src/components/events/EventsHeader.vue @@ -16,7 +16,9 @@ /> From edef9a682f2dcd107cb443926ffbe3eb0b777de4 Mon Sep 17 00:00:00 2001 From: MalibusParty <76796838+MalibusParty@users.noreply.github.com> Date: Tue, 27 Feb 2024 17:30:21 +0100 Subject: [PATCH 06/20] fixed edgecase, when dishes get deleted but component depends on it --- .../components/menuParticipants/MenuTableData.vue | 15 ++++++++++----- .../components/menuParticipants/MenuTableHead.vue | 2 +- src/Resources/src/services/useMealIdToDishId.ts | 3 ++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Resources/src/components/menuParticipants/MenuTableData.vue b/src/Resources/src/components/menuParticipants/MenuTableData.vue index 6ab35fd5a..f768c1a82 100644 --- a/src/Resources/src/components/menuParticipants/MenuTableData.vue +++ b/src/Resources/src/components/menuParticipants/MenuTableData.vue @@ -68,9 +68,9 @@ const { addParticipantToMeal, removeParticipantFromMeal, hasParticipantBookedMea const { getDishById } = useDishes(); const isCombi = computed(() => props.meal.dish === 'combined-dish'); -const bookedCombi = computed(() => - hasParticipantBookedCombiDish(props.dayId, props.participant, mealIdToDishIdDict.get(props.meal.id)) -); +const bookedCombi = computed(() => { + return hasParticipantBookedCombiDish(props.dayId, props.participant, mealIdToDishIdDict.get(props.meal.id)) +}); const bookedMeal = computed(() => hasParticipantBookedMeal(props.dayId, props.participant, props.meal.id)); function handleClick() { @@ -92,8 +92,13 @@ function addParticipantOrOpenCombi(meal: SimpleMeal, participant: string, dayId: async function closeCombiModal(combiMeals: number[]) { openCombi.value = null; if (combiMeals !== undefined && combiMeals.length === 2) { - const dishSlugs = combiMeals.map((mealId) => getDishById(mealIdToDishIdDict.get(mealId)).slug); - await addParticipantToMeal(props.meal.id, props.participant, props.dayId, dishSlugs); + const dishSlugs = combiMeals.map((mealId) => { + const dishId = mealIdToDishIdDict.get(mealId); + return dishId !== -1 ? getDishById(dishId).slug : null + }); + if (dishSlugs !== null) { + await addParticipantToMeal(props.meal.id, props.participant, props.dayId, dishSlugs); + } } } diff --git a/src/Resources/src/components/menuParticipants/MenuTableHead.vue b/src/Resources/src/components/menuParticipants/MenuTableHead.vue index 3398cde05..1aa858ec3 100644 --- a/src/Resources/src/components/menuParticipants/MenuTableHead.vue +++ b/src/Resources/src/components/menuParticipants/MenuTableHead.vue @@ -36,7 +36,7 @@ class="sticky top-0 z-20 border-b-2 border-r-2 border-solid border-gray-200 bg-[#f4f7f9] px-2 text-center" > - {{ locale === 'en' ? getDishBySlug(meal.dish).titleEn : getDishBySlug(meal.dish).titleDe }} + {{ locale === 'en' ? getDishBySlug(meal.dish)?.titleEn : getDishBySlug(meal.dish)?.titleDe }} diff --git a/src/Resources/src/services/useMealIdToDishId.ts b/src/Resources/src/services/useMealIdToDishId.ts index 7d70002a4..1f88100ea 100644 --- a/src/Resources/src/services/useMealIdToDishId.ts +++ b/src/Resources/src/services/useMealIdToDishId.ts @@ -25,7 +25,8 @@ export function useMealIdToDishId(weekId: number) { for (const day of Object.values(week.days)) { for (const meals of Object.values(day.meals)) { meals.forEach((meal) => { - const dishId = getDishBySlug(meal.dish).id; + const dish = getDishBySlug(meal.dish); + const dishId = dish !== null ? dish.id : -1; mealIdToDishIdDict.set(meal.id, dishId); }); } From e8db829602fc3c1ea6d62c71d41087c04f3f53c3 Mon Sep 17 00:00:00 2001 From: MalibusParty <76796838+MalibusParty@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:59:37 +0100 Subject: [PATCH 07/20] #262688: participation limit icon now changes color if a limit is set --- src/Resources/src/components/menu/MenuDay.vue | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Resources/src/components/menu/MenuDay.vue b/src/Resources/src/components/menu/MenuDay.vue index 3ce624f52..0fde7b243 100644 --- a/src/Resources/src/components/menu/MenuDay.vue +++ b/src/Resources/src/components/menu/MenuDay.vue @@ -10,12 +10,15 @@ :translate-x-max="'-5%'" > @@ -83,6 +86,17 @@ const emit = defineEmits(['update:modelValue']); const selectedDishOne = ref(null); const selectedDishTwo = ref(null); const selectedEvent = ref(null); +const participationLimitNotZero = computed(() => { + let limitNotZero = false; + (Object.values(props.modelValue.meals) as MealDTO[][]).forEach(meals => { + meals.forEach(meal => { + if (meal.participationLimit !== 0) { + limitNotZero = true + } + }); + }); + return limitNotZero; +}); const mealKeys = computed(() => { const combiDish = getDishBySlug('combined-dish'); From 51b98b38bf63885dc35cfcdd2161ee3efa60291c Mon Sep 17 00:00:00 2001 From: MalibusParty <76796838+MalibusParty@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:00:37 +0100 Subject: [PATCH 08/20] #262686: spacing of drop downs in the menu now respects mobile views --- src/Mealz/MealBundle/Controller/MealAdminController.php | 6 +++++- src/Resources/src/components/costs/CashPaymentPanel.vue | 3 +++ src/Resources/src/components/menu/EventInput.vue | 2 +- src/Resources/src/components/menu/MenuInput.vue | 2 +- .../src/components/menu/MenuParticipationPanel.vue | 7 ++++--- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Mealz/MealBundle/Controller/MealAdminController.php b/src/Mealz/MealBundle/Controller/MealAdminController.php index c37ecd7c5..9db038fa2 100644 --- a/src/Mealz/MealBundle/Controller/MealAdminController.php +++ b/src/Mealz/MealBundle/Controller/MealAdminController.php @@ -197,7 +197,11 @@ public function count(): JsonResponse private function setParticipationLimit(Meal $mealEntity, $meal): void { - if (true === isset($meal['participationLimit']) && 0 < $meal['participationLimit']) { + if ( + true === isset($meal['participationLimit']) && + 0 < $meal['participationLimit'] && + count($mealEntity->getParticipants()) < $meal['participationLimit'] + ) { $mealEntity->setParticipationLimit($meal['participationLimit']); } else { $mealEntity->setParticipationLimit(0); diff --git a/src/Resources/src/components/costs/CashPaymentPanel.vue b/src/Resources/src/components/costs/CashPaymentPanel.vue index 0d85c8a42..7ea14fba3 100644 --- a/src/Resources/src/components/costs/CashPaymentPanel.vue +++ b/src/Resources/src/components/costs/CashPaymentPanel.vue @@ -32,10 +32,13 @@ const props = defineProps<{ username: string; }>(); +const emit = defineEmits(['closePanel']); + async function onSubmit() { const parsedAmount = parseFloat(amount.value); if (parsedAmount > 0) { await sendCashPayment(props.username, parsedAmount); } + emit('closePanel'); } diff --git a/src/Resources/src/components/menu/EventInput.vue b/src/Resources/src/components/menu/EventInput.vue index 50918aa44..89062cd55 100644 --- a/src/Resources/src/components/menu/EventInput.vue +++ b/src/Resources/src/components/menu/EventInput.vue @@ -57,7 +57,7 @@ :value="event" >
  • diff --git a/src/Resources/src/components/menu/MenuParticipationPanel.vue b/src/Resources/src/components/menu/MenuParticipationPanel.vue index e733dae6d..9f407db05 100644 --- a/src/Resources/src/components/menu/MenuParticipationPanel.vue +++ b/src/Resources/src/components/menu/MenuParticipationPanel.vue @@ -6,7 +6,7 @@ ; - close: () => void; + meals: Dictionary }>(); +const emit = defineEmits(['closePanel']); + const mealList = computed(() => { const keys = Object.keys(props.meals); return [...props.meals[keys[0]], ...props.meals[keys[1]]]; From 57b5aa23baa9f4af018e13c4e39d84a13103c500 Mon Sep 17 00:00:00 2001 From: MalibusParty <76796838+MalibusParty@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:20:08 +0100 Subject: [PATCH 09/20] #262687: fixed distance to edge for lockdate picker and participation limit picker popups --- src/Resources/src/components/menu/MenuDay.vue | 2 +- src/Resources/src/components/menu/MenuLockDatePicker.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Resources/src/components/menu/MenuDay.vue b/src/Resources/src/components/menu/MenuDay.vue index 0fde7b243..abcce38f1 100644 --- a/src/Resources/src/components/menu/MenuDay.vue +++ b/src/Resources/src/components/menu/MenuDay.vue @@ -6,7 +6,7 @@ class="col-start-1 row-span-3 row-start-1 grid w-[24px] grid-rows-[24px_minmax(0,1fr)_24px] justify-center rounded-l-lg bg-[#1c5298] py-1" >