diff --git a/package.json b/package.json index dd0c3f6..2d244e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "my-weekly-todo-list", - "version": "1.96.0", + "version": "1.96.1", "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/user/export-week-view/route.ts b/src/app/api/user/export-week-view/route.ts index 2330934..be9144b 100644 --- a/src/app/api/user/export-week-view/route.ts +++ b/src/app/api/user/export-week-view/route.ts @@ -306,8 +306,8 @@ function WeekCalendarPDF({ flexDirection: 'row', height: calendarH, borderWidth: 1, - borderColor: BORDER, - borderRadius: 4, + borderColor: '#e8eaed', + borderRadius: 2, overflow: 'hidden', }, }, @@ -319,8 +319,8 @@ function WeekCalendarPDF({ flexDirection: 'column', flexShrink: 0, borderRightWidth: 1, - borderRightColor: BORDER, - backgroundColor: '#f8fafc', + borderRightColor: '#ebebeb', + backgroundColor: '#fafafa', }, }, // Spacer matching day header row @@ -411,11 +411,11 @@ function WeekCalendarPDF({ flex: 1, flexDirection: 'column', borderRightWidth: 1, - borderRightColor: BORDER, + borderRightColor: '#ebebeb', }, }, - // ── Day header (colored weekday name + date, matching webapp) + // ── Day header: date first (top), then weekday name (bottom) — matches webapp "above" layout React.createElement(View, { style: { height: DAY_HDR_H, @@ -427,6 +427,15 @@ function WeekCalendarPDF({ paddingHorizontal: 3, }, }, + React.createElement(Text, { + style: { + fontSize: 7, + color: dayColor(d, isToday, userStyle), + textAlign: 'center', + fontFamily: 'Helvetica', + lineHeight: 1.2, + }, + }, dateStr), React.createElement(Text, { style: { fontFamily: headlineFontFamily, @@ -436,17 +445,9 @@ function WeekCalendarPDF({ textAlign: 'center', letterSpacing: 0.5, lineHeight: 1.1, + marginTop: 1, }, }, dayName), - React.createElement(Text, { - style: { - fontSize: 7.5, - color: dayColor(d, isToday, userStyle), - textAlign: 'center', - marginTop: 2, - fontFamily: 'Helvetica', - }, - }, dateStr), wLabel ? React.createElement(Text, { style: { fontSize: 6, color: MUTED, textAlign: 'center', marginTop: 1 }, }, wLabel) : null, @@ -506,7 +507,7 @@ function WeekCalendarPDF({ backgroundColor: isToday ? todayColBg : WHITE, }, }, - // Alternating hour stripe + // Very subtle alternating hour stripe (lighter than before) ...Array.from({ length: numHours }, (_, i) => { if (i % 2 === 0) return null; return React.createElement(View, { @@ -516,12 +517,12 @@ function WeekCalendarPDF({ top: minutesToY(i * 60), left: 0, right: 0, height: minutesToY(60), - backgroundColor: isToday ? '#e8f2ff' : STRIPE, + backgroundColor: isToday ? '#f0f7ff' : '#fafafa', }, }); }).filter(Boolean), - // Hour separator lines + // Light hour separator lines ...Array.from({ length: numHours - 1 }, (_, i) => React.createElement(View, { key: `hl${i}`, @@ -530,21 +531,7 @@ function WeekCalendarPDF({ top: minutesToY((i + 1) * 60), left: 0, right: 0, height: 1, - backgroundColor: BORDER, - }, - }) - ), - - // Half-hour dashes - ...Array.from({ length: numHours }, (_, i) => - React.createElement(View, { - key: `hh${i}`, - style: { - position: 'absolute', - top: minutesToY(i * 60 + 30), - left: 0, right: 0, - height: 1, - backgroundColor: '#f0f4f8', + backgroundColor: '#ececec', }, }) ), @@ -556,7 +543,7 @@ function WeekCalendarPDF({ const startMins = parseTimeMinutes(t.startTime)!; const endMins = t.endTime ? parseTimeMinutes(t.endTime)! - : startMins + 60; + : startMins + 30; // 30min default, not 60 const gridStart = startHour * 60; const gridEnd = endHour * 60; @@ -568,67 +555,50 @@ function WeekCalendarPDF({ const rawH = minutesToY(ceMin - csMin); const taskH = Math.max(rawH, 14); - const accentColor = t.project?.color || userStyle.weekdayColor; - const isShort = (ceMin - csMin) <= 30; - const showTime = t.startTime && (!t.startTime.endsWith(':00') || isShort); + // Project color → left border; external events always have calendarColor + const projectColor = t.project?.color || null; + const isShort = (ceMin - csMin) <= 30; + const showTime = !!t.startTime && (!t.startTime.endsWith(':00') || isShort); + const baseStyle = { position: 'absolute' as const, top: topPx + 1, left: 2, right: 2, height: taskH - 2, overflow: 'hidden' as const }; if (t.completed) { - // Completed: subtle strikethrough-style, always plain return React.createElement(View, { key: t.id, - style: { - position: 'absolute', top: topPx + 1, left: 2, right: 2, - height: taskH - 2, backgroundColor: WHITE, - borderLeftWidth: 2, borderLeftColor: DONE_BG, - paddingLeft: 5, paddingRight: 3, paddingVertical: 2, - overflow: 'hidden', - }, + style: { ...baseStyle, paddingLeft: 4, paddingRight: 3, paddingVertical: 2 }, }, - React.createElement(Text, { - style: { fontSize: 7, color: DONE_TEXT, lineHeight: 1.25 }, - }, (t.title || '').slice(0, 44)), + React.createElement(Text, { style: { fontSize: 7, color: DONE_TEXT, lineHeight: 1.25 } }, (t.title || '').slice(0, 44)), ); } if (t.isExternal) { - // External calendar event: light tinted background box - const bg = lighten(accentColor, 0.8); + // Calendar event: light tinted bg + left border + rounded corners + const evColor = projectColor || '#6366f1'; + const bg = lighten(evColor, 0.8); return React.createElement(View, { key: t.id, style: { - position: 'absolute', top: topPx + 1, left: 2, right: 2, - height: taskH - 2, backgroundColor: bg, - borderRadius: 3, borderLeftWidth: 3, borderLeftColor: accentColor, + ...baseStyle, backgroundColor: bg, + borderRadius: 3, borderLeftWidth: 3, borderLeftColor: evColor, paddingLeft: 5, paddingRight: 3, paddingVertical: 2, - overflow: 'hidden', }, }, - React.createElement(Text, { - style: { fontFamily: 'Helvetica-Bold', fontSize: 7, color: '#1e293b', lineHeight: 1.25 }, - }, (t.title || '').slice(0, 44)), - showTime ? React.createElement(Text, { - style: { fontSize: 6, color: accentColor, marginTop: 0.5 }, - }, fmtTime(t.startTime!)) : null, + React.createElement(Text, { style: { fontFamily: 'Helvetica-Bold', fontSize: 7, color: '#1e293b', lineHeight: 1.25 } }, (t.title || '').slice(0, 44)), + showTime ? React.createElement(Text, { style: { fontSize: 6, color: evColor, marginTop: 0.5 } }, fmtTime(t.startTime!)) : null, ); } - // Regular user task: transparent, thin colored left border (matches webapp simple view) + // Regular user task: left border only if task has a project color return React.createElement(View, { key: t.id, style: { - position: 'absolute', top: topPx + 1, left: 2, right: 2, - height: taskH - 2, - borderLeftWidth: 3, borderLeftColor: accentColor, - paddingLeft: 5, paddingRight: 3, paddingVertical: 2, - overflow: 'hidden', + ...baseStyle, + ...(projectColor ? { borderLeftWidth: 3, borderLeftColor: projectColor } : {}), + paddingLeft: projectColor ? 5 : 2, + paddingRight: 3, paddingVertical: 2, }, }, - React.createElement(Text, { - style: { fontFamily: 'Helvetica-Bold', fontSize: 7, color: '#1e293b', lineHeight: 1.25 }, - }, (t.title || '').slice(0, 44)), - showTime ? React.createElement(Text, { - style: { fontSize: 6, color: accentColor, marginTop: 0.5 }, - }, fmtTime(t.startTime!)) : null, + React.createElement(Text, { style: { fontFamily: 'Helvetica-Bold', fontSize: 7, color: '#1e293b', lineHeight: 1.25 } }, (t.title || '').slice(0, 44)), + showTime && projectColor ? React.createElement(Text, { style: { fontSize: 6, color: projectColor, marginTop: 0.5 } }, fmtTime(t.startTime!)) : null, ); }).filter(Boolean), ), // end time grid diff --git a/src/components/WeeklyView.tsx b/src/components/WeeklyView.tsx index 53a08ef..413975d 100644 --- a/src/components/WeeklyView.tsx +++ b/src/components/WeeklyView.tsx @@ -9244,7 +9244,7 @@ export default function WeeklyView() { startHour={startHour} endHour={endHour} language={profile.language || "de"} - weatherEnabled={!!(profile.weatherEnabled && profile.weatherLat && profile.weatherLon)} + weatherEnabled={!!(profile.weatherLat && profile.weatherLon)} /> {/* Mobile: Floating Action Button with quick menu */}