Revert "Fix RSS time filters and add draggable grid layout"

This reverts commit 4ee365cfc0.
This commit is contained in:
Shivam Patel
2026-02-09 17:56:49 -05:00
parent 4ee365cfc0
commit cebcb4c8cd
13 changed files with 47 additions and 324 deletions

View File

@@ -1,168 +1,29 @@
'use client';
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { ResponsiveGridLayout, useContainerWidth, verticalCompactor, type ResponsiveLayouts, type Layout } from 'react-grid-layout';
import { RotateCcw } from 'lucide-react';
const STORAGE_KEY = 'dashboard-layouts';
const BREAKPOINTS = { lg: 1024, md: 768, sm: 0 };
const COLS = { lg: 6, md: 4, sm: 1 };
const ROW_HEIGHT = 200;
const MARGIN: [number, number] = [16, 16];
const DEFAULT_LAYOUTS: ResponsiveLayouts = {
lg: [
{ i: 'uptime', x: 0, y: 0, w: 2, h: 1, minW: 2, minH: 1 },
{ i: 'weather', x: 2, y: 0, w: 2, h: 1, minW: 2, minH: 1 },
{ i: 'globe', x: 4, y: 0, w: 2, h: 2, minW: 2, minH: 2 },
{ i: 'newsfeed', x: 0, y: 1, w: 4, h: 3, minW: 2, minH: 2 },
],
md: [
{ i: 'uptime', x: 0, y: 0, w: 2, h: 1, minW: 2, minH: 1 },
{ i: 'weather', x: 2, y: 0, w: 2, h: 1, minW: 2, minH: 1 },
{ i: 'globe', x: 0, y: 1, w: 2, h: 2, minW: 2, minH: 2 },
{ i: 'newsfeed', x: 2, y: 1, w: 2, h: 3, minW: 2, minH: 2 },
],
sm: [
{ i: 'uptime', x: 0, y: 0, w: 1, h: 1, minW: 1, minH: 1 },
{ i: 'weather', x: 0, y: 1, w: 1, h: 1, minW: 1, minH: 1 },
{ i: 'globe', x: 0, y: 2, w: 1, h: 2, minW: 1, minH: 2 },
{ i: 'newsfeed', x: 0, y: 4, w: 1, h: 3, minW: 1, minH: 2 },
],
};
const DRAG_CONFIG = { handle: '.widget-drag-handle' };
// --- Layout Context ---
interface LayoutContextValue {
updateWidgetSize: (key: string, w: number, h: number) => void;
}
const LayoutContext = createContext<LayoutContextValue>({
updateWidgetSize: () => {},
});
export function useLayoutContext() {
return useContext(LayoutContext);
}
// --- GridShell ---
import React from 'react';
interface GridShellProps {
children: React.ReactNode;
}
function loadSavedLayouts(): ResponsiveLayouts | null {
if (typeof window === 'undefined') return null;
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (raw) return JSON.parse(raw);
} catch {}
return null;
}
function persistLayouts(layouts: ResponsiveLayouts) {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(layouts));
} catch {}
}
export function GridShell({ children }: GridShellProps) {
const [layouts, setLayouts] = useState<ResponsiveLayouts>(DEFAULT_LAYOUTS);
const [ready, setReady] = useState(false);
const { width, containerRef, mounted } = useContainerWidth({ initialWidth: 1280 });
useEffect(() => {
const saved = loadSavedLayouts();
if (saved) setLayouts(saved);
setReady(true);
}, []);
const handleLayoutChange = useCallback((_layout: Layout, allLayouts: ResponsiveLayouts) => {
setLayouts(allLayouts);
persistLayouts(allLayouts);
}, []);
const handleReset = useCallback(() => {
setLayouts(DEFAULT_LAYOUTS);
persistLayouts(DEFAULT_LAYOUTS);
}, []);
const updateWidgetSize = useCallback((key: string, w: number, h: number) => {
setLayouts((prev) => {
const next: ResponsiveLayouts = {};
for (const bp of Object.keys(prev)) {
const bpLayout = prev[bp];
if (!bpLayout) continue;
next[bp] = bpLayout.map((item) =>
item.i === key ? { ...item, w, h } : item
);
}
persistLayouts(next);
return next;
});
}, []);
const contextValue = useMemo(
() => ({ updateWidgetSize }),
[updateWidgetSize]
);
const childArray = React.Children.toArray(children);
return (
<LayoutContext.Provider value={contextValue}>
<div className="min-h-screen bg-neutral-950 text-neutral-200 p-4 md:p-8">
<div className="max-w-7xl mx-auto">
<header className="mb-8 flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight text-white mb-1">Mission Control</h1>
</div>
<div className="flex items-center gap-4">
<button
onClick={handleReset}
className="flex items-center gap-1.5 text-xs text-neutral-500 hover:text-neutral-300 transition-colors px-2 py-1 rounded-lg hover:bg-neutral-800"
title="Reset layout"
>
<RotateCcw size={13} />
Reset layout
</button>
<div className="flex gap-2 items-center">
<div className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse" />
<span className="text-xs font-mono text-emerald-500">SYSTEM ONLINE</span>
</div>
</div>
</header>
<div className="min-h-screen bg-neutral-950 text-neutral-200 p-4 md:p-8">
<div className="max-w-7xl mx-auto">
<header className="mb-8 flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight text-white mb-1">Mission Control</h1>
<div ref={containerRef as React.RefObject<HTMLDivElement>}>
{mounted && ready && (
<ResponsiveGridLayout
width={width}
layouts={layouts}
breakpoints={BREAKPOINTS}
cols={COLS}
rowHeight={ROW_HEIGHT}
margin={MARGIN}
onLayoutChange={handleLayoutChange}
dragConfig={DRAG_CONFIG}
compactor={verticalCompactor}
>
{childArray.map((child) => {
if (!React.isValidElement(child)) return null;
const key = child.key as string;
return (
<div key={key} className="h-full">
{child}
</div>
);
})}
</ResponsiveGridLayout>
)}
</div>
</div>
<div className="flex gap-2">
{/* Future header controls */}
<div className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse" />
<span className="text-xs font-mono text-emerald-500">SYSTEM ONLINE</span>
</div>
</header>
<main className="grid grid-cols-1 md:grid-cols-4 lg:grid-cols-6 gap-4 auto-rows-[200px]">
{children}
</main>
</div>
</LayoutContext.Provider>
</div>
);
}