Fix additional use of localstorage in the server side
Some checks failed
Check usage of free licenses / build-static-assets (pull_request) Successful in 58s
Add copyright notice / copyright_notice (pull_request) Successful in 1m19s
Build Nginx-based docker image / build-static-assets (push) Successful in 5m39s
Playwright Tests / test (pull_request) Failing after 9m0s

This commit is contained in:
Manuel Bustillo 2025-06-08 13:12:51 +02:00
parent 7719929e43
commit 1c0570d1a8
4 changed files with 29 additions and 21 deletions

View File

@ -22,28 +22,31 @@ import { Invitation, InvitationSerializer } from '@/app/lib/invitation';
export default function Page() { export default function Page() {
const [slug, setSlug] = useState<string>("default"); const [slug, setSlug] = useState<string>("default");
useEffect(() => { setSlug(getSlug()) }, []);
useEffect(() => {
setSlug(getSlug());
refreshGroups();
refreshGuests();
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);
setGuestsLoaded(true);
}); });
} }
function refreshGroups() { function refreshGroups() {
new AbstractApi<Group>().getAll(new GroupSerializer(), (objects: Group[]) => { new AbstractApi<Group>().getAll(new GroupSerializer(), (objects: Group[]) => {
setGroups(objects); setGroups(objects);
setGroupsLoaded(true);
}); });
} }
function refreshInvitations() { function refreshInvitations() {
new AbstractApi<Invitation>().getAll(new InvitationSerializer(), (objects: Invitation[]) => { new AbstractApi<Invitation>().getAll(new InvitationSerializer(), (objects: Invitation[]) => {
setInvitations(objects); setInvitations(objects);
setInvitationsLoaded(true);
}); });
} }
@ -75,23 +78,17 @@ export default function Page() {
}); });
} }
const [groupsLoaded, setGroupsLoaded] = useState(false);
const [groups, setGroups] = useState<Array<Group>>([]); const [groups, setGroups] = useState<Array<Group>>([]);
const [groupBeingEdited, setGroupBeingEdited] = useState<Group | undefined>(undefined); const [groupBeingEdited, setGroupBeingEdited] = useState<Group | undefined>(undefined);
const [groupAffinitiesBeingEditted, setGroupAffinitiesBeingEditted] = useState<Group | undefined>(undefined); const [groupAffinitiesBeingEditted, setGroupAffinitiesBeingEditted] = useState<Group | undefined>(undefined);
const [guestsLoaded, setGuestsLoaded] = useState(false);
const [guests, setGuests] = useState<Array<Guest>>([]); const [guests, setGuests] = useState<Array<Guest>>([]);
const [guestBeingEdited, setGuestBeingEdited] = useState<Guest | undefined>(undefined); const [guestBeingEdited, setGuestBeingEdited] = useState<Guest | undefined>(undefined);
const [invitationsLoaded, setInvitationsLoaded] = useState(false);
const [invitations, setInvitations] = useState<Array<Invitation>>([]); const [invitations, setInvitations] = useState<Array<Invitation>>([]);
const [invitationBeingEdited, setInvitationBeingEdited] = useState<Invitation | undefined>(undefined);
!groupsLoaded && refreshGroups();
!guestsLoaded && refreshGuests();
!invitationsLoaded && refreshInvitations();
return ( return (
<div className="w-full"> <div className="w-full">

View File

@ -5,7 +5,6 @@
import { AbstractApi } from '@/app/api/abstract-api'; import { AbstractApi } from '@/app/api/abstract-api';
import { TableArrangement } from '@/app/lib/definitions'; import { TableArrangement } from '@/app/lib/definitions';
import { TableSimulation, TableSimulationSerializer } from '@/app/lib/tableSimulation'; import { TableSimulation, TableSimulationSerializer } from '@/app/lib/tableSimulation';
import { getSlug } from '@/app/lib/utils';
import { Table } from '@/app/ui/components/table'; import { Table } from '@/app/ui/components/table';
import { lusitana } from '@/app/ui/fonts'; import { lusitana } from '@/app/ui/fonts';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';

View File

@ -11,19 +11,23 @@ import Link from 'next/link';
import { usePathname } from 'next/navigation'; import { usePathname } from 'next/navigation';
import clsx from 'clsx'; import clsx from 'clsx';
import { getSlug } from '@/app/lib/utils'; import { getSlug } from '@/app/lib/utils';
import { useEffect, useState } from 'react';
// Map of links to display in the side navigation. // Map of links to display in the side navigation.
// Depending on the size of the application, this would be stored in a database. // 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() { export default function NavLinks() {
const pathname = usePathname(); const pathname = usePathname();
const [slug, setSlug] = useState<string>("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 ( return (
<> <>
{links.map((link) => { {links.map((link) => {

View File

@ -9,15 +9,23 @@ import { gloriaHallelujah } from '@/app/ui/fonts';
import { logout } from '@/app/api/authentication'; import { logout } from '@/app/api/authentication';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { getSlug } from '@/app/lib/utils'; import { getSlug } from '@/app/lib/utils';
import { useEffect, useState } from 'react';
export default function SideNav() { export default function SideNav() {
const router = useRouter(); const router = useRouter();
const [slug, setSlug] = useState<string>("default");
useEffect(() => { setSlug(getSlug()) }, []);
const [currentUser, setCurrentUser] = useState<{ email: string } | null>(null);
useEffect(() => { setCurrentUser(JSON.parse(localStorage.getItem('currentUser') || '{}')) }, []);
return ( return (
<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={`/${getSlug()}/dashboard`} href={`/${slug}/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>
@ -26,14 +34,14 @@ export default function SideNav() {
<div className="flex grow flex-row justify-between space-x-2 md:flex-col md:space-x-0 md:space-y-2"> <div className="flex grow flex-row justify-between space-x-2 md:flex-col md:space-x-0 md:space-y-2">
<NavLinks /> <NavLinks />
<div className="hidden h-auto w-full grow rounded-md bg-gray-50 md:block"></div> <div className="hidden h-auto w-full grow rounded-md bg-gray-50 md:block"></div>
<span>Logged in as {JSON.parse(localStorage.getItem('currentUser') || '{}').email}</span> <span>Logged in as {currentUser?.email}</span>
<button <button
className="flex h-[48px] w-full grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3" className="flex h-[48px] w-full grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
onClick={() => { onClick={() => {
logout({ logout({
onLogout: () => { onLogout: () => {
localStorage.clear(); localStorage.clear();
router.push(`/${getSlug()}`); router.push(`/${slug}`);
} }
}); });
}} }}