Skip to content

Commit

Permalink
added endpoint to generate invite link and view to display the invite
Browse files Browse the repository at this point in the history
  • Loading branch information
Felix Ruf committed Jan 25, 2024
1 parent 9e4726a commit e80d7bf
Show file tree
Hide file tree
Showing 19 changed files with 226 additions and 55 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,6 @@ IDP_CLIENT_SECRET=client-secret
*EventParticipationController 8xx*
* 801: User has no permission to enter or leave
* 802: User could not join the event
* 803: User could not leave the event
* 803: User could not leave the event
*MealGuestController 9xx*
* 901: Could not find the Invitation for the given hash
2 changes: 1 addition & 1 deletion config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ security:
- { path: ^/api/guest-invitation, 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] }
- { path: '^/participation/slots-status/\d{4}-\d{2}-\d{2}$', roles: [IS_AUTHENTICATED_ANONYMOUSLY] }
- { path: '^/participation/count-status/\d{4}-\d{2}-\d{2}$', roles: [IS_AUTHENTICATED_ANONYMOUSLY] }
- { path: ^/language-switch, roles: [IS_AUTHENTICATED_ANONYMOUSLY] }
- { path: ^/css, roles: [IS_AUTHENTICATED_ANONYMOUSLY] }
- { path: ^/js, roles: [IS_AUTHENTICATED_ANONYMOUSLY] }
- { path: ^/images, roles: [IS_AUTHENTICATED_ANONYMOUSLY] }
Expand Down
26 changes: 0 additions & 26 deletions src/Mealz/MealBundle/Controller/LanguageController.php

This file was deleted.

50 changes: 42 additions & 8 deletions src/Mealz/MealBundle/Controller/MealGuestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Mealz\MealBundle\Controller;

use App\Mealz\MealBundle\Entity\Day;
use App\Mealz\MealBundle\Entity\GuestInvitation;
use App\Mealz\MealBundle\Entity\Participant;
use App\Mealz\MealBundle\Event\ParticipationUpdateEvent;
use App\Mealz\MealBundle\Event\SlotAllocationUpdateEvent;
Expand Down Expand Up @@ -62,14 +63,38 @@ public function newGuestInvitation(
): JsonResponse {
$guestInvitation = $guestInvitationRepo->findOrCreateInvitation($this->getUser()->getProfile(), $mealDay);

return new JsonResponse(
[
'url' => $this->generateUrl(
'MealzMealBundle_Meal_guest',
['hash' => $guestInvitation->getId()],
UrlGeneratorInterface::ABSOLUTE_URL),
], 200
);
return new JsonResponse(['url' => $this->generateInvitationUrl($guestInvitation),], 200);
}

/**
* @Security("is_granted('ROLE_USER')")
*/
public function newGuestEventInvitation(
Day $dayId,
GuestInvitationRepositoryInterface $guestInvitationRepo
): JsonResponse {
$eventInvitation = $guestInvitationRepo->findOrCreateInvitation($this->getUser()->getProfile(), $dayId);

return new JsonResponse(['url' => $this->generateInvitationUrl($eventInvitation, false),], 200);
}

public function getEventInvitationData(
string $invitationId,
GuestInvitationRepositoryInterface $guestInvitationRepo
): JsonResponse {
/** @var GuestInvitation $invitation */
$invitation = $guestInvitationRepo->find($invitationId);
if (null === $invitation) {
return new JsonResponse(['message' => '901: Could not find invitation for the given hash', 403]);
}

$guestData = [
'date' => $invitation->getDay()->getDateTime(),
'lockDate' => $invitation->getDay()->getLockParticipationDateTime(),
'event' => $invitation->getDay()->getEvent()->getEvent()->getTitle(),
];

return new JsonResponse($guestData, 200);
}

