Improve map page UI with modern SaaS design
- Redesign header with consistent button heights and spacing - Move all controls to single compact row on desktop - Add proper visual hierarchy with subtle shadows and borders - Implement modern color scheme (gray-50/200/300/700/900) - Optimize spacing to maximize map visibility - Improve responsive layout for mobile devices - Add smooth transitions and hover states 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -62,38 +62,22 @@ export default function MapPage() {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col">
|
||||
{/* Header with controls */}
|
||||
<div className="bg-white shadow-md p-3 sm:p-4">
|
||||
<div className="flex flex-col gap-3">
|
||||
{/* Top row: Title and Admin link */}
|
||||
<div className="flex items-center justify-between">
|
||||
<h1 className="text-lg sm:text-xl font-bold text-black">Location Tracker</h1>
|
||||
<div className="flex gap-2">
|
||||
<a
|
||||
href="/export"
|
||||
className="px-3 py-1 text-sm bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors whitespace-nowrap"
|
||||
>
|
||||
📥 Export
|
||||
</a>
|
||||
<a
|
||||
href="/admin"
|
||||
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors whitespace-nowrap"
|
||||
>
|
||||
Admin
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-screen flex flex-col bg-gray-50">
|
||||
{/* Modern SaaS Header - Compact */}
|
||||
<div className="bg-white border-b border-gray-200 shadow-sm">
|
||||
<div className="px-4 sm:px-6 py-3">
|
||||
{/* Single row with title and controls */}
|
||||
<div className="flex flex-col lg:flex-row gap-3 items-stretch lg:items-center">
|
||||
{/* Title - left aligned */}
|
||||
<h1 className="text-lg sm:text-xl font-semibold text-gray-900 lg:mr-4">Location Tracker</h1>
|
||||
|
||||
{/* Controls row - responsive grid */}
|
||||
<div className="flex flex-col sm:flex-row gap-2 sm:gap-4 items-stretch sm:items-center">
|
||||
{/* Device Filter */}
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="text-xs sm:text-sm font-medium text-black whitespace-nowrap">Device:</label>
|
||||
<div className="flex items-center gap-2 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
|
||||
<label className="text-sm font-medium text-gray-700 whitespace-nowrap">Device</label>
|
||||
<select
|
||||
value={selectedDevice}
|
||||
onChange={(e) => setSelectedDevice(e.target.value)}
|
||||
className="flex-1 sm:flex-none px-2 sm:px-3 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
className="flex-1 lg:w-44 px-2 py-1.5 text-sm bg-white border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
>
|
||||
<option value="all">All My Devices</option>
|
||||
{devices.map((device) => (
|
||||
@@ -105,12 +89,12 @@ export default function MapPage() {
|
||||
</div>
|
||||
|
||||
{/* Time Filter */}
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="text-xs sm:text-sm font-medium text-black whitespace-nowrap">Time:</label>
|
||||
<div className="flex items-center gap-2 bg-gray-50 px-3 py-2 rounded-lg border border-gray-200">
|
||||
<label className="text-sm font-medium text-gray-700 whitespace-nowrap">Time</label>
|
||||
<select
|
||||
value={timeFilter}
|
||||
onChange={(e) => setTimeFilter(Number(e.target.value))}
|
||||
className="flex-1 sm:flex-none px-2 sm:px-3 py-1 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
className="flex-1 lg:w-32 px-2 py-1.5 text-sm bg-white border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
>
|
||||
{TIME_FILTERS.map((filter) => (
|
||||
<option key={filter.value} value={filter.value}>
|
||||
@@ -120,48 +104,71 @@ export default function MapPage() {
|
||||
</select>
|
||||
<button
|
||||
onClick={() => setFilterMode(filterMode === "quick" ? "custom" : "quick")}
|
||||
className="px-2 sm:px-3 py-1 text-xs sm:text-sm font-medium bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition-colors whitespace-nowrap"
|
||||
className="inline-flex items-center px-2.5 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 hover:border-gray-400 transition-all duration-200"
|
||||
title="Toggle Custom Range"
|
||||
>
|
||||
📅 {filterMode === "quick" ? "Custom" : "Quick"}
|
||||
📅
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Pause/Resume Button */}
|
||||
<button
|
||||
onClick={() => setIsPaused(!isPaused)}
|
||||
className={`px-3 sm:px-4 py-1 text-sm rounded-md font-semibold transition-colors whitespace-nowrap ${
|
||||
className={`inline-flex items-center justify-center px-4 py-2 text-sm font-medium rounded-lg transition-all duration-200 shadow-sm ${
|
||||
isPaused
|
||||
? "bg-green-500 hover:bg-green-600 text-white"
|
||||
: "bg-red-500 hover:bg-red-600 text-white"
|
||||
? "bg-green-600 hover:bg-green-700 text-white border border-green-600 hover:border-green-700"
|
||||
: "bg-red-600 hover:bg-red-700 text-white border border-red-600 hover:border-red-700"
|
||||
}`}
|
||||
>
|
||||
{isPaused ? "▶ Resume" : "⏸ Pause"}
|
||||
<span className="mr-1.5">{isPaused ? "▶" : "⏸"}</span>
|
||||
{isPaused ? "Resume" : "Pause"}
|
||||
</button>
|
||||
|
||||
{/* Spacer to push buttons to the right */}
|
||||
<div className="hidden lg:block lg:flex-1"></div>
|
||||
|
||||
{/* Export and Admin Buttons */}
|
||||
<div className="flex items-center gap-2">
|
||||
<a
|
||||
href="/export"
|
||||
className="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 hover:border-gray-400 transition-all duration-200 shadow-sm"
|
||||
>
|
||||
<span className="mr-1.5">📥</span>
|
||||
Export
|
||||
</a>
|
||||
<a
|
||||
href="/admin"
|
||||
className="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-blue-600 rounded-lg hover:bg-blue-700 hover:border-blue-700 transition-all duration-200 shadow-sm"
|
||||
>
|
||||
Admin
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Custom Range (only visible when active) */}
|
||||
{/* Custom Range - Modern Card Style */}
|
||||
{filterMode === "custom" && (
|
||||
<div className="flex flex-col sm:flex-row items-stretch sm:items-center gap-2 border border-blue-300 bg-blue-50 rounded-md p-2">
|
||||
<div className="flex items-center gap-1">
|
||||
<label className="text-xs font-medium text-black whitespace-nowrap">From:</label>
|
||||
<div className="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
|
||||
<div className="flex flex-col sm:flex-row items-stretch sm:items-center gap-4">
|
||||
<div className="flex items-center gap-3 flex-1">
|
||||
<label className="text-sm font-medium text-gray-700 whitespace-nowrap min-w-[60px]">From</label>
|
||||
<input
|
||||
type="datetime-local"
|
||||
value={startTime}
|
||||
onChange={(e) => setStartTime(e.target.value)}
|
||||
className="flex-1 sm:flex-none px-2 py-1 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 text-xs"
|
||||
className="flex-1 px-3 py-2 text-sm bg-white border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<label className="text-xs font-medium text-black whitespace-nowrap">To:</label>
|
||||
<div className="flex items-center gap-3 flex-1">
|
||||
<label className="text-sm font-medium text-gray-700 whitespace-nowrap min-w-[60px]">To</label>
|
||||
<input
|
||||
type="datetime-local"
|
||||
value={endTime}
|
||||
onChange={(e) => setEndTime(e.target.value)}
|
||||
className="flex-1 sm:flex-none px-2 py-1 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 text-xs"
|
||||
className="flex-1 px-3 py-2 text-sm bg-white border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user