Add light/dark mode with toggle, fix all theme-aware text colors

This commit is contained in:
Andy
2026-03-21 12:18:14 +00:00
parent 4741546adf
commit 75e1d0083f
9 changed files with 211 additions and 91 deletions

View File

@@ -5,6 +5,7 @@ import { useState, useEffect } from "react"
import { motion } from "framer-motion"
import Link from "next/link"
import { Restaurant } from "@/app/types"
import { useTheme } from "@/app/components/ThemeProvider"
const MapView = dynamic(() => import("@/app/components/MapView"), { ssr: false })
@@ -19,6 +20,7 @@ export default function MapPage() {
const [restaurants, setRestaurants] = useState<Restaurant[]>([])
const [loading, setLoading] = useState(true)
const [selected, setSelected] = useState<string | null>(null)
const { theme } = useTheme()
useEffect(() => {
fetch("/api/restaurants")
@@ -35,7 +37,7 @@ export default function MapPage() {
{/* Map */}
<div className="flex-1 relative">
{loading ? (
<div className="flex items-center justify-center h-full bg-[#0d0d0d]">
<div className="flex items-center justify-center h-full bg-[#fafafa] dark:bg-[#0d0d0d]">
<motion.div
animate={{ rotate: 360 }}
transition={{ duration: 1, repeat: Infinity, ease: "linear" }}
@@ -47,14 +49,15 @@ export default function MapPage() {
restaurants={restaurants}
selectedId={selected}
onSelect={setSelected}
theme={theme}
/>
)}
</div>
{/* Desktop sidebar */}
<aside className="hidden md:flex w-80 flex-col border-l border-white/[0.06] bg-[#0d0d0d] overflow-y-auto">
<div className="p-5 border-b border-white/[0.06]">
<h2 className="text-lg font-black tracking-tight">
<aside className="hidden md:flex w-80 flex-col border-l border-black/[0.06] dark:border-white/[0.06] bg-[#fafafa] dark:bg-[#0d0d0d] overflow-y-auto">
<div className="p-5 border-b border-black/[0.06] dark:border-white/[0.06]">
<h2 className="text-lg font-black tracking-tight text-[#111] dark:text-[#f5f5f5]">
{restaurants.length} places
</h2>
</div>
@@ -66,18 +69,18 @@ export default function MapPage() {
className={`w-full text-left rounded-xl p-3 transition-all border ${
selected === r.id
? "bg-[#f59e0b]/10 border-[#f59e0b]/30"
: "bg-white/[0.02] border-white/[0.06] hover:bg-white/[0.05]"
: "bg-black/[0.02] dark:bg-white/[0.02] border-black/[0.06] dark:border-white/[0.06] hover:bg-black/[0.04] dark:hover:bg-white/[0.05]"
}`}
>
<p className="font-semibold text-sm text-[#f5f5f5]">{r.name}</p>
<p className="text-xs text-white/40 mt-0.5">
<p className="font-semibold text-sm text-[#111] dark:text-[#f5f5f5]">{r.name}</p>
<p className="text-xs text-black/40 dark:text-white/40 mt-0.5">
{r.city} · {r.cuisine[0]}
</p>
<div className="flex items-center gap-2 mt-1.5">
<span className="text-[#f59e0b] text-xs font-bold">
{avgRating(r).toFixed(1)}
</span>
<span className="text-white/25 text-xs">
<span className="text-black/25 dark:text-white/25 text-xs">
{r.visits.length} {r.visits.length === 1 ? "visit" : "visits"}
</span>
</div>
@@ -88,7 +91,7 @@ export default function MapPage() {
{/* Mobile bottom sheet */}
<motion.div
className="md:hidden fixed bottom-16 left-0 right-0 bg-[#111]/95 backdrop-blur-xl border-t border-white/[0.06] max-h-64 overflow-y-auto z-40"
className="md:hidden fixed bottom-16 left-0 right-0 bg-white/95 dark:bg-[#111]/95 backdrop-blur-xl border-t border-black/[0.06] dark:border-white/[0.06] max-h-64 overflow-y-auto z-40"
initial={{ y: 200 }}
animate={{ y: 0 }}
transition={{ delay: 0.3, duration: 0.4 }}
@@ -101,11 +104,11 @@ export default function MapPage() {
className={`text-left rounded-xl p-3 transition-all border ${
selected === r.id
? "bg-[#f59e0b]/10 border-[#f59e0b]/30"
: "bg-white/[0.03] border-white/[0.06]"
: "bg-black/[0.03] dark:bg-white/[0.03] border-black/[0.06] dark:border-white/[0.06]"
}`}
>
<p className="font-semibold text-xs text-[#f5f5f5] truncate">{r.name}</p>
<p className="text-[10px] text-white/40">{r.city}</p>
<p className="font-semibold text-xs text-[#111] dark:text-[#f5f5f5] truncate">{r.name}</p>
<p className="text-[10px] text-black/40 dark:text-white/40">{r.city}</p>
<span className="text-[#f59e0b] text-xs font-bold">
{avgRating(r).toFixed(1)}
</span>