diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e17ebbb..a0a86fa 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -66,6 +66,7 @@ model User { weekendColorSat String? @default("#666666") weekendColorSun String? @default("#dc2626") + pastDayColor String? @default("#a6a6a7") accounts Account[] sessions Session[] diff --git a/src/app/api/user/profile/route.ts b/src/app/api/user/profile/route.ts index d6dd25e..b59a338 100644 --- a/src/app/api/user/profile/route.ts +++ b/src/app/api/user/profile/route.ts @@ -1,12 +1,9 @@ import { NextRequest, NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/lib/auth'; -import { PrismaClient } from '@prisma/client'; +import { prisma } from '@/lib/prisma'; import bcrypt from 'bcryptjs'; -const prisma = new PrismaClient(); -// Prisma client re-initialized to pick up schema changes - // Get user profile export async function GET(request: NextRequest) { const session = await getServerSession(authOptions); @@ -59,6 +56,7 @@ export async function GET(request: NextRequest) { todayHighlightColor: true, weekendColorSat: true, weekendColorSun: true, + pastDayColor: true, createdAt: true } }); @@ -92,7 +90,8 @@ export async function PATCH(request: NextRequest) { bodyFont, taskFontFamily, taskFontSize, taskFontWeight, eventFontFamily, eventFontSize, eventFontWeight, fontWeight, weekendColorSat, weekendColorSun, - weekdayColor, dateColor, taskColor, todayHighlightColor + weekdayColor, dateColor, taskColor, todayHighlightColor, + pastDayColor } = body; const updateData: any = { @@ -139,6 +138,7 @@ export async function PATCH(request: NextRequest) { ...(todayHighlightColor !== undefined && { todayHighlightColor }), ...(weekendColorSat !== undefined && { weekendColorSat }), ...(weekendColorSun !== undefined && { weekendColorSun }), + ...(pastDayColor !== undefined && { pastDayColor }), }; if (password && password.trim() !== "") { updateData.passwordHash = await bcrypt.hash(password, 10); @@ -193,6 +193,7 @@ export async function PATCH(request: NextRequest) { todayHighlightColor: true, weekendColorSat: true, weekendColorSun: true, + pastDayColor: true, } }); diff --git a/src/app/globals.css b/src/app/globals.css index 3da759b..b710e05 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -452,6 +452,19 @@ h3 { --weekly-border: #eeeeee; --weekly-completed: #cccccc; --weekly-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + + /* Settings Sidebar Theme */ + --weekly-settings-bg: white; + --weekly-settings-item-bg: #f8fafc; + --weekly-settings-label: #475569; + --weekly-settings-title: #111827; + --weekly-settings-input-bg: white; + --weekly-settings-input-border: #dddddd; + --weekly-settings-text: #111827; + --weekly-settings-toggle-bg: #f3f4f6; + --weekly-settings-toggle-active-bg: white; + --weekly-settings-toggle-text: #6b7280; + --weekly-settings-toggle-active-text: #111827; } /* Weekly Main Container */ @@ -643,6 +656,11 @@ h3 { background-color: var(--weekly-today-highlight); } +.weekly-day-column.is-past .weekly-day-name, +.weekly-day-column.is-past .weekly-day-date { + color: var(--weekly-past-color, #a6a6a7); +} + /* Day Header */ .weekly-day-header { padding: 1rem 1rem 0.75rem; @@ -940,8 +958,9 @@ h3 { color: var(--weekly-text); } +/* Removed rogue color override for weekly-day-name */ .weekly-day-name { - color: var(--weekly-text-light); + /* color: var(--weekly-text-light); */ } .weekly-someday-title { @@ -976,7 +995,6 @@ h3 { flex-direction: row; flex-wrap: nowrap; gap: 1rem; - border-top: 1px solid var(--weekly-border); width: 100%; overflow-x: auto; overflow-y: hidden; /* Prevent vertical Scrollbar on container */ @@ -1390,11 +1408,24 @@ h3 { /* Dark Mode */ .weekly-container.dark-mode { - --weekly-bg: #1a1a1a; + --weekly-bg: #323232; --weekly-text: #f0f0f0; - --weekly-text-light: #888888; - --weekly-border: #333333; + --weekly-text-light: #aaa; + --weekly-border: #4a4a4a; --weekly-completed: #666666; + + /* Settings Sidebar Theme (Dark) */ + --weekly-settings-bg: #111111; + --weekly-settings-item-bg: #1a1a1a; + --weekly-settings-label: #aaaaaa; + --weekly-settings-title: #ffffff; + --weekly-settings-input-bg: #222222; + --weekly-settings-input-border: #333333; + --weekly-settings-text: #ffffff; + --weekly-settings-toggle-bg: #222222; + --weekly-settings-toggle-active-bg: #333333; + --weekly-settings-toggle-text: #888888; + --weekly-settings-toggle-active-text: #ffffff; } .weekly-container.dark-mode .weekly-task-item:hover { @@ -1511,7 +1542,7 @@ h3 { .time-slot.hour-start { /* Weekly-style: subtle dotted line at hour boundaries */ - border-top: 1px dotted rgba(0, 0, 0, 0.1); + border-top: 1px dotted var(--weekly-border); } .time-slot:hover { @@ -1833,11 +1864,11 @@ h3 { } .weekly-container.dark-mode .time-slot { - border-bottom-color: #2a2a2a; + border-top: 1px dotted transparent; } .weekly-container.dark-mode .time-slot.hour-start { - border-bottom-color: var(--weekly-border); + border-top-color: var(--weekly-border); } .weekly-container.dark-mode .time-slot.drop-target:hover { @@ -2467,6 +2498,28 @@ h3 { margin-bottom: 12px; } +/* Form Elements in Settings */ +.weekly-input, +.weekly-settings-sidebar select, +.weekly-settings-sidebar input[type="text"], +.weekly-settings-sidebar input[type="number"] { + background: var(--weekly-settings-input-bg) !important; + color: var(--weekly-settings-text) !important; + border: 1px solid var(--weekly-settings-input-border) !important; + border-radius: 4px; + padding: 8px; + width: 100%; + font-family: inherit; + font-size: 0.9rem; +} + +.weekly-input:focus, +.weekly-settings-sidebar select:focus, +.weekly-settings-sidebar input:focus { + outline: 2px solid var(--weekly-teal); + outline-offset: -1px; +} + .event-title { font-family: var(--weekly-event-font); font-weight: var(--weekly-event-weight); diff --git a/src/components/WeeklyView.tsx b/src/components/WeeklyView.tsx index c123c9e..e91561a 100644 --- a/src/components/WeeklyView.tsx +++ b/src/components/WeeklyView.tsx @@ -310,6 +310,25 @@ const isAllDayEvent = (event: CalendarEvent): boolean => { return durationHours >= 24 && (isLocalMidnight || isUTCMidnight); }; +// Helper to invert colors for dark mode +function invertColor(hex: string): string { + if (!hex) return hex; + let color = hex.startsWith('#') ? hex.slice(1) : hex; + if (color.length === 3) { + color = color.split('').map(c => c + c).join(''); + } + if (color.length !== 6) return hex; + + try { + const r = (255 - parseInt(color.slice(0, 2), 16)).toString(16).padStart(2, '0'); + const g = (255 - parseInt(color.slice(2, 4), 16)).toString(16).padStart(2, '0'); + const b = (255 - parseInt(color.slice(4, 6), 16)).toString(16).padStart(2, '0'); + return `#${r}${g}${b}`; + } catch (e) { + return hex; + } +} + // Main Component export default function WeeklyView() { const { data: session } = useSession(); @@ -400,6 +419,7 @@ export default function WeeklyView() { dateColor?: string; taskColor?: string; todayHighlightColor?: string; + pastDayColor?: string; }>({ name: session?.user?.name || '', email: session?.user?.email || '', @@ -439,7 +459,8 @@ export default function WeeklyView() { weekendColorSat: '#666666', weekendColorSun: '#dc2626', focusTimerDuration: 25, - focusBreakDuration: 5 + focusBreakDuration: 5, + pastDayColor: '#a6a6a7' }); const [showSummary, setShowSummary] = useState(false); @@ -1702,12 +1723,13 @@ export default function WeeklyView() { '--weekly-event-size': profile.eventFontSize || eventFontSize || '0.85rem', '--weekly-event-weight': profile.eventFontWeight || eventFontWeight || '400', '--font-weight-body': profile.fontWeight || fontWeight || '400', - '--weekly-weekend-sat': profile.weekendColorSat || '#666666', - '--weekly-weekend-sun': profile.weekendColorSun || '#dc2626', - '--weekly-weekday-color': profile.weekdayColor || '#888888', - '--weekly-date-color': profile.dateColor || '#888888', - '--weekly-task-color': profile.taskColor || '#333333', - '--weekly-today-highlight': profile.todayHighlightColor || '#f0fafa', + '--weekly-weekend-sat': darkMode ? invertColor(profile.weekendColorSat || '#666666') : (profile.weekendColorSat || '#666666'), + '--weekly-weekend-sun': darkMode ? invertColor(profile.weekendColorSun || '#dc2626') : (profile.weekendColorSun || '#dc2626'), + '--weekly-weekday-color': darkMode ? invertColor(profile.weekdayColor || '#888888') : (profile.weekdayColor || '#888888'), + '--weekly-date-color': darkMode ? invertColor(profile.dateColor || '#888888') : (profile.dateColor || '#888888'), + '--weekly-task-color': darkMode ? invertColor(profile.taskColor || '#333333') : (profile.taskColor || '#333333'), + '--weekly-today-highlight': darkMode ? invertColor(profile.todayHighlightColor || '#f0fafa') : (profile.todayHighlightColor || '#f0fafa'), + '--weekly-past-color': darkMode ? invertColor(profile.pastDayColor || '#a6a6a7') : (profile.pastDayColor || '#a6a6a7'), } as React.CSSProperties; if (isLoading) { @@ -1996,7 +2018,7 @@ export default function WeeklyView() { {getVisibleDays().map((date, colIndex) => (
{/* Day Header */} @@ -2184,7 +2206,7 @@ export default function WeeklyView() { if (e.key === 'Enter') e.currentTarget.blur(); }} className="weekly-task-text" - style={{ width: '100%', background: 'transparent', border: 'none', borderBottom: '1px solid #777', outline: 'none' }} + style={{ width: '100%', background: 'transparent', border: 'none', borderBottom: '1px solid var(--weekly-border)', outline: 'none' }} /> {/* Duration Presets */}
@@ -2526,7 +2548,7 @@ export default function WeeklyView() { {(somedayLists.length > 0 ? somedayLists : [{ id: 'default', title: 'LISTE', tasks: [] }]).slice(0, Math.max(somedayLists.length, viewDays)).map(list => (
{Array.from({ length: Math.max(0, 5 - list.tasks.length) }).map((_, i) => (
  • +
  • { e.preventDefault(); handleSubmit(); }} style={{ width: '100%' }}> ({ name: '', email: '', @@ -3966,7 +3989,7 @@ function SettingsSidebar({ onChange={(e) => setMotto(e.target.value)} className="weekly-input" placeholder={t.mottoOfWeek} - style={{ width: '100%', padding: '8px', border: '1px solid #ddd', borderRadius: '4px' }} + style={{ width: '100%' }} />
  • @@ -4173,8 +4196,8 @@ function SettingsSidebar({ {/* Text Size setting */}
    - -
    + +
    {(['S', 'M', 'L'] as const).map((size) => (