feat: implement color settings, today highlight, and smooth scrolling

This commit is contained in:
mARTin 2026-02-15 15:42:22 +01:00
parent 779181ddde
commit 1bf01e4f12
4 changed files with 138 additions and 16 deletions

View File

@ -57,6 +57,13 @@ model User {
eventFontSize String? @default("0.85rem")
eventFontWeight String? @default("400")
fontWeight String @default("400") // Legacy/Generic
// Color Settings
weekdayColor String? @default("#888888")
dateColor String? @default("#888888")
taskColor String? @default("#333333")
todayHighlightColor String? @default("#f0fafa")
weekendColorSat String? @default("#666666")
weekendColorSun String? @default("#dc2626")

View File

@ -53,6 +53,10 @@ export async function GET(request: NextRequest) {
eventFontSize: true,
eventFontWeight: true,
fontWeight: true,
weekdayColor: true,
dateColor: true,
taskColor: true,
todayHighlightColor: true,
weekendColorSat: true,
weekendColorSun: true,
createdAt: true
@ -87,7 +91,8 @@ export async function PATCH(request: NextRequest) {
timeTaskFontFamily, timeTaskFontSize, timeTaskFontWeight,
bodyFont, taskFontFamily, taskFontSize, taskFontWeight,
eventFontFamily, eventFontSize, eventFontWeight,
fontWeight, weekendColorSat, weekendColorSun
fontWeight, weekendColorSat, weekendColorSun,
weekdayColor, dateColor, taskColor, todayHighlightColor
} = body;
const updateData: any = {
@ -128,6 +133,10 @@ export async function PATCH(request: NextRequest) {
...(eventFontSize !== undefined && { eventFontSize }),
...(eventFontWeight !== undefined && { eventFontWeight }),
...(fontWeight !== undefined && { fontWeight }),
...(weekdayColor !== undefined && { weekdayColor }),
...(dateColor !== undefined && { dateColor }),
...(taskColor !== undefined && { taskColor }),
...(todayHighlightColor !== undefined && { todayHighlightColor }),
...(weekendColorSat !== undefined && { weekendColorSat }),
...(weekendColorSun !== undefined && { weekendColorSun }),
};
@ -178,6 +187,10 @@ export async function PATCH(request: NextRequest) {
eventFontSize: true,
eventFontWeight: true,
fontWeight: true,
weekdayColor: true,
dateColor: true,
taskColor: true,
todayHighlightColor: true,
weekendColorSat: true,
weekendColorSun: true,
}

View File

@ -639,6 +639,10 @@ h3 {
color: var(--weekly-weekend-sun, #dc2626);
}
.weekly-day-column.is-today {
background-color: var(--weekly-today-highlight);
}
/* Day Header */
.weekly-day-header {
padding: 1rem 1rem 0.75rem;

View File

@ -396,6 +396,10 @@ export default function WeeklyView() {
fontWeight?: string;
weekendColorSat?: string;
weekendColorSun?: string;
weekdayColor?: string;
dateColor?: string;
taskColor?: string;
todayHighlightColor?: string;
}>({
name: session?.user?.name || '',
email: session?.user?.email || '',
@ -768,12 +772,16 @@ export default function WeeklyView() {
taskFontFamily: string;
taskFontSize: string;
taskFontWeight: string;
eventFontFamily: string;
eventFontSize: string;
eventFontWeight: string;
fontWeight: string;
weekendColorSat: string;
weekendColorSun: string;
eventFontFamily?: string;
eventFontSize?: string;
eventFontWeight?: string;
fontWeight?: string;
weekendColorSat?: string;
weekendColorSun?: string;
weekdayColor?: string;
dateColor?: string;
taskColor?: string;
todayHighlightColor?: string;
}) => {
setShowTimeGrid(newSettings.showTimeGrid);
setCellDuration(newSettings.cellDuration);
@ -801,12 +809,25 @@ export default function WeeklyView() {
setTaskFontFamily(newSettings.taskFontFamily);
setTaskFontSize(newSettings.taskFontSize);
setTaskFontWeight(newSettings.taskFontWeight);
setEventFontFamily(newSettings.eventFontFamily);
setEventFontSize(newSettings.eventFontSize);
setEventFontWeight(newSettings.eventFontWeight);
setFontWeight(newSettings.fontWeight);
setWeekendColorSat(newSettings.weekendColorSat);
setWeekendColorSun(newSettings.weekendColorSun);
if (newSettings.eventFontFamily) setEventFontFamily(newSettings.eventFontFamily);
if (newSettings.eventFontSize) setEventFontSize(newSettings.eventFontSize);
if (newSettings.eventFontWeight) setEventFontWeight(newSettings.eventFontWeight);
if (newSettings.fontWeight) setFontWeight(newSettings.fontWeight);
if (newSettings.weekendColorSat) setWeekendColorSat(newSettings.weekendColorSat);
if (newSettings.weekendColorSun) setWeekendColorSun(newSettings.weekendColorSun);
setProfile((prev: any) => ({
...prev,
weekdayColor: newSettings.weekdayColor || prev.weekdayColor,
dateColor: newSettings.dateColor || prev.dateColor,
taskColor: newSettings.taskColor || prev.taskColor,
todayHighlightColor: newSettings.todayHighlightColor || prev.todayHighlightColor,
weekendColorSat: newSettings.weekendColorSat,
weekendColorSun: newSettings.weekendColorSun,
eventFontFamily: newSettings.eventFontFamily || prev.eventFontFamily,
eventFontSize: newSettings.eventFontSize || prev.eventFontSize,
eventFontWeight: newSettings.eventFontWeight || prev.eventFontWeight
}));
// Custom start/end hours might affect task placement if we filter strictly
fetchTasks();
@ -857,6 +878,10 @@ export default function WeeklyView() {
...data.user,
name: data.user.name || prev.name,
email: data.user.email || prev.email,
weekdayColor: data.user.weekdayColor || '#888888',
dateColor: data.user.dateColor || '#888888',
taskColor: data.user.taskColor || '#333333',
todayHighlightColor: data.user.todayHighlightColor || '#f0fafa',
}));
if (data.user.focusTimerDuration) setFocusTimerDuration(data.user.focusTimerDuration);
@ -1677,6 +1702,10 @@ export default function WeeklyView() {
'--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',
} as React.CSSProperties;
if (isLoading) {
@ -1956,11 +1985,14 @@ export default function WeeklyView() {
)}
{/* Day Columns */}
<main className={`weekly-days-grid cols-${viewDays} ${slideDirection ? `slide-${slideDirection}` : ''}`}>
<main
className={`weekly-days-grid cols-${viewDays} ${slideDirection ? `slide-${slideDirection}` : ''}`}
style={{ viewTransitionName: 'week-grid' } as React.CSSProperties}
>
{getVisibleDays().map((date, colIndex) => (
<div
key={date.toISOString()}
className={`weekly-day-column ${date.getDay() === 6 ? 'is-sat' : ''} ${date.getDay() === 0 ? 'is-sun' : ''}`}
className={`weekly-day-column ${date.getDay() === 6 ? 'is-sat' : ''} ${date.getDay() === 0 ? 'is-sun' : ''} ${isSameDay(date, new Date()) ? 'is-today' : ''}`}
style={{ viewTransitionName: `day-${date.getFullYear()}-${date.getMonth()}-${date.getDate()}` } as any}
>
{/* Day Header */}
@ -3439,6 +3471,13 @@ interface SettingsSidebarProps {
fontWeight: string;
weekendColorSat: string;
weekendColorSun: string;
eventFontFamily?: string;
eventFontSize?: string;
eventFontWeight?: string;
weekdayColor?: string;
dateColor?: string;
taskColor?: string;
todayHighlightColor?: string;
}) => void;
showTimeGrid: boolean;
setShowTimeGrid: (show: boolean) => void;
@ -3584,6 +3623,10 @@ function SettingsSidebar({
fontWeight?: string;
weekendColorSat?: string;
weekendColorSun?: string;
weekdayColor?: string;
dateColor?: string;
taskColor?: string;
todayHighlightColor?: string;
}>({
name: '',
email: '',
@ -3620,7 +3663,11 @@ function SettingsSidebar({
taskFontWeight: '400',
fontWeight: '400',
weekendColorSat: '#666666',
weekendColorSun: '#dc2626'
weekendColorSun: '#dc2626',
weekdayColor: '#888888',
dateColor: '#888888',
taskColor: '#333333',
todayHighlightColor: '#f0fafa'
});
const t = translations[profile.language || 'en'] || translations['en'];
@ -3683,6 +3730,10 @@ function SettingsSidebar({
eventFontWeight: data.user.eventFontWeight || '400',
weekendColorSat: data.user.weekendColorSat || '#666666',
weekendColorSun: data.user.weekendColorSun || '#dc2626',
weekdayColor: data.user.weekdayColor || '#888888',
dateColor: data.user.dateColor || '#888888',
taskColor: data.user.taskColor || '#333333',
todayHighlightColor: data.user.todayHighlightColor || '#f0fafa',
});
if (data.user.showTimeGrid !== undefined) setShowTimeGrid(data.user.showTimeGrid);
@ -3820,6 +3871,10 @@ function SettingsSidebar({
fontWeight: fontWeight,
weekendColorSat: weekendColorSat,
weekendColorSun: weekendColorSun,
weekdayColor: profile.weekdayColor,
dateColor: profile.dateColor,
taskColor: profile.taskColor,
todayHighlightColor: profile.todayHighlightColor,
});
}
@ -4312,6 +4367,49 @@ function SettingsSidebar({
</div>
{/* Element Colors */}
<div style={{ background: '#f8fafc', padding: '12px', borderRadius: '8px', marginBottom: '12px' }}>
<label style={{ display: 'block', fontSize: '0.85rem', fontWeight: 600, color: '#475569', marginBottom: '8px' }}>Element Colors</label>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px' }}>
<div>
<label style={{ display: 'block', fontSize: '0.75rem', color: '#666', marginBottom: '4px' }}>Weekday Name</label>
<input
type="color"
value={profile.weekdayColor || '#888888'}
onChange={(e) => setProfile({ ...profile, weekdayColor: e.target.value })}
style={{ width: '100%', height: '30px', cursor: 'pointer', border: 'none', background: 'transparent' }}
/>
</div>
<div>
<label style={{ display: 'block', fontSize: '0.75rem', color: '#666', marginBottom: '4px' }}>Date</label>
<input
type="color"
value={profile.dateColor || '#888888'}
onChange={(e) => setProfile({ ...profile, dateColor: e.target.value })}
style={{ width: '100%', height: '30px', cursor: 'pointer', border: 'none', background: 'transparent' }}
/>
</div>
<div>
<label style={{ display: 'block', fontSize: '0.75rem', color: '#666', marginBottom: '4px' }}>Task Text</label>
<input
type="color"
value={profile.taskColor || '#333333'}
onChange={(e) => setProfile({ ...profile, taskColor: e.target.value })}
style={{ width: '100%', height: '30px', cursor: 'pointer', border: 'none', background: 'transparent' }}
/>
</div>
<div>
<label style={{ display: 'block', fontSize: '0.75rem', color: '#666', marginBottom: '4px' }}>Today Highlight</label>
<input
type="color"
value={profile.todayHighlightColor || '#f0fafa'}
onChange={(e) => setProfile({ ...profile, todayHighlightColor: e.target.value })}
style={{ width: '100%', height: '30px', cursor: 'pointer', border: 'none', background: 'transparent' }}
/>
</div>
</div>
</div>
{/* Weekend Colors */}
<div style={{ background: '#f8fafc', padding: '12px', borderRadius: '8px', marginBottom: '12px' }}>
<label style={{ display: 'block', fontSize: '0.85rem', fontWeight: 600, color: '#475569', marginBottom: '8px' }}>Weekend Highlight Colors</label>