Compare commits

..

43 Commits

Author SHA1 Message Date
7e31629de6 Merge pull request 'Add a button to download a PDF file with all QR codes' (#306) from invitations-download-pdf into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 54s
Playwright Tests / test (push) Successful in 4m15s
Build Nginx-based docker image / build-static-assets (push) Successful in 4m54s
Reviewed-on: #306
2025-07-01 15:54:30 +00:00
b4ec903ce0 Add a button to download a PDF file with all QR codes
All checks were successful
Add copyright notice / copyright_notice (pull_request) Successful in 29s
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m34s
Build Nginx-based docker image / build-static-assets (push) Successful in 3m17s
Playwright Tests / test (pull_request) Successful in 4m18s
2025-07-01 17:49:49 +02:00
d390d6e055 Merge pull request 'Update dependency node to v24.3.0' (#300) from renovate/node-24.x into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 43s
Playwright Tests / test (push) Successful in 5m12s
Build Nginx-based docker image / build-static-assets (push) Successful in 6m31s
Reviewed-on: #300
2025-06-30 15:47:28 +00:00
Renovate Bot
f4e49d2594 Update dependency node to v24.3.0
All checks were successful
Add copyright notice / copyright_notice (pull_request) Successful in 8m31s
Check usage of free licenses / build-static-assets (pull_request) Successful in 2m20s
Build Nginx-based docker image / build-static-assets (push) Successful in 1h5m37s
Playwright Tests / test (pull_request) Successful in 58m48s
2025-06-30 02:06:50 +00:00
Renovate Bot
140650d682 Update dependency next-auth to v5.0.0-beta.29
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 4m11s
Playwright Tests / test (push) Successful in 19m33s
Check usage of free licenses / build-static-assets (pull_request) Successful in 3m7s
Add copyright notice / copyright_notice (pull_request) Successful in 7m32s
Build Nginx-based docker image / build-static-assets (push) Successful in 29m53s
Playwright Tests / test (pull_request) Successful in 18m56s
2025-06-29 02:04:57 +00:00
Renovate Bot
c239f81e8b Update dependency @atlaskit/pragmatic-drag-and-drop to v1.7.4
All checks were successful
Build Nginx-based docker image / build-static-assets (push) Successful in 38m37s
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m39s
Add copyright notice / copyright_notice (pull_request) Successful in 2m41s
Playwright Tests / test (pull_request) Successful in 20m17s
Check usage of free licenses / build-static-assets (push) Successful in 4m0s
Playwright Tests / test (push) Successful in 18m22s
2025-06-28 02:03:55 +00:00
1e52f68d16 Merge pull request 'Update dependency @tiptap/pm to v2.23.0' (#302) from renovate/tiptap-pm-2.x-lockfile into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 54s
Playwright Tests / test (push) Successful in 6m32s
Build Nginx-based docker image / build-static-assets (push) Successful in 8m56s
Reviewed-on: #302
2025-06-27 06:44:21 +00:00
Renovate Bot
7ee0502a66 Update dependency @tiptap/pm to v2.23.0
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m44s
Add copyright notice / copyright_notice (pull_request) Successful in 2m12s
Build Nginx-based docker image / build-static-assets (push) Successful in 46m44s
Playwright Tests / test (pull_request) Successful in 52m0s
2025-06-27 02:07:15 +00:00
Renovate Bot
f3af4ade2b Update pnpm to v10.12.3
Some checks failed
Playwright Tests / test (push) Failing after 50m53s
Build Nginx-based docker image / build-static-assets (push) Successful in 1h12m32s
Playwright Tests / test (pull_request) Successful in 28m38s
Check usage of free licenses / build-static-assets (push) Successful in 4m50s
Check usage of free licenses / build-static-assets (pull_request) Successful in 7m2s
Add copyright notice / copyright_notice (pull_request) Successful in 7m17s
2025-06-25 02:05:37 +00:00
Renovate Bot
0788f7c6e4 Update dependency @tiptap/react to v2.22.3
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 4m18s
Playwright Tests / test (push) Successful in 17m12s
Build Nginx-based docker image / build-static-assets (push) Successful in 18m55s
Add copyright notice / copyright_notice (pull_request) Successful in 2m28s
Check usage of free licenses / build-static-assets (pull_request) Successful in 3m9s
Playwright Tests / test (pull_request) Successful in 33m8s
2025-06-23 02:07:12 +00:00
203887da10 Merge pull request 'Update dependency zod to v3.25.67' (#289) from renovate/zod-3.x-lockfile into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 1m16s
Playwright Tests / test (push) Successful in 4m53s
Build Nginx-based docker image / build-static-assets (push) Successful in 5m28s
Reviewed-on: #289
2025-06-22 08:55:25 +00:00
fc7bb9729d Merge pull request 'Update dependency @tiptap/pm to v2.22.3' (#292) from renovate/tiptap-pm-2.x-lockfile into main
Some checks failed
Build Nginx-based docker image / build-static-assets (push) Has been cancelled
Check usage of free licenses / build-static-assets (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
Reviewed-on: #292
2025-06-22 08:55:19 +00:00
Renovate Bot
d354c15e64 Update dependency @tiptap/pm to v2.22.3
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m44s
Add copyright notice / copyright_notice (pull_request) Successful in 2m47s
Playwright Tests / test (pull_request) Successful in 39m17s
Build Nginx-based docker image / build-static-assets (push) Successful in 52m56s
2025-06-22 02:07:23 +00:00
Renovate Bot
79e4998e3c Update dependency zod to v3.25.67
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m34s
Add copyright notice / copyright_notice (pull_request) Successful in 2m49s
Build Nginx-based docker image / build-static-assets (push) Successful in 39m48s
Playwright Tests / test (pull_request) Successful in 40m34s
2025-06-22 02:07:11 +00:00
Renovate Bot
07e89b4717 Update dependency @atlaskit/pragmatic-drag-and-drop to v1.7.3
Some checks failed
Add copyright notice / copyright_notice (pull_request) Successful in 1m49s
Check usage of free licenses / build-static-assets (pull_request) Successful in 2m2s
Playwright Tests / test (pull_request) Successful in 39m15s
Check usage of free licenses / build-static-assets (push) Successful in 1m34s
Playwright Tests / test (push) Failing after 40m27s
Build Nginx-based docker image / build-static-assets (push) Successful in 58m2s
2025-06-21 02:06:39 +00:00
4c52444110 Merge pull request 'Update dependency @playwright/test to v1.53.1' (#290) from renovate/playwright-test-1.x-lockfile into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 1m32s
Playwright Tests / test (push) Successful in 6m25s
Build Nginx-based docker image / build-static-assets (push) Successful in 7m47s
Reviewed-on: #290
2025-06-20 09:12:56 +00:00
cb51fbddd7 Merge pull request 'Update dependency @tiptap/react to v2.14.1' (#293) from renovate/tiptap-react-2.x-lockfile into main
Some checks failed
Build Nginx-based docker image / build-static-assets (push) Has been cancelled
Check usage of free licenses / build-static-assets (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
Reviewed-on: #293
2025-06-20 09:12:46 +00:00
Renovate Bot
dcd61a0f38 Update dependency @tiptap/react to v2.14.1
All checks were successful
Add copyright notice / copyright_notice (pull_request) Successful in 1m16s
Check usage of free licenses / build-static-assets (pull_request) Successful in 2m32s
Build Nginx-based docker image / build-static-assets (push) Successful in 28m24s
Playwright Tests / test (pull_request) Successful in 35m45s
2025-06-20 02:06:59 +00:00
Renovate Bot
4e908ba62a Update dependency @playwright/test to v1.53.1
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m29s
Add copyright notice / copyright_notice (pull_request) Successful in 2m27s
Build Nginx-based docker image / build-static-assets (push) Successful in 27m52s
Playwright Tests / test (pull_request) Successful in 32m21s
2025-06-20 02:06:48 +00:00
b8ecc6de98 Merge pull request 'Update dependency next to v15.3.4' (#291) from renovate/next-15.x into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 56s
Playwright Tests / test (push) Successful in 7m16s
Build Nginx-based docker image / build-static-assets (push) Successful in 7m35s
Reviewed-on: #291
2025-06-19 06:59:27 +00:00
Renovate Bot
3338dcb604 Update dependency next to v15.3.4
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 2m30s
Add copyright notice / copyright_notice (pull_request) Successful in 4m31s
Playwright Tests / test (pull_request) Successful in 30m41s
Build Nginx-based docker image / build-static-assets (push) Successful in 36m59s
2025-06-19 02:07:50 +00:00
e09a6892cc Merge pull request 'Improve groups specs and add confirmation dialog to delete action' (#288) from groups-specs into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 39s
Playwright Tests / test (push) Successful in 4m16s
Build Nginx-based docker image / build-static-assets (push) Successful in 4m38s
Reviewed-on: #288
2025-06-17 18:45:56 +00:00
bcc86f2c3b Add specs when group is deleted (+ add confirmation dialog)
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m9s
Add copyright notice / copyright_notice (pull_request) Successful in 1m33s
Build Nginx-based docker image / build-static-assets (push) Successful in 3m29s
Playwright Tests / test (pull_request) Successful in 4m40s
2025-06-17 20:39:40 +02:00
1b957879d4 Add specs for group update operation 2025-06-17 20:35:50 +02:00
536f74cd7a Merge pull request 'Update dependency @types/node to v24.0.3' (#286) from renovate/node-24.x into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 1m7s
Playwright Tests / test (push) Successful in 6m48s
Build Nginx-based docker image / build-static-assets (push) Successful in 7m34s
Reviewed-on: #286
2025-06-17 17:15:54 +00:00
2399f6238c Merge pull request 'Update dependency postcss to v8.5.6' (#287) from renovate/postcss-8.x into main
Some checks failed
Check usage of free licenses / build-static-assets (push) Has been cancelled
Build Nginx-based docker image / build-static-assets (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
Reviewed-on: #287
2025-06-17 17:15:39 +00:00
Renovate Bot
5d2c43cfef Update dependency postcss to v8.5.6
All checks were successful
Add copyright notice / copyright_notice (pull_request) Successful in 6m3s
Check usage of free licenses / build-static-assets (pull_request) Successful in 3m24s
Build Nginx-based docker image / build-static-assets (push) Successful in 16m33s
Playwright Tests / test (pull_request) Successful in 11m1s
2025-06-17 02:04:30 +00:00
Renovate Bot
2055c95c82 Update dependency @types/node to v24.0.3
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 5m3s
Add copyright notice / copyright_notice (pull_request) Successful in 6m14s
Build Nginx-based docker image / build-static-assets (push) Successful in 16m45s
Playwright Tests / test (pull_request) Successful in 17m23s
2025-06-17 02:04:23 +00:00
71a976eced Merge pull request 'Update node Docker tag to v24' (#249) from renovate/node-24.x into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 31s
Playwright Tests / test (push) Successful in 4m22s
Build Nginx-based docker image / build-static-assets (push) Successful in 5m20s
Reviewed-on: #249
2025-06-15 13:37:43 +00:00
41bd2ad2b5 Fix CI to use the node versino defined in .nvmrc
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 4m27s
Add copyright notice / copyright_notice (pull_request) Successful in 4m37s
Build Nginx-based docker image / build-static-assets (push) Successful in 7m2s
Playwright Tests / test (pull_request) Successful in 8m10s
2025-06-15 13:35:24 +02:00
cd6574389f Merge pull request 'Add a confirmation dialog before deleting a guest' (#284) from confirmation-dialog-remove-guest into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 51s
Playwright Tests / test (push) Successful in 11m49s
Build Nginx-based docker image / build-static-assets (push) Successful in 12m11s
Reviewed-on: #284
2025-06-15 11:28:14 +00:00
e9e0ec7c13 Update .nvmrc
Some checks failed
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m21s
Add copyright notice / copyright_notice (pull_request) Successful in 1m59s
Build Nginx-based docker image / build-static-assets (push) Has been cancelled
Playwright Tests / test (pull_request) Successful in 11m39s
2025-06-15 13:27:44 +02:00
cb89310425 Update specs accordingly
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 55s
Add copyright notice / copyright_notice (pull_request) Successful in 1m7s
Build Nginx-based docker image / build-static-assets (push) Successful in 3m53s
Playwright Tests / test (pull_request) Successful in 4m0s
2025-06-15 13:24:09 +02:00
1e2829da25 Merge pull request 'Fix the color of the table arrangements' (#285) from fix-table-arrangement-colors into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 41s
Playwright Tests / test (push) Successful in 5m37s
Build Nginx-based docker image / build-static-assets (push) Successful in 6m4s
Reviewed-on: #285
2025-06-15 10:45:35 +00:00
4d1f83cc33 Fix the color of the table arrangements
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m8s
Add copyright notice / copyright_notice (pull_request) Successful in 1m8s
Build Nginx-based docker image / build-static-assets (push) Successful in 4m13s
Playwright Tests / test (pull_request) Successful in 4m6s
2025-06-15 12:32:06 +02:00
471b98fb53 Add a confirmation dialog before deleting a guest
Some checks failed
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m44s
Add copyright notice / copyright_notice (pull_request) Successful in 2m24s
Build Nginx-based docker image / build-static-assets (push) Successful in 8m30s
Playwright Tests / test (pull_request) Failing after 8m55s
2025-06-15 12:12:04 +02:00
Renovate Bot
055ef75510 Update node Docker tag to v24
All checks were successful
Add copyright notice / copyright_notice (pull_request) Successful in 2m49s
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m50s
Build Nginx-based docker image / build-static-assets (push) Successful in 10m4s
Playwright Tests / test (pull_request) Successful in 10m24s
2025-06-15 02:04:31 +00:00
8306cfe249 Merge pull request 'Adjust group creation to avoid a full reload' (#283) from group-specs into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 44s
Playwright Tests / test (push) Successful in 4m18s
Build Nginx-based docker image / build-static-assets (push) Successful in 5m1s
Reviewed-on: #283
2025-06-14 17:05:46 +00:00
67e4ad5d16 Refactor feature to add groups avoiding reload and improve specs
All checks were successful
Build Nginx-based docker image / build-static-assets (push) Successful in 2m0s
Check usage of free licenses / build-static-assets (pull_request) Successful in 45s
Add copyright notice / copyright_notice (pull_request) Successful in 59s
Playwright Tests / test (pull_request) Successful in 3m44s
2025-06-14 11:27:44 +02:00
5164491e64 Merge pull request 'Extract API mocks to their own file' (#282) from extract-mocks into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 34s
Playwright Tests / test (push) Successful in 4m7s
Build Nginx-based docker image / build-static-assets (push) Successful in 4m44s
Reviewed-on: #282
2025-06-14 07:49:10 +00:00
89e9c211d7 Refactor: extract groups specs to their own file 2025-06-14 09:46:35 +02:00
02760e5068 Extract API mocks to their own file
All checks were successful
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m11s
Add copyright notice / copyright_notice (pull_request) Successful in 1m27s
Build Nginx-based docker image / build-static-assets (push) Successful in 4m12s
Playwright Tests / test (pull_request) Successful in 4m18s
2025-06-14 09:44:31 +02:00
2ebd9796e3 Merge pull request 'Fix minor UI bugs and test guest CRUD' (#281) from improve-specs-guests into main
All checks were successful
Check usage of free licenses / build-static-assets (push) Successful in 46s
Playwright Tests / test (push) Successful in 4m14s
Build Nginx-based docker image / build-static-assets (push) Successful in 4m46s
Reviewed-on: #281
2025-06-14 06:35:14 +00:00
18 changed files with 521 additions and 395 deletions

View File

@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version: lts/* node-version-file: .nvmrc
- name: Install dependencies - name: Install dependencies
run: npm install -g pnpm && pnpm install run: npm install -g pnpm && pnpm install
- name: Build the service that will be tested - name: Build the service that will be tested

2
.nvmrc
View File

@ -1 +1 @@
23.11.1 24.3.0

View File

@ -1,6 +1,6 @@
# Based on https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile # Based on https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
FROM node:23-alpine AS base FROM node:24-alpine AS base
# Install dependencies only when needed # Install dependencies only when needed
FROM base AS deps FROM base AS deps

View File

@ -1,6 +1,6 @@
# Based on https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile # Based on https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
FROM node:23-alpine AS base FROM node:24-alpine AS base
# Install dependencies only when needed # Install dependencies only when needed
FROM base AS deps FROM base AS deps

View File

@ -18,6 +18,7 @@ import { Toast } from 'primereact/toast';
import { Suspense, useEffect, useRef, useState } from 'react'; import { Suspense, useEffect, useRef, useState } from 'react';
import InvitationsBoard from '@/app/ui/invitations/board'; import InvitationsBoard from '@/app/ui/invitations/board';
import { Invitation, InvitationSerializer } from '@/app/lib/invitation'; import { Invitation, InvitationSerializer } from '@/app/lib/invitation';
import { Entity } from '@/app/lib/definitions';
export default function Page() { export default function Page() {
@ -29,9 +30,9 @@ export default function Page() {
refreshGuests(); refreshGuests();
refreshInvitations(); refreshInvitations();
}, []); }, []);
const toast = useRef<Toast>(null); const toast = useRef<Toast>(null);
function refreshGuests() { function refreshGuests() {
new AbstractApi<Guest>().getAll(new GuestSerializer(), (objects: Guest[]) => { new AbstractApi<Guest>().getAll(new GuestSerializer(), (objects: Guest[]) => {
setGuests(objects); setGuests(objects);
@ -54,20 +55,20 @@ export default function Page() {
fetch(`/api/${slug}/groups/affinities/reset`, { fetch(`/api/${slug}/groups/affinities/reset`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
'X-CSRF-TOKEN': getCsrfToken(), 'X-CSRF-TOKEN': getCsrfToken(),
} }
}) })
.then(response => { .then(response => {
if (response.ok) { if (response.ok) {
showAffinitiesResetSuccess(); showAffinitiesResetSuccess();
} else { } else {
console.error('Failed to reset affinities'); console.error('Failed to reset affinities');
} }
}) })
.catch(error => { .catch(error => {
console.error('Error resetting affinities:', error); console.error('Error resetting affinities:', error);
}); });
} }
function showAffinitiesResetSuccess() { function showAffinitiesResetSuccess() {
@ -88,7 +89,22 @@ export default function Page() {
const [invitations, setInvitations] = useState<Array<Invitation>>([]); const [invitations, setInvitations] = useState<Array<Invitation>>([]);
function updateList<T extends Entity>(originalList: T[], element: T): T[] {
{
const index = originalList.findIndex(g => g.id === element?.id);
if (index !== -1) {
// Replace existing element
return [
element!,
...originalList.slice(0, index),
...originalList.slice(index + 1)
];
} else {
// Add new element at the start
return [element!, ...originalList];
}
}
}
return ( return (
<div className="w-full"> <div className="w-full">
@ -99,22 +115,9 @@ export default function Page() {
<GuestFormDialog <GuestFormDialog
key={guestBeingEdited?.id} key={guestBeingEdited?.id}
groups={groups} groups={groups}
onCreate={(newGuest) => { onCreate={(newGuest) => {
setGuests(prevGuests => { setGuests(guests => updateList(guests, newGuest));
const index = prevGuests.findIndex(g => g.id === newGuest?.id); setGuestBeingEdited(undefined);
if (index !== -1) {
// Replace existing guest
return [
newGuest!,
...prevGuests.slice(0, index),
...prevGuests.slice(index + 1)
];
} else {
// Add new guest at the start
return [newGuest!, ...prevGuests];
}
});
setGuestBeingEdited(undefined) ;
}} }}
guest={guestBeingEdited} guest={guestBeingEdited}
visible={guestBeingEdited !== undefined} visible={guestBeingEdited !== undefined}
@ -141,7 +144,10 @@ export default function Page() {
<GroupFormDialog <GroupFormDialog
key={groupBeingEdited?.id} key={groupBeingEdited?.id}
groups={groups} groups={groups}
onCreate={() => { refreshGroups(); setGroupBeingEdited(undefined) }} onCreate={(newGroup) => {
setGroups(groups => updateList(groups, newGroup));
setGroupBeingEdited(undefined)
}}
group={groupBeingEdited} group={groupBeingEdited}
visible={groupBeingEdited !== undefined} visible={groupBeingEdited !== undefined}
onHide={() => { setGroupBeingEdited(undefined) }} onHide={() => { setGroupBeingEdited(undefined) }}
@ -165,7 +171,7 @@ export default function Page() {
</div> </div>
</ TabPanel> </ TabPanel>
<TabPanel header="Invitations" leftIcon="pi pi-envelope mx-2"> <TabPanel header="Invitations" leftIcon="pi pi-envelope mx-2">
<InvitationsBoard guests={guests} invitations={invitations}/> <InvitationsBoard guests={guests} invitations={invitations} />
</TabPanel> </TabPanel>
</ TabView> </ TabView>
</div> </div>

View File

@ -3,6 +3,7 @@
import { Entity } from '@/app/lib/definitions'; import { Entity } from '@/app/lib/definitions';
import { getCsrfToken, getSlug } from '@/app/lib/utils'; import { getCsrfToken, getSlug } from '@/app/lib/utils';
export interface Api<T extends Entity> { export interface Api<T extends Entity> {
getAll(serializable: Serializable<T>, callback: (objets: T[]) => void): void; getAll(serializable: Serializable<T>, callback: (objets: T[]) => void): void;
get(serializable: Serializable<T>, id: string, callback: (object: T) => void): void; get(serializable: Serializable<T>, id: string, callback: (object: T) => void): void;
@ -30,6 +31,18 @@ export class AbstractApi<T extends Entity> implements Api<T> {
}); });
} }
getAllPdf(serializable: Serializable<T>, callback: () => void): void {
fetch(`/api/${getSlug()}/${serializable.apiPath()}`, {
headers: {
'Accept': 'application/pdf',
}
}).then(res => res.blob())
.then(blob => {
var file = window.URL.createObjectURL(blob);
window.location.assign(file);
});
}
get(serializable: Serializable<T>, id: (string | undefined), callback: (object: T) => void): void { get(serializable: Serializable<T>, id: (string | undefined), callback: (object: T) => void): void {
const endpoint = id ? `/api/${getSlug()}/${serializable.apiPath()}/${id}` : `/api/${getSlug()}/${serializable.apiPath()}`; const endpoint = id ? `/api/${getSlug()}/${serializable.apiPath()}/${id}` : `/api/${getSlug()}/${serializable.apiPath()}`;
fetch(endpoint) fetch(endpoint)

View File

@ -34,7 +34,7 @@ export class TableSimulationSerializer implements Serializable<TableSimulation>
return new TableSimulation(data.id, data.tables.map((table: any) => { return new TableSimulation(data.id, data.tables.map((table: any) => {
return { return {
number: table.number, number: table.number,
guests: table.guests.map((guest: any) => new Guest(guest.id, guest.name, guest.group?.name, guest.group?.id, guest.color)), guests: table.guests.map((guest: any) => new Guest(guest.id, guest.name, guest.color, guest.status, [], guest.group)),
discomfort: { discomfort: {
discomfort: table.discomfort.discomfort, discomfort: table.discomfort.discomfort,
breakdown: { breakdown: {

View File

@ -5,7 +5,7 @@ import clsx from "clsx";
type ButtonColor = 'primary' | 'blue' | 'green' | 'red' | 'yellow' | 'gray'; type ButtonColor = 'primary' | 'blue' | 'green' | 'red' | 'yellow' | 'gray';
export function classNames(type: ButtonColor) { export function classNames(type: ButtonColor) {
return (clsx("text-white py-1 px-2 mx-1 rounded disabled:opacity-50 disabled:cursor-not-allowed", { return (clsx("text-white py-1 px-2 m-2 rounded disabled:opacity-50 disabled:cursor-not-allowed", {
'bg-blue-400 hover:bg-blue-600': type === 'primary' || type === 'blue', 'bg-blue-400 hover:bg-blue-600': type === 'primary' || type === 'blue',
'bg-green-500 hover:bg-green-600': type === 'green', 'bg-green-500 hover:bg-green-600': type === 'green',
'bg-red-500 hover:bg-red-600': type === 'red', 'bg-red-500 hover:bg-red-600': type === 'red',

View File

@ -14,7 +14,7 @@ import { useState } from 'react';
export default function GroupFormDialog({ groups, onCreate, onHide, group, visible }: { export default function GroupFormDialog({ groups, onCreate, onHide, group, visible }: {
groups: Group[], groups: Group[],
onCreate?: () => void, onCreate?: (newGroup: Group) => void,
onHide: () => void, onHide: () => void,
group?: Group, group?: Group,
visible: boolean, visible: boolean,
@ -46,15 +46,15 @@ export default function GroupFormDialog({ groups, onCreate, onHide, group, visib
group.color = color; group.color = color;
group.parentId = parentId; group.parentId = parentId;
api.update(serializer, group, () => { api.update(serializer, group, (newGroup) => {
resetForm(); resetForm();
onCreate && onCreate(); onCreate && onCreate(newGroup);
}); });
} else { } else {
api.create(serializer, new Group(undefined, name, undefined, icon, undefined, parentId, color), () => { api.create(serializer, new Group(undefined, name, undefined, icon, undefined, parentId, color), (newGroup) => {
resetForm(); resetForm();
onCreate && onCreate(); onCreate && onCreate(newGroup);
}); });
} }
} }

View File

@ -21,7 +21,12 @@ export default function GroupsTable({ groups, onUpdate, onEdit, onEditAffinities
const actions = (group: Group) => ( const actions = (group: Group) => (
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<TrashIcon className='size-6 cursor-pointer' onClick={() => { api.destroy(serializer, group, onUpdate) }} /> <TrashIcon className='size-6 cursor-pointer' onClick={() => {
if (window.confirm(`Are you sure you want to delete guest "${group.name}"?`)) {
api.destroy(serializer, group, onUpdate)
}
}}
/>
<PencilIcon className='size-6 cursor-pointer' onClick={() => onEdit(group)} /> <PencilIcon className='size-6 cursor-pointer' onClick={() => onEdit(group)} />
<AdjustmentsHorizontalIcon className='size-6 cursor-pointer' onClick={() => onEditAffinities(group)} /> <AdjustmentsHorizontalIcon className='size-6 cursor-pointer' onClick={() => onEditAffinities(group)} />
</div> </div>

View File

@ -3,7 +3,7 @@
'use client'; 'use client';
import { AbstractApi } from '@/app/api/abstract-api'; import { AbstractApi } from '@/app/api/abstract-api';
import { Guest , GuestSerializer} from '@/app/lib/guest'; import { Guest, GuestSerializer } from '@/app/lib/guest';
import { PencilIcon, TrashIcon } from '@heroicons/react/24/outline'; import { PencilIcon, TrashIcon } from '@heroicons/react/24/outline';
import clsx from 'clsx'; import clsx from 'clsx';
import TableOfContents from '../components/table-of-contents'; import TableOfContents from '../components/table-of-contents';
@ -48,7 +48,12 @@ export default function guestsTable({ guests, onUpdate, onEdit }: {
</td> </td>
<td> <td>
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<TrashIcon className='size-6 cursor-pointer' onClick={() => { api.destroy(serializer, guest, onUpdate)}} /> <TrashIcon className='size-6 cursor-pointer' onClick={() => {
if (window.confirm(`Are you sure you want to delete guest "${guest.name}"?`)) {
api.destroy(serializer, guest, onUpdate)
}
}}
/>
<PencilIcon className='size-6 cursor-pointer' onClick={() => onEdit(guest)} /> <PencilIcon className='size-6 cursor-pointer' onClick={() => onEdit(guest)} />
</div> </div>
</td> </td>

View File

@ -10,6 +10,7 @@ import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-d
import { LinkIcon, TrashIcon } from "@heroicons/react/24/outline"; import { LinkIcon, TrashIcon } from "@heroicons/react/24/outline";
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import { useState } from "react"; import { useState } from "react";
import { classNames } from "../components/button";
function InvitationCard({ invitation, allGuests, onGuestAdded, onDestroy }: { function InvitationCard({ invitation, allGuests, onGuestAdded, onDestroy }: {
invitation: Invitation, invitation: Invitation,
@ -144,6 +145,12 @@ export default function InvitationsBoard({ guests, invitations: originalInvitati
}); });
} }
function handleDownloadQrCodes() {
api.getAllPdf(serializer, () => {
console.log("QR codes downloaded");
});
}
return ( return (
<div className="flex h-screen"> <div className="flex h-screen">
{/* Left Column: Guests */} {/* Left Column: Guests */}
@ -164,11 +171,18 @@ export default function InvitationsBoard({ guests, invitations: originalInvitati
<button <button
onClick={handleCreateInvitation} onClick={handleCreateInvitation}
className="mb-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600" className={classNames('primary')}
> >
Create New Invitation Create New Invitation
</button> </button>
<button
onClick={handleDownloadQrCodes}
className={classNames('primary')}
>
Download QR codes
</button>
<div className="grid grid-cols-4 gap-6"> <div className="grid grid-cols-4 gap-6">

View File

@ -16,9 +16,9 @@
"bcrypt": "^6.0.0", "bcrypt": "^6.0.0",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"dompurify": "^3.2.6", "dompurify": "^3.2.6",
"next": "15.3.3", "next": "15.3.4",
"next-auth": "5.0.0-beta.28", "next-auth": "5.0.0-beta.29",
"postcss": "8.5.5", "postcss": "8.5.6",
"primeicons": "^7.0.0", "primeicons": "^7.0.0",
"primereact": "^10.8.2", "primereact": "^10.8.2",
"react": "19.0.0-rc-f38c22b244-20240704", "react": "19.0.0-rc-f38c22b244-20240704",
@ -32,7 +32,7 @@
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.52.0", "@playwright/test": "^1.52.0",
"@types/bcrypt": "^5.0.2", "@types/bcrypt": "^5.0.2",
"@types/node": "22.15.31", "@types/node": "24.0.7",
"@types/react": "18.3.23", "@types/react": "18.3.23",
"@types/react-dom": "18.3.7", "@types/react-dom": "18.3.7",
"wait-on": "^8.0.3" "wait-on": "^8.0.3"
@ -40,5 +40,5 @@
"engines": { "engines": {
"node": ">=23.0.0" "node": ">=23.0.0"
}, },
"packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac" "packageManager": "pnpm@10.12.3+sha512.467df2c586056165580ad6dfb54ceaad94c5a30f80893ebdec5a44c5aa73c205ae4a5bb9d5ed6bb84ea7c249ece786642bbb49d06a307df218d03da41c317417"
} }

391
pnpm-lock.yaml generated
View File

@ -10,7 +10,7 @@ importers:
dependencies: dependencies:
'@atlaskit/pragmatic-drag-and-drop': '@atlaskit/pragmatic-drag-and-drop':
specifier: ^1.7.0 specifier: ^1.7.0
version: 1.7.2 version: 1.7.4
'@heroicons/react': '@heroicons/react':
specifier: ^2.1.4 specifier: ^2.1.4
version: 2.2.0(react@19.0.0-rc-f38c22b244-20240704) version: 2.2.0(react@19.0.0-rc-f38c22b244-20240704)
@ -19,16 +19,16 @@ importers:
version: 0.5.10(tailwindcss@3.4.17) version: 0.5.10(tailwindcss@3.4.17)
'@tiptap/pm': '@tiptap/pm':
specifier: ^2.14.0 specifier: ^2.14.0
version: 2.14.0 version: 2.23.0
'@tiptap/react': '@tiptap/react':
specifier: ^2.14.0 specifier: ^2.14.0
version: 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704) version: 2.22.3(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
'@tiptap/starter-kit': '@tiptap/starter-kit':
specifier: ^2.14.0 specifier: ^2.14.0
version: 2.14.0 version: 2.14.0
autoprefixer: autoprefixer:
specifier: 10.4.21 specifier: 10.4.21
version: 10.4.21(postcss@8.5.5) version: 10.4.21(postcss@8.5.6)
bcrypt: bcrypt:
specifier: ^6.0.0 specifier: ^6.0.0
version: 6.0.0 version: 6.0.0
@ -39,14 +39,14 @@ importers:
specifier: ^3.2.6 specifier: ^3.2.6
version: 3.2.6 version: 3.2.6
next: next:
specifier: 15.3.3 specifier: 15.3.4
version: 15.3.3(@playwright/test@1.53.0)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704) version: 15.3.4(@playwright/test@1.53.1)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
next-auth: next-auth:
specifier: 5.0.0-beta.28 specifier: 5.0.0-beta.29
version: 5.0.0-beta.28(next@15.3.3(@playwright/test@1.53.0)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704) version: 5.0.0-beta.29(next@15.3.4(@playwright/test@1.53.1)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
postcss: postcss:
specifier: 8.5.5 specifier: 8.5.6
version: 8.5.5 version: 8.5.6
primeicons: primeicons:
specifier: ^7.0.0 specifier: ^7.0.0
version: 7.0.0 version: 7.0.0
@ -73,17 +73,17 @@ importers:
version: 11.1.0 version: 11.1.0
zod: zod:
specifier: ^3.23.8 specifier: ^3.23.8
version: 3.25.64 version: 3.25.67
devDependencies: devDependencies:
'@playwright/test': '@playwright/test':
specifier: ^1.52.0 specifier: ^1.52.0
version: 1.53.0 version: 1.53.1
'@types/bcrypt': '@types/bcrypt':
specifier: ^5.0.2 specifier: ^5.0.2
version: 5.0.2 version: 5.0.2
'@types/node': '@types/node':
specifier: 22.15.31 specifier: 24.0.7
version: 22.15.31 version: 24.0.7
'@types/react': '@types/react':
specifier: 18.3.23 specifier: 18.3.23
version: 18.3.23 version: 18.3.23
@ -100,11 +100,11 @@ packages:
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'} engines: {node: '>=10'}
'@atlaskit/pragmatic-drag-and-drop@1.7.2': '@atlaskit/pragmatic-drag-and-drop@1.7.4':
resolution: {integrity: sha512-GFlFVusm+PpzNwpk4ju8+w9a9pWD5NIGi4DoJ9g6CXTUMlQ4BCsivvmUk+azsV31luEKZtf2J0tg1y3vdltrTQ==} resolution: {integrity: sha512-lZHnO9BJdHPKnwB0uvVUCyDnIhL+WAHzXQ2EXX0qacogOsnvIUiCgY0BLKhBqTCWln3/f/Ox5jU54MKO6ayh9A==}
'@auth/core@0.39.1': '@auth/core@0.40.0':
resolution: {integrity: sha512-McD8slui0oOA1pjR5sPjLPl5Zm//nLP/8T3kr8hxIsvNLvsiudYvPHhDFPjh1KcZ2nFxCkZmP6bRxaaPd/AnLA==} resolution: {integrity: sha512-n53uJE0RH5SqZ7N1xZoMKekbHfQgjd0sAEyUbE+IYJnmuQkbvuZnXItCU7d+i7Fj8VGOgqvNO7Mw4YfBTlZeQw==}
peerDependencies: peerDependencies:
'@simplewebauthn/browser': ^9.0.1 '@simplewebauthn/browser': ^9.0.1
'@simplewebauthn/server': ^9.0.2 '@simplewebauthn/server': ^9.0.2
@ -267,53 +267,53 @@ packages:
'@jridgewell/trace-mapping@0.3.25': '@jridgewell/trace-mapping@0.3.25':
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
'@next/env@15.3.3': '@next/env@15.3.4':
resolution: {integrity: sha512-OdiMrzCl2Xi0VTjiQQUK0Xh7bJHnOuET2s+3V+Y40WJBAXrJeGA3f+I8MZJ/YQ3mVGi5XGR1L66oFlgqXhQ4Vw==} resolution: {integrity: sha512-ZkdYzBseS6UjYzz6ylVKPOK+//zLWvD6Ta+vpoye8cW11AjiQjGYVibF0xuvT4L0iJfAPfZLFidaEzAOywyOAQ==}
'@next/swc-darwin-arm64@15.3.3': '@next/swc-darwin-arm64@15.3.4':
resolution: {integrity: sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg==} resolution: {integrity: sha512-z0qIYTONmPRbwHWvpyrFXJd5F9YWLCsw3Sjrzj2ZvMYy9NPQMPZ1NjOJh4ojr4oQzcGYwgJKfidzehaNa1BpEg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@next/swc-darwin-x64@15.3.3': '@next/swc-darwin-x64@15.3.4':
resolution: {integrity: sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw==} resolution: {integrity: sha512-Z0FYJM8lritw5Wq+vpHYuCIzIlEMjewG2aRkc3Hi2rcbULknYL/xqfpBL23jQnCSrDUGAo/AEv0Z+s2bff9Zkw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@next/swc-linux-arm64-gnu@15.3.3': '@next/swc-linux-arm64-gnu@15.3.4':
resolution: {integrity: sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw==} resolution: {integrity: sha512-l8ZQOCCg7adwmsnFm8m5q9eIPAHdaB2F3cxhufYtVo84pymwKuWfpYTKcUiFcutJdp9xGHC+F1Uq3xnFU1B/7g==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@next/swc-linux-arm64-musl@15.3.3': '@next/swc-linux-arm64-musl@15.3.4':
resolution: {integrity: sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA==} resolution: {integrity: sha512-wFyZ7X470YJQtpKot4xCY3gpdn8lE9nTlldG07/kJYexCUpX1piX+MBfZdvulo+t1yADFVEuzFfVHfklfEx8kw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@next/swc-linux-x64-gnu@15.3.3': '@next/swc-linux-x64-gnu@15.3.4':
resolution: {integrity: sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==} resolution: {integrity: sha512-gEbH9rv9o7I12qPyvZNVTyP/PWKqOp8clvnoYZQiX800KkqsaJZuOXkWgMa7ANCCh/oEN2ZQheh3yH8/kWPSEg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@next/swc-linux-x64-musl@15.3.3': '@next/swc-linux-x64-musl@15.3.4':
resolution: {integrity: sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==} resolution: {integrity: sha512-Cf8sr0ufuC/nu/yQ76AnarbSAXcwG/wj+1xFPNbyNo8ltA6kw5d5YqO8kQuwVIxk13SBdtgXrNyom3ZosHAy4A==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@next/swc-win32-arm64-msvc@15.3.3': '@next/swc-win32-arm64-msvc@15.3.4':
resolution: {integrity: sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ==} resolution: {integrity: sha512-ay5+qADDN3rwRbRpEhTOreOn1OyJIXS60tg9WMYTWCy3fB6rGoyjLVxc4dR9PYjEdR2iDYsaF5h03NA+XuYPQQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@next/swc-win32-x64-msvc@15.3.3': '@next/swc-win32-x64-msvc@15.3.4':
resolution: {integrity: sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==} resolution: {integrity: sha512-4kDt31Bc9DGyYs41FTL1/kNpDeHyha2TC0j5sRRoKCyrhNcfZ/nRQkAUlF27mETwm8QyHqIjHJitfcza2Iykfg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
@ -337,8 +337,8 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'} engines: {node: '>=14'}
'@playwright/test@1.53.0': '@playwright/test@1.53.1':
resolution: {integrity: sha512-15hjKreZDcp7t6TL/7jkAo6Df5STZN09jGiv5dbP9A6vMVncXRqE7/B2SncsyOwrkZRBH2i6/TPOL8BVmm3c7w==} resolution: {integrity: sha512-Z4c23LHV0muZ8hfv4jw6HngPJkbbtZxTkxPNIg7cJcTc9C28N/p2q7g3JZS2SiKBBHJ3uM1dgDye66bB7LEk5w==}
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
@ -383,8 +383,8 @@ packages:
peerDependencies: peerDependencies:
'@tiptap/core': ^2.7.0 '@tiptap/core': ^2.7.0
'@tiptap/extension-bubble-menu@2.14.0': '@tiptap/extension-bubble-menu@2.22.3':
resolution: {integrity: sha512-sN15n0RjPh+2Asvxs7l47hVEvX6c0aPempU8QQWcPUlHoGf1D/XkyHXy6GWVPSxZ5Rj5uAwgKvhHsG/FJ/YGKQ==} resolution: {integrity: sha512-8iQLNrRf3iBPKqI3dQnfvMxMfgp6y9TAbO803LihvzbIGqBaX264ES7fHtoyFIIeVjy2xFruVsTZCZofWTupGg==}
peerDependencies: peerDependencies:
'@tiptap/core': ^2.7.0 '@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0 '@tiptap/pm': ^2.7.0
@ -416,8 +416,8 @@ packages:
'@tiptap/core': ^2.7.0 '@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0 '@tiptap/pm': ^2.7.0
'@tiptap/extension-floating-menu@2.14.0': '@tiptap/extension-floating-menu@2.22.3':
resolution: {integrity: sha512-Khx7M7RfZlD1/T/PUlpJmao6FtEBa2L6td2hhaW1USflwGJGk0U/ud4UEqh+aZoJZrkot/EMhEvzmORF3nq+xw==} resolution: {integrity: sha512-GeJRRdulxpwsshxzBkpOf/xJkLD2fa+49o+3FqRCmrm7AioC8oUcZZmzuzjLj5a3ZNGKPuJ9xxDkYWUjH4tE1g==}
peerDependencies: peerDependencies:
'@tiptap/core': ^2.7.0 '@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0 '@tiptap/pm': ^2.7.0
@ -485,11 +485,11 @@ packages:
peerDependencies: peerDependencies:
'@tiptap/core': ^2.7.0 '@tiptap/core': ^2.7.0
'@tiptap/pm@2.14.0': '@tiptap/pm@2.23.0':
resolution: {integrity: sha512-cnsfaIlvTFCDtLP/A2Fd3LmpttgY0O/tuTM2fC71vetONz83wUTYT+aD9uvxdX0GkSocoh840b0TsEazbBxhpA==} resolution: {integrity: sha512-PQFi8H+OrcaNXNGxbXSjJmZFh1wxiFMbUg25LjOX148d7i+21uWKy6avsr5rsBQNBAKIIMB6PQY61Lhv5r61uA==}
'@tiptap/react@2.14.0': '@tiptap/react@2.22.3':
resolution: {integrity: sha512-6mtksbT2+EWXFLdHVFag9PSoh0GXPmL97Cm+4sJoyECUmBkAyoErapAccmZIljyMaVIHBYpYkNdp9Pw1B73ezw==} resolution: {integrity: sha512-Te6e6/carhUAavcJgxC03rffLAZz1or4cjnRDFNF8G4vPOqkNgQd368N47wTMjwh5mQTdMUUI3ToZIpc45Q7Tw==}
peerDependencies: peerDependencies:
'@tiptap/core': ^2.7.0 '@tiptap/core': ^2.7.0
'@tiptap/pm': ^2.7.0 '@tiptap/pm': ^2.7.0
@ -511,8 +511,8 @@ packages:
'@types/mdurl@2.0.0': '@types/mdurl@2.0.0':
resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
'@types/node@22.15.31': '@types/node@24.0.7':
resolution: {integrity: sha512-jnVe5ULKl6tijxUhvQeNbQG/84fHfg+yMak02cT8QVhBx/F05rAVxCGBYYTh2EKz22D6JF5ktXuNwdx7b9iEGw==} resolution: {integrity: sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw==}
'@types/prop-types@15.7.12': '@types/prop-types@15.7.12':
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
@ -932,13 +932,8 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true hasBin: true
nanoid@3.3.8: next-auth@5.0.0-beta.29:
resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} resolution: {integrity: sha512-Ukpnuk3NMc/LiOl32njZPySk7pABEzbjhMUFd5/n10I0ZNC7NCuVv8IY2JgbDek2t/PUOifQEoUiOOTLy4os5A==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
next-auth@5.0.0-beta.28:
resolution: {integrity: sha512-2RDR1h3DJb4nizcd5UBBwC2gtyP7j/jTvVLvEtDaFSKUWNfou3Gek2uTNHSga/Q4I/GF+OJobA4mFbRaWJgIDQ==}
peerDependencies: peerDependencies:
'@simplewebauthn/browser': ^9.0.1 '@simplewebauthn/browser': ^9.0.1
'@simplewebauthn/server': ^9.0.2 '@simplewebauthn/server': ^9.0.2
@ -953,8 +948,8 @@ packages:
nodemailer: nodemailer:
optional: true optional: true
next@15.3.3: next@15.3.4:
resolution: {integrity: sha512-JqNj29hHNmCLtNvd090SyRbXJiivQ+58XjCcrC50Crb5g5u2zi7Y2YivbsEfzk6AtVI80akdOQbaMZwWB1Hthw==} resolution: {integrity: sha512-mHKd50C+mCjam/gcnwqL1T1vPx/XQNFlXqFIVdgQdVAFY9iIQtY0IfaVflEYzKiqjeA7B0cYYMaCrmAYFjs4rA==}
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
@ -1033,13 +1028,13 @@ packages:
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
playwright-core@1.53.0: playwright-core@1.53.1:
resolution: {integrity: sha512-mGLg8m0pm4+mmtB7M89Xw/GSqoNC+twivl8ITteqvAndachozYe2ZA7srU6uleV1vEdAHYqjq+SV8SNxRRFYBw==} resolution: {integrity: sha512-Z46Oq7tLAyT0lGoFx4DOuB1IA9D1TPj0QkYxpPVUnGDqHHvDpCftu1J2hM2PiWsNMoZh8+LQaarAWcDfPBc6zg==}
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
playwright@1.53.0: playwright@1.53.1:
resolution: {integrity: sha512-ghGNnIEYZC4E+YtclRn4/p6oYbdPiASELBIYkBXfaTVKreQUYbMUYQDwS12a8F0/HtIjr/CkGjtwABeFPGcS4Q==} resolution: {integrity: sha512-LJ13YLr/ocweuwxyGf1XNFWIU4M2zUSo149Qbp+A4cpwDjsxRPj7k6H25LBrEHiEwxvRbD8HdwvQmRMSvquhYw==}
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
@ -1084,8 +1079,8 @@ packages:
resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
engines: {node: ^10 || ^12 || >=14} engines: {node: ^10 || ^12 || >=14}
postcss@8.5.5: postcss@8.5.6:
resolution: {integrity: sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==} resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14} engines: {node: ^10 || ^12 || >=14}
preact-render-to-string@6.5.11: preact-render-to-string@6.5.11:
@ -1332,8 +1327,8 @@ packages:
uc.micro@2.1.0: uc.micro@2.1.0:
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
undici-types@6.21.0: undici-types@7.8.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==}
update-browserslist-db@1.1.3: update-browserslist-db@1.1.3:
resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
@ -1385,20 +1380,20 @@ packages:
engines: {node: '>= 14'} engines: {node: '>= 14'}
hasBin: true hasBin: true
zod@3.25.64: zod@3.25.67:
resolution: {integrity: sha512-hbP9FpSZf7pkS7hRVUrOjhwKJNyampPgtXKc3AN6DsWtoHsg2Sb4SQaS4Tcay380zSwd2VPo9G9180emBACp5g==} resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==}
snapshots: snapshots:
'@alloc/quick-lru@5.2.0': {} '@alloc/quick-lru@5.2.0': {}
'@atlaskit/pragmatic-drag-and-drop@1.7.2': '@atlaskit/pragmatic-drag-and-drop@1.7.4':
dependencies: dependencies:
'@babel/runtime': 7.27.6 '@babel/runtime': 7.27.6
bind-event-listener: 3.0.0 bind-event-listener: 3.0.0
raf-schd: 4.0.3 raf-schd: 4.0.3
'@auth/core@0.39.1': '@auth/core@0.40.0':
dependencies: dependencies:
'@panva/hkdf': 1.2.1 '@panva/hkdf': 1.2.1
jose: 6.0.10 jose: 6.0.10
@ -1527,30 +1522,30 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2 '@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/sourcemap-codec': 1.4.15
'@next/env@15.3.3': {} '@next/env@15.3.4': {}
'@next/swc-darwin-arm64@15.3.3': '@next/swc-darwin-arm64@15.3.4':
optional: true optional: true
'@next/swc-darwin-x64@15.3.3': '@next/swc-darwin-x64@15.3.4':
optional: true optional: true
'@next/swc-linux-arm64-gnu@15.3.3': '@next/swc-linux-arm64-gnu@15.3.4':
optional: true optional: true
'@next/swc-linux-arm64-musl@15.3.3': '@next/swc-linux-arm64-musl@15.3.4':
optional: true optional: true
'@next/swc-linux-x64-gnu@15.3.3': '@next/swc-linux-x64-gnu@15.3.4':
optional: true optional: true
'@next/swc-linux-x64-musl@15.3.3': '@next/swc-linux-x64-musl@15.3.4':
optional: true optional: true
'@next/swc-win32-arm64-msvc@15.3.3': '@next/swc-win32-arm64-msvc@15.3.4':
optional: true optional: true
'@next/swc-win32-x64-msvc@15.3.3': '@next/swc-win32-x64-msvc@15.3.4':
optional: true optional: true
'@nodelib/fs.scandir@2.1.5': '@nodelib/fs.scandir@2.1.5':
@ -1570,9 +1565,9 @@ snapshots:
'@pkgjs/parseargs@0.11.0': '@pkgjs/parseargs@0.11.0':
optional: true optional: true
'@playwright/test@1.53.0': '@playwright/test@1.53.1':
dependencies: dependencies:
playwright: 1.53.0 playwright: 1.53.1
'@popperjs/core@2.11.8': {} '@popperjs/core@2.11.8': {}
@ -1597,104 +1592,104 @@ snapshots:
mini-svg-data-uri: 1.4.4 mini-svg-data-uri: 1.4.4
tailwindcss: 3.4.17 tailwindcss: 3.4.17
'@tiptap/core@2.14.0(@tiptap/pm@2.14.0)': '@tiptap/core@2.14.0(@tiptap/pm@2.23.0)':
dependencies: dependencies:
'@tiptap/pm': 2.14.0 '@tiptap/pm': 2.23.0
'@tiptap/extension-blockquote@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-blockquote@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-bold@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-bold@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-bubble-menu@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)': '@tiptap/extension-bubble-menu@2.22.3(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/pm': 2.14.0 '@tiptap/pm': 2.23.0
tippy.js: 6.3.7 tippy.js: 6.3.7
'@tiptap/extension-bullet-list@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-bullet-list@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-code-block@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)': '@tiptap/extension-code-block@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/pm': 2.14.0 '@tiptap/pm': 2.23.0
'@tiptap/extension-code@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-code@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-document@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-document@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-dropcursor@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)': '@tiptap/extension-dropcursor@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/pm': 2.14.0 '@tiptap/pm': 2.23.0
'@tiptap/extension-floating-menu@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)': '@tiptap/extension-floating-menu@2.22.3(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/pm': 2.14.0 '@tiptap/pm': 2.23.0
tippy.js: 6.3.7 tippy.js: 6.3.7
'@tiptap/extension-gapcursor@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)': '@tiptap/extension-gapcursor@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/pm': 2.14.0 '@tiptap/pm': 2.23.0
'@tiptap/extension-hard-break@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-hard-break@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-heading@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-heading@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-history@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)': '@tiptap/extension-history@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/pm': 2.14.0 '@tiptap/pm': 2.23.0
'@tiptap/extension-horizontal-rule@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)': '@tiptap/extension-horizontal-rule@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/pm': 2.14.0 '@tiptap/pm': 2.23.0
'@tiptap/extension-italic@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-italic@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-list-item@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-list-item@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-ordered-list@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-ordered-list@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-paragraph@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-paragraph@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-strike@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-strike@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-text-style@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-text-style@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-text@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-text@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/pm@2.14.0': '@tiptap/pm@2.23.0':
dependencies: dependencies:
prosemirror-changeset: 2.3.1 prosemirror-changeset: 2.3.1
prosemirror-collab: 1.3.1 prosemirror-collab: 1.3.1
@ -1715,12 +1710,12 @@ snapshots:
prosemirror-transform: 1.10.4 prosemirror-transform: 1.10.4
prosemirror-view: 1.40.0 prosemirror-view: 1.40.0
'@tiptap/react@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)': '@tiptap/react@2.22.3(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-bubble-menu': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0) '@tiptap/extension-bubble-menu': 2.22.3(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)
'@tiptap/extension-floating-menu': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0) '@tiptap/extension-floating-menu': 2.22.3(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)
'@tiptap/pm': 2.14.0 '@tiptap/pm': 2.23.0
'@types/use-sync-external-store': 0.0.6 '@types/use-sync-external-store': 0.0.6
fast-deep-equal: 3.1.3 fast-deep-equal: 3.1.3
react: 19.0.0-rc-f38c22b244-20240704 react: 19.0.0-rc-f38c22b244-20240704
@ -1729,31 +1724,31 @@ snapshots:
'@tiptap/starter-kit@2.14.0': '@tiptap/starter-kit@2.14.0':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.23.0)
'@tiptap/extension-blockquote': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-blockquote': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-bold': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-bold': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-bullet-list': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-bullet-list': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-code': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-code': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-code-block': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0) '@tiptap/extension-code-block': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)
'@tiptap/extension-document': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-document': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-dropcursor': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0) '@tiptap/extension-dropcursor': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)
'@tiptap/extension-gapcursor': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0) '@tiptap/extension-gapcursor': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)
'@tiptap/extension-hard-break': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-hard-break': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-heading': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-heading': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-history': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0) '@tiptap/extension-history': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)
'@tiptap/extension-horizontal-rule': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0) '@tiptap/extension-horizontal-rule': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))(@tiptap/pm@2.23.0)
'@tiptap/extension-italic': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-italic': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-list-item': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-list-item': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-ordered-list': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-ordered-list': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-paragraph': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-paragraph': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-strike': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-strike': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-text': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-text': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/extension-text-style': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0)) '@tiptap/extension-text-style': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.23.0))
'@tiptap/pm': 2.14.0 '@tiptap/pm': 2.23.0
'@types/bcrypt@5.0.2': '@types/bcrypt@5.0.2':
dependencies: dependencies:
'@types/node': 22.15.31 '@types/node': 24.0.7
'@types/linkify-it@5.0.0': {} '@types/linkify-it@5.0.0': {}
@ -1764,9 +1759,9 @@ snapshots:
'@types/mdurl@2.0.0': {} '@types/mdurl@2.0.0': {}
'@types/node@22.15.31': '@types/node@24.0.7':
dependencies: dependencies:
undici-types: 6.21.0 undici-types: 7.8.0
'@types/prop-types@15.7.12': {} '@types/prop-types@15.7.12': {}
@ -1811,14 +1806,14 @@ snapshots:
asynckit@0.4.0: {} asynckit@0.4.0: {}
autoprefixer@10.4.21(postcss@8.5.5): autoprefixer@10.4.21(postcss@8.5.6):
dependencies: dependencies:
browserslist: 4.24.4 browserslist: 4.24.4
caniuse-lite: 1.0.30001702 caniuse-lite: 1.0.30001702
fraction.js: 4.3.7 fraction.js: 4.3.7
normalize-range: 0.1.2 normalize-range: 0.1.2
picocolors: 1.1.1 picocolors: 1.1.1
postcss: 8.5.5 postcss: 8.5.6
postcss-value-parser: 4.2.0 postcss-value-parser: 4.2.0
axios@1.9.0: axios@1.9.0:
@ -2165,17 +2160,15 @@ snapshots:
nanoid@3.3.11: {} nanoid@3.3.11: {}
nanoid@3.3.8: {} next-auth@5.0.0-beta.29(next@15.3.4(@playwright/test@1.53.1)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704):
next-auth@5.0.0-beta.28(next@15.3.3(@playwright/test@1.53.0)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704):
dependencies: dependencies:
'@auth/core': 0.39.1 '@auth/core': 0.40.0
next: 15.3.3(@playwright/test@1.53.0)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704) next: 15.3.4(@playwright/test@1.53.1)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
react: 19.0.0-rc-f38c22b244-20240704 react: 19.0.0-rc-f38c22b244-20240704
next@15.3.3(@playwright/test@1.53.0)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704): next@15.3.4(@playwright/test@1.53.1)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704):
dependencies: dependencies:
'@next/env': 15.3.3 '@next/env': 15.3.4
'@swc/counter': 0.1.3 '@swc/counter': 0.1.3
'@swc/helpers': 0.5.15 '@swc/helpers': 0.5.15
busboy: 1.6.0 busboy: 1.6.0
@ -2185,15 +2178,15 @@ snapshots:
react-dom: 19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704) react-dom: 19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704)
styled-jsx: 5.1.6(react@19.0.0-rc-f38c22b244-20240704) styled-jsx: 5.1.6(react@19.0.0-rc-f38c22b244-20240704)
optionalDependencies: optionalDependencies:
'@next/swc-darwin-arm64': 15.3.3 '@next/swc-darwin-arm64': 15.3.4
'@next/swc-darwin-x64': 15.3.3 '@next/swc-darwin-x64': 15.3.4
'@next/swc-linux-arm64-gnu': 15.3.3 '@next/swc-linux-arm64-gnu': 15.3.4
'@next/swc-linux-arm64-musl': 15.3.3 '@next/swc-linux-arm64-musl': 15.3.4
'@next/swc-linux-x64-gnu': 15.3.3 '@next/swc-linux-x64-gnu': 15.3.4
'@next/swc-linux-x64-musl': 15.3.3 '@next/swc-linux-x64-musl': 15.3.4
'@next/swc-win32-arm64-msvc': 15.3.3 '@next/swc-win32-arm64-msvc': 15.3.4
'@next/swc-win32-x64-msvc': 15.3.3 '@next/swc-win32-x64-msvc': 15.3.4
'@playwright/test': 1.53.0 '@playwright/test': 1.53.1
sharp: 0.34.1 sharp: 0.34.1
transitivePeerDependencies: transitivePeerDependencies:
- '@babel/core' - '@babel/core'
@ -2234,36 +2227,36 @@ snapshots:
pirates@4.0.6: {} pirates@4.0.6: {}
playwright-core@1.53.0: {} playwright-core@1.53.1: {}
playwright@1.53.0: playwright@1.53.1:
dependencies: dependencies:
playwright-core: 1.53.0 playwright-core: 1.53.1
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.2
postcss-import@15.1.0(postcss@8.5.5): postcss-import@15.1.0(postcss@8.5.6):
dependencies: dependencies:
postcss: 8.5.5 postcss: 8.5.6
postcss-value-parser: 4.2.0 postcss-value-parser: 4.2.0
read-cache: 1.0.0 read-cache: 1.0.0
resolve: 1.22.8 resolve: 1.22.8
postcss-js@4.0.1(postcss@8.5.5): postcss-js@4.0.1(postcss@8.5.6):
dependencies: dependencies:
camelcase-css: 2.0.1 camelcase-css: 2.0.1
postcss: 8.5.5 postcss: 8.5.6
postcss-load-config@4.0.2(postcss@8.5.5): postcss-load-config@4.0.2(postcss@8.5.6):
dependencies: dependencies:
lilconfig: 3.1.3 lilconfig: 3.1.3
yaml: 2.4.3 yaml: 2.4.3
optionalDependencies: optionalDependencies:
postcss: 8.5.5 postcss: 8.5.6
postcss-nested@6.2.0(postcss@8.5.5): postcss-nested@6.2.0(postcss@8.5.6):
dependencies: dependencies:
postcss: 8.5.5 postcss: 8.5.6
postcss-selector-parser: 6.1.2 postcss-selector-parser: 6.1.2
postcss-selector-parser@6.1.2: postcss-selector-parser@6.1.2:
@ -2275,11 +2268,11 @@ snapshots:
postcss@8.4.31: postcss@8.4.31:
dependencies: dependencies:
nanoid: 3.3.8 nanoid: 3.3.11
picocolors: 1.1.1 picocolors: 1.1.1
source-map-js: 1.2.1 source-map-js: 1.2.1
postcss@8.5.5: postcss@8.5.6:
dependencies: dependencies:
nanoid: 3.3.11 nanoid: 3.3.11
picocolors: 1.1.1 picocolors: 1.1.1
@ -2566,11 +2559,11 @@ snapshots:
normalize-path: 3.0.0 normalize-path: 3.0.0
object-hash: 3.0.0 object-hash: 3.0.0
picocolors: 1.1.1 picocolors: 1.1.1
postcss: 8.5.5 postcss: 8.5.6
postcss-import: 15.1.0(postcss@8.5.5) postcss-import: 15.1.0(postcss@8.5.6)
postcss-js: 4.0.1(postcss@8.5.5) postcss-js: 4.0.1(postcss@8.5.6)
postcss-load-config: 4.0.2(postcss@8.5.5) postcss-load-config: 4.0.2(postcss@8.5.6)
postcss-nested: 6.2.0(postcss@8.5.5) postcss-nested: 6.2.0(postcss@8.5.6)
postcss-selector-parser: 6.1.2 postcss-selector-parser: 6.1.2
resolve: 1.22.8 resolve: 1.22.8
sucrase: 3.35.0 sucrase: 3.35.0
@ -2601,7 +2594,7 @@ snapshots:
uc.micro@2.1.0: {} uc.micro@2.1.0: {}
undici-types@6.21.0: {} undici-types@7.8.0: {}
update-browserslist-db@1.1.3(browserslist@4.24.4): update-browserslist-db@1.1.3(browserslist@4.24.4):
dependencies: dependencies:
@ -2651,4 +2644,4 @@ snapshots:
yaml@2.4.3: {} yaml@2.4.3: {}
zod@3.25.64: {} zod@3.25.67: {}

82
tests/groups.spec.ts Normal file
View File

@ -0,0 +1,82 @@
import { test, expect, Page } from '@playwright/test'
import mockGroupsAPI from './mocks/groups';
import mockGuestsAPI from './mocks/guests';
test('should allow CRUD on groups', async ({ page }) => {
await mockGuestsAPI({ page });
await mockGroupsAPI({ page });
await page.goto('/default/dashboard/guests');
await page.getByRole('tab', { name: 'Groups' }).click();
await expect(page.getByRole('button', { name: 'Add new' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Reset affinities' })).toBeVisible();
// List all groups
await expect(page.getByRole('row')).toHaveCount(3); // 1 header row + 2 data rows
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(0)).toHaveText('Name');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(1)).toHaveText('Color');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(2)).toHaveText('Confirmed');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(3)).toHaveText('Tentative');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(4)).toHaveText('Pending');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(5)).toHaveText('Declined');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(6)).toHaveText('Considered');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(7)).toHaveText('Total');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(8)).toHaveText('Actions');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toContainText('Pam\'s family');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(4)).toHaveText('1');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(5)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(6)).toHaveText('2');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(7)).toHaveText('3');
await expect(page.getByRole('row').nth(1).locator('svg:visible')).toHaveCount(3);
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(0)).toContainText('Pam\'s work');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(2)).toHaveText('0');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(3)).toHaveText('2');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(4)).toHaveText('0');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(5)).toHaveText('0');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(6)).toHaveText('0');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(7)).toHaveText('2');
await expect(page.getByRole('row').nth(2).locator('svg:visible')).toHaveCount(3);
// Add a new group
await page.getByRole('button', { name: 'Add new' }).click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
await dialog.getByLabel('Name').fill("Pam's friends");
await dialog.getByRole('button', { name: 'Create' }).click();
await expect(page.getByRole('row')).toHaveCount(4); // 1 header row + 3 data rows
await expect(dialog).not.toBeVisible();
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toContainText('Pam\'s friends');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(4)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(5)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(6)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(7)).toHaveText('0');
await expect(page.getByRole('row').nth(1).locator('svg:visible')).toHaveCount(3);
// Modify the newly added group
await page.getByRole('row').nth(1).locator('svg').nth(2).click(); // Click edit icon
await expect(dialog).toBeVisible();
await expect(dialog.getByLabel('Name')).toHaveValue("Pam's friends");
await dialog.getByLabel('Name').fill('Pam\'s best friends');
await dialog.getByRole('button', { name: 'Update' }).click();
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toContainText('Pam\'s best friends');
// Delete the newly added group
page.on('dialog', dialog => dialog.accept());
await page.getByRole('row').nth(1).locator('svg').nth(1).click(); // Click delete icon
await expect(page.getByRole('row')).toHaveCount(3); // 1 header row + 2 data rows
});

