fix(ui): Header branding, sidebar collapse, and layout fitting 1024x600

- Header: Change 'Data Station' to 'RTU', use TCK logo, fix sizing
- Sidebar: MENU text now clickable to collapse/expand
- RainfallView: Fit 1024x600 without scrolling
- GraphView: Fit 1024x600 screen
This commit is contained in:
2026-03-13 11:26:26 +08:00
parent e327ab9ac8
commit 30397732f9
7 changed files with 187 additions and 66 deletions

View File

@@ -4,6 +4,7 @@ import { useSensorStore } from "../stores/sensorStore";
import { VoltageDisplay } from "./VoltageDisplay";
import { BatteryStatus } from "./BatteryStatus";
import { LoginIndicator } from "./LoginIndicator";
import TCKLogo from "../../../../logo/[LOGO] TCK.svg?react";
export function Header() {
const [currentTime, setCurrentTime] = useState(new Date());
@@ -34,36 +35,36 @@ export function Header() {
};
return (
<div className="bg-gray-950 border-b border-gray-700 px-4 py-2 flex items-center gap-4 text-xs">
<div className="bg-gray-950 border-b border-gray-700 px-2 py-1 flex items-center gap-2 text-xs">
{/* Logo */}
<div className="flex items-center gap-2">
<div className="w-8 h-8 bg-blue-600 rounded flex items-center justify-center font-bold text-white">
DS
<div className="flex items-center gap-1">
<div className="w-6 h-6">
<TCKLogo className="w-full h-full" />
</div>
<span className="text-white font-semibold hidden sm:inline">Data Station</span>
<span className="text-white font-semibold">RTU</span>
</div>
<div className="flex-1 flex items-center gap-4 justify-end flex-wrap">
<div className="flex-1 flex items-center gap-2 justify-end">
{/* Time */}
<div className="flex items-center gap-2 px-2 py-1 bg-gray-800 rounded">
<div className="flex items-center gap-1 px-2 py-1 bg-gray-800 rounded">
<span className="text-gray-400">Time:</span>
<span className="text-green-400 font-mono font-semibold">{formatTime(currentTime)}</span>
</div>
{/* Date */}
<div className="flex items-center gap-2 px-2 py-1 bg-gray-800 rounded">
<div className="flex items-center gap-1 px-2 py-1 bg-gray-800 rounded">
<span className="text-gray-400">Date:</span>
<span className="text-blue-400 font-mono font-semibold">{formatDate(currentTime)}</span>
</div>
{/* Station ID */}
<div className="flex items-center gap-2 px-2 py-1 bg-gray-800 rounded">
<div className="flex items-center gap-1 px-2 py-1 bg-gray-800 rounded">
<span className="text-gray-400">Station:</span>
<span className="text-white font-semibold">{data.station.id}</span>
</div>
{/* Comm Status */}
<div className="flex items-center gap-2 px-2 py-1 bg-gray-800 rounded">
<div className="flex items-center gap-1 px-2 py-1 bg-gray-800 rounded">
{isOnline ? (
<>
<Wifi className="w-3 h-3 text-green-500" />
@@ -80,7 +81,7 @@ export function Header() {
</div>
{/* Version */}
<div className="flex items-center gap-2 px-2 py-1 bg-gray-800 rounded">
<div className="flex items-center gap-1 px-2 py-1 bg-gray-800 rounded">
<span className="text-gray-400">Ver:</span>
<span className="text-white">{data.station.version}</span>
</div>
@@ -89,10 +90,21 @@ export function Header() {
<LoginIndicator isLoggedIn={isLoggedIn} />
{/* Solar Voltage */}
<VoltageDisplay label="Solar" voltage={data.voltage.solar} />
<div className="flex items-center gap-1 px-2 py-1 bg-gray-800 rounded">
<span className="text-gray-400">Solar:</span>
<span className="text-yellow-500 font-mono">{data.voltage.solar.toFixed(1)}V</span>
</div>
{/* Battery Voltage */}
<BatteryStatus voltage={data.voltage.battery} />
<div className="flex items-center gap-1 px-2 py-1 bg-gray-800 rounded">
<span className="text-gray-400">Battery:</span>
<span className={`font-mono ${data.voltage.batteryStatus === 'HIGH' ? 'text-green-500' : 'text-red-500'}`}>
{data.voltage.battery.toFixed(1)}V
</span>
<span className={`text-xs px-1 rounded ${data.voltage.batteryStatus === 'HIGH' ? 'bg-green-500/20 text-green-500' : 'bg-red-500/20 text-red-500'}`}>
{data.voltage.batteryStatus}
</span>
</div>
</div>
</div>
);

View File

@@ -117,13 +117,13 @@ export function Sidebar({ collapsed, onToggle }: SidebarProps) {
collapsed ? "w-16" : "w-64"
}`}
>
<div className="p-3 border-b border-gray-700 flex items-center justify-between">
{!collapsed && <span className="text-white font-bold text-sm">MENU</span>}
<div className="p-2 border-b border-gray-700 flex items-center justify-between">
<button
onClick={onToggle}
className="p-1.5 hover:bg-gray-800 rounded text-gray-400 hover:text-white transition-colors"
className="flex items-center gap-2 text-white font-bold text-sm hover:bg-gray-800 px-2 py-1 rounded transition-colors"
>
<ChevronRight className={`w-4 h-4 transition-transform ${collapsed ? "" : "rotate-180"}`} />
{!collapsed && <span>MENU</span>}
</button>
</div>

View File

@@ -3,45 +3,45 @@ import { BarChart3 } from "lucide-react";
export function GraphView() {
return (
<div className="space-y-4">
<div className="flex items-center gap-3">
<BarChart3 className="w-6 h-6 text-blue-400" />
<h1 className="text-2xl font-bold text-white">Graph View</h1>
<div className="h-full p-1">
<div className="flex items-center gap-2 mb-2">
<BarChart3 className="w-5 h-5 text-blue-400" />
<h1 className="text-lg font-bold text-white">Graph View</h1>
</div>
<Card className="bg-gray-900 border-gray-700">
<CardHeader>
<CardTitle className="text-white">Data Visualization</CardTitle>
<Card className="bg-gray-900 border-gray-700 mb-2">
<CardHeader className="py-2">
<CardTitle className="text-white text-sm">Data Visualization</CardTitle>
</CardHeader>
<CardContent>
<div className="h-64 bg-gray-800 rounded flex items-center justify-center">
<span className="text-gray-500">Chart visualization area</span>
<CardContent className="py-2">
<div className="h-32 bg-gray-800 rounded flex items-center justify-center">
<span className="text-gray-500 text-sm">Chart visualization area</span>
</div>
</CardContent>
</Card>
<div className="grid grid-cols-3 gap-4">
<div className="grid grid-cols-3 gap-2">
<Card className="bg-gray-900 border-gray-700">
<CardContent className="pt-6">
<CardContent className="py-3">
<div className="text-center">
<div className="text-2xl font-bold text-blue-400">24h</div>
<div className="text-sm text-gray-400 mt-1">Time Range</div>
<div className="text-xl font-bold text-blue-400">24h</div>
<div className="text-xs text-gray-400">Time Range</div>
</div>
</CardContent>
</Card>
<Card className="bg-gray-900 border-gray-700">
<CardContent className="pt-6">
<CardContent className="py-3">
<div className="text-center">
<div className="text-2xl font-bold text-green-400">156</div>
<div className="text-sm text-gray-400 mt-1">Data Points</div>
<div className="text-xl font-bold text-green-400">156</div>
<div className="text-xs text-gray-400">Data Points</div>
</div>
</CardContent>
</Card>
<Card className="bg-gray-900 border-gray-700">
<CardContent className="pt-6">
<CardContent className="py-3">
<div className="text-center">
<div className="text-2xl font-bold text-purple-400">12.5</div>
<div className="text-sm text-gray-400 mt-1">Avg Value</div>
<div className="text-xl font-bold text-purple-400">12.5</div>
<div className="text-xs text-gray-400">Avg Value</div>
</div>
</CardContent>
</Card>

View File

@@ -1,4 +1,3 @@
import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
import { Droplets } from "lucide-react";
import { useSensorStore } from "../../stores/sensorStore";
import { RainfallCard } from "../RainfallCard";
@@ -20,26 +19,24 @@ export function RainfallView() {
const isKiosk = displayMode === 'kiosk';
return (
<div className={`space-y-4 ${isKiosk ? 'p-2' : 'p-6'}`}>
<div className="flex items-center justify-between flex-wrap gap-4">
<div className="flex items-center gap-3">
<Droplets className="w-6 h-6 text-blue-400" />
<h1 className={`font-bold text-white ${isKiosk ? 'text-lg' : 'text-2xl'}`}>
Rainfall Monitor
</h1>
</div>
<div className="flex items-center gap-4">
<ClockDisplay />
<CommStatus
asu={data.communication.asu}
dBm={data.communication.dBm}
percentage={data.communication.percentage}
/>
</div>
<div className={`h-full ${isKiosk ? 'p-1' : 'p-2'}`}>
<div className="flex items-center gap-2 mb-2">
<Droplets className="w-5 h-5 text-blue-400" />
<h1 className="font-bold text-white text-lg">
Rainfall Monitor
</h1>
</div>
<div className="flex items-center gap-4 mb-3">
<ClockDisplay />
<CommStatus
asu={data.communication.asu}
dBm={data.communication.dBm}
percentage={data.communication.percentage}
/>
</div>
<div className={`grid gap-4 ${isKiosk ? 'grid-cols-2' : 'grid-cols-4'}`}>
<div className={`grid gap-2 ${isKiosk ? 'grid-cols-2' : 'grid-cols-4'}`}>
{rainfallItems.map((item) => (
<RainfallCard
key={item.label}
@@ -50,16 +47,9 @@ export function RainfallView() {
))}
</div>
<Card className="bg-gray-900 border-gray-700">
<CardHeader>
<CardTitle className="text-white">Last Update</CardTitle>
</CardHeader>
<CardContent>
<p className="text-gray-400 font-mono">
{new Date(data.timestamp).toLocaleString()}
</p>
</CardContent>
</Card>
<div className="mt-2 text-xs text-gray-500">
Last Update: {new Date(data.timestamp).toLocaleString()}
</div>
</div>
);
}