mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
added full width button
This commit is contained in:
@@ -86,6 +86,8 @@ interface SessionTableProps {
|
||||
onColumnFiltersChange: (filters: Record<string, Set<string>>) => void;
|
||||
onDeleteSession: (sessionId: string, tenantId: string, deviceName?: string) => void;
|
||||
onBlockDevice: (serialNumber: string, tenantId: string, deviceName?: string) => void;
|
||||
fullWidth: boolean;
|
||||
onToggleFullWidth: () => void;
|
||||
}
|
||||
|
||||
export function SessionTable({
|
||||
@@ -123,6 +125,8 @@ export function SessionTable({
|
||||
onColumnFiltersChange,
|
||||
onDeleteSession,
|
||||
onBlockDevice,
|
||||
fullWidth,
|
||||
onToggleFullWidth,
|
||||
}: SessionTableProps) {
|
||||
const router = useRouter();
|
||||
const [visibleColumns, setVisibleColumns] = useState<Set<string>>(getInitialVisibleColumns);
|
||||
@@ -328,6 +332,31 @@ export function SessionTable({
|
||||
))}
|
||||
</select>
|
||||
|
||||
{/* Full-width toggle */}
|
||||
<button
|
||||
onClick={onToggleFullWidth}
|
||||
className={`inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium border transition-colors ${
|
||||
fullWidth
|
||||
? "text-blue-700 bg-blue-50 border-blue-200 hover:bg-blue-100"
|
||||
: "text-gray-600 bg-gray-100 hover:bg-gray-200 border-gray-200"
|
||||
}`}
|
||||
title={fullWidth ? "Switch to default width" : "Expand to full width"}
|
||||
aria-pressed={fullWidth}
|
||||
>
|
||||
{fullWidth ? (
|
||||
// collapse: arrows pointing inward (>-<)
|
||||
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12h18M3 8l4 4-4 4M21 8l-4 4 4 4" />
|
||||
</svg>
|
||||
) : (
|
||||
// expand: arrows pointing outward (<-->)
|
||||
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12h18M7 8l-4 4 4 4M17 8l4 4-4 4" />
|
||||
</svg>
|
||||
)}
|
||||
<span className="hidden sm:inline">{fullWidth ? "Default" : "Full width"}</span>
|
||||
</button>
|
||||
|
||||
{/* Column Selector */}
|
||||
<div className="relative" ref={columnSelectorRef}>
|
||||
<button
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Suspense, useEffect, useRef, useState } from "react";
|
||||
import { Suspense, useCallback, useEffect, useRef, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { ProtectedRoute } from "../../components/ProtectedRoute";
|
||||
@@ -30,12 +30,51 @@ export default function Home() {
|
||||
);
|
||||
}
|
||||
|
||||
const FULL_WIDTH_STORAGE_KEY = "dashboard_fullWidth";
|
||||
|
||||
function HomeContent() {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
// Opt-in full-width layout via ?span=full (also accepts wide/max) — drops the max-w-7xl cap.
|
||||
const spanParam = searchParams?.get("span")?.toLowerCase();
|
||||
const fullWidth = spanParam === "full" || spanParam === "wide" || spanParam === "max";
|
||||
// Full-width layout: URL `?span=full|wide|max` overrides + persists; `?span=default|normal|off` clears.
|
||||
// Without a URL override, falls back to the last user choice from localStorage.
|
||||
const [fullWidth, setFullWidth] = useState<boolean>(() => {
|
||||
const span = searchParams?.get("span")?.toLowerCase();
|
||||
if (span === "full" || span === "wide" || span === "max") return true;
|
||||
if (span === "default" || span === "normal" || span === "off") return false;
|
||||
if (typeof window !== "undefined") {
|
||||
try {
|
||||
return localStorage.getItem(FULL_WIDTH_STORAGE_KEY) === "1";
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Persist any URL-driven override on first mount so it survives subsequent visits without the param.
|
||||
useEffect(() => {
|
||||
const span = searchParams?.get("span")?.toLowerCase();
|
||||
if (span === "full" || span === "wide" || span === "max") {
|
||||
try { localStorage.setItem(FULL_WIDTH_STORAGE_KEY, "1"); } catch { /* ignore */ }
|
||||
} else if (span === "default" || span === "normal" || span === "off") {
|
||||
try { localStorage.setItem(FULL_WIDTH_STORAGE_KEY, "0"); } catch { /* ignore */ }
|
||||
}
|
||||
// Run once on mount; URL re-sync happens via toggleFullWidth.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const toggleFullWidth = useCallback(() => {
|
||||
setFullWidth((prev) => {
|
||||
const next = !prev;
|
||||
try { localStorage.setItem(FULL_WIDTH_STORAGE_KEY, next ? "1" : "0"); } catch { /* ignore */ }
|
||||
if (typeof window !== "undefined") {
|
||||
const url = new URL(window.location.href);
|
||||
if (next) url.searchParams.set("span", "full");
|
||||
else url.searchParams.delete("span");
|
||||
window.history.replaceState(null, "", url.toString());
|
||||
}
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const mainClassName = fullWidth
|
||||
? "w-full px-4 sm:px-6 lg:px-8 py-4"
|
||||
: "max-w-7xl mx-auto py-4 sm:px-6 lg:px-8";
|
||||
@@ -309,6 +348,8 @@ function HomeContent() {
|
||||
onColumnFiltersChange={setColumnFilters}
|
||||
onDeleteSession={deleteSession}
|
||||
onBlockDevice={blockDevice}
|
||||
fullWidth={fullWidth}
|
||||
onToggleFullWidth={toggleFullWidth}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user