View File

@ -1,104 +1,6 @@
import { test, expect, Page } from '@playwright/test' import { expect, test } from '@playwright/test';
import { mock } from 'node:test'; import mockGroupsAPI from './mocks/groups';
import mockGuestsAPI from './mocks/guests';
const mockGuestsAPI = ({ page }: { page: Page }) => {
page.route('*/**/api/default/guests', async route => {
if (route.request().method() === 'GET') {
const json = [
{
"id": "f4a09c28-40ea-4553-90a5-96935a59cac6",
"status": "tentative",
"name": "Kristofer Rohan DVM",
"group": {
"id": "ee44ffb9-1147-4842-a378-9eaeb0f0871a",
"name": "Pam's family",
}
},
{
"id": "bd585c40-0937-4cde-960a-bb23acfd6f18",
"status": "invited",
"name": "Olevia Quigley Jr.",
"group": {
"id": "c8bda6ca-d8af-4bb8-b2bf-e6ec1c21b1e6",
"name": "Pam's work",
}
},
];
await route.fulfill({ json })
} else if (route.request().method() === 'POST') {
const json = {
"id": "ff58aa2d-643d-4c29-be9c-50e10ae6853c",
"name": "John Snow",
"status": "invited",
"group": {
"id": "c8bda6ca-d8af-4bb8-b2bf-e6ec1c21b1e6",
"name": "Pam's work",
}
};
await route.fulfill({ json });
}
})
page.route("*/**/api/default/guests/*", async route => {
if (route.request().method() === 'PUT') {
const json = {
"id": "ff58aa2d-643d-4c29-be9c-50e10ae6853c",
"name": "John Fire",
"status": "declined",
"group": {
"id": "ee44ffb9-1147-4842-a378-9eaeb0f0871a",
"name": "Pam's family",
}
}
await route.fulfill({ json });
} else if (route.request().method() === 'DELETE') {
const json = {}
await route.fulfill({ json });
}
});
}
const mockGroupsAPI = ({ page }: { page: Page }) => {
page.route('*/**/api/default/groups', async route => {
const json = [
{
"id": "ee44ffb9-1147-4842-a378-9eaeb0f0871a",
"name": "Pam's family",
"icon": "pi pi-users",
"parent_id": null,
"color": "#ff0000",
"attendance": {
"total": 3,
"considered": 2,
"invited": 1,
"confirmed": 0,
"declined": 0,
"tentative": 0
}
},
{
"id": "c8bda6ca-d8af-4bb8-b2bf-e6ec1c21b1e6",
"name": "Pam's work",
"icon": "pi pi-desktop",
"parent_id": null,
"color": "#00ff00",
"attendance": {
"total": 2,
"considered": 0,
"invited": 0,
"confirmed": 0,
"declined": 0,
"tentative": 2
}
},
];
await route.fulfill({ json })
})
}
test('should allow CRUD on guests', async ({ page }) => { test('should allow CRUD on guests', async ({ page }) => {
await mockGuestsAPI({ page }); await mockGuestsAPI({ page });
@ -168,48 +70,7 @@ test('should allow CRUD on guests', async ({ page }) => {
await expect(page.getByText('There are 3 elements in the list')).toBeVisible(); await expect(page.getByText('There are 3 elements in the list')).toBeVisible();
// Delete John Fire // Delete John Fire
page.on('dialog', dialog => dialog.accept());
await page.getByRole('row').nth(1).locator('svg').nth(0).click(); // Click delete icon await page.getByRole('row').nth(1).locator('svg').nth(0).click(); // Click delete icon
await expect(page.getByText('There are 2 elements in the list')).toBeVisible(); await expect(page.getByText('There are 2 elements in the list')).toBeVisible();
}); });
test('should display the list of groups', async ({ page }) => {
await mockGroupsAPI({ page });
await page.goto('/default/dashboard/guests');
await page.getByRole('tab', { name: 'Groups' }).click();
await expect(page.getByRole('button', { name: 'Add new' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Reset affinities' })).toBeVisible();
await expect(page.getByRole('row')).toHaveCount(3); // 1 header row + 2 data rows
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(0)).toHaveText('Name');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(1)).toHaveText('Color');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(2)).toHaveText('Confirmed');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(3)).toHaveText('Tentative');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(4)).toHaveText('Pending');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(5)).toHaveText('Declined');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(6)).toHaveText('Considered');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(7)).toHaveText('Total');
await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(8)).toHaveText('Actions');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toContainText('Pam\'s family');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(4)).toHaveText('1');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(5)).toHaveText('0');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(6)).toHaveText('2');
await expect(page.getByRole('row').nth(1).getByRole('cell').nth(7)).toHaveText('3');
await expect(page.getByRole('row').nth(1).locator('svg:visible')).toHaveCount(3);
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(0)).toContainText('Pam\'s work');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(2)).toHaveText('0');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(3)).toHaveText('2');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(4)).toHaveText('0');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(5)).toHaveText('0');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(6)).toHaveText('0');
await expect(page.getByRole('row').nth(2).getByRole('cell').nth(7)).toHaveText('2');
await expect(page.getByRole('row').nth(2).locator('svg:visible')).toHaveCount(3);
});

