diff --git a/client/src/App.jsx b/client/src/App.jsx
index b4c635c..c18c32e 100644
--- a/client/src/App.jsx
+++ b/client/src/App.jsx
@@ -1,6 +1,6 @@
import 'leaflet/dist/leaflet.css';
import { Routes, Route, Navigate, Outlet } from 'react-router-dom';
-import { useRecipe, Grid, GridItem, useDialog } from "@chakra-ui/react";
+import { useRecipe, Grid, GridItem, useDialog, Flex, Heading } from "@chakra-ui/react";
import { createContext } from "react";
import Login from "@/Login.jsx";
import Sidebar from "./components/Sidebar/Sidebar.jsx";
@@ -44,7 +44,11 @@ function AppFoundation() {
// if (user) return children;
// else return ;
// }
-
+const Placeholder = ({ name }) => (
+
+ {name} Dashboard - Coming Soon
+
+);
function App() {
const sidebarContext = createContext(["Home", "Global Map", "Regional Map", "Volcano", "Admin"]);
// const [user, setUser] = useState(null);
@@ -56,7 +60,16 @@ function App() {
{/*Non-Public Routes*/}
}>
- } />
+
+ }>
+ {/* We use our "pass" component to fill the Outlet until the real pages are built */}
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
} />
} />
} />
diff --git a/client/src/components/Canvas/views/Home.jsx b/client/src/components/Canvas/views/Home.jsx
index cb6383f..1ff06c7 100644
--- a/client/src/components/Canvas/views/Home.jsx
+++ b/client/src/components/Canvas/views/Home.jsx
@@ -1,186 +1,64 @@
-import { HStack, Flex, Tabs, Button } from "@chakra-ui/react";
-import { useState } from "react";
-import MyDashboard from "./HomeTabs/MyDashboard";
+import { HStack, Flex, Box } from "@chakra-ui/react";
+import { NavLink, Outlet, useLocation } from "react-router-dom";
import { SearchBar } from "../CanvasComponents/SearchBar";
import { SettingsButton } from "../CanvasComponents/SettingsButton";
-import { DailyActivity } from "./HomeTabs/DailyActivity";
-import { Gas } from "./HomeTabs/Gas";
-import { Seismic } from "./HomeTabs/Seismic";
-import { RemoteSensing } from "./HomeTabs/RemoteSensing";
-import { CancelButton } from "../CanvasComponents/CancelButton";
-import { SaveButton } from "../CanvasComponents/SaveButton";
-import DeleteAllButton from "../CanvasComponents/DeleteAllButton";
-import { v4 as uuid } from 'uuid';
-import { CanvasHeaderTabs } from '../CanvasComponents/CanvasHeaderTabs';
-import { DASHBOARD_TABS } from "@/constants/viewKeys";
export default function Home() {
- const [isEditable, setIsEditable] = useState(false); // editable=true means static=false (vice versa)
- const [isDelete, setIsDelete] = useState(false);
- const [originalLayout, setOriginalLayout] = useState([]);
- const [originalWidgets, setOriginalWidgets] = useState([]);
- const [layout, setLayout] = useState([]);
- const [widgetArray, setWidgetArray] = useState([]);
+ const location = useLocation();
+ const isPersonalDashboard = location.pathname === "/home" || location.pathname === "/home/";
- function appendWidget(name, w, h, min_w, minh, max_w, max_h) {
- saveLayoutState(); // Save state before anything else
-
- const newID = uuid(); // could be replaced with something else like guid
- const COLS = 16;
- const W = w ?? 3;
- const H = h ?? 3;
-
- setWidgetArray([ // updating widget array containing info on the types of widgets
- ...widgetArray,
- {i: newID, widget: name }
- ]);
- // onAddWidget(newID, w, h, min_w, minh, max_w, max_h); // updating array containing info on layout of widgets
-
- setLayout(prev => [
- ...prev,
- {
- i: newID,
- x: (prev.length * W) % COLS,
- y: 0,
- w: w,
- h: h,
- minW: min_w,
- minH: minh,
- maxW: max_w,
- maxH: max_h,
- static: false,
- resizeHandles: ['se']
- },
- ]);
- }
-
- const onSave = () => {
- console.log("saving widgets...");
- // Set all widgets back to static: true
- setLayout(prevLayout =>
- prevLayout.map(item => ({
- ...item,
- static: true
- }))
- );
- setIsEditable(false);
- setIsDelete(false);
- setOriginalLayout([]); // Clear backup layout
- setOriginalWidgets([]);
- }
-
- const onEditWidgets = () => {
- console.log("Start deleting widgets...");
- saveLayoutState(); // Save state before anything else
- setLayout(prevLayout =>
- prevLayout.map(item => ({
- ...item,
- static: false
- }))
- );
- setIsEditable(true);
- setIsDelete(true);
- }
-
- const DeleteWidget = (ID) => {
- console.log("Deleting widget with id: ", ID);
- setLayout(layout => layout.filter(w => w.i !== ID));
- setWidgetArray(widgetArray => widgetArray.filter(w => w.i !== ID));
- }
-
- const DeleteAll = () => {
- const confirm = window.confirm(
- "Are you sure you want to delete all widgets?"
- );
- if (confirm) {
- setLayout([]);
- setWidgetArray([]);
- onSave();
- }
- else return;
- }
-
-
- const saveLayoutState = () => {
- if ( !isEditable ) {
- setOriginalLayout(layout);
- setOriginalWidgets(widgetArray);
+ // 1. 🎨 CSS Magic: Replicates Chakra's `` exactly
+ const tabStyles = {
+ fontSize: "lg",
+ fontWeight: "normal",
+ color: "fg.muted",
+ px: 4, // Horizontal padding
+ py: 2, // Vertical padding
+ borderBottom: "2px solid transparent",
+ mb: "-2px", // 🔥 The trick: Pulls the active border down to overlap the container's line
+ transition: "all 0.2s",
+ _hover: { color: "fg" },
+ _activeLink: {
+ color: "color", // Or whatever your primary text color is
+ borderColor: "currentColor", // The active underline
}
};
- const onCancel = () => {
- console.log("canceling changes...");
- console.log(originalWidgets);
- if (originalLayout.length) {
- setLayout(originalLayout.map(item => ({
- ...item,
- static: true
- })));
- }
- setWidgetArray(originalWidgets);
- setIsEditable(false);
- setIsDelete(false);
- setOriginalLayout([]);
- setOriginalWidgets([]);
- }
-
- const onLayoutChange = (newLayout) => setLayout(newLayout);
-
-
- // Prop Forwarding
- const MyDashboardProps = { layout, onLayoutChange, isEditable, saveLayoutState, isDelete, DeleteWidget, widgetArray, appendWidget };
- const settingsButtonProps = { onEditWidgets, appendWidget };
-
return (
- /* SUB HEADER */
-
-
- {/* TABS */}
- {/* */} {/* TODO: rename to SubHeaderTabs */}
-
- {DASHBOARD_TABS.map(({ value, label }) =>
-
- { label }
-
- )}
-
+
+
+ {/* 2. 🛠️ SUB HEADER: Matches your original padding and background */}
+
+
+ {/* TABS CONTAINER - Replicates the Tabs.List line container */}
+
+ My Dashboard
+ Gas
+ Seismic
+ Remote Sensing
+ Daily Activity
+
+
+ {/* EDIT MODE BUTTONS & CONTROLS */}
+
+ {isPersonalDashboard ? (
+ <>
+
+ {/* This will eventually trigger your Zustand store's edit mode! */}
+
+ >
+ ) : (
+
+ )}
+
+
+
+
+ {/* 3. 🛠️ CANVAS AREA */}
+
+
+
- {/* EDIT MODE BUTTONS */}
-
- {isEditable ? (
- <>
-
-
- {isDelete ? (
-
- ):(null)
- }
- >
- ):(
- <>
-
-
- >
- )}
-
-
- {/* CANVAS */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
);
}
\ No newline at end of file
diff --git a/client/src/constants/widgetRegistry.jsx b/client/src/constants/widgetRegistry.jsx
new file mode 100644
index 0000000..8d39b68
--- /dev/null
+++ b/client/src/constants/widgetRegistry.jsx
@@ -0,0 +1,52 @@
+// config/widgetRegistry.js
+
+// We assume a 12-column grid.
+// w: 12 = full screen width
+// w: 6 = half screen width
+// w: 4 = one-third screen width
+// w: 3 = one-quarter screen width
+
+export const WIDGET_REGISTRY = {
+ "vaa_activity": {
+ name: "VAA 7 Day Activity",
+ description: "Displays 7-day flight level timelines across multiple volcanoes.",
+ allowedSizes: {
+ large: { w: 12, h: 8 }, // Spans the entire width of the screen
+ }
+ },
+
+ "db_cache_health": {
+ name: "DB Cache Health",
+ description: "Bar chart showing cache table operational status.",
+ allowedSizes: {
+ medium: { w: 4, h: 6 }, // 1/3 width
+ large: { w: 6, h: 6 } // 1/2 width
+ }
+ },
+
+ "ivans_alerts": {
+ name: "IVANS",
+ description: "Feed of recent IVANS reports and reviewer statuses.",
+ allowedSizes: {
+ small: { w: 3, h: 6 }, // 1/4 width (tall and skinny)
+ medium: { w: 4, h: 8 } // 1/3 width
+ }
+ },
+
+ "remote_sensing": {
+ name: "Remote Sensing",
+ description: "Feed of recent remote sensing reports.",
+ allowedSizes: {
+ medium: { w: 4, h: 5 }, // 1/3 width
+ }
+ },
+
+ "alert_levels": {
+ name: "Alert Level Changes",
+ description: "List of 7-day alert level changes with trend arrows.",
+ allowedSizes: {
+ small: { w: 3, h: 5 },
+ medium: { w: 4, h: 5 }
+ }
+ }
+};
\ No newline at end of file