Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions backend/app/Exports/AttendeesExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
namespace HiEvents\Exports;

use Carbon\Carbon;
use HiEvents\DomainObjects\AttendeeDomainObject;
use HiEvents\DomainObjects\Enums\QuestionTypeEnum;
use HiEvents\DomainObjects\Enums\TicketType;
use HiEvents\DomainObjects\QuestionDomainObject;
use HiEvents\DomainObjects\TicketDomainObject;
use HiEvents\DomainObjects\TicketPriceDomainObject;
use HiEvents\Resources\Attendee\AttendeeResource;
use HiEvents\Services\Domain\Question\QuestionAnswerFormatter;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
Expand Down Expand Up @@ -50,6 +54,7 @@ public function headings(): array
'Is Checked In',
'Checked In At',
'Ticket ID',
'Ticket Name',
'Event ID',
'Public ID',
'Short ID',
Expand All @@ -58,6 +63,10 @@ public function headings(): array
], $questionTitles);
}

/**
* @param AttendeeDomainObject $attendee
* @return array
*/
public function map($attendee): array
{
$answers = $this->questions->map(function (QuestionDomainObject $question) use ($attendee) {
Expand All @@ -70,17 +79,28 @@ public function map($attendee): array
);
});

/** @var TicketDomainObject $ticket */
$ticket = $attendee->getTicket();
$ticketName = $ticket->getTitle();
if ($attendee->getTicket()?->getType() === TicketType::TIERED->name) {
$ticketName .= ' - ' . $ticket
->getTicketPrices()
->first(fn(TicketPriceDomainObject $tp) => $tp->getId() === $attendee->getTicketPriceId())
->getLabel();
}

