Skip to content

Commit 82b5491

Browse files
committed
Add ability to add notes to attendees
1 parent 8041231 commit 82b5491

File tree

21 files changed

+298
-258
lines changed

21 files changed

+298
-258
lines changed

backend/app/DomainObjects/Generated/AttendeeDomainObjectAbstract.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ abstract class AttendeeDomainObjectAbstract extends \HiEvents\DomainObjects\Abst
2828
final public const UPDATED_AT = 'updated_at';
2929
final public const DELETED_AT = 'deleted_at';
3030
final public const LOCALE = 'locale';
31+
final public const NOTES = 'notes';
3132

3233
protected int $id;
3334
protected int $order_id;
@@ -47,6 +48,7 @@ abstract class AttendeeDomainObjectAbstract extends \HiEvents\DomainObjects\Abst
4748
protected string $updated_at;
4849
protected ?string $deleted_at = null;
4950
protected string $locale = 'en';
51+
protected ?string $notes = null;
5052

5153
public function toArray(): array
5254
{
@@ -69,6 +71,7 @@ public function toArray(): array
6971
'updated_at' => $this->updated_at ?? null,
7072
'deleted_at' => $this->deleted_at ?? null,
7173
'locale' => $this->locale ?? null,
74+
'notes' => $this->notes ?? null,
7275
];
7376
}
7477

@@ -269,4 +272,15 @@ public function getLocale(): string
269272
{
270273
return $this->locale;
271274
}
275+
276+
public function setNotes(?string $notes): self
277+
{
278+
$this->notes = $notes;
279+
return $this;
280+
}
281+
282+
public function getNotes(): ?string
283+
{
284+
return $this->notes;
285+
}
272286
}

backend/app/Http/Actions/Attendees/EditAttendeeAction.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function __invoke(EditAttendeeRequest $request, int $eventId, int $attend
3737
'product_price_id' => $request->input('product_price_id'),
3838
'event_id' => $eventId,
3939
'attendee_id' => $attendeeId,
40+
'notes' => $request->input('notes'),
4041
]));
4142
} catch (NoTicketsAvailableException $exception) {
4243
throw ValidationException::withMessages([

backend/app/Http/Request/Attendee/EditAttendeeRequest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public function rules(): array
1515
'last_name' => RulesHelper::REQUIRED_STRING,
1616
'product_id' => RulesHelper::REQUIRED_NUMERIC,
1717
'product_price_id' => RulesHelper::REQUIRED_NUMERIC,
18+
'notes' => RulesHelper::OPTIONAL_TEXT_MEDIUM_LENGTH,
1819
];
1920
}
2021

@@ -29,6 +30,7 @@ public function messages(): array
2930
'product_price_id.required' => __('Product price is required'),
3031
'product_id.numeric' => '',
3132
'product_price_id.numeric' => '',
33+
'notes.max' => __('Notes must be less than 2000 characters'),
3234
];
3335
}
3436
}

backend/app/Http/Request/ProductCategory/UpsertProductCategoryRequest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public function rules(): array
1212
'name' => ['string', 'required', 'max:50'],
1313
'description' => ['string', 'max:255', 'nullable'],
1414
'is_hidden' => ['boolean', 'required'],
15-
'no_products_message' => ['string', 'max:255', 'required'],
15+
'no_products_message' => ['string', 'max:255', 'nullable'],
1616
];
1717
}
1818
}