/**
Expand All @@ -91,4 +116,13 @@ private function triggerJoinEvents(array $participants): void
$this->eventDispatcher->dispatch(new SlotAllocationUpdateEvent($participant->getMeal()->getDay(), $slot));
}
}

private function generateInvitationUrl(GuestInvitation $invitation, bool $isMeal = true): string
{
return $this->generateUrl(
true === $isMeal ? 'MealzMealBundle_Meal_guest' : 'MealzMealBundle_Meal_guest_event',
['hash' => $invitation->getId()],
UrlGeneratorInterface::ABSOLUTE_URL
);
}
}
20 changes: 16 additions & 4 deletions src/Mealz/MealBundle/Resources/config/routing.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
MealzMealBundle_language_switch:
path: /language-switch
defaults: { _controller: App\Mealz\MealBundle\Controller\LanguageController::switch }

MealzMealBundle_api_dashboard:
path: /api/dashboard
defaults: { _controller: App\Mealz\MealBundle\Controller\ApiController::getDashboardData }
Expand Down Expand Up @@ -87,6 +83,11 @@ MealzMealBundle_Meal_guest:
defaults: { _controller: App\Mealz\MealBundle\Controller\FrontendController::renderIndex }
methods: [ GET, POST ]

MealzMealBundle_Meal_guest_event:
path: /guest/event/{hash}
defaults: { _controller: App\Mealz\MealBundle\Controller\FrontendController::renderIndex }
methods: [ GET, POST ]

MealzMealBundle_balance:
path: /balance
defaults: { _controller: App\Mealz\MealBundle\Controller\FrontendController::renderIndex }
Expand Down Expand Up @@ -167,6 +168,11 @@ MealzMealBundle_api_invitationdata:
defaults: { _controller: App\Mealz\MealBundle\Controller\ApiController::getGuestData }
methods: [ GET ]

MealzMealBundle_api_event_invitation_data:
path: /api/event/invitation/{invitationId}
defaults: { _controller: App\Mealz\MealBundle\Controller\MealGuestController::getEventInvitationData }
methods: [ GET ]

MealzMealBundle_api_events:
path: /api/events
defaults: { _controller: App\Mealz\MealBundle\Controller\EventController::getEventList }
Expand Down Expand Up @@ -197,6 +203,12 @@ MealzMealBundle_api_events_leave:
defaults: { _controller: App\Mealz\MealBundle\Controller\EventController::leave }
methods: [ DELETE ]

MealzMealBundle_Meal_api_guest_event_invitation:
path: /event/invitation/{dayId}
defaults: { _controller: App\Mealz\MealBundle\Controller\MealGuestController::newGuestEventInvitation }
requirements:
dayId: '[1-9][0-9]*'

MealzMealBundle_Meal_offers:
path: /menu/{date}/{dish}/offers
defaults: { _controller: App\Mealz\MealBundle\Controller\MealController::getOffers }
Expand Down
1 change: 1 addition & 0 deletions src/Mealz/MealBundle/Service/EventParticipationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public function getEventParticipationData(Day $day, Profile $profile = null): ?a
'eventId' => $eventParticipation->getEvent()->getId(),
'participationId' => $eventParticipation->getId(),
'participations' => count($eventParticipation->getParticipants()),
'isPublic' => $eventParticipation->getEvent()->isPublic()
];

if (null !== $profile) {
Expand Down
3 changes: 2 additions & 1 deletion src/Resources/src/api/getDashboardData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ export type EventParticipation = {
eventId: number,
participationId: number,
participations: number,
isParticipating: boolean
isParticipating: boolean,
isPublic: boolean
}

export type Day = {
Expand Down
13 changes: 13 additions & 0 deletions src/Resources/src/api/getEventGuestLink.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import useApi from "./api";
import { Link } from "./getGuestLink";

export default async function getEventGuestLink(dayId: string) {
const { error, response: link, request } = useApi<Link>(
'GET',
`/event/invitation/${dayId}`
);

await request();

return { link, error };
}
19 changes: 19 additions & 0 deletions src/Resources/src/api/getEventInvitionData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { IMessage } from "@/interfaces/IMessage";
import useApi from "./api";

export interface EventInvitationData {
date: string,
lockDate: string,
event: string
}

export default async function getEventInvitationData(invitationHash: string) {
const { error, request, response } = useApi<EventInvitationData | IMessage>(
'GET',
`/api/event/invitation/${invitationHash}`
);

await request();

return { error, response };
}
2 changes: 1 addition & 1 deletion src/Resources/src/api/getGuestLink.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import useApi from '@/api/api';
import { ref } from 'vue';

type Link = {
export type Link = {
url: string
}

Expand Down
8 changes: 6 additions & 2 deletions src/Resources/src/components/dashboard/Day.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
v-if="!day.isLocked && !emptyDay && !guestData && day.isEnabled"
:dayID="dayID"
:index="index"
:invitation="Invitation.MEAL"
:icon-white="true"
class="row-start-2 w-[24px] pl-[3px] text-center"
/>
</div>
Expand All @@ -38,7 +40,7 @@
v-for="(meal, mealID) in day.meals"
:key="mealID"
class="mx-[15px] border-b-[0.7px] last:border-b-0"
:class="isEventDay ? 'pt-[13px] pb-[13px] last:pb-0 last:pt-[21px]' : 'py-[13px]'"
:class="isEventDay && !guestData ? 'pt-[13px] pb-[13px] last:pb-0 last:pt-[21px]' : 'py-[13px]'"
>
<VariationsData
v-if="meal.variations"
Expand Down Expand Up @@ -68,9 +70,10 @@
</span>
</div>
<EventData
v-if="isEventDay"
v-if="isEventDay && !guestData"
class="col-start-2 row-start-2"
:day="day"
:dayId="dayID"
/>
</div>
</template>
Expand All @@ -86,6 +89,7 @@ import GuestButton from '@/components/dashboard/GuestButton.vue';
import { translateWeekday } from 'tools/localeHelper';
import { GuestDay } from '@/api/getInvitationData';
import EventData from './EventData.vue';
import { Invitation } from '@/enums/Invitation';
const { t, locale } = useI18n()
Expand Down
13 changes: 12 additions & 1 deletion src/Resources/src/components/dashboard/EventData.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
<span class="mr-[5px] inline-block grow self-center break-words text-[12px] font-bold leading-[20px] tracking-[0.5px] text-primary-1 min-[380px]:text-note">
{{ getEventById(day.event.eventId)?.title }}
</span>
<GuestButton
v-if="!day.isLocked && day.event.isPublic"
:dayID="dayId"
:index="0"
:invitation="Invitation.EVENT"
:icon-white="false"
class="w-[24px] text-center"
/>
<EventPopup
class="justify-self-end"
:event-title="getEventById(day.event.eventId)?.title"
Expand Down Expand Up @@ -55,9 +63,12 @@ import EventIcon from '../misc/EventIcon.vue';
import BannerSpacer from '../misc/BannerSpacer.vue';
import { useI18n } from 'vue-i18n';
import EventPopup from '@/components/eventParticipation/EventPopup.vue';
import GuestButton from './GuestButton.vue';
import { Invitation } from '@/enums/Invitation';
defineProps<{
day: Day
day: Day,
dayId: string
}>();
const { t } = useI18n();
Expand Down
13 changes: 10 additions & 3 deletions src/Resources/src/components/dashboard/GuestButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
<Icons
icon="guest"
box="0 0 13 13"
class="h-[13px] w-[13px] fill-white"
class="h-[13px] w-[13px]"
:class="iconWhite ? 'fill-white' : 'fill-[#1c5298]'"
/>
</PopoverButton>

<PopoverPanel :class="[index === 4 ? '-top-12' : 'top-12' , 'absolute -left-6 z-[2]']">
<GuestLink :dayID="String(dayID)" />
<GuestLink
:dayID="String(dayID)"
:invitation="invitation"
/>
</PopoverPanel>
</Popover>
</template>
Expand All @@ -18,9 +22,12 @@
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue';
import Icons from '@/components/misc/Icons.vue';
import GuestLink from '@/components/dashboard/GuestLink.vue';
import { Invitation } from '@/enums/Invitation';
defineProps<{
dayID: number | string,
index: number
index: number,
invitation: Invitation,
iconWhite: boolean
}>();
</script>
7 changes: 5 additions & 2 deletions src/Resources/src/components/dashboard/GuestLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,22 @@

<script setup lang="ts">
import {useGuestLink} from '@/api/getGuestLink';
import getEventGuestLink from '@/api/getEventGuestLink';
import {useI18n} from 'vue-i18n';
import { CheckIcon } from '@heroicons/vue/solid';
import { onMounted, ref } from 'vue';
import { Invitation } from '@/enums/Invitation';
const props = defineProps<{
dayID: string
dayID: string,
invitation: Invitation
}>();
const { t } = useI18n()
const url = ref('');
onMounted(async () => {
const { link, error } = await useGuestLink(props.dayID)
const { link, error } = props.invitation === Invitation.MEAL ? await useGuestLink(props.dayID) : await getEventGuestLink(props.dayID)
if (error.value === false) {
copyTextToClipboard(link.value.url)
url.value = link.value.url
Expand Down
4 changes: 4 additions & 0 deletions src/Resources/src/enums/Invitation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum Invitation {
MEAL = 'Meal',
EVENT = 'Event'
}
9 changes: 7 additions & 2 deletions src/Resources/src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@
"events": {
"created": "Das Event wurde erfolgreich erstellt.",
"deleted": "Das Event wurde erfolgreich gelöscht.",
"updated": "Das Event wurde erfolgreich bearbeitet."
"edited": "Das Event wurde erfolgreich bearbeitet."
},
"finance": {
"empty": "Es gibt keine Transaktionen im ausgewählten Zeitraum"
Expand Down Expand Up @@ -229,7 +229,12 @@
"resolve_success": "Essensbuchung erfolgreich!",
"resolve_error": "Fehler bei der Essensbuchung.",
"title": "Mittagessen bei AOE",
"description": "Als Gast in unserem Haus laden wir Sie gerne zu einem Mittagessen in der AOE Eatery ein. Für Ihre Bestellung tragen Sie sich bitte bis spätestens einen Tag vorher mit Ihren Daten ein und wählen das gewünschte Gericht aus, das dann an unsere Köche weitergeleitet wird.\n\nGuten Appetit wünscht Ihnen,\nAOE"
"description": "Als Gast in unserem Haus laden wir Sie gerne zu einem Mittagessen in der AOE Eatery ein. Für Ihre Bestellung tragen Sie sich bitte bis spätestens einen Tag vorher mit Ihren Daten ein und wählen das gewünschte Gericht aus, das dann an unsere Köche weitergeleitet wird.\n\nGuten Appetit wünscht Ihnen,\nAOE",
"event": {
"submit": "An Event teilnehmen",
"title": "Event bei AOE",
"description": "Hiermit laden wir Sie zu dem Event \"%EventTitle%\" bei uns ein."
}
},
"header": {
"navigation": {
Expand Down
Loading

0 comments on commit e80d7bf

Please sign in to comment.