feat: Add GridDashboard component and update routing; replace Prueba_appshell with Grid_Dashboard

This commit is contained in:
2025-05-08 23:31:05 +02:00
parent 20173e9042
commit 8d35da1972
10 changed files with 412 additions and 27 deletions
+55 -5
View File
@@ -15,6 +15,7 @@
"@tabler/icons-react": "^3.31.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-rnd": "^10.5.2",
"react-router-dom": "^7.4.0"
},
"devDependencies": {
@@ -6268,7 +6269,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true,
"license": "MIT"
},
"node_modules/js-yaml": {
@@ -6513,7 +6513,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
@@ -6842,7 +6841,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -7531,7 +7529,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.4.0",
@@ -7543,7 +7540,6 @@
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true,
"license": "MIT"
},
"node_modules/proxy-addr": {
@@ -7633,6 +7629,16 @@
"node": ">= 0.8"
}
},
"node_modules/re-resizable": {
"version": "6.11.2",
"resolved": "https://registry.npmjs.org/re-resizable/-/re-resizable-6.11.2.tgz",
"integrity": "sha512-2xI2P3OHs5qw7K0Ud1aLILK6MQxW50TcO+DetD9eIV58j84TqYeHoZcL9H4GXFXXIh7afhH8mv5iUCXII7OW7A==",
"license": "MIT",
"peerDependencies": {
"react": "^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react": {
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
@@ -7699,6 +7705,29 @@
"react": "^19.1.0"
}
},
"node_modules/react-draggable": {
"version": "4.4.6",
"resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.6.tgz",
"integrity": "sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==",
"license": "MIT",
"dependencies": {
"clsx": "^1.1.1",
"prop-types": "^15.8.1"
},
"peerDependencies": {
"react": ">= 16.3.0",
"react-dom": ">= 16.3.0"
}
},
"node_modules/react-draggable/node_modules/clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -7794,6 +7823,27 @@
}
}
},
"node_modules/react-rnd": {
"version": "10.5.2",
"resolved": "https://registry.npmjs.org/react-rnd/-/react-rnd-10.5.2.tgz",
"integrity": "sha512-0Tm4x7k7pfHf2snewJA8x7Nwgt3LV+58MVEWOVsFjk51eYruFEa6Wy7BNdxt4/lH0wIRsu7Gm3KjSXY2w7YaNw==",
"license": "MIT",
"dependencies": {
"re-resizable": "6.11.2",
"react-draggable": "4.4.6",
"tslib": "2.6.2"
},
"peerDependencies": {
"react": ">=16.3.0",
"react-dom": ">=16.3.0"
}
},
"node_modules/react-rnd/node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
"license": "0BSD"
},
"node_modules/react-router": {
"version": "7.5.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.5.3.tgz",
+1
View File
@@ -27,6 +27,7 @@
"@tabler/icons-react": "^3.31.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-rnd": "^10.5.2",
"react-router-dom": "^7.4.0"
},
"devDependencies": {
+3 -3
View File
@@ -2,7 +2,7 @@ import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import { HomePage } from './pages/Home.page';
import { Consulta_API } from './pages/Consulta_api';
import { Error_404 } from './pages/404'; // Ajusta si está en otra carpeta
import { Prueba_appshell } from './pages/Prueba_appshell'; // Ajusta si está en otra carpeta
import { Grid_Dashboard } from './pages/Grid_dashboard'; // Ajusta si está en otra carpeta
const router = createBrowserRouter([
{
@@ -14,8 +14,8 @@ const router = createBrowserRouter([
element: <Consulta_API />,
},
{
path: '/prueba_appshell',
element: <Prueba_appshell />,
path: '/Grid_Dashboard',
element: <Grid_Dashboard />,
},
{
path: '*',
@@ -9,13 +9,12 @@ import {
Title,
} from '@mantine/core';
import { default as LogoIcon } from '../../assets/icons/favicon'; // ruta relativa ajusta según tu estructura
import { default as LogoIcon } from '../../assets/icons/favicon';
import { useMantineTheme } from '@mantine/core';
import { mainLinksdata } from '../../data/navigationsLinks_1'; // ajusta la ruta
import { submenuLinks } from '../../data/submenuLinks_1'; // ajusta la ruta según tu estructura
import { mainLinksdata } from '../../data/navigationsLinks_1';
import { submenuLinks } from '../../data/submenuLinks_1';
import { useDisclosure, useMediaQuery } from '@mantine/hooks';
import { useEffect, useMemo, useState } from 'react';
+114
View File
@@ -0,0 +1,114 @@
import { Card, Text, Switch, Group, useMantineTheme, useComputedColorScheme } from '@mantine/core';
import { Rnd } from 'react-rnd';
import { useState } from 'react';
const GRID_SIZE = 30;
function hexToRgba(hex: string, alpha: number): string {
const sanitized = hex.replace('#', '');
const bigint = parseInt(sanitized, 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
interface CardData {
id: string;
x: number;
y: number;
width: number;
height: number;
}
const initialCards: CardData[] = [
{ id: '1', x: 0, y: 0, width: GRID_SIZE * 2, height: GRID_SIZE * 2 },
{ id: '2', x: GRID_SIZE * 2, y: 0, width: GRID_SIZE * 3, height: GRID_SIZE * 2 },
{ id: '3', x: GRID_SIZE * 3, y: 0, width: GRID_SIZE * 3, height: GRID_SIZE * 2 },
];
export const GridDashboard = () => {
const theme = useMantineTheme();
const colorScheme = useComputedColorScheme(); // ✅ directamente 'light' o 'dark'
const isDark = colorScheme === 'dark';
// Color de la rejilla adaptado al modo del tema
const gridBaseColor = isDark ? theme.colors.dark[4] : theme.colors.gray[3];
const gridColor = hexToRgba(gridBaseColor, 0.25); // Ajusta la opacidad aquí
const [cards, setCards] = useState<CardData[]>(initialCards);
const [showGrid, setShowGrid] = useState(true);
const updateCard = (id: string, updates: Partial<CardData>) => {
setCards((prev) =>
prev.map((card) => (card.id === id ? { ...card, ...updates } : card))
);
};
return (
<>
<Group p="md">
<Switch
checked={showGrid}
onChange={(event) => setShowGrid(event.currentTarget.checked)}
label="Mostrar cuadrícula"
/>
</Group>
<div
style={{
width: '100%',
height: '700px',
backgroundSize: `${GRID_SIZE}px ${GRID_SIZE}px`,
backgroundImage: showGrid
? `linear-gradient(to right, ${gridColor} 1px, transparent 1px),
linear-gradient(to bottom, ${gridColor} 1px, transparent 1px)`
: 'none',
position: 'relative',
}}
>
{cards.map((card) => (
<Rnd
key={card.id}
size={{
width: Math.round(card.width / GRID_SIZE) * GRID_SIZE,
height: Math.round(card.height / GRID_SIZE) * GRID_SIZE,
}}
position={{ x: card.x, y: card.y }}
minWidth={GRID_SIZE * 8}
minHeight={GRID_SIZE * 8}
bounds="parent"
grid={[GRID_SIZE, GRID_SIZE]}
onDragStop={(_, d) =>
updateCard(card.id, {
x: Math.round(d.x / GRID_SIZE) * GRID_SIZE,
y: Math.round(d.y / GRID_SIZE) * GRID_SIZE,
})
}
onResizeStop={(_, __, ref, ___, pos) =>
updateCard(card.id, {
width: Math.round(ref.offsetWidth / GRID_SIZE) * GRID_SIZE,
height: Math.round(ref.offsetHeight / GRID_SIZE) * GRID_SIZE,
x: Math.round(pos.x / GRID_SIZE) * GRID_SIZE,
y: Math.round(pos.y / GRID_SIZE) * GRID_SIZE,
})
}
>
<Card
shadow="sm"
padding="md"
radius="md"
withBorder
style={{ height: '100%', userSelect: 'none' }}
>
<Text fw={500}>Card {card.id}</Text>
<Text size="sm">Mueve o redimensiona</Text>
</Card>
</Rnd>
))}
</div>
</>
);
};
+1 -1
View File
@@ -4,7 +4,7 @@ export const submenuLinks = {
Home: [
{ label: 'Inicio', to: '/' },
{ label: 'Consulta Api', to: '/Consulta_API' },
{ label: 'Prueba_appshell', to: '/prueba_appshell' },
{ label: 'Grid_Dashboard', to: '/Grid_Dashboard' },
],
Dashboard: [
{ label: 'Resumen', to: '/dashboard/resumen' },
+14
View File
@@ -0,0 +1,14 @@
import { Grid } from '@mantine/core';
import { AppShellWithMenu } from '../components/Appshell/Appshell';
import { GridDashboard } from '../components/Grid_dashboard';
export function Grid_Dashboard() {
return (
<AppShellWithMenu>
<GridDashboard></GridDashboard>
</AppShellWithMenu>
);
}
-12
View File
@@ -1,12 +0,0 @@
import { AppShellWithMenu } from '../components/Appshell/Appshell';
export function Prueba_appshell() {
return (
<AppShellWithMenu>
</AppShellWithMenu>
);
}
+34 -2
View File
@@ -1419,6 +1419,11 @@ check-error@^2.1.1:
resolved "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz"
integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==
clsx@^1.1.1:
version "1.2.1"
resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz"
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
clsx@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
@@ -3613,6 +3618,11 @@ raw-body@^3.0.0:
iconv-lite "0.6.3"
unpipe "1.0.0"
re-resizable@6.11.2:
version "6.11.2"
resolved "https://registry.npmjs.org/re-resizable/-/re-resizable-6.11.2.tgz"
integrity sha512-2xI2P3OHs5qw7K0Ud1aLILK6MQxW50TcO+DetD9eIV58j84TqYeHoZcL9H4GXFXXIh7afhH8mv5iUCXII7OW7A==
react-docgen-typescript@^2.2.2:
version "2.2.2"
resolved "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz"
@@ -3634,13 +3644,21 @@ react-docgen@^7.0.0:
resolve "^1.22.1"
strip-indent "^4.0.0"
"react-dom@^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom@^18.0.0 || ^19.0.0", "react-dom@^18.x || ^19.x", react-dom@^19.0.0, react-dom@^19.1.0, react-dom@>=16.13, react-dom@>=16.8.0, react-dom@>=18:
"react-dom@^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom@^18.0.0 || ^19.0.0", "react-dom@^18.x || ^19.x", react-dom@^19.0.0, react-dom@^19.1.0, "react-dom@>= 16.3.0", react-dom@>=16.13, react-dom@>=16.3.0, react-dom@>=16.8.0, react-dom@>=18:
version "19.1.0"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz"
integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==
dependencies:
scheduler "^0.26.0"
react-draggable@4.4.6:
version "4.4.6"
resolved "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.6.tgz"
integrity sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==
dependencies:
clsx "^1.1.1"
prop-types "^15.8.1"
react-is@^16.13.1:
version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
@@ -3687,6 +3705,15 @@ react-remove-scroll@^2.6.2:
use-callback-ref "^1.3.3"
use-sidecar "^1.1.3"
react-rnd@^10.5.2:
version "10.5.2"
resolved "https://registry.npmjs.org/react-rnd/-/react-rnd-10.5.2.tgz"
integrity sha512-0Tm4x7k7pfHf2snewJA8x7Nwgt3LV+58MVEWOVsFjk51eYruFEa6Wy7BNdxt4/lH0wIRsu7Gm3KjSXY2w7YaNw==
dependencies:
re-resizable "6.11.2"
react-draggable "4.4.6"
tslib "2.6.2"
react-router-dom@^7.4.0:
version "7.5.3"
resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.5.3.tgz"
@@ -3725,7 +3752,7 @@ react-use-measure@^2.1.7:
resolved "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz"
integrity sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==
"react@^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react@^18.0.0 || ^19.0.0", "react@^18.x || ^19.x", react@^19.0.0, react@^19.1.0, "react@>= 16", react@>=16.13, react@>=16.8.0, react@>=17.0, react@>=18, react@>=18.0.0:
"react@^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react@^18.0.0 || ^19.0.0", "react@^18.x || ^19.x", react@^19.0.0, react@^19.1.0, "react@>= 16", "react@>= 16.3.0", react@>=16.13, react@>=16.3.0, react@>=16.8.0, react@>=17.0, react@>=18, react@>=18.0.0:
version "19.1.0"
resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz"
integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
@@ -4535,6 +4562,11 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0:
resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
tslib@2.6.2:
version "2.6.2"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
turbo-stream@2.4.0:
version "2.4.0"
resolved "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz"