add event editing
This commit is contained in:
@@ -180,12 +180,15 @@ function AddEventModal({
|
||||
onClose,
|
||||
onAdd,
|
||||
prefill,
|
||||
editEventId,
|
||||
}: {
|
||||
trip: TripRecord;
|
||||
onClose: () => void;
|
||||
onAdd: (body: object) => Promise<void>;
|
||||
prefill?: Partial<TripEvent>;
|
||||
editEventId?: string;
|
||||
}) {
|
||||
const isEdit = !!editEventId;
|
||||
const availableTags = trip.available_tags ?? [];
|
||||
const [title, setTitle] = useState(prefill?.title ?? "");
|
||||
const [date, setDate] = useState(prefill?.date ?? trip.start_date);
|
||||
@@ -224,7 +227,7 @@ function AddEventModal({
|
||||
});
|
||||
onClose();
|
||||
} catch {
|
||||
setError("Failed to add event. Check the date is within the trip range.");
|
||||
setError(isEdit ? "Failed to save changes." : "Failed to add event. Check the date is within the trip range.");
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
@@ -236,7 +239,7 @@ function AddEventModal({
|
||||
onSubmit={handleSubmit}
|
||||
className="bg-gray-900 border border-gray-700 rounded-xl p-6 w-full max-w-lg space-y-4 max-h-[90vh] overflow-y-auto"
|
||||
>
|
||||
<h2 className="text-white font-bold text-lg">Add Event</h2>
|
||||
<h2 className="text-white font-bold text-lg">{isEdit ? "Edit Event" : "Add Event"}</h2>
|
||||
|
||||
<div>
|
||||
<label className="text-xs text-gray-400 block mb-1">Title</label>
|
||||
@@ -341,7 +344,7 @@ function AddEventModal({
|
||||
type="submit" disabled={saving}
|
||||
className="bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white text-sm rounded-lg px-4 py-2"
|
||||
>
|
||||
{saving ? "Adding…" : "Add Event"}
|
||||
{saving ? (isEdit ? "Saving…" : "Adding…") : (isEdit ? "Save Changes" : "Add Event")}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -359,12 +362,14 @@ function DayTimeline({
|
||||
events,
|
||||
isAdmin,
|
||||
onDelete,
|
||||
onEdit,
|
||||
driveSegments,
|
||||
availableTags,
|
||||
}: {
|
||||
events: TripEvent[];
|
||||
isAdmin: boolean;
|
||||
onDelete: (id: string) => void;
|
||||
onEdit: (event: TripEvent) => void;
|
||||
driveSegments: { fromId: string; toId: string; text: string }[];
|
||||
availableTags: string[];
|
||||
}) {
|
||||
@@ -472,12 +477,20 @@ function DayTimeline({
|
||||
</a>
|
||||
)}
|
||||
{isAdmin && (
|
||||
<button
|
||||
onClick={() => onDelete(e.event_id)}
|
||||
className="text-gray-600 hover:text-red-400 text-base leading-none opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<>
|
||||
<button
|
||||
onClick={() => onEdit(e)}
|
||||
className="text-gray-600 hover:text-indigo-400 text-xs opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
onClick={() => onDelete(e.event_id)}
|
||||
className="text-gray-600 hover:text-red-400 text-base leading-none opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -526,10 +539,16 @@ function DayTimeline({
|
||||
</a>
|
||||
)}
|
||||
{isAdmin && (
|
||||
<button onClick={() => onDelete(e.event_id)}
|
||||
className="text-gray-600 hover:text-red-400 text-sm opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
×
|
||||
</button>
|
||||
<>
|
||||
<button onClick={() => onEdit(e)}
|
||||
className="text-xs text-gray-600 hover:text-indigo-400 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
Edit
|
||||
</button>
|
||||
<button onClick={() => onDelete(e.event_id)}
|
||||
className="text-gray-600 hover:text-red-400 text-sm opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
×
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -842,6 +861,7 @@ export default function TripDetailPage() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [selectedDay, setSelectedDay] = useState<string>("");
|
||||
const [showAdd, setShowAdd] = useState(false);
|
||||
const [editEvent, setEditEvent] = useState<TripEvent | null>(null);
|
||||
const [driveTimes, setDriveTimes] = useState<Record<string, { fromId: string; toId: string; text: string }[]>>({});
|
||||
const [tagInput, setTagInput] = useState("");
|
||||
|
||||
@@ -901,6 +921,18 @@ export default function TripDetailPage() {
|
||||
} catch (e) { console.error(e); }
|
||||
}
|
||||
|
||||
async function handleUpdateEvent(body: object) {
|
||||
if (!trip || !editEvent) return;
|
||||
const updated = await c2api.updateTripEvent(trip.trip_id, editEvent.event_id, body);
|
||||
setTrip((prev) => {
|
||||
if (!prev) return prev;
|
||||
const events = prev.events.map((e) => e.event_id === updated.event_id ? updated : e)
|
||||
.sort((a, b) => a.date.localeCompare(b.date) || (a.start_time ?? "").localeCompare(b.start_time ?? ""));
|
||||
return { ...prev, events };
|
||||
});
|
||||
setEditEvent(null);
|
||||
}
|
||||
|
||||
async function handleAddEvent(body: object) {
|
||||
if (!trip) return;
|
||||
const event = await c2api.createTripEvent(trip.trip_id, body);
|
||||
@@ -1079,6 +1111,7 @@ export default function TripDetailPage() {
|
||||
events={dayEvents}
|
||||
isAdmin={isAdmin}
|
||||
onDelete={handleDeleteEvent}
|
||||
onEdit={setEditEvent}
|
||||
driveSegments={driveTimes[selectedDay] ?? []}
|
||||
availableTags={trip.available_tags ?? []}
|
||||
/>
|
||||
@@ -1100,6 +1133,17 @@ export default function TripDetailPage() {
|
||||
prefill={selectedDay ? { date: selectedDay } : undefined}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Edit event modal */}
|
||||
{editEvent && (
|
||||
<AddEventModal
|
||||
trip={trip}
|
||||
onClose={() => setEditEvent(null)}
|
||||
onAdd={handleUpdateEvent}
|
||||
prefill={editEvent}
|
||||
editEventId={editEvent.event_id}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user