Compare commits
No commits in common. "42d1de933f0ea8677123ea209bec97a437b03afb" and "c03df8920cfebf9b269981c098ee9f35eafcbf3c" have entirely different histories.
42d1de933f
...
c03df8920c
@ -1,109 +0,0 @@
|
|||||||
/* Copyright (C) 2024-2025 LibreWeddingPlanner contributors*/
|
|
||||||
|
|
||||||
'use client';
|
|
||||||
|
|
||||||
import { AbstractApi } from '@/app/api/abstract-api';
|
|
||||||
import { Guest } from '@/app/lib/guest';
|
|
||||||
import { Invitation, InvitationSerializer } from '@/app/lib/invitation';
|
|
||||||
import { useParams } from 'next/navigation';
|
|
||||||
import { Dropdown } from 'primereact/dropdown';
|
|
||||||
import { TabPanel, TabView } from 'primereact/tabview';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
|
|
||||||
function GuestForm({ guest }: { guest: Guest }) {
|
|
||||||
const [formResponses, setFormResponses] = useState<Guest['formResponses']>(guest.formResponses || {});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col gap-4">
|
|
||||||
<div>
|
|
||||||
<label className="block font-medium">Will you use the bus to get to the venue?</label>
|
|
||||||
<Dropdown
|
|
||||||
value={formResponses?.busNeeded ? 'Yes' : formResponses?.busNeeded === false ? 'No' : ''}
|
|
||||||
options={[
|
|
||||||
{ label: '', value: '' }, // Blank option as default
|
|
||||||
{ label: 'Yes', value: 'Yes' },
|
|
||||||
{ label: 'No', value: 'No' },
|
|
||||||
]}
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormResponses((prev) => ({
|
|
||||||
...prev,
|
|
||||||
busNeeded: e.value === 'Yes',
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
placeholder="Select an option"
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="block font-medium">Dietary Restrictions</label>
|
|
||||||
<textarea
|
|
||||||
value={formResponses?.dietaryRestrictions}
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormResponses((prev) => ({
|
|
||||||
...prev,
|
|
||||||
dietaryRestrictions: e.target.value,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
className="w-full p-2 border border-gray-300 rounded-md"
|
|
||||||
rows={3}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="block font-medium">Meal Preference</label>
|
|
||||||
<Dropdown
|
|
||||||
value={formResponses?.mealPreference}
|
|
||||||
options={[
|
|
||||||
{ label: '', value: '' }, // Blank option as default
|
|
||||||
{ label: 'Meat', value: 'Meat' },
|
|
||||||
{ label: 'Fish', value: 'Fish' },
|
|
||||||
]}
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormResponses((prev) => ({
|
|
||||||
...prev,
|
|
||||||
mealPreference: e.value,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
placeholder="Select an option"
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default function Page() {
|
|
||||||
const params = useParams<{ slug: string, id: string }>()
|
|
||||||
|
|
||||||
const serializer = new InvitationSerializer();
|
|
||||||
const api = new AbstractApi<Invitation>();
|
|
||||||
|
|
||||||
const [invitation, setInvitation] = useState<Invitation | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
api.get(serializer, params.id, (invitation) => {
|
|
||||||
setInvitation(invitation);
|
|
||||||
});
|
|
||||||
}, [params.slug, params.id]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{invitation && (
|
|
||||||
<div>
|
|
||||||
<p className="mb-4 font-medium">
|
|
||||||
{invitation.guests.length} seats have been reserved for this invitation.
|
|
||||||
</p>
|
|
||||||
<TabView className="border border-gray-300 rounded-md">
|
|
||||||
{invitation.guests.map((guest) => (
|
|
||||||
<TabPanel header={guest.name} >
|
|
||||||
<GuestForm guest={guest} />
|
|
||||||
</TabPanel>
|
|
||||||
))}
|
|
||||||
</TabView>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</div >
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col min-h-screen">
|
|
||||||
{/* Full-width image */}
|
|
||||||
<div className="w-full">
|
|
||||||
<img
|
|
||||||
src="/path-to-your-image.jpg"
|
|
||||||
alt="Wedding Banner"
|
|
||||||
className="w-full h-64 object-cover"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
{/* Body */}
|
|
||||||
<main className="flex-grow p-6 mx-auto" style={{ maxWidth: '60%' }}>
|
|
||||||
{children}
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -14,72 +14,25 @@ export class Guest implements Entity {
|
|||||||
color?: string;
|
color?: string;
|
||||||
status?: GuestStatus;
|
status?: GuestStatus;
|
||||||
children?: Guest[];
|
children?: Guest[];
|
||||||
formResponses?: {
|
|
||||||
busNeeded?: boolean;
|
|
||||||
dietaryRestrictions?: string;
|
|
||||||
mealPreference?: 'meat' | 'fish' | undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(
|
constructor(id?: string, name?: string, group_name?: string, groupId?: string, color?: string, status?: GuestStatus, children?: Guest[]) {
|
||||||
id?: string,
|
|
||||||
name?: string,
|
|
||||||
groupName?: string,
|
|
||||||
groupId?: string,
|
|
||||||
color?: string,
|
|
||||||
status?: GuestStatus,
|
|
||||||
children?: Guest[],
|
|
||||||
formResponses?: {
|
|
||||||
busNeeded?: boolean;
|
|
||||||
dietaryRestrictions?: string;
|
|
||||||
mealPreference?: 'meat' | 'fish' | undefined;
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.group_name = groupName;
|
this.group_name = group_name;
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.color = color;
|
this.color = color;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
this.children = children;
|
this.children = children;
|
||||||
this.formResponses = formResponses;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GuestSerializer implements Serializable<Guest> {
|
export class GuestSerializer implements Serializable<Guest> {
|
||||||
fromJson(data: any): Guest {
|
fromJson(data: any): Guest {
|
||||||
return new Guest(
|
return new Guest(data.id, data.name, data.group?.name, data.group?.id, data.color, data.status, data.children);
|
||||||
data.id,
|
|
||||||
data.name,
|
|
||||||
data.group?.name,
|
|
||||||
data.group?.id,
|
|
||||||
data.color,
|
|
||||||
data.status,
|
|
||||||
data.children,
|
|
||||||
data.form_responses
|
|
||||||
? {
|
|
||||||
busNeeded: data.form_responses.bus_needed,
|
|
||||||
dietaryRestrictions: data.form_responses.dietary_restrictions,
|
|
||||||
mealPreference: data.form_responses.meal_preference,
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toJson(guest: Guest): string {
|
toJson(guest: Guest): string {
|
||||||
return JSON.stringify({
|
return JSON.stringify({ guest: { name: guest.name, status: guest.status, group_id: guest.groupId } });
|
||||||
guest: {
|
|
||||||
name: guest.name,
|
|
||||||
status: guest.status,
|
|
||||||
group_id: guest.groupId,
|
|
||||||
form_responses: guest.formResponses
|
|
||||||
? {
|
|
||||||
bus_needed: guest.formResponses.busNeeded,
|
|
||||||
dietary_restrictions: guest.formResponses.dietaryRestrictions,
|
|
||||||
meal_preference: guest.formResponses.mealPreference,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apiPath(): string {
|
apiPath(): string {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user