backend/app/Resources/Attendee/AttendeeResource.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public function toArray(Request $request): array
3030
'public_id' => $this->getPublicId(),
3131
'short_id' => $this->getShortId(),
3232
'locale' => $this->getLocale(),
33+
'notes' => $this->getNotes(),
3334
'product' => $this->when(
3435
!is_null($this->getProduct()),
3536
fn() => new ProductResource($this->getProduct()),

backend/app/Services/Application/Handlers/Attendee/DTO/EditAttendeeDTO.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
class EditAttendeeDTO extends BaseDTO
88
{
99
public function __construct(
10-
public string $first_name,
11-
public string $last_name,
12-
public string $email,
13-
public int $product_id,
14-
public int $product_price_id,
15-
public int $event_id,
16-
public int $attendee_id,
10+
public string $first_name,
11+
public string $last_name,
12+
public string $email,
13+
public int $product_id,
14+
public int $product_price_id,
15+
public int $event_id,
16+
public int $attendee_id,
17+
public ?string $notes = null,
1718
)
1819
{
1920
}

backend/app/Services/Application/Handlers/Attendee/EditAttendeeHandler.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use HiEvents\DomainObjects\Enums\ProductPriceType;
77
use HiEvents\DomainObjects\Generated\AttendeeDomainObjectAbstract;
88
use HiEvents\DomainObjects\Generated\ProductDomainObjectAbstract;
9+
use HiEvents\DomainObjects\ProductDomainObject;
910
use HiEvents\DomainObjects\ProductPriceDomainObject;
1011
use HiEvents\Exceptions\NoTicketsAvailableException;
1112
use HiEvents\Repository\Interfaces\AttendeeRepositoryInterface;
@@ -59,6 +60,7 @@ private function updateAttendee(EditAttendeeDTO $editAttendeeDTO): AttendeeDomai
5960
'last_name' => $editAttendeeDTO->last_name,
6061
'email' => $editAttendeeDTO->email,
6162
'product_id' => $editAttendeeDTO->product_id,
63+
'notes' => $editAttendeeDTO->notes,
6264
], [
6365
'event_id' => $editAttendeeDTO->event_id,
6466
]);
@@ -70,6 +72,7 @@ private function updateAttendee(EditAttendeeDTO $editAttendeeDTO): AttendeeDomai
7072
*/
7173
private function validateProductId(EditAttendeeDTO $editAttendeeDTO): void
7274
{
75+
/** @var ProductDomainObject $product */
7376
$product = $this->productRepository
7477
->loadRelation(ProductPriceDomainObject::class)
7578
->findFirstWhere([

backend/app/Services/Application/Handlers/ProductCategory/CreateProductCategoryHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public function handle(UpsertProductCategoryDTO $dto): ProductCategoryDomainObje
2121
isHidden: $dto->is_hidden,
2222
eventId: $dto->event_id,
2323
description: $dto->description,
24-
noProductsMessage: $dto->no_products_message,
24+
noProductsMessage: $dto->no_products_message ?? __('There are no products available in this category'),
2525
);
2626
}
2727
}

backend/app/Services/Application/Handlers/ProductCategory/EditProductCategoryHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public function handle(UpsertProductCategoryDTO $dto): ProductCategoryDomainObje
2121
'name' => $dto->name,
2222
'is_hidden' => $dto->is_hidden,
2323
'description' => $dto->description,
24-
'no_products_message' => $dto->no_products_message,
24+
'no_products_message' => $dto->no_products_message ?? __('There are no products available in this category'),
2525
],
2626
where: [
2727
'id' => $dto->product_category_id,

backend/app/Validators/Rules/RulesHelper.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ class RulesHelper
1616

1717
public const REQUIRED_EMAIL = ['email' , 'required', 'max:100'];
1818

19+
public const OPTIONAL_TEXT_MEDIUM_LENGTH = ['string', 'max:2000', 'nullable'];
1920
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration {
8+
public function up(): void
9+
{
10+
Schema::table('attendees', static function (Blueprint $table) {
11+
$table->text('notes')->nullable();
12+
});
13+
}
14+
15+
public function down(): void
16+
{
17+
Schema::table('attendees', static function (Blueprint $table) {
18+
$table->dropColumn('notes');
19+
});
20+
}
21+
};

frontend/src/api/attendee.client.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface EditAttendeeRequest {
88
first_name: string;
99
last_name: string;
1010
email: string;
11+
notes?: string;
1112
product_id?: IdParam;
1213
product_price_id?: IdParam;
1314
status?: string;

frontend/src/components/common/AttendeeDetails/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {getLocaleName, SupportedLocales} from "../../../locales.ts";
77

88
export const AttendeeDetails = ({attendee}: { attendee: Attendee }) => {
99
return (
10-
<div className={classes.orderDetails} variant={'lightGray'}>
10+
<div className={classes.orderDetails}>
1111
<div className={classes.block}>
1212
<div className={classes.title}>
1313
{t`Name`}
@@ -29,7 +29,7 @@ export const AttendeeDetails = ({attendee}: { attendee: Attendee }) => {
2929
{t`Status`}
3030
</div>
3131
<div className={classes.amount}>
32-
{attendee.status}
32+
{attendee.status === 'ACTIVE' ? <span style={{color: '#0d7553'}}>{t`Active`}</span> : <span style={{color: '#EF4444'}}>{t`Canceled`}</span>}
3333
</div>
3434
</div>
3535
<div className={classes.block}>

frontend/src/components/common/AttendeeTable/index.tsx

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import {Anchor, Avatar, Badge, Button, Table as MantineTable,} from '@mantine/core';
22
import {Attendee, MessageType} from "../../../types.ts";
3-
import {IconEye, IconMailForward, IconPencil, IconPlus, IconSend, IconTrash} from "@tabler/icons-react";
3+
import {IconMailForward, IconPlus, IconSend, IconTrash, IconUserCog} from "@tabler/icons-react";
44
import {getInitials, getProductFromEvent} from "../../../utilites/helpers.ts";
55
import {Table, TableHead} from "../Table";
66
import {useDisclosure} from "@mantine/hooks";
77
import {SendMessageModal} from "../../modals/SendMessageModal";
88
import {useState} from "react";
99
import {NoResultsSplash} from "../NoResultsSplash";
1010
import {useParams} from "react-router-dom";
11-
import {EditAttendeeModal} from "../../modals/EditAttendeeModal";
1211
import {useGetEvent} from "../../../queries/useGetEvent.ts";
1312
import Truncate from "../Truncate";
1413
import {notifications} from "@mantine/notifications";
@@ -17,7 +16,7 @@ import {showError, showSuccess} from "../../../utilites/notifications.tsx";
1716
import {t, Trans} from "@lingui/macro";
1817
import {confirmationDialog} from "../../../utilites/confirmationDialog.tsx";
1918
import {useResendAttendeeTicket} from "../../../mutations/useResendAttendeeTicket.ts";
20-
import {ViewAttendeeModal} from "../../modals/ViewAttendeeModal";
19+
import {ManageAttendeeModal} from "../../modals/ManageAttendeeModal";
2120
import {ActionMenu} from '../ActionMenu';
2221

2322
interface AttendeeTableProps {
@@ -28,7 +27,6 @@ interface AttendeeTableProps {
2827
export const AttendeeTable = ({attendees, openCreateModal}: AttendeeTableProps) => {
2928
const {eventId} = useParams();
3029
const [isMessageModalOpen, messageModal] = useDisclosure(false);
31-
const [isEditModalOpen, editModal] = useDisclosure(false);
3230
const [isViewModalOpem, viewModalOpen] = useDisclosure(false);
3331
const [selectedAttendee, setSelectedAttendee] = useState<Attendee>();
3432
const {data: event} = useGetEvent(eventId);
@@ -161,20 +159,15 @@ export const AttendeeTable = ({attendees, openCreateModal}: AttendeeTableProps)
161159
label: t`Actions`,
162160
items: [
163161
{
164-
label: t`View attendee`,
165-
icon: <IconEye size={14}/>,
162+
label: t`Manage attendee`,
163+
icon: <IconUserCog size={14}/>,
166164
onClick: () => handleModalClick(attendee, viewModalOpen),
167165
},
168166
{
169167
label: t`Message attendee`,
170168
icon: <IconSend size={14}/>,
171169
onClick: () => handleModalClick(attendee, messageModal),
172170
},
173-
{
174-
label: t`Edit attendee`,
175-
icon: <IconPencil size={14}/>,
176-
onClick: () => handleModalClick(attendee, editModal),
177-
},
178171
{
179172
label: t`Resend ticket email`,
180173
icon: <IconMailForward size={14}/>,
@@ -207,12 +200,7 @@ export const AttendeeTable = ({attendees, openCreateModal}: AttendeeTableProps)
207200
attendeeId={selectedAttendee.id}
208201
messageType={MessageType.Attendee}
209202
/>}
210-
{(selectedAttendee?.id && isEditModalOpen) && <EditAttendeeModal
211-
attendeeId={selectedAttendee.id}
212-
onClose={editModal.close}
213-
/>}
214-
215-
{(selectedAttendee?.id && isViewModalOpem) && <ViewAttendeeModal
203+
{(selectedAttendee?.id && isViewModalOpem) && <ManageAttendeeModal
216204
attendeeId={selectedAttendee.id}
217205
onClose={viewModalOpen.close}
218206
/>}

frontend/src/components/forms/ProductCategoryForm/index.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export const ProductCategoryForm = ({form}: ProductCategoryFormProps) => {
2121
<TextInput
2222
label={"No products message"}
2323
description={"A message to display when there are no products in this category."}
24-
required
2524
{...form.getInputProps("no_products_message")}
2625
/>
2726

frontend/src/components/modals/EditAttendeeModal/index.tsx

Lines changed: 0 additions & 115 deletions
This file was deleted.

0 commit comments

Comments
 (0)