diff --git a/package.json b/package.json index 6bdff20..f833b1f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "my-weekly-todo-list", - "version": "1.81.14", + "version": "1.81.15", "description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view", "main": "index.js", "scripts": { diff --git a/src/app/api/calendar/events/route.ts b/src/app/api/calendar/events/route.ts index 7ba68f4..2db57a9 100644 --- a/src/app/api/calendar/events/route.ts +++ b/src/app/api/calendar/events/route.ts @@ -5,10 +5,10 @@ import { prisma } from '@/lib/prisma'; import { createCalendarEvent, updateCalendarEvent, deleteCalendarEvent, CalendarConnection } from '@/lib/calendar-events'; import { upsertCachedEvent, deleteCachedEvent } from '@/lib/calendar-cache'; -// Helper to find connection by calendarId -async function findConnectionForCalendar(userId: string, calendarId: string) { +// Helper to find connection by calendarId (look up by email to avoid stale session IDs) +async function findConnectionForCalendar(email: string, calendarId: string) { const user = await prisma.user.findUnique({ - where: { id: userId }, + where: { email }, include: { calendarConnections: true } }); diff --git a/src/app/api/calendar/sync/route.ts b/src/app/api/calendar/sync/route.ts index 3137e4f..9661b7e 100644 --- a/src/app/api/calendar/sync/route.ts +++ b/src/app/api/calendar/sync/route.ts @@ -9,8 +9,7 @@ import { runSyncRules } from '@/lib/calendar-cross-sync'; export async function POST(request: NextRequest) { try { const session = await getServerSession(authOptions); - const userId = (session?.user as any)?.id; - if (!userId) { + if (!session?.user?.email) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } @@ -20,19 +19,12 @@ export async function POST(request: NextRequest) { const timeMinDate = new Date(timeMin ?? Date.now()); const timeMaxDate = new Date(timeMax ?? Date.now() + 7 * 24 * 60 * 60 * 1000); - let user = await prisma.user.findUnique({ - where: { id: userId }, + // Look up by email — session ID can be stale after DB restore/migration + const user = await prisma.user.findUnique({ + where: { email: session.user.email }, include: { calendarConnections: true }, }); - // Fallback: session ID may be stale (e.g. after DB restore) — try by email - if (!user && session?.user?.email) { - user = await prisma.user.findUnique({ - where: { email: session.user.email }, - include: { calendarConnections: true }, - }) ?? null; - } - if (!user) { return NextResponse.json({ error: 'User not found' }, { status: 404 }); } diff --git a/src/app/api/goal/route.ts b/src/app/api/goal/route.ts index 5bbfce9..440dfe9 100644 --- a/src/app/api/goal/route.ts +++ b/src/app/api/goal/route.ts @@ -10,15 +10,10 @@ export const dynamic = 'force-dynamic'; export async function GET(req: Request) { try { const session = await getServerSession(authOptions); - if (!session || !session.user) { + if (!session?.user?.email) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } - const userId = (session.user as any).id; - if (!userId) { - return NextResponse.json({ error: 'User ID missing from session' }, { status: 400 }); - } - const { searchParams } = new URL(req.url); const weekStartParam = searchParams.get('weekStart'); @@ -29,10 +24,11 @@ export async function GET(req: Request) { const date = new Date(weekStartParam); date.setUTCHours(0, 0, 0, 0); - // Fetch user preferences + // Look up by email — session ID can be stale after DB restore const user = await prisma.user.findUnique({ - where: { id: userId }, + where: { email: session.user.email }, select: { + id: true, goalFallbackType: true, goalDefaultSentence: true, language: true, @@ -40,6 +36,9 @@ export async function GET(req: Request) { } }); + if (!user) return NextResponse.json({ error: 'User not found' }, { status: 404 }); + const userId = user.id; + // 1. Check if user has a custom set goal for THIS week specifically const goal = await prisma.weeklyGoal.findUnique({ where: { @@ -134,14 +133,13 @@ export async function POST(req: Request) { export async function PUT(req: Request) { try { const session = await getServerSession(authOptions); - if (!session || !session.user) { + if (!session?.user?.email) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } - const userId = (session.user as any).id; - if (!userId) { - return NextResponse.json({ error: 'User ID missing from session' }, { status: 400 }); - } + const dbUser = await prisma.user.findUnique({ where: { email: session.user.email }, select: { id: true } }); + if (!dbUser) return NextResponse.json({ error: 'User not found' }, { status: 404 }); + const userId = dbUser.id; const { weekStart, text } = await req.json(); diff --git a/src/app/api/weather/route.ts b/src/app/api/weather/route.ts index 53191c6..6fcadbd 100644 --- a/src/app/api/weather/route.ts +++ b/src/app/api/weather/route.ts @@ -11,13 +11,12 @@ const CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes export async function GET(request: NextRequest) { const session = await getServerSession(authOptions); - const userId = (session?.user as any)?.id; - if (!userId) { + if (!session?.user?.email) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const user = await prisma.user.findUnique({ - where: { id: userId }, + where: { email: session.user.email }, select: { weatherEnabled: true, weatherLat: true, weatherLon: true }, }); diff --git a/src/components/WeeklyView.tsx b/src/components/WeeklyView.tsx index e28e350..41c9a4f 100644 --- a/src/components/WeeklyView.tsx +++ b/src/components/WeeklyView.tsx @@ -1040,7 +1040,7 @@ export default function WeeklyView() { const effectiveShowAllDay = getEffective("showAllDayEvents", profile.showAllDayEvents ?? true); const effectiveAllDayPosition = getEffective("allDayPosition", profile.allDayPosition ?? "above") || "above"; const effectiveShowCompletedTasks = getEffective("showCompletedTasks", profile.showCompletedTasks !== false); - const effectiveCellDuration = getEffective("cellDuration", profile.cellDuration ?? 30) as CellDuration; + const effectiveCellDuration = getEffective("cellDuration", cellDuration) as CellDuration; const effectiveStartHour = getEffective("startHour", profile.startHour ?? 8) ?? 8; const effectiveEndHour = getEffective("endHour", profile.endHour ?? 18) ?? 18; @@ -5444,22 +5444,30 @@ export default function WeeklyView() { - {/* Slot Duration (only with time grid) */} + {/* Slot Duration + sub-hour slots (only with time grid) */} {profile.showTimeGrid && (