added event todo list

This commit is contained in:
2025-06-29 11:00:52 -04:00
parent c7c121e23d
commit 11a0bb00e3
11 changed files with 342 additions and 63 deletions

View File

@@ -97,6 +97,7 @@ export default function EditGuestBookEntryModal({ isOpen, onClose, initialData,
className="input input-bordered w-full"
type="tel"
name="phone"
placeholder="phone"
value={formData.phone || ''}
onChange={handleChange}
/>
@@ -104,6 +105,7 @@ export default function EditGuestBookEntryModal({ isOpen, onClose, initialData,
className="input input-bordered w-full"
type="text"
name="address"
placeholder="address"
value={formData.address || ''}
onChange={handleChange}
/>
@@ -111,12 +113,14 @@ export default function EditGuestBookEntryModal({ isOpen, onClose, initialData,
className="input input-bordered w-full"
type="text"
name="side"
placeholder="Bride/Groom"
value={formData.side || ''}
onChange={handleChange}
/>
<textarea
className='input input-bordered w-full'
name='notes'
placeholder="notes"
value={formData.notes || ''}
onChange={handleChange}
/>

View File

@@ -5,6 +5,8 @@
import React, { useState } from 'react'
import AddGuestFromGuestBook from './AddGuestFromGuestBook'
import EventNotesEditor from './EventNotesEditor'
import ToDoList from './ToDoList'
import { fetchEventTodos } from '@/lib/helper/fetchTodos'
interface Creator {
id: string
@@ -13,6 +15,15 @@ interface Creator {
role: 'COUPLE' | 'PLANNER' | 'GUEST'
}
interface Todo {
id: string
name: string
complete: boolean
dueDate?: string | null
createdAt: string
updatedAt?: string
}
interface EventData {
id: string
name: string
@@ -24,6 +35,7 @@ interface EventData {
guests: any[]
notes?: string
eventGuests: any[]
todos: Todo[]
}
interface Props {
@@ -33,6 +45,7 @@ interface Props {
export default function EventInfoDisplay({ event }: Props) {
const [isEditing, setIsEditing] = useState(false);
const [showSearch, setShowSearch] = useState(false);
const [todos, setTodos] = useState(event.todos)
const eventGuests = event.eventGuests
console.log(eventGuests)
@@ -83,29 +96,14 @@ export default function EventInfoDisplay({ event }: Props) {
}
}
// async function handleChangeRsvp(e: any) {
// const newRsvp = e.target.value as 'YES' | 'NO' | 'PENDING';
// try {
// const res = await fetch(
// `/api/events/${guest.eventId}/guests/${guest.guestBookEntryId}/rsvp`,
// {
// method: 'PATCH',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({ rsvp: newRsvp }),
// }
// );
// if (!res.ok) {
// throw new Error('Failed to update RSVP');
// }
// // Optionally trigger re-fetch or state update here
// } catch (err) {
// console.error('RSVP update error:', err);
// // Optionally show error message in UI
// }
// }
async function refreshTodos() {
try {
const data = await fetchEventTodos(event.id)
setTodos(data)
} catch (err) {
console.error('Failed to refresh todos:', err)
}
}
function formatDate(date: string) {
const d = new Date(date)
@@ -241,8 +239,12 @@ export default function EventInfoDisplay({ event }: Props) {
</ul>
</div>
<div>
Vendors
<div className='col-span-3'>
<ToDoList
eventId={event.id}
initialTodos={todos}
onUpdate={refreshTodos}
/>
</div>
</div>
)

117
components/ToDoList.tsx Normal file
View File

@@ -0,0 +1,117 @@
'use client'
import React, { useState } from 'react'
interface Todo {
id: string
name: string
complete: boolean
dueDate?: string | null
}
interface Props {
eventId: string
initialTodos: Todo[]
onUpdate: () => void
}
export default function ToDoList({ eventId, initialTodos, onUpdate }: Props) {
const [todos, setTodos] = useState(initialTodos)
const [newName, setNewName] = useState('')
const [newDueDate, setNewDueDate] = useState('')
async function handleAdd() {
if (!newName.trim()) return
const res = await fetch(`/api/events/${eventId}/todo`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: newName, dueDate: newDueDate || null }),
})
const data = await res.json()
if (res.ok) {
setTodos(prev => [...prev, data])
setNewName('')
setNewDueDate('')
}
if (onUpdate) await onUpdate()
}
async function toggleComplete(id: string, complete: boolean) {
const res = await fetch(`/api/events/${eventId}/todo/${id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ complete }),
})
if (res.ok) {
setTodos(prev =>
prev.map(todo =>
todo.id === id ? { ...todo, complete } : todo
)
)
}
if (onUpdate) await onUpdate()
}
async function handleDelete(id: string) {
const res = await fetch(`/api/events/${eventId}/todo/${id}`, {
method: 'DELETE',
})
if (res.ok) {
setTodos(prev => prev.filter(todo => todo.id !== id))
}
if (onUpdate) await onUpdate()
}
return (
<div className="space-y-4">
<h2 className="text-xl font-semibold">To Do List</h2>
<div className="flex gap-2">
<input
className="input input-bordered w-full"
placeholder="New To Do..."
value={newName}
onChange={e => setNewName(e.target.value)}
/>
<input
type="date"
className="input input-bordered"
value={newDueDate}
onChange={e => setNewDueDate(e.target.value)}
/>
<button className="btn btn-primary" onClick={handleAdd}>Add</button>
</div>
<ul className="space-y-2">
{todos.map(todo => (
<li
key={todo.id}
className="flex items-center justify-between p-3 bg-[#00000010] rounded-lg"
>
<div className="flex items-center gap-2">
<input
type="checkbox"
checked={todo.complete}
onChange={e => toggleComplete(todo.id, e.target.checked)}
/>
<span className={todo.complete ? 'line-through text-gray-400' : ''}>
{todo.name}
</span>
{todo.dueDate && (
<span className="text-sm text-gray-500 ml-2">
(Due {new Date(todo.dueDate).toLocaleDateString()})
</span>
)}
</div>
<button className="text-red-500 text-sm" onClick={() => handleDelete(todo.id)}>
Delete
</button>
</li>
))}
</ul>
</div>
)
}