Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions app/api/shifts/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,64 @@ export async function DELETE(
);
}
}

// PUT/UPDATE shift (requires write permission)
export async function PUT(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const { id } = await params;
const user = await getSessionUser(request.headers);
const body = await request.json();

// Fetch shift to get calendar ID
const [existingShift] = await db.select().from(shifts).where(eq(shifts.id, id));

if (!existingShift) {
return NextResponse.json({ error: "Shift not found" }, { status: 404 });
}

// Check if shift is externally synced (read-only)
if (existingShift.externalSyncId || existingShift.syncedFromExternal) {
return NextResponse.json(
{ error: "Cannot edit externally synced shifts. They are read-only." },
{ status: 403 }
);
}

// Check write permission (works for both authenticated users and guests)
const hasAccess = await canEditCalendar(user?.id, existingShift.calendarId);
if (!hasAccess) {
return NextResponse.json(
{ error: "Insufficient permissions. Write access required." },
{ status: 403 }
);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// Update the shift
const [updatedShift] = await db
.update(shifts)
.set({
date: body.date ? new Date(body.date) : existingShift.date,
startTime: body.startTime ?? existingShift.startTime,
endTime: body.endTime ?? existingShift.endTime,
title: body.title ?? existingShift.title,
color: body.color ?? existingShift.color,
notes: body.notes ?? existingShift.notes,
isAllDay: body.isAllDay ?? existingShift.isAllDay,
presetId: body.presetId ?? existingShift.presetId,
updatedAt: new Date(),
})
.where(eq(shifts.id, id))
.returning();

return NextResponse.json(updatedShift);
} catch (error) {
console.error("Failed to update shift:", error);
return NextResponse.json(
{ error: "Failed to update shift" },
{ status: 500 }
);
}
}
38 changes: 36 additions & 2 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { CalendarCompareView } from "@/components/calendar-compare-view";
import { AppFooter } from "@/components/app-footer";
import { AppHeader } from "@/components/app-header";
import { DialogManager } from "@/components/dialog-manager";
import { ShiftFormData } from "@/components/shift-sheet";
import { getCalendarDays } from "@/lib/calendar-utils";
import { formatDateToLocal, parseLocalDate } from "@/lib/date-utils";
import { findNotesForDate } from "@/lib/event-utils";
Expand Down Expand Up @@ -67,6 +68,7 @@ function HomeContent() {
hasLoadedOnce: shiftsLoadedOnce,
createShift: createShiftHook,
deleteShift: deleteShiftHook,
updateShift: updateShiftHook,
refetchShifts,
} = useShifts(selectedCalendar);

Expand All @@ -85,6 +87,7 @@ function HomeContent() {
const [compareNoteCalendarId, setCompareNoteCalendarId] = useState<
string | undefined
>();
const [editingShift, setEditingShift] = useState<ShiftWithCalendar | undefined>();

// Compare mode state (needs to be before useNotes hook)
const [isCompareMode, setIsCompareMode] = useState(false);
Expand Down Expand Up @@ -358,6 +361,34 @@ function HomeContent() {
refetchShifts();
};

// Handler for editing a shift from the day shifts dialog
const handleEditShiftFromDayDialog = (shift: ShiftWithCalendar) => {
setEditingShift(shift);
setSelectedDate(shift.date as Date);
dialogStates.setShowShiftDialog(true);
};

// Clear editing state when dialog closes
const handleShiftDialogChange = (open: boolean) => {
dialogStates.setShowShiftDialog(open);
if (!open) {
setEditingShift(undefined);
}
};

// Handle shift submit (create or update)
const handleShiftSubmit = async (formData: ShiftFormData) => {
if (editingShift) {
// Update existing shift
await updateShiftHook(editingShift.id, formData);
setEditingShift(undefined);
refetchShifts();
} else {
// Create new shift
await shiftActions.handleShiftSubmit(formData);
}
};

// Compare mode handlers
const handleCompareClick = () => {
setShowCompareSelector(true);
Expand Down Expand Up @@ -897,6 +928,7 @@ function HomeContent() {
onShowAllShifts={handleShowAllShifts}
onShowSyncedShifts={handleShowSyncedShifts}
onDeleteShift={shiftActions.handleDeleteShift}
onEditShift={handleEditShiftFromDayDialog}
/>
</div>

Expand Down Expand Up @@ -924,11 +956,12 @@ function HomeContent() {
onCalendarDialogChange={dialogStates.setShowCalendarDialog}
onCreateCalendar={createCalendarHook}
showShiftDialog={dialogStates.showShiftDialog}
onShiftDialogChange={dialogStates.setShowShiftDialog}
onShiftSubmit={shiftActions.handleShiftSubmit}
onShiftDialogChange={handleShiftDialogChange}
onShiftSubmit={handleShiftSubmit}
selectedDate={selectedDate}
selectedCalendar={selectedCalendar || null}
calendars={calendars}
editingShift={editingShift}
showCalendarSettingsDialog={dialogStates.showCalendarSettingsDialog}
onCalendarSettingsDialogChange={
dialogStates.setShowCalendarSettingsDialog
Expand All @@ -951,6 +984,7 @@ function HomeContent() {
selectedDayShifts={dialogStates.selectedDayShifts}
locale={locale}
onDeleteShiftFromDayDialog={handleDeleteShiftFromDayDialog}
onEditShiftFromDayDialog={handleEditShiftFromDayDialog}
showSyncedShiftsDialog={dialogStates.showSyncedShiftsDialog}
onSyncedShiftsDialogChange={dialogStates.setShowSyncedShiftsDialog}
selectedSyncedShifts={dialogStates.selectedSyncedShifts}
Expand Down
3 changes: 3 additions & 0 deletions components/calendar-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface CalendarContentProps {
onShowAllShifts: (date: Date, shifts: ShiftWithCalendar[]) => void;
onShowSyncedShifts: (date: Date, shifts: ShiftWithCalendar[]) => void;
onDeleteShift?: (id: string) => void;
onEditShift?: (shift: ShiftWithCalendar) => void;
}

export function CalendarContent(props: CalendarContentProps) {
Expand Down Expand Up @@ -87,6 +88,7 @@ export function CalendarContent(props: CalendarContentProps) {
onLongPress={props.onLongPress}
onShowAllShifts={props.onShowAllShifts}
onShowSyncedShifts={props.onShowSyncedShifts}
onEditShift={props.onEditShift}
/>

<motion.div
Expand Down Expand Up @@ -128,6 +130,7 @@ export function CalendarContent(props: CalendarContentProps) {
shifts={props.shifts}
currentDate={props.currentDate}
onDeleteShift={props.onDeleteShift}
onEditShift={props.onEditShift}
calendarId={props.selectedCalendar || undefined}
/>
</div>
Expand Down
Loading
Loading