Compare commits

...

13 Commits

Author SHA1 Message Date
Renovate Bot
a0ef88063d Update dependency react-dom to v19.0.0
Some checks failed
Add copyright notice / copyright_notice (pull_request) Failing after 25s
Playwright Tests / test (pull_request) Has been skipped
Check usage of free licenses / build-static-assets (pull_request) Successful in 1m37s
2024-12-29 01:12:59 +00:00
c540828463 Merge pull request 'Fix build issue with types returned by the Slider component' (#162) from fix-build into main
Some checks failed
Playwright Tests / test (push) Has been skipped
Check usage of free licenses / build-static-assets (push) Successful in 36s
Build Nginx-based docker image / build-static-assets (push) Failing after 1m40s
Reviewed-on: #162
2024-12-28 19:28:06 +00:00
a6b678c6ae Fix build issue with types returned by the Slider component
All checks were successful
Playwright Tests / test (pull_request) Has been skipped
Add copyright notice / copyright_notice (pull_request) Successful in 33s
Check usage of free licenses / build-static-assets (pull_request) Successful in 2m31s
2024-12-28 20:23:35 +01:00
6d35009593 Merge pull request 'Allow configuring affinity between groups' (#161) from group-affinities into main
Some checks failed
Playwright Tests / test (push) Has been skipped
Check usage of free licenses / build-static-assets (push) Successful in 33s
Build Nginx-based docker image / build-static-assets (push) Failing after 2m20s
Reviewed-on: #161
2024-12-28 18:56:17 +00:00
dc735f1a2c Add copyright notice
All checks were successful
Playwright Tests / test (pull_request) Has been skipped
Check usage of free licenses / build-static-assets (pull_request) Successful in 43s
Add copyright notice / copyright_notice (pull_request) Successful in 47s
2024-12-28 18:53:59 +00:00
c49acf8ab6 Merge remote-tracking branch 'origin/main' into group-affinities
All checks were successful
Playwright Tests / test (pull_request) Has been skipped
Check usage of free licenses / build-static-assets (pull_request) Successful in 39s
Add copyright notice / copyright_notice (pull_request) Successful in 32s
2024-12-28 16:49:46 +01:00
52fb808d45 Define a dialog to configure the affinities between groups
Some checks failed
Playwright Tests / test (pull_request) Has been skipped
Check usage of free licenses / build-static-assets (pull_request) Failing after 34s
Add copyright notice / copyright_notice (pull_request) Failing after 34s
2024-12-28 14:18:14 +01:00
d307ff6927 Update status of the parent component 2024-12-28 13:04:01 +01:00
b7e2bbb46f Initial approach to configure affinities between groups 2024-12-28 13:00:24 +01:00
3f38a9191f Merge pull request 'Define a health endpoint for docker compose' (#160) from health-check-endpoint into main
Some checks failed
Playwright Tests / test (push) Has been skipped
Check usage of free licenses / build-static-assets (push) Successful in 27s
Build Nginx-based docker image / build-static-assets (push) Failing after 1m22s
Reviewed-on: #160
2024-12-28 10:51:18 +00:00
07476221c3 Add copyright notice
All checks were successful
Playwright Tests / test (pull_request) Has been skipped
Check usage of free licenses / build-static-assets (pull_request) Successful in 32s
Add copyright notice / copyright_notice (pull_request) Successful in 34s
2024-12-28 10:46:08 +00:00
b1339e2ce9 Define a health endpoint for docker compose
All checks were successful
Playwright Tests / test (pull_request) Has been skipped
Add copyright notice / copyright_notice (pull_request) Successful in 22s
Check usage of free licenses / build-static-assets (pull_request) Successful in 35s
2024-12-28 11:45:22 +01:00
ff73133e05 Define a health endpoint for docker compose 2024-12-28 11:42:22 +01:00
9 changed files with 175 additions and 43 deletions

View File

@ -2,8 +2,10 @@
'use client';
import { AbstractApi, } from '@/app/api/abstract-api';
import { AbstractApi, } from '@/app/api/abstract-api';
import { Group, GroupSerializer } from '@/app/lib/group';
import { Guest, GuestSerializer } from '@/app/lib/guest';
import AffinitiesFormDialog from '@/app/ui/components/affinities-form-dialog';
import { classNames } from '@/app/ui/components/button';
import GroupFormDialog from '@/app/ui/components/group-form-dialog';
import GuestFormDialog from '@/app/ui/components/guest-form-dialog';
@ -12,7 +14,6 @@ import SkeletonTable from '@/app/ui/guests/skeleton-row';
import GuestsTable from '@/app/ui/guests/table';
import { TabPanel, TabView } from 'primereact/tabview';
import { Suspense, useState } from 'react';
import { Group, GroupSerializer } from '@/app/lib/group';
export default function Page() {
@ -34,6 +35,8 @@ export default function Page() {
const [groups, setGroups] = useState<Array<Group>>([]);
const [groupBeingEdited, setGroupBeingEdited] = useState<Group | undefined>(undefined);
const [groupAffinitiesBeingEditted, setGroupAffinitiesBeingEditted] = useState<Group | undefined>(undefined);
const [guestsLoaded, setGuestsLoaded] = useState(false);
const [guests, setGuests] = useState<Array<Guest>>([]);
const [guestBeingEdited, setGuestBeingEdited] = useState<Guest | undefined>(undefined);
@ -77,11 +80,19 @@ export default function Page() {
onHide={() => { setGroupBeingEdited(undefined) }}
/>
<AffinitiesFormDialog
groups={groups}
group={groupAffinitiesBeingEditted}
visible={groupAffinitiesBeingEditted !== undefined}
onHide={() => { setGroupAffinitiesBeingEditted(undefined) }}
/>
<Suspense fallback={<SkeletonTable />}>
<GroupsTable
<GroupsTable
groups={groups}
onUpdate={refreshGroups}
onEdit={(group) => setGroupBeingEdited(group)}
onEditAffinities={(group) => setGroupAffinitiesBeingEditted(group)}
/>
</Suspense>
</div>

7
app/api/health/route.ts Normal file
View File

@ -0,0 +1,7 @@
/* Copyright (C) 2024 Manuel Bustillo*/
import { NextResponse } from "next/server";
export function GET() {
return NextResponse.json({});
}

5
app/lib/affinities.tsx Normal file
View File

@ -0,0 +1,5 @@
/* Copyright (C) 2024 Manuel Bustillo*/
export class Affinities {
[key:string]: number;
}

View File

@ -0,0 +1,69 @@
/* Copyright (C) 2024 Manuel Bustillo*/
'use client';
import { Affinities } from '@/app/lib/affinities';
import { Group } from '@/app/lib/group';
import { getCsrfToken, getSlug } from '@/app/lib/utils';
import { classNames } from '@/app/ui/components/button';
import { Dialog } from 'primereact/dialog';
import { useEffect, useState } from 'react';
import AffinitySlider from './form/affinitySlider';
export default function AffinitiesFormDialog({ groups, group, visible, onHide }: {
groups: Group[],
group?: Group,
visible: boolean,
onHide: () => void,
}) {
const [affinities, setAffinities] = useState<Affinities>({});
const [isLoadingAffinities, setIsLoadingAffinities] = useState(true);
useEffect(() => {
setIsLoadingAffinities(true);
if (group?.id === undefined) {
setAffinities({});
setIsLoadingAffinities(false)
} else {
fetch(`/api/${getSlug()}/groups/${group?.id}/affinities`)
.then((response) => response.json())
.then((data) => {
setAffinities(data);
setIsLoadingAffinities(false)
});
}
}, [group]);
function submitAffinities() {
const formattedAffinities = Object.entries(affinities).map(([groupId, affinity]) => ({ group_id: groupId, affinity: affinity }));
fetch(`/api/${getSlug()}/groups/${group?.id}/affinities/bulk_update`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': getCsrfToken(),
},
body: JSON.stringify({ affinities: formattedAffinities })
}).then(() => {
onHide();
});
}
return (
<Dialog header="Update affinities" visible={visible} style={{ width: '60vw' }} onHide={onHide}>
{!isLoadingAffinities && <div className="card justify-evenly py-5 bg-gray-200 flex flex-col">
<span className="text-center p-4">Describe the affinity with the rest of the groups</span>
{
groups.filter((currentGroup) => currentGroup.id !== group?.id).map((group) =>
<div key={group.id} className="flex flex-row hover:bg-gray-300 px-3 py-2 items-center">
<span className="w-1/3 text-right px-4">{group.name}</span>
<AffinitySlider value={group.id && affinities[group.id] || 1} onChange={(value) => setAffinities({ ...affinities, [group.id || "default"]: value })} />
</div>)
}
<button className={classNames('primary')} onClick={submitAffinities} >Update</button>
</div>
}
</Dialog>
);
}

View File

@ -0,0 +1,40 @@
/* Copyright (C) 2024 Manuel Bustillo*/
import { Slider } from 'primereact/slider';
export default function AffinitySlider({ value, onChange }: { value: number, onChange: (value: number) => void }) {
const toNumber = (value : number | [number, number]) => {
if(value instanceof Array) {
return value[0];
}
return value;
}
const label = (value: number) => {
if (value < 0.2) {
return 'Nemesis';
} else if (value < 0.5) {
return 'Enemies';
} else if (value < 0.9) {
return 'Bad vibes';
} else if (value < 1.1) {
return 'Neutral';
} else if (value < 1.5) {
return 'Good vibes';
} else if (value < 1.8) {
return 'Good friends';
} else {
return 'Besties';
}
}
return (
<>
<Slider value={value} min={0} max={2} step={.1} onChange={(e) => onChange(toNumber(e.value))} className='w-80 bg-gray-400' />
<span className="px-4 w-1/5">
{label(value)}
</span>
</>
)
}

View File

@ -2,18 +2,17 @@
'use client';
import { AbstractApi } from '@/app/api/abstract-api';
import { Group, GroupSerializer } from '@/app/lib/group';
import { classNames } from '@/app/ui/components/button';
import { Dialog } from 'primereact/dialog';
import { ColorPicker } from 'primereact/colorpicker';
import { Dialog } from 'primereact/dialog';
import { Dropdown } from 'primereact/dropdown';
import { FloatLabel } from 'primereact/floatlabel';
import { InputText } from 'primereact/inputtext';
import { useState } from 'react';
import { Group, GroupSerializer } from '@/app/lib/group';
import { ApiError } from 'next/dist/server/api-utils';
import { AbstractApi } from '@/app/api/abstract-api';
export default function GroupFormDialog({groups, onCreate, onHide, group, visible }: {
export default function GroupFormDialog({ groups, onCreate, onHide, group, visible }: {
groups: Group[],
onCreate?: () => void,
onHide: () => void,

View File

@ -2,18 +2,18 @@
'use client';
import { Group, GroupSerializer } from '@/app/lib/group';
import TableOfContents from '../components/table-of-contents';
import { MapPinIcon, PencilIcon, TrashIcon } from '@heroicons/react/24/outline';
import { AbstractApi } from '@/app/api/abstract-api';
import { TreeTable } from 'primereact/treetable';
import { Group, GroupSerializer } from '@/app/lib/group';
import { AdjustmentsHorizontalIcon, PencilIcon, TrashIcon } from '@heroicons/react/24/outline';
import { Column } from 'primereact/column';
import { TreeNode } from 'primereact/treenode';
import { TreeTable } from 'primereact/treetable';
export default function GroupsTable({ groups, onUpdate, onEdit }: {
export default function GroupsTable({ groups, onUpdate, onEdit, onEditAffinities }: {
groups: Group[],
onUpdate: () => void,
onEdit: (group: Group) => void,
onEditAffinities: (group: Group) => void,
}) {
const api = new AbstractApi<Group>();
@ -23,6 +23,7 @@ export default function GroupsTable({ groups, onUpdate, onEdit }: {
<div className="flex flex-row items-center">
<TrashIcon className='size-6 cursor-pointer' onClick={() => { api.destroy(serializer, group, onUpdate) }} />
<PencilIcon className='size-6 cursor-pointer' onClick={() => onEdit(group)} />
<AdjustmentsHorizontalIcon className='size-6 cursor-pointer' onClick={() => onEditAffinities(group)} />
</div>
);

View File

@ -17,7 +17,7 @@
"primeicons": "^7.0.0",
"primereact": "^10.8.2",
"react": "19.0.0-rc-f38c22b244-20240704",
"react-dom": "19.0.0-rc-f38c22b244-20240704",
"react-dom": "19.0.0",
"tailwindcss": "3.4.17",
"typescript": "5.7.2",
"use-debounce": "^10.0.1",
@ -29,7 +29,7 @@
"@types/bcrypt": "^5.0.2",
"@types/node": "22.10.2",
"@types/react": "18.3.18",
"@types/react-dom": "18.3.5"
"@types/react-dom": "19.0.2"
},
"engines": {
"node": ">=23.0.0"

56
pnpm-lock.yaml generated
View File

@ -25,10 +25,10 @@ importers:
version: 2.1.1
next:
specifier: 15.1.2
version: 15.1.2(@playwright/test@1.49.1)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
version: 15.1.2(@playwright/test@1.49.1)(react-dom@19.0.0(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
next-auth:
specifier: 5.0.0-beta.25
version: 5.0.0-beta.25(next@15.1.2(@playwright/test@1.49.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)
version: 5.0.0-beta.25(next@15.1.2(@playwright/test@1.49.1)(react-dom@19.0.0(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
postcss:
specifier: 8.4.49
version: 8.4.49
@ -37,13 +37,13 @@ importers:
version: 7.0.0
primereact:
specifier: ^10.8.2
version: 10.8.5(@types/react@18.3.18)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
version: 10.8.5(@types/react@18.3.18)(react-dom@19.0.0(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
react:
specifier: 19.0.0-rc-f38c22b244-20240704
version: 19.0.0-rc-f38c22b244-20240704
react-dom:
specifier: 19.0.0-rc-f38c22b244-20240704
version: 19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704)
specifier: 19.0.0
version: 19.0.0(react@19.0.0-rc-f38c22b244-20240704)
tailwindcss:
specifier: 3.4.17
version: 3.4.17
@ -73,8 +73,8 @@ importers:
specifier: 18.3.18
version: 18.3.18
'@types/react-dom':
specifier: 18.3.5
version: 18.3.5(@types/react@18.3.18)
specifier: 19.0.2
version: 19.0.2(@types/react@18.3.18)
packages:
@ -337,10 +337,10 @@ packages:
'@types/prop-types@15.7.12':
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
'@types/react-dom@18.3.5':
resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==}
'@types/react-dom@19.0.2':
resolution: {integrity: sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==}
peerDependencies:
'@types/react': ^18.0.0
'@types/react': ^19.0.0
'@types/react-transition-group@4.4.11':
resolution: {integrity: sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==}
@ -926,10 +926,10 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
react-dom@19.0.0-rc-f38c22b244-20240704:
resolution: {integrity: sha512-g89q2pf3irdpKFUMgCQgtxgqo3TSV1k1J6Sc8God4FwfxuNmAOOthkijENe5XZe6VeV1tor9DPzpjdTD9EyvNw==}
react-dom@19.0.0:
resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==}
peerDependencies:
react: 19.0.0-rc-f38c22b244-20240704
react: ^19.0.0
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@ -977,8 +977,8 @@ packages:
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
scheduler@0.25.0-rc-f38c22b244-20240704:
resolution: {integrity: sha512-uAELK9fHhvg7kDQhk29+uO8FUMWUpkg9WpzkNXFP+BJy5HEtqnajde3CxuSgh202WH9TqoaiWT1mdA3DvUu6cQ==}
scheduler@0.25.0:
resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
@ -1376,7 +1376,7 @@ snapshots:
'@types/prop-types@15.7.12': {}
'@types/react-dom@18.3.5(@types/react@18.3.18)':
'@types/react-dom@19.0.2(@types/react@18.3.18)':
dependencies:
'@types/react': 18.3.18
@ -1741,13 +1741,13 @@ snapshots:
nanoid@3.3.7: {}
next-auth@5.0.0-beta.25(next@15.1.2(@playwright/test@1.49.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.25(next@15.1.2(@playwright/test@1.49.1)(react-dom@19.0.0(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704):
dependencies:
'@auth/core': 0.37.2
next: 15.1.2(@playwright/test@1.49.1)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
next: 15.1.2(@playwright/test@1.49.1)(react-dom@19.0.0(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
react: 19.0.0-rc-f38c22b244-20240704
next@15.1.2(@playwright/test@1.49.1)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704):
next@15.1.2(@playwright/test@1.49.1)(react-dom@19.0.0(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704):
dependencies:
'@next/env': 15.1.2
'@swc/counter': 0.1.3
@ -1756,7 +1756,7 @@ snapshots:
caniuse-lite: 1.0.30001651
postcss: 8.4.31
react: 19.0.0-rc-f38c22b244-20240704
react-dom: 19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704)
react-dom: 19.0.0(react@19.0.0-rc-f38c22b244-20240704)
styled-jsx: 5.1.6(react@19.0.0-rc-f38c22b244-20240704)
optionalDependencies:
'@next/swc-darwin-arm64': 15.1.2
@ -1889,12 +1889,12 @@ snapshots:
primeicons@7.0.0: {}
primereact@10.8.5(@types/react@18.3.18)(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704):
primereact@10.8.5(@types/react@18.3.18)(react-dom@19.0.0(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704):
dependencies:
'@types/react-transition-group': 4.4.11
react: 19.0.0-rc-f38c22b244-20240704
react-dom: 19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704)
react-transition-group: 4.4.5(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
react-dom: 19.0.0(react@19.0.0-rc-f38c22b244-20240704)
react-transition-group: 4.4.5(react-dom@19.0.0(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704)
optionalDependencies:
'@types/react': 18.3.18
@ -1906,21 +1906,21 @@ snapshots:
queue-microtask@1.2.3: {}
react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704):
react-dom@19.0.0(react@19.0.0-rc-f38c22b244-20240704):
dependencies:
react: 19.0.0-rc-f38c22b244-20240704
scheduler: 0.25.0-rc-f38c22b244-20240704
scheduler: 0.25.0
react-is@16.13.1: {}
react-transition-group@4.4.5(react-dom@19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704):
react-transition-group@4.4.5(react-dom@19.0.0(react@19.0.0-rc-f38c22b244-20240704))(react@19.0.0-rc-f38c22b244-20240704):
dependencies:
'@babel/runtime': 7.26.0
dom-helpers: 5.2.1
loose-envify: 1.4.0
prop-types: 15.8.1
react: 19.0.0-rc-f38c22b244-20240704
react-dom: 19.0.0-rc-f38c22b244-20240704(react@19.0.0-rc-f38c22b244-20240704)
react-dom: 19.0.0(react@19.0.0-rc-f38c22b244-20240704)
react@19.0.0-rc-f38c22b244-20240704: {}
@ -1958,7 +1958,7 @@ snapshots:
safe-buffer@5.2.1: {}
scheduler@0.25.0-rc-f38c22b244-20240704: {}
scheduler@0.25.0: {}
semver@6.3.1: {}