editing event data

This commit is contained in:
2025-06-25 13:18:16 -04:00
parent a659401bde
commit 6751bcb8b4
10 changed files with 346 additions and 16 deletions

View File

@@ -0,0 +1,172 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
'use client'
import React, { useState } from 'react'
interface Creator {
id: string
email: string
name: string | null
role: 'COUPLE' | 'PLANNER' | 'GUEST'
}
interface EventData {
id: string
name: string
date: Date | null
location: string | null
creatorId: string
createdAt: string
creator: Creator
guests: any[]
}
interface Props {
event: EventData
}
export default function EventInfoDisplay({ event }: Props) {
const [isEditing, setIsEditing] = useState(false)
const [saving, setSaving] = useState(false)
const [error, setError] = useState('')
const [dateTime, setDateTime] = useState(() => {
if (event.date) {
const date = new Date(event.date);
return new Date(date.getTime() - date.getTimezoneOffset() * 60000)
.toISOString()
.slice(0, 16); // format: "yyyy-MM-ddTHH:mm"
}
return '';
});
const [form, setForm] = useState({
name: event.name,
date: dateTime,
location: event.location || '',
})
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
const { name, value } = e.target
setForm(prev => ({ ...prev, [name]: value }))
}
async function handleSave() {
setSaving(true)
setError('')
try {
const res = await fetch(`/api/events/${event.id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(form),
})
if (!res.ok) {
const data = await res.json()
setError(data.message || 'Update failed')
return
}
setIsEditing(false)
} catch (err) {
setError('Something went wrong.')
} finally {
setSaving(false)
}
}
function formatDate(date: string) {
const d = new Date(date)
return `${d.toLocaleDateString()} ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`
}
return (
<div className="border p-6 rounded-lg shadow bg-white space-y-4">
<div className="flex justify-between items-start">
<h2 className="text-2xl font-bold">Event Info</h2>
<button
onClick={() => setIsEditing(prev => !prev)}
className="text-sm text-blue-600 underline"
>
{isEditing ? 'Cancel' : 'Edit'}
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{/* Event Name */}
<div>
<label className="block text-sm font-semibold">Event Name</label>
{isEditing ? (
<input
name="name"
type="text"
className="input input-bordered w-full"
value={form.name}
onChange={handleChange}
required
/>
) : (
<p>{event.name}</p>
)}
</div>
{/* Event Date */}
<div>
<label className="block text-sm font-semibold">Date</label>
{isEditing ? (
<input
type="datetime-local"
className="input input-bordered w-full"
value={dateTime}
onChange={(e) => setDateTime(e.target.value)}
/>
) : (
<p>{event.date ? formatDate(event.date.toDateString()) : 'N/A'}</p>
)}
</div>
{/* Location */}
<div>
<label className="block text-sm font-semibold">Location</label>
{isEditing ? (
<input
name="location"
type="text"
className="input input-bordered w-full"
value={form.location}
onChange={handleChange}
/>
) : (
<p>{event.location || 'N/A'}</p>
)}
</div>
{/* Creator Email */}
<div>
<label className="block text-sm font-semibold">Creator Email</label>
<p>{event.creator.email}</p>
</div>
{/* Created At */}
<div className="md:col-span-2">
<label className="block text-sm font-semibold">Created At</label>
<p>{formatDate(event.createdAt)}</p>
</div>
</div>
{error && <p className="text-red-500 text-sm">{error}</p>}
{isEditing && (
<div className="text-right">
<button
onClick={handleSave}
disabled={saving}
className="btn btn-primary"
>
{saving ? 'Saving...' : 'Save Changes'}
</button>
</div>
)}
</div>
)
}

View File

@@ -0,0 +1,77 @@
'use client'
import React, { useState } from 'react'
import PencilIcon from './icons/PencilIcon'
export default function HeadingWithEdit({
title,
eventId,
}: {
title: string
eventId: string
}) {
const [edit, setEdit] = useState(false)
const [currentTitle, setCurrentTitle] = useState(title)
const [newTitle, setNewTitle] = useState(title)
const [saving, setSaving] = useState(false)
const [error, setError] = useState('')
async function handleSave() {
setSaving(true)
setError('')
try {
const res = await fetch(`/api/events/${eventId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: newTitle }),
})
if (!res.ok) {
const data = await res.json()
setError(data.message || 'Failed to update event')
return
}
setCurrentTitle(newTitle) // update display title
setEdit(false)
} catch (err) {
console.error(err)
setError('Something went wrong')
} finally {
setSaving(false)
}
}
return (
<>
<h1 className="text-4xl font-bold flex gap-2 items-center">
{edit ? (
<input
type="text"
value={newTitle}
onChange={(e) => setNewTitle(e.target.value)}
className="border rounded-lg px-2 py-1"
/>
) : (
currentTitle
)}
<button onClick={() => setEdit(!edit)} className="hover:cursor-pointer">
<PencilIcon />
</button>
{edit && (
<button
onClick={handleSave}
disabled={saving}
className="text-sm bg-blue-600 text-white rounded px-2 py-1"
>
{saving ? 'Saving...' : 'Save'}
</button>
)}
</h1>
{error && <p className="text-red-500 text-sm mt-1">{error}</p>}
</>
)
}

View File

@@ -0,0 +1,11 @@
import React from 'react'
export default function PencilIcon() {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="size-6">
<path d="M21.731 2.269a2.625 2.625 0 0 0-3.712 0l-1.157 1.157 3.712 3.712 1.157-1.157a2.625 2.625 0 0 0 0-3.712ZM19.513 8.199l-3.712-3.712-8.4 8.4a5.25 5.25 0 0 0-1.32 2.214l-.8 2.685a.75.75 0 0 0 .933.933l2.685-.8a5.25 5.25 0 0 0 2.214-1.32l8.4-8.4Z" />
<path d="M5.25 5.25a3 3 0 0 0-3 3v10.5a3 3 0 0 0 3 3h10.5a3 3 0 0 0 3-3V13.5a.75.75 0 0 0-1.5 0v5.25a1.5 1.5 0 0 1-1.5 1.5H5.25a1.5 1.5 0 0 1-1.5-1.5V8.25a1.5 1.5 0 0 1 1.5-1.5h5.25a.75.75 0 0 0 0-1.5H5.25Z" />
</svg>
)
}