diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 522514a..7b863f2 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -9,7 +9,6 @@ concurrency: cancel-in-progress: true jobs: test: - if: false timeout-minutes: 60 runs-on: ubuntu-latest container: @@ -22,10 +21,15 @@ jobs: - name: Install dependencies run: npm install -g pnpm && pnpm install - name: Build the service that will be tested - run: npm run build + run: | + pnpm run build + cp -r public .next/standalone/ + cp -r .next/static .next/standalone/.next/ - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run the service that will be tested - run: npm run start & + run: HOSTNAME=127.0.0.1 node .next/standalone/server.js & + - name: Wait for the service to be ready + run: npx wait-on http://127.0.0.1:3000/default/ --timeout 30000 - name: Run Playwright tests run: pnpm exec playwright test diff --git a/app/[slug]/dashboard/guests/page.tsx b/app/[slug]/dashboard/guests/page.tsx index 7915188..137cd10 100644 --- a/app/[slug]/dashboard/guests/page.tsx +++ b/app/[slug]/dashboard/guests/page.tsx @@ -15,37 +15,43 @@ import SkeletonTable from '@/app/ui/guests/skeleton-row'; import GuestsTable from '@/app/ui/guests/table'; import { TabPanel, TabView } from 'primereact/tabview'; import { Toast } from 'primereact/toast'; -import { Suspense, useRef, useState } from 'react'; +import { Suspense, useEffect, useRef, useState } from 'react'; import InvitationsBoard from '@/app/ui/invitations/board'; import { Invitation, InvitationSerializer } from '@/app/lib/invitation'; export default function Page() { + const [slug, setSlug] = useState("default"); + + useEffect(() => { + setSlug(getSlug()); + refreshGroups(); + refreshGuests(); + refreshInvitations(); + }, []); + const toast = useRef(null); function refreshGuests() { new AbstractApi().getAll(new GuestSerializer(), (objects: Guest[]) => { setGuests(objects); - setGuestsLoaded(true); }); } function refreshGroups() { new AbstractApi().getAll(new GroupSerializer(), (objects: Group[]) => { setGroups(objects); - setGroupsLoaded(true); }); } function refreshInvitations() { new AbstractApi().getAll(new InvitationSerializer(), (objects: Invitation[]) => { setInvitations(objects); - setInvitationsLoaded(true); }); } function resetAffinities() { - fetch(`/api/${getSlug()}/groups/affinities/reset`, { + fetch(`/api/${slug}/groups/affinities/reset`, { method: 'POST', headers: { 'Accept': 'application/json', @@ -72,23 +78,17 @@ export default function Page() { }); } - const [groupsLoaded, setGroupsLoaded] = useState(false); const [groups, setGroups] = useState>([]); const [groupBeingEdited, setGroupBeingEdited] = useState(undefined); const [groupAffinitiesBeingEditted, setGroupAffinitiesBeingEditted] = useState(undefined); - const [guestsLoaded, setGuestsLoaded] = useState(false); const [guests, setGuests] = useState>([]); const [guestBeingEdited, setGuestBeingEdited] = useState(undefined); - const [invitationsLoaded, setInvitationsLoaded] = useState(false); const [invitations, setInvitations] = useState>([]); - const [invitationBeingEdited, setInvitationBeingEdited] = useState(undefined); - !groupsLoaded && refreshGroups(); - !guestsLoaded && refreshGuests(); - !invitationsLoaded && refreshInvitations(); + return (
diff --git a/app/[slug]/page.tsx b/app/[slug]/page.tsx index f189a6a..a4d9a70 100644 --- a/app/[slug]/page.tsx +++ b/app/[slug]/page.tsx @@ -16,11 +16,11 @@ export default async function Page() { if (getCsrfToken() == 'unknown') { retrieveCSRFToken(); } - }, []); - if (typeof window !== 'undefined') { - localStorage.setItem('slug', await params.slug); - } + if (typeof window !== 'undefined') { + localStorage.setItem('slug', params.slug); + } + }, []); return (
diff --git a/app/ui/arrangements/arrangement.tsx b/app/ui/arrangements/arrangement.tsx index d8bf0b1..d2ec567 100644 --- a/app/ui/arrangements/arrangement.tsx +++ b/app/ui/arrangements/arrangement.tsx @@ -5,7 +5,6 @@ import { AbstractApi } from '@/app/api/abstract-api'; import { TableArrangement } from '@/app/lib/definitions'; import { TableSimulation, TableSimulationSerializer } from '@/app/lib/tableSimulation'; -import { getSlug } from '@/app/lib/utils'; import { Table } from '@/app/ui/components/table'; import { lusitana } from '@/app/ui/fonts'; import { useState, useEffect } from 'react'; diff --git a/app/ui/components/login-form.tsx b/app/ui/components/login-form.tsx index 7b808c2..fd575b6 100644 --- a/app/ui/components/login-form.tsx +++ b/app/ui/components/login-form.tsx @@ -15,6 +15,9 @@ export default function LoginForm() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); + const [slug, setSlug] = useState("default"); + useEffect(() => {setSlug(getSlug())}, []); + const router = useRouter(); const [currentUser, setCurrentUser] = useState(null); @@ -41,7 +44,7 @@ export default function LoginForm() { password: password, onLogin: (user) => { setCurrentUser(user); - router.push(`${getSlug()}/dashboard`) + router.push(`${slug}/dashboard`) } })}> Sign in diff --git a/app/ui/components/registration-form.tsx b/app/ui/components/registration-form.tsx index 3de63ea..f6594c6 100644 --- a/app/ui/components/registration-form.tsx +++ b/app/ui/components/registration-form.tsx @@ -17,7 +17,9 @@ export default function RegistrationForm() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [passwordConfirmation, setPasswordConfirmation] = useState(""); - const [slug, setSlug] = useState(getSlug()); + + const [slug, setSlug] = useState("default"); + useEffect(() => { setSlug(getSlug()) }, []); const [captchaId, setCaptchaId] = useState(""); const [captchaUrl, setCaptchaUrl] = useState(""); diff --git a/app/ui/dashboard/nav-links.tsx b/app/ui/dashboard/nav-links.tsx index ef3e4ea..336d798 100644 --- a/app/ui/dashboard/nav-links.tsx +++ b/app/ui/dashboard/nav-links.tsx @@ -11,19 +11,23 @@ import Link from 'next/link'; import { usePathname } from 'next/navigation'; import clsx from 'clsx'; import { getSlug } from '@/app/lib/utils'; +import { useEffect, useState } from 'react'; // Map of links to display in the side navigation. // Depending on the size of the application, this would be stored in a database. -const links = [ - { name: 'Guests', href: `/${getSlug()}/dashboard/guests`, icon: UserGroupIcon }, - { name: 'Expenses', href: `/${getSlug()}/dashboard/expenses`, icon: BanknotesIcon }, - { name: 'Table distributions', href: `/${getSlug()}/dashboard/tables`, icon: RectangleGroupIcon }, -]; - export default function NavLinks() { const pathname = usePathname(); + const [slug, setSlug] = useState("default"); + useEffect(() => { setSlug(getSlug()) }, []); + + const links = [ + { name: 'Guests', href: `/${slug}/dashboard/guests`, icon: UserGroupIcon }, + { name: 'Expenses', href: `/${slug}/dashboard/expenses`, icon: BanknotesIcon }, + { name: 'Table distributions', href: `/${slug}/dashboard/tables`, icon: RectangleGroupIcon }, + ]; + return ( <> {links.map((link) => { diff --git a/app/ui/dashboard/sidenav.tsx b/app/ui/dashboard/sidenav.tsx index fbba770..067de4b 100644 --- a/app/ui/dashboard/sidenav.tsx +++ b/app/ui/dashboard/sidenav.tsx @@ -9,15 +9,23 @@ import { gloriaHallelujah } from '@/app/ui/fonts'; import { logout } from '@/app/api/authentication'; import { useRouter } from 'next/navigation'; import { getSlug } from '@/app/lib/utils'; +import { useEffect, useState } from 'react'; export default function SideNav() { const router = useRouter(); + const [slug, setSlug] = useState("default"); + useEffect(() => { setSlug(getSlug()) }, []); + + const [currentUser, setCurrentUser] = useState<{ email: string } | null>(null); + useEffect(() => { setCurrentUser(JSON.parse(localStorage.getItem('currentUser') || '{}')) }, []); + + return (

Wedding Planner

@@ -26,14 +34,14 @@ export default function SideNav() {
- Logged in as {JSON.parse(localStorage.getItem('currentUser') || '{}').email} + Logged in as {currentUser?.email}