return array_merge([
$attendee->getId(),
$attendee->getFirstName(),
$attendee->getLastName(),
$attendee->getEmail(),
$attendee->getStatus(),
$attendee->getCheckedInAt() ? 'Yes' : 'No',
$attendee->getCheckedInAt()
? Carbon::parse($attendee->getCheckedInAt())->format('Y-m-d H:i:s')
$attendee->getCheckIn() ? 'Yes' : 'No',
$attendee->getCheckIn()
? Carbon::parse($attendee->getCheckIn()->getCreatedAt())->format('Y-m-d H:i:s')
: '',
$attendee->getTicketId(),
$ticketName,
$attendee->getEventId(),
$attendee->getPublicId(),
$attendee->getShortId(),
Expand Down
17 changes: 17 additions & 0 deletions backend/app/Http/Actions/Attendees/ExportAttendeesAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

namespace HiEvents\Http\Actions\Attendees;

use HiEvents\DomainObjects\AttendeeCheckInDomainObject;
use HiEvents\DomainObjects\Enums\QuestionBelongsTo;
use HiEvents\DomainObjects\EventDomainObject;
use HiEvents\DomainObjects\QuestionAndAnswerViewDomainObject;
use HiEvents\DomainObjects\TicketDomainObject;
use HiEvents\DomainObjects\TicketPriceDomainObject;
use HiEvents\Exports\AttendeesExport;
use HiEvents\Http\Actions\BaseAction;
use HiEvents\Repository\Eloquent\Value\Relationship;
use HiEvents\Repository\Interfaces\AttendeeRepositoryInterface;
use HiEvents\Repository\Interfaces\QuestionRepositoryInterface;
use Maatwebsite\Excel\Facades\Excel;
Expand All @@ -31,6 +35,19 @@ public function __invoke(int $eventId): BinaryFileResponse

$attendees = $this->attendeeRepository
->loadRelation(QuestionAndAnswerViewDomainObject::class)
->loadRelation(new Relationship(
domainObject: AttendeeCheckInDomainObject::class,
name: 'check_in',
))
->loadRelation(new Relationship(
domainObject: TicketDomainObject::class,
nested: [
new Relationship(
domainObject: TicketPriceDomainObject::class,
),
],
name: 'ticket'
))
->findByEventIdForExport($eventId);

$questions = $this->questionRepository->findWhere([
Expand Down
7 changes: 6 additions & 1 deletion backend/app/Http/Actions/Attendees/GetAttendeeAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace HiEvents\Http\Actions\Attendees;

use HiEvents\DomainObjects\AttendeeCheckInDomainObject;
use HiEvents\DomainObjects\EventDomainObject;
use HiEvents\DomainObjects\QuestionAndAnswerViewDomainObject;
use HiEvents\DomainObjects\TicketDomainObject;
Expand All @@ -27,14 +28,18 @@ public function __invoke(int $eventId, int $attendeeId): Response|JsonResponse
$this->isActionAuthorized($eventId, EventDomainObject::class);

$attendee = $this->attendeeRepository
->loadRelation(QuestionAndAnswerViewDomainObject::class)
->loadRelation(relationship: QuestionAndAnswerViewDomainObject::class)
->loadRelation(new Relationship(
domainObject: TicketDomainObject::class,
nested: [
new Relationship(
domainObject: TicketPriceDomainObject::class,
),
], name: 'ticket'))
->loadRelation(new Relationship(
domainObject: AttendeeCheckInDomainObject::class,
name: 'check_in',
))
->findFirstWhere([
'id' => $attendeeId,
'event_id' => $eventId,
Expand Down
1 change: 1 addition & 0 deletions backend/app/Repository/Eloquent/CheckInListRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public function getCheckedInAttendeeCountById(int $checkInListId): CheckedInAtte
JOIN ticket_check_in_lists tcil ON a.ticket_id = tcil.ticket_id
WHERE a.deleted_at IS NULL
AND tcil.deleted_at IS NULL
AND a.status = 'ACTIVE'
)
SELECT
cil.id AS check_in_list_id,
Expand Down
17 changes: 11 additions & 6 deletions backend/app/Resources/Attendee/AttendeeResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use HiEvents\DomainObjects\AttendeeDomainObject;
use HiEvents\DomainObjects\Enums\QuestionBelongsTo;
use HiEvents\Resources\CheckInList\AttendeeCheckInResource;
use HiEvents\Resources\Order\OrderResource;
use HiEvents\Resources\Question\QuestionAnswerViewResource;
use HiEvents\Resources\Ticket\TicketResource;
Expand All @@ -30,17 +31,21 @@ public function toArray(Request $request): array
'public_id' => $this->getPublicId(),
'short_id' => $this->getShortId(),
'locale' => $this->getLocale(),
'check_in' => $this->when(
condition: $this->getCheckIn() !== null,
value: fn() => new AttendeeCheckInResource($this->getCheckIn()),
),
'ticket' => $this->when(
!is_null($this->getTicket()),
fn() => new TicketResource($this->getTicket()),
condition: !is_null($this->getTicket()),
value: fn() => new TicketResource($this->getTicket()),
),
'order' => $this->when(
!is_null($this->getOrder()),
fn() => new OrderResource($this->getOrder())
condition: !is_null($this->getOrder()),
value: fn() => new OrderResource($this->getOrder())
),
'question_answers' => $this->when(
$this->getQuestionAndAnswerViews() !== null,
fn() => QuestionAnswerViewResource::collection(
condition: $this->getQuestionAndAnswerViews() !== null,
value: fn() => QuestionAnswerViewResource::collection(
$this->getQuestionAndAnswerViews()
?->filter(fn($qav) => $qav->getBelongsTo() === QuestionBelongsTo::TICKET->name)
)
Expand Down
25 changes: 25 additions & 0 deletions backend/app/Resources/CheckInList/AttendeeCheckInResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace HiEvents\Resources\CheckInList;

use HiEvents\DomainObjects\AttendeeCheckInDomainObject;
use Illuminate\Http\Resources\Json\JsonResource;

/**
* @mixin AttendeeCheckInDomainObject
*/
class AttendeeCheckInResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->getId(),
'attendee_id' => $this->getAttendeeId(),
'check_in_list_id' => $this->getCheckInListId(),
'ticket_id' => $this->getTicketId(),
'event_id' => $this->getEventId(),
'short_id' => $this->getShortId(),
'created_at' => $this->getCreatedAt(),
];
}
}
7 changes: 3 additions & 4 deletions frontend/src/api/check-in.client.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import {publicApi} from "./public-client";
import {
Attendee,
CheckIn,
CheckInList,
GenericDataResponse,
GenericPaginatedResponse,
IdParam,
IdParam, PublicCheckIn,
QueryFilters,
} from "../types";
import {queryParamsHelper} from "../utilites/queryParamsHelper";
Expand All @@ -20,13 +19,13 @@ export const publicCheckInClient = {
return response.data;
},
createCheckIn: async (checkInListShortId: IdParam, attendeePublicId: IdParam) => {
const response = await publicApi.post<GenericDataResponse<CheckIn[]>>(`/check-in-lists/${checkInListShortId}/check-ins`, {
const response = await publicApi.post<GenericDataResponse<PublicCheckIn[]>>(`/check-in-lists/${checkInListShortId}/check-ins`, {
"attendee_public_ids": [attendeePublicId],
});
return response.data;
},
deleteCheckIn: async (checkInListShortId: IdParam, checkInShortId: IdParam) => {
const response = await publicApi.delete<GenericDataResponse<CheckIn>>(`/check-in-lists/${checkInListShortId}/check-ins/${checkInShortId}`);
const response = await publicApi.delete<GenericDataResponse<PublicCheckIn>>(`/check-in-lists/${checkInListShortId}/check-ins/${checkInShortId}`);
return response.data;
},
};
4 changes: 2 additions & 2 deletions frontend/src/components/common/AttendeeDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const AttendeeDetails = ({attendee}: { attendee: Attendee }) => {
{t`Checked In`}
</div>
<div className={classes.amount}>
{attendee.checked_in_at ? t`Yes` : t`No`}
{attendee.check_in ? t`Yes` : t`No`}
</div>
</div>
<div className={classes.block}>
Expand All @@ -59,4 +59,4 @@ export const AttendeeDetails = ({attendee}: { attendee: Attendee }) => {
</div>
</Card>
);
}
}
22 changes: 13 additions & 9 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,19 @@ export interface Attendee {
checked_in_by?: number;
question_answers?: QuestionAnswer[];
locale?: SupportedLocales;
check_in?: CheckIn;
check_in?: AttendeeCheckIn;
}

export type PublicCheckIn = Pick<AttendeeCheckIn, 'id' | 'attendee_id' | 'check_in_list_id' | 'ticket_id' | 'event_id'>;

export interface AttendeeCheckIn {
id: IdParam;
attendee_id: IdParam;
check_in_list_id: IdParam;
ticket_id: IdParam;
event_id: IdParam;
short_id: IdParam;
created_at: string;
}

export interface Address {
Expand Down Expand Up @@ -475,14 +487,6 @@ export type CheckInListRequest =
ticket_ids: IdParam[];
};

export interface CheckIn {
id: number;
short_id: string;
check_in_list_id: number;
attendee_id: number;
checked_in_at: string;
}

export interface QuestionRequestData {
title: string;
description?: string;
Expand Down
Loading