86
tests/mocks/groups.tsx Normal file
View File

@ -0,0 +1,86 @@
import { Page } from "@playwright/test";
export default async function mockGroupsAPI({ page }: { page: Page }): Promise<void> {
page.route('*/**/api/default/groups', async route => {
if (route.request().method() === 'GET') {
const json = [
{
"id": "ee44ffb9-1147-4842-a378-9eaeb0f0871a",
"name": "Pam's family",
"icon": "pi pi-users",
"parent_id": null,
"color": "#ff0000",
"attendance": {
"total": 3,
"considered": 2,
"invited": 1,
"confirmed": 0,
"declined": 0,
"tentative": 0
}
},
{
"id": "c8bda6ca-d8af-4bb8-b2bf-e6ec1c21b1e6",
"name": "Pam's work",
"icon": "pi pi-desktop",
"parent_id": null,
"color": "#00ff00",
"attendance": {
"total": 2,
"considered": 0,
"invited": 0,
"confirmed": 0,
"declined": 0,
"tentative": 2
}
},
];
await route.fulfill({ json })
} else if (route.request().method() === 'POST') {
const json = {
"id": "4d55bc34-6f42-4e2e-82a1-71ae32da2466",
"name": "Pam's friends",
"icon": "pi pi-desktop",
"parent_id": null,
"color": "#0000ff",
"attendance": {
"total": 0,
"considered": 0,
"invited": 0,
"confirmed": 0,
"declined": 0,
"tentative": 0
}
}
await route.fulfill({ json })
}
})
page.route("*/**/api/default/groups/*", async route => {
if (route.request().method() === 'PUT') {
const json = {
"id": "4d55bc34-6f42-4e2e-82a1-71ae32da2466",
"name": "Pam's best friends",
"icon": "pi pi-desktop",
"parent_id": null,
"color": "#0000ff",
"attendance": {
"total": 0,
"considered": 0,
"invited": 0,
"confirmed": 0,
"declined": 0,
"tentative": 0
}
}
await route.fulfill({ json });
} else if (route.request().method() === 'DELETE') {
const json = {}
await route.fulfill({ json });
}
});
}

