fix: dark mode event colors, sidebar height, calendar default, photo badge
- event-config: all bgClass/borderClass get dark:bg-*-950/50 + dark:border-*-800 variants — fixes bright pastel backgrounds in dark mode - nav: h-screen → h-[100dvh] — fixes sidebar bottom buttons hidden behind mobile browser chrome - calendar: selectedDay defaults to today, never null — events shown immediately on load - timeline + dashboard: photo indicator (ImageIcon) on events with metadata.photo Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -45,19 +45,21 @@ export default function CalendarPage() {
|
||||
|
||||
const days = eachDayOfInterval({ start: calStart, end: calEnd });
|
||||
|
||||
const [selectedDay, setSelectedDay] = useState<Date | null>(null);
|
||||
const [selectedDay, setSelectedDay] = useState<Date>(() => new Date());
|
||||
|
||||
const dayEvents = (day: Date) => events.filter((e) => isSameDay(new Date(e.startedAt), day));
|
||||
|
||||
const selectedDayEvents = selectedDay ? dayEvents(selectedDay) : [];
|
||||
const selectedDayEvents = dayEvents(selectedDay);
|
||||
|
||||
function prevMonth() {
|
||||
setCursor(new Date(cursor.getFullYear(), cursor.getMonth() - 1, 1));
|
||||
setSelectedDay(null);
|
||||
const first = new Date(cursor.getFullYear(), cursor.getMonth() - 1, 1);
|
||||
setCursor(first);
|
||||
setSelectedDay(first);
|
||||
}
|
||||
function nextMonth() {
|
||||
setCursor(new Date(cursor.getFullYear(), cursor.getMonth() + 1, 1));
|
||||
setSelectedDay(null);
|
||||
const first = new Date(cursor.getFullYear(), cursor.getMonth() + 1, 1);
|
||||
setCursor(first);
|
||||
setSelectedDay(first);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -75,7 +77,7 @@ export default function CalendarPage() {
|
||||
className="w-9 h-9 rounded-lg flex items-center justify-center text-slate-500 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-800 transition">
|
||||
<ChevronLeft className="w-5 h-5" />
|
||||
</button>
|
||||
<button onClick={() => { setCursor(new Date()); setSelectedDay(null); }}
|
||||
<button onClick={() => { setCursor(new Date()); setSelectedDay(new Date()); }}
|
||||
className="px-3 py-1.5 text-xs font-medium text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg transition">
|
||||
Aujourd'hui
|
||||
</button>
|
||||
@@ -102,13 +104,13 @@ export default function CalendarPage() {
|
||||
{days.map((day, i) => {
|
||||
const inMonth = day.getMonth() === cursor.getMonth();
|
||||
const evs = dayEvents(day);
|
||||
const isSelected = selectedDay ? isSameDay(day, selectedDay) : false;
|
||||
const isSelected = isSameDay(day, selectedDay);
|
||||
const today = isToday(day);
|
||||
|
||||
return (
|
||||
<button
|
||||
key={i}
|
||||
onClick={() => setSelectedDay(isSameDay(day, selectedDay ?? new Date(0)) ? null : day)}
|
||||
onClick={() => setSelectedDay(day)}
|
||||
className={`min-h-[52px] sm:min-h-[64px] p-1 sm:p-1.5 text-left border-b border-r border-slate-100 dark:border-slate-800 last:border-r-0 transition ${
|
||||
isSelected
|
||||
? "bg-indigo-50 dark:bg-indigo-950"
|
||||
@@ -146,7 +148,6 @@ export default function CalendarPage() {
|
||||
</div>
|
||||
|
||||
{/* Selected day detail */}
|
||||
{selectedDay && (
|
||||
<div className="mt-4">
|
||||
<div className="flex items-baseline justify-between mb-3">
|
||||
<h2 className="text-sm font-semibold text-slate-700 dark:text-slate-200 capitalize">
|
||||
@@ -189,7 +190,6 @@ export default function CalendarPage() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!selectedBaby && (
|
||||
<div className="text-center py-16 text-slate-400 dark:text-slate-500">
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useBaby } from "@/contexts/baby-context";
|
||||
import { checkFeedAlert, getThresholds } from "@/lib/notifications";
|
||||
import { format, isToday } from "date-fns";
|
||||
import { fr } from "date-fns/locale";
|
||||
import { AlertTriangle, Clock, CheckCircle2, Pin, PinOff, Pencil, Check, X, Plus, Trash2, FileText } from "lucide-react";
|
||||
import { AlertTriangle, Clock, CheckCircle2, Pin, PinOff, Pencil, Check, X, Plus, Trash2, FileText, ImageIcon } from "lucide-react";
|
||||
import { useSession } from "next-auth/react";
|
||||
|
||||
const QUICK_LOG_GROUPS: { label: string; types: EventType[] }[] = [
|
||||
@@ -790,6 +790,9 @@ export default function DashboardPage() {
|
||||
<span className="text-xs text-slate-400 dark:text-slate-500 ml-2">{getEventSummary(ev)}</span>
|
||||
)}
|
||||
</div>
|
||||
{typeof ev.metadata?.photo === "string" && ev.metadata.photo && (
|
||||
<ImageIcon className="w-3.5 h-3.5 text-slate-400 dark:text-slate-500 flex-shrink-0" />
|
||||
)}
|
||||
<span className="text-xs text-slate-400 dark:text-slate-500 flex-shrink-0 font-mono">
|
||||
{format(new Date(ev.startedAt), "HH:mm")}
|
||||
</span>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { EventIcon } from "@/components/event-icon";
|
||||
import { useBaby } from "@/contexts/baby-context";
|
||||
import { format, isToday, isYesterday } from "date-fns";
|
||||
import { fr } from "date-fns/locale";
|
||||
import { Trash2, StickyNote, Pencil, CheckSquare, Square, XCircle } from "lucide-react";
|
||||
import { Trash2, StickyNote, Pencil, CheckSquare, Square, XCircle, ImageIcon } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import { EventModal } from "@/components/event-modal";
|
||||
|
||||
@@ -271,6 +271,9 @@ export default function TimelinePage() {
|
||||
{summary && <span className="text-xs text-slate-400 dark:text-slate-500 ml-2">{summary}</span>}
|
||||
{ev.notes && <p className="text-xs text-slate-400 dark:text-slate-500 truncate mt-0.5 italic">{ev.notes}</p>}
|
||||
</div>
|
||||
{typeof ev.metadata?.photo === "string" && ev.metadata.photo && (
|
||||
<ImageIcon className="w-3.5 h-3.5 text-slate-400 dark:text-slate-500 flex-shrink-0" />
|
||||
)}
|
||||
<span className="text-xs text-slate-400 dark:text-slate-500 flex-shrink-0 font-mono">
|
||||
{format(new Date(ev.startedAt), "HH:mm")}
|
||||
</span>
|
||||
|
||||
@@ -117,7 +117,7 @@ export function SidebarNav() {
|
||||
const { babies, selectedBaby, setSelectedBabyId } = useBaby();
|
||||
|
||||
return (
|
||||
<aside className="hidden md:flex flex-col w-[220px] border-r border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 fixed left-0 top-0 h-screen z-20">
|
||||
<aside className="hidden md:flex flex-col w-[220px] border-r border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 fixed left-0 top-0 h-[100dvh] z-20">
|
||||
{/* Brand */}
|
||||
<div className="px-5 py-4 border-b border-slate-100 dark:border-slate-700">
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
+26
-26
@@ -32,8 +32,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Heart",
|
||||
color: "#f43f5e",
|
||||
colorClass: "text-rose-500",
|
||||
bgClass: "bg-rose-50",
|
||||
borderClass: "border-rose-200",
|
||||
bgClass: "bg-rose-50 dark:bg-rose-950/50",
|
||||
borderClass: "border-rose-200 dark:border-rose-800",
|
||||
hasDuration: true,
|
||||
hasTimer: true,
|
||||
defaultDurationMin: 15,
|
||||
@@ -43,8 +43,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "GlassWater",
|
||||
color: "#3b82f6",
|
||||
colorClass: "text-blue-500",
|
||||
bgClass: "bg-blue-50",
|
||||
borderClass: "border-blue-200",
|
||||
bgClass: "bg-blue-50 dark:bg-blue-950/50",
|
||||
borderClass: "border-blue-200 dark:border-blue-800",
|
||||
hasDuration: false,
|
||||
hasTimer: false,
|
||||
},
|
||||
@@ -53,8 +53,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Milk",
|
||||
color: "#0891b2",
|
||||
colorClass: "text-cyan-600",
|
||||
bgClass: "bg-cyan-50",
|
||||
borderClass: "border-cyan-200",
|
||||
bgClass: "bg-cyan-50 dark:bg-cyan-950/50",
|
||||
borderClass: "border-cyan-200 dark:border-cyan-800",
|
||||
hasDuration: true,
|
||||
hasTimer: true,
|
||||
defaultDurationMin: 15,
|
||||
@@ -64,8 +64,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Droplets",
|
||||
color: "#06b6d4",
|
||||
colorClass: "text-cyan-500",
|
||||
bgClass: "bg-cyan-50",
|
||||
borderClass: "border-cyan-200",
|
||||
bgClass: "bg-cyan-50 dark:bg-cyan-950/50",
|
||||
borderClass: "border-cyan-200 dark:border-cyan-800",
|
||||
hasDuration: false,
|
||||
hasTimer: false,
|
||||
},
|
||||
@@ -74,8 +74,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "CircleDot",
|
||||
color: "#d97706",
|
||||
colorClass: "text-amber-600",
|
||||
bgClass: "bg-amber-50",
|
||||
borderClass: "border-amber-200",
|
||||
bgClass: "bg-amber-50 dark:bg-amber-950/50",
|
||||
borderClass: "border-amber-200 dark:border-amber-800",
|
||||
hasDuration: false,
|
||||
hasTimer: false,
|
||||
},
|
||||
@@ -84,8 +84,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Sunset",
|
||||
color: "#7c3aed",
|
||||
colorClass: "text-violet-600",
|
||||
bgClass: "bg-violet-50",
|
||||
borderClass: "border-violet-200",
|
||||
bgClass: "bg-violet-50 dark:bg-violet-950/50",
|
||||
borderClass: "border-violet-200 dark:border-violet-800",
|
||||
hasDuration: true,
|
||||
hasTimer: true,
|
||||
defaultDurationMin: 45,
|
||||
@@ -95,8 +95,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Moon",
|
||||
color: "#4338ca",
|
||||
colorClass: "text-indigo-700",
|
||||
bgClass: "bg-indigo-50",
|
||||
borderClass: "border-indigo-200",
|
||||
bgClass: "bg-indigo-50 dark:bg-indigo-950/50",
|
||||
borderClass: "border-indigo-200 dark:border-indigo-800",
|
||||
hasDuration: true,
|
||||
hasTimer: true,
|
||||
defaultDurationMin: 480,
|
||||
@@ -106,8 +106,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Pill",
|
||||
color: "#16a34a",
|
||||
colorClass: "text-green-600",
|
||||
bgClass: "bg-green-50",
|
||||
borderClass: "border-green-200",
|
||||
bgClass: "bg-green-50 dark:bg-green-950/50",
|
||||
borderClass: "border-green-200 dark:border-green-800",
|
||||
hasDuration: false,
|
||||
hasTimer: false,
|
||||
},
|
||||
@@ -116,8 +116,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Thermometer",
|
||||
color: "#dc2626",
|
||||
colorClass: "text-red-600",
|
||||
bgClass: "bg-red-50",
|
||||
borderClass: "border-red-200",
|
||||
bgClass: "bg-red-50 dark:bg-red-950/50",
|
||||
borderClass: "border-red-200 dark:border-red-800",
|
||||
hasDuration: false,
|
||||
hasTimer: false,
|
||||
},
|
||||
@@ -126,8 +126,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Bath",
|
||||
color: "#0284c7",
|
||||
colorClass: "text-sky-600",
|
||||
bgClass: "bg-sky-50",
|
||||
borderClass: "border-sky-200",
|
||||
bgClass: "bg-sky-50 dark:bg-sky-950/50",
|
||||
borderClass: "border-sky-200 dark:border-sky-800",
|
||||
hasDuration: true,
|
||||
hasTimer: true,
|
||||
defaultDurationMin: 10,
|
||||
@@ -137,8 +137,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Footprints",
|
||||
color: "#65a30d",
|
||||
colorClass: "text-lime-600",
|
||||
bgClass: "bg-lime-50",
|
||||
borderClass: "border-lime-200",
|
||||
bgClass: "bg-lime-50 dark:bg-lime-950/50",
|
||||
borderClass: "border-lime-200 dark:border-lime-800",
|
||||
hasDuration: true,
|
||||
hasTimer: true,
|
||||
defaultDurationMin: 30,
|
||||
@@ -148,8 +148,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Baby",
|
||||
color: "#d97706",
|
||||
colorClass: "text-amber-600",
|
||||
bgClass: "bg-amber-50",
|
||||
borderClass: "border-amber-200",
|
||||
bgClass: "bg-amber-50 dark:bg-amber-950/50",
|
||||
borderClass: "border-amber-200 dark:border-amber-800",
|
||||
hasDuration: true,
|
||||
hasTimer: true,
|
||||
defaultDurationMin: 5,
|
||||
@@ -159,8 +159,8 @@ export const EVENT_CONFIG: Record<
|
||||
icon: "Activity",
|
||||
color: "#dc2626",
|
||||
colorClass: "text-red-600",
|
||||
bgClass: "bg-red-50",
|
||||
borderClass: "border-red-200",
|
||||
bgClass: "bg-red-50 dark:bg-red-950/50",
|
||||
borderClass: "border-red-200 dark:border-red-800",
|
||||
hasDuration: false,
|
||||
hasTimer: false,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user