Compare commits

...

8 Commits

Author SHA1 Message Date
Renovate Bot
c2424ef40f Update dependency @types/react-dom to v18.3.5
All checks were successful
Playwright Tests / test (pull_request) Has been skipped
Check usage of free licenses / build-static-assets (pull_request) Successful in 5m54s
Add copyright notice / copyright_notice (pull_request) Successful in 8m17s
2024-12-12 01:09:23 +00:00
09a37675a9 Merge pull request 'Fix compilation issue' (#151) from dashboard into main
All checks were successful
Playwright Tests / test (push) Has been skipped
Check usage of free licenses / build-static-assets (push) Successful in 35s
Build Nginx-based docker image / build-static-assets (push) Successful in 3m11s
Reviewed-on: #151
2024-12-11 23:20:55 +00:00
9029d756e7 Fix compilation issue
All checks were successful
Playwright Tests / test (pull_request) Has been skipped
Check usage of free licenses / build-static-assets (pull_request) Successful in 28s
Add copyright notice / copyright_notice (pull_request) Successful in 33s
2024-12-12 00:19:46 +01:00
93662f5903 Merge pull request 'Load dashboard information from the backend' (#150) from dashboard into main
Some checks failed
Playwright Tests / test (push) Has been skipped
Check usage of free licenses / build-static-assets (push) Successful in 23s
Build Nginx-based docker image / build-static-assets (push) Failing after 3m39s
Reviewed-on: #150
2024-12-11 07:45:08 +00:00
7dbfbb76b7 Load dashboard information from the backend
All checks were successful
Playwright Tests / test (pull_request) Has been skipped
Check usage of free licenses / build-static-assets (pull_request) Successful in 18s
Add copyright notice / copyright_notice (pull_request) Successful in 20s
2024-12-11 08:38:50 +01:00
Renovate Bot
53811299c8 Update dependency node to v23.4.0
All checks were successful
Playwright Tests / test (push) Has been skipped
Check usage of free licenses / build-static-assets (push) Successful in 2m31s
Build Nginx-based docker image / build-static-assets (push) Successful in 33m47s
2024-12-11 02:20:15 +00:00
Renovate Bot
6731dcc874 Update dependency @playwright/test to v1.49.1
Some checks failed
Playwright Tests / test (pull_request) Has been skipped
Check usage of free licenses / build-static-assets (pull_request) Successful in 4m22s
Add copyright notice / copyright_notice (pull_request) Successful in 18m42s
Check usage of free licenses / build-static-assets (push) Waiting to run
Playwright Tests / test (push) Waiting to run
Build Nginx-based docker image / build-static-assets (push) Has been cancelled
2024-12-11 01:09:29 +00:00
c57bdec9fc Fix navigation link to the dashboard 2024-12-11 00:35:56 +01:00
8 changed files with 105 additions and 70 deletions

2
.nvmrc
View File

@ -1 +1 @@
23.3.0 23.4.0

View File

@ -1,9 +1,26 @@
/* Copyright (C) 2024 Manuel Bustillo*/ /* Copyright (C) 2024 Manuel Bustillo*/
'use client'
import { GlobalSummary as Summary } from '@/app/lib/definitions';
import { getSlug } from '@/app/lib/utils';
import GlobalSummary from '@/app/ui/dashboard/global-summary'; import GlobalSummary from '@/app/ui/dashboard/global-summary';
import { useEffect, useState } from 'react';
export default function Page() { export default function Page() {
return( const [globalSummary, setGlobalSummary] = useState<Summary | undefined>(undefined);
<GlobalSummary />
function refreshSummary() {
fetch(`/api/${getSlug()}/summary`)
.then((response) => response.json())
.then((data) => {
setGlobalSummary(data);
})
}
useEffect(refreshSummary, []);
return (
globalSummary && <GlobalSummary summary={globalSummary} />
); );
} }

View File

@ -1,5 +1,6 @@
/* Copyright (C) 2024 Manuel Bustillo*/ /* Copyright (C) 2024 Manuel Bustillo*/
import { AttendanceSummary } from "./group";
import { Guest } from "./guest"; import { Guest } from "./guest";
export interface Entity { export interface Entity {
@ -38,3 +39,22 @@ export type Captcha = {
export type StructuredErrors = { export type StructuredErrors = {
[key: string]: string[] | string; [key: string]: string[] | string;
}; };
export type GlobalSummary = {
expenses: ExpenseSummary;
guests: AttendanceSummary
}
export type ExpenseSummary = {
projected: ExpensePossibleSummary;
confirmed: ExpensePossibleSummary;
status: StatusSummary;
}
export type ExpensePossibleSummary = {
total: number;
guests: number;
}
export type StatusSummary = {
paid: number;
}

View File

@ -21,7 +21,7 @@ const colorClasses = (style: Style) => {
} }
} }
export async function MainCard({ amount, title, subtitle, style, iconName }: export function MainCard({ amount, title, subtitle, style, iconName }:
{ {
amount: string, amount: string,
title: string, title: string,
@ -42,7 +42,7 @@ export async function MainCard({ amount, title, subtitle, style, iconName }:
); );
} }
export async function SecondaryCard({ amount, title, iconName, style }: { amount: string, title: string, iconName: keyof typeof HeroIcon, style: Style }) { export function SecondaryCard({ amount, title, iconName, style }: { amount: string, title: string, iconName: keyof typeof HeroIcon, style: Style }) {
return ( return (
<div className={`h-12 w-80 m-1 p-2 text-white flex flex-row items-center ${colorClasses(style)}`}> <div className={`h-12 w-80 m-1 p-2 text-white flex flex-row items-center ${colorClasses(style)}`}>
<Icon className="m-3 h-7 w-7" name={iconName} /> <Icon className="m-3 h-7 w-7" name={iconName} />

View File

@ -1,45 +1,41 @@
/* Copyright (C) 2024 Manuel Bustillo*/ /* Copyright (C) 2024 Manuel Bustillo*/
import { GlobalSummary as Summary} from '@/app/lib/definitions';
import { MainCard, SecondaryCard } from '../components/dashboard-cards'; import { MainCard, SecondaryCard } from '../components/dashboard-cards';
export default async function GlobalSummary() { export default function GlobalSummary({ summary }: { summary: Summary }) {
return ( return (
<div className="my-4"> <div className="my-4">
<div className="flex flex-row w-full my-2"> <div className="flex flex-row w-full my-2">
<MainCard style="green" amount="65000€" title="Projected" subtitle="150 guests" iconName="ArrowTrendingUpIcon" />
<div className="flex flex-col"> <div className="flex flex-col">
<MainCard amount="10000€" title="Paid already" iconName="Square3Stack3DIcon" style='blue' /> <MainCard amount={`${summary.expenses.projected.total}`} title="Projected" subtitle={`${summary.expenses.projected.guests} guests`} style="blue" iconName="ArrowTrendingUpIcon" />
<MainCard amount="198€" title="/ guest" iconName="UserIcon" style='blue' /> <MainCard amount={`${Math.round(summary.expenses.projected.total / summary.expenses.projected.guests)}`} title="/ guest" iconName="UserIcon" style='blue' />
</div> </div>
<div className="flex flex-col"> <div className="flex flex-col">
<MainCard amount="78000€" title="Max." subtitle='200 guests' iconName="ChevronDoubleUpIcon" style="orange" /> <MainCard amount={`${summary.expenses.confirmed.total}`} title="Min." subtitle={`${summary.expenses.confirmed.guests} guests`} iconName="ChevronDoubleDownIcon" style="green" />
<MainCard amount="45000€" title="Min." subtitle="125 guests" iconName="ChevronDoubleDownIcon" style="green" /> <MainCard amount={`${Math.round(summary.expenses.confirmed.total / summary.expenses.confirmed.guests)}`} title="/ guest" iconName="UserIcon" style='green' />
</div>
<div className="flex flex-col">
<MainCard amount={`${summary.expenses.status.paid}`} title="Paid already" subtitle={`${Math.round(summary.expenses.status.paid / summary.expenses.projected.total * 100)}% of projected`} iconName="CheckIcon" style='blue' />
<MainCard amount={`${summary.expenses.projected.total - summary.expenses.status.paid}`} title="To pay" subtitle={`${100 - Math.round(summary.expenses.status.paid / summary.expenses.projected.total * 100)}% of projected`} iconName="BanknotesIcon" style="orange" />
</div> </div>
</div> </div>
<div className="flex flex-row w-full my-2"> <div className="flex flex-row w-full my-2">
<MainCard style="blue" amount="150" title="Invites sent" iconName="UsersIcon" /> <MainCard style="blue" amount={summary.guests.total.toString()} title="Invites sent" iconName="UsersIcon" />
<div className="flex flex-col"> <div className="flex flex-col">
<SecondaryCard amount="31%" title="confirmed (27 guests)" iconName="CheckIcon" style='green' /> <SecondaryCard amount={`${Math.round(summary.guests.confirmed / summary.guests.total * 100)}%`} title={`confirmed (${summary.guests.confirmed} guests)`} iconName="CheckIcon" style='green' />
<SecondaryCard amount="5%" title="declined (8 guests)" iconName="XMarkIcon" style='red' /> <SecondaryCard amount={`${Math.round(summary.guests.declined / summary.guests.total * 100)}%`} title={`declined (${summary.guests.declined} guests)`} iconName="XMarkIcon" style='red' />
</div> </div>
<div className="flex flex-col"> <div className="flex flex-col">
<SecondaryCard amount="17%" title="tentative (14 guests)" iconName="QuestionMarkCircleIcon" style='orange' /> <SecondaryCard amount={`${Math.round(summary.guests.tentative / summary.guests.total * 100)}%`} title={`tentative (${summary.guests.tentative} guests)`} iconName="QuestionMarkCircleIcon" style='orange' />
<SecondaryCard amount="65%" title="awaiting (72 guests)" iconName="EllipsisHorizontalIcon" style='gray' /> <SecondaryCard amount={`${Math.round(summary.guests.invited / summary.guests.total * 100)}%`} title={`awaiting (${summary.guests.invited} guests)`} iconName="EllipsisHorizontalIcon" style='gray' />
</div> </div>
</div> </div>
<div className="flex flex-row w-full my-2">
<MainCard style="blue" amount="5" title="Table simulations" iconName="ServerStackIcon" />
<MainCard style="blue" amount="9" title="Bus simulations" iconName="TruckIcon" />
<MainCard style="blue" amount="98" title="QR codes" iconName="QrCodeIcon" />
</div>
</div> </div>
); );
} }

View File

@ -17,7 +17,7 @@ export default function SideNav() {
<div className="flex h-full flex-col px-3 py-4 md:px-2"> <div className="flex h-full flex-col px-3 py-4 md:px-2">
<Link <Link
className="mb-2 flex h-20 items-center justify-start rounded-md bg-blue-600 p-4 md:h-20" className="mb-2 flex h-20 items-center justify-start rounded-md bg-blue-600 p-4 md:h-20"
href="/dashboard/guests" href={`/${getSlug()}/dashboard`}
> >
<div className={`${gloriaHallelujah.className} "w-32 text-white md:w-40 antialiased`}> <div className={`${gloriaHallelujah.className} "w-32 text-white md:w-40 antialiased`}>
<h1>Wedding Planner</h1> <h1>Wedding Planner</h1>

View File

@ -28,7 +28,7 @@
"@types/bcrypt": "^5.0.2", "@types/bcrypt": "^5.0.2",
"@types/node": "22.10.1", "@types/node": "22.10.1",
"@types/react": "18.3.12", "@types/react": "18.3.12",
"@types/react-dom": "18.3.1" "@types/react-dom": "18.3.5"
}, },
"engines": { "engines": {
"node": ">=23.0.0" "node": ">=23.0.0"

48
pnpm-lock.yaml generated
View File

@ -25,10 +25,10 @@ importers:
version: 2.1.1 version: 2.1.1
next: next:
specifier: 15.0.3 specifier: 15.0.3
version: 15.0.3(@playwright/test@1.49.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.0.3(@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-auth: next-auth:
specifier: 5.0.0-beta.25 specifier: 5.0.0-beta.25
version: 5.0.0-beta.25(next@15.0.3(@playwright/test@1.49.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.25(next@15.0.3(@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)
postcss: postcss:
specifier: 8.4.49 specifier: 8.4.49
version: 8.4.49 version: 8.4.49
@ -59,7 +59,7 @@ importers:
devDependencies: devDependencies:
'@playwright/test': '@playwright/test':
specifier: ^1.46.0 specifier: ^1.46.0
version: 1.49.0 version: 1.49.1
'@types/bcrypt': '@types/bcrypt':
specifier: ^5.0.2 specifier: ^5.0.2
version: 5.0.2 version: 5.0.2
@ -70,8 +70,8 @@ importers:
specifier: 18.3.12 specifier: 18.3.12
version: 18.3.12 version: 18.3.12
'@types/react-dom': '@types/react-dom':
specifier: 18.3.1 specifier: 18.3.5
version: 18.3.1 version: 18.3.5(@types/react@18.3.12)
packages: packages:
@ -306,8 +306,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.49.0': '@playwright/test@1.49.1':
resolution: {integrity: sha512-DMulbwQURa8rNIQrf94+jPJQ4FmOVdpE5ZppRNvWVjvhC+6sOeo28r8MgIpQRYouXRtt/FCCXU7zn20jnHR4Qw==} resolution: {integrity: sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==}
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
@ -334,8 +334,10 @@ packages:
'@types/prop-types@15.7.12': '@types/prop-types@15.7.12':
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
'@types/react-dom@18.3.1': '@types/react-dom@18.3.5':
resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==} resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==}
peerDependencies:
'@types/react': ^18.0.0
'@types/react-transition-group@4.4.11': '@types/react-transition-group@4.4.11':
resolution: {integrity: sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==} resolution: {integrity: sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==}
@ -835,13 +837,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.49.0: playwright-core@1.49.1:
resolution: {integrity: sha512-R+3KKTQF3npy5GTiKH/T+kdhoJfJojjHESR1YEWhYuEKRVfVaxH3+4+GvXE5xyCngCxhxnykk0Vlah9v8fs3jA==} resolution: {integrity: sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==}
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
playwright@1.49.0: playwright@1.49.1:
resolution: {integrity: sha512-eKpmys0UFDnfNb3vfsf8Vx2LEOtflgRebl0Im2eQQnYMA4Aqd+Zw8bEOB+7ZKvN76901mRnqdsiOGKxzVTbi7A==} resolution: {integrity: sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==}
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
@ -1337,9 +1339,9 @@ snapshots:
'@pkgjs/parseargs@0.11.0': '@pkgjs/parseargs@0.11.0':
optional: true optional: true
'@playwright/test@1.49.0': '@playwright/test@1.49.1':
dependencies: dependencies:
playwright: 1.49.0 playwright: 1.49.1
'@swc/counter@0.1.3': {} '@swc/counter@0.1.3': {}
@ -1364,7 +1366,7 @@ snapshots:
'@types/prop-types@15.7.12': {} '@types/prop-types@15.7.12': {}
'@types/react-dom@18.3.1': '@types/react-dom@18.3.5(@types/react@18.3.12)':
dependencies: dependencies:
'@types/react': 18.3.12 '@types/react': 18.3.12
@ -1729,13 +1731,13 @@ snapshots:
nanoid@3.3.7: {} nanoid@3.3.7: {}
next-auth@5.0.0-beta.25(next@15.0.3(@playwright/test@1.49.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): next-auth@5.0.0-beta.25(next@15.0.3(@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):
dependencies: dependencies:
'@auth/core': 0.37.2 '@auth/core': 0.37.2
next: 15.0.3(@playwright/test@1.49.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.0.3(@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 react: 19.0.0-rc-f38c22b244-20240704
next@15.0.3(@playwright/test@1.49.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.0.3(@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):
dependencies: dependencies:
'@next/env': 15.0.3 '@next/env': 15.0.3
'@swc/counter': 0.1.3 '@swc/counter': 0.1.3
@ -1755,7 +1757,7 @@ snapshots:
'@next/swc-linux-x64-musl': 15.0.3 '@next/swc-linux-x64-musl': 15.0.3
'@next/swc-win32-arm64-msvc': 15.0.3 '@next/swc-win32-arm64-msvc': 15.0.3
'@next/swc-win32-x64-msvc': 15.0.3 '@next/swc-win32-x64-msvc': 15.0.3
'@playwright/test': 1.49.0 '@playwright/test': 1.49.1
sharp: 0.33.5 sharp: 0.33.5
transitivePeerDependencies: transitivePeerDependencies:
- '@babel/core' - '@babel/core'
@ -1815,11 +1817,11 @@ snapshots:
pirates@4.0.6: {} pirates@4.0.6: {}
playwright-core@1.49.0: {} playwright-core@1.49.1: {}
playwright@1.49.0: playwright@1.49.1:
dependencies: dependencies:
playwright-core: 1.49.0 playwright-core: 1.49.1
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.2