61
tests/mocks/guests.tsx Normal file
View File

@ -0,0 +1,61 @@
import { Page } from "@playwright/test";
export default async function mockGuestsAPI({ page }: { page: Page }): Promise<void> {
page.route('*/**/api/default/guests', async route => {
if (route.request().method() === 'GET') {
const json = [
{
"id": "f4a09c28-40ea-4553-90a5-96935a59cac6",
"status": "tentative",
"name": "Kristofer Rohan DVM",
"group": {
"id": "ee44ffb9-1147-4842-a378-9eaeb0f0871a",
"name": "Pam's family",
}
},
{
"id": "bd585c40-0937-4cde-960a-bb23acfd6f18",
"status": "invited",
"name": "Olevia Quigley Jr.",
"group": {
"id": "c8bda6ca-d8af-4bb8-b2bf-e6ec1c21b1e6",
"name": "Pam's work",
}
},
];
await route.fulfill({ json })
} else if (route.request().method() === 'POST') {
const json = {
"id": "ff58aa2d-643d-4c29-be9c-50e10ae6853c",
"name": "John Snow",
"status": "invited",
"group": {
"id": "c8bda6ca-d8af-4bb8-b2bf-e6ec1c21b1e6",
"name": "Pam's work",
}
};
await route.fulfill({ json });
}
})
page.route("*/**/api/default/guests/*", async route => {
if (route.request().method() === 'PUT') {
const json = {
"id": "ff58aa2d-643d-4c29-be9c-50e10ae6853c",
"name": "John Fire",
"status": "declined",
"group": {
"id": "ee44ffb9-1147-4842-a378-9eaeb0f0871a",
"name": "Pam's family",
}
}
await route.fulfill({ json });
} else if (route.request().method() === 'DELETE') {
const json = {}
await route.fulfill({ json });
}
});
}