feat: ajustar layout abaixo do banner do Hub e ocultar targa no Modo Smart
This commit is contained in:
@@ -5,6 +5,7 @@ import { ProtectedRoute } from './ProtectedRoute';
|
||||
import { ProtectedAdminRoute } from './ProtectedAdminRoute';
|
||||
import { ProtectedRouteByResource } from './ProtectedRouteByResource';
|
||||
import { routeConfig, RouteDefinition } from '@/config/routeConfig';
|
||||
import { useHubBanner } from '@/hooks/useHubBanner';
|
||||
|
||||
// ============================================================================
|
||||
// Fallback de loading para Suspense
|
||||
@@ -84,6 +85,8 @@ function wrapWithGuard(
|
||||
// ============================================================================
|
||||
|
||||
export function AppRoutes() {
|
||||
useHubBanner();
|
||||
|
||||
const routes = useMemo(
|
||||
() =>
|
||||
routeConfig.map((route) => {
|
||||
|
||||
@@ -26,9 +26,9 @@ export const Layout = ({ children }: LayoutProps) => {
|
||||
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<div className="min-h-screen flex w-full">
|
||||
<div className="min-h-[calc(100vh-var(--hub-banner-height,0px))] flex w-full">
|
||||
<AppSidebar />
|
||||
<main className="flex-1 overflow-hidden flex flex-col">
|
||||
<main className="flex-1 overflow-hidden flex flex-col h-[calc(100vh-var(--hub-banner-height,0px))]">
|
||||
{/* Header fixo com SidebarTrigger, Modo Smart e ThemeToggle */}
|
||||
<header className="h-14 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 flex items-center justify-between px-4 shrink-0">
|
||||
<div className="flex items-center">
|
||||
|
||||
@@ -202,6 +202,8 @@ const Sidebar = React.forwardRef<
|
||||
style={
|
||||
{
|
||||
"--sidebar-width": SIDEBAR_WIDTH_MOBILE,
|
||||
top: "var(--hub-banner-height, 0px)",
|
||||
height: "calc(100vh - var(--hub-banner-height, 0px))",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
side={side}
|
||||
@@ -224,17 +226,20 @@ const Sidebar = React.forwardRef<
|
||||
{/* This is what handles the sidebar gap on desktop */}
|
||||
<div
|
||||
className={cn(
|
||||
"duration-200 relative h-svh w-[--sidebar-width] bg-transparent transition-[width] ease-linear",
|
||||
"duration-200 relative w-[--sidebar-width] bg-transparent transition-[width] ease-linear",
|
||||
"group-data-[collapsible=offcanvas]:w-0",
|
||||
"group-data-[side=right]:rotate-180",
|
||||
variant === "floating" || variant === "inset"
|
||||
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]"
|
||||
: "group-data-[collapsible=icon]:w-[--sidebar-width-icon]"
|
||||
)}
|
||||
style={{
|
||||
height: "calc(100svh - var(--hub-banner-height, 0px))",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={cn(
|
||||
"duration-200 fixed inset-y-0 z-10 hidden h-svh w-[--sidebar-width] transition-[left,right,width] ease-linear md:flex",
|
||||
"duration-200 fixed bottom-0 z-10 hidden w-[--sidebar-width] transition-[left,right,width] ease-linear md:flex",
|
||||
side === "left"
|
||||
? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
|
||||
: "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
|
||||
@@ -244,6 +249,10 @@ const Sidebar = React.forwardRef<
|
||||
: "group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l",
|
||||
className
|
||||
)}
|
||||
style={{
|
||||
top: "var(--hub-banner-height, 0px)",
|
||||
height: "calc(100svh - var(--hub-banner-height, 0px))",
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
/**
|
||||
* Hook para gerenciar e compensar a presença do cabeçalho / targa do BrainSteel Hub.
|
||||
* - Detecta se o banner do SDK (#brainsteel-guard-banner) está ativo.
|
||||
* - Sincroniza a variável CSS --hub-banner-height para que sidebars e layouts se ajustem.
|
||||
* - Oculta automaticamente o banner quando no Modo Smart (/smart).
|
||||
*/
|
||||
export function useHubBanner() {
|
||||
const location = useLocation();
|
||||
const isSmartMode = location.pathname.startsWith('/smart');
|
||||
|
||||
useEffect(() => {
|
||||
function updateBannerState() {
|
||||
const banner = document.getElementById('brainsteel-guard-banner');
|
||||
const isBannerPresent = Boolean(banner);
|
||||
|
||||
if (isSmartMode) {
|
||||
document.body.classList.add('modo-smart-active');
|
||||
document.body.classList.remove('has-hub-banner');
|
||||
document.documentElement.style.setProperty('--hub-banner-height', '0px');
|
||||
document.body.style.paddingTop = '0px';
|
||||
} else if (isBannerPresent) {
|
||||
document.body.classList.remove('modo-smart-active');
|
||||
document.body.classList.add('has-hub-banner');
|
||||
document.documentElement.style.setProperty('--hub-banner-height', '34px');
|
||||
document.body.style.paddingTop = '34px';
|
||||
} else {
|
||||
document.body.classList.remove('modo-smart-active');
|
||||
document.body.classList.remove('has-hub-banner');
|
||||
document.documentElement.style.setProperty('--hub-banner-height', '0px');
|
||||
document.body.style.paddingTop = '0px';
|
||||
}
|
||||
}
|
||||
|
||||
updateBannerState();
|
||||
|
||||
// Observa inserções dinâmicas do banner pelo script SDK do Hub
|
||||
const observer = new MutationObserver(() => {
|
||||
updateBannerState();
|
||||
});
|
||||
|
||||
observer.observe(document.body, { childList: true, subtree: false });
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, [isSmartMode]);
|
||||
}
|
||||
@@ -41,6 +41,32 @@
|
||||
--chart-5: 340 75% 55%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
--hub-banner-height: 0px;
|
||||
}
|
||||
|
||||
body:has(#brainsteel-guard-banner) {
|
||||
--hub-banner-height: 34px;
|
||||
}
|
||||
|
||||
body.has-hub-banner {
|
||||
--hub-banner-height: 34px;
|
||||
}
|
||||
|
||||
/* Modo Smart: oculta completamente a targa do BrainSteel Hub */
|
||||
body.modo-smart-active #brainsteel-guard-banner,
|
||||
body.hide-hub-banner #brainsteel-guard-banner {
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
height: 0 !important;
|
||||
min-height: 0 !important;
|
||||
opacity: 0 !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
body.modo-smart-active,
|
||||
body.hide-hub-banner {
|
||||
padding-top: 0px !important;
|
||||
--hub-banner-height: 0px !important;
|
||||
}
|
||||
|
||||
.light {
|
||||
|
||||
@@ -73,6 +73,23 @@ export const ModoSmart: React.FC = () => {
|
||||
carregarProducaoHoje();
|
||||
}, [carregarProducaoHoje]);
|
||||
|
||||
// Modo Smart: Oculta a targa do BrainSteel Hub para maximizar a área de trabalho
|
||||
useEffect(() => {
|
||||
document.body.classList.add('modo-smart-active');
|
||||
document.documentElement.style.setProperty('--hub-banner-height', '0px');
|
||||
document.body.style.paddingTop = '0px';
|
||||
|
||||
return () => {
|
||||
document.body.classList.remove('modo-smart-active');
|
||||
const banner = document.getElementById('brainsteel-guard-banner');
|
||||
if (banner) {
|
||||
document.body.classList.add('has-hub-banner');
|
||||
document.documentElement.style.setProperty('--hub-banner-height', '34px');
|
||||
document.body.style.paddingTop = '34px';
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleSelectObra = (of: OFAtiva) => {
|
||||
setObraAtiva(of);
|
||||
setTelaAtiva('hub');
|
||||
|
||||
@@ -501,7 +501,7 @@ export default function Visualizador3D() {
|
||||
const hasSavedModel = Boolean(currentOFInfo?.ifc_url);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-[calc(100vh-4rem)] p-4 md:p-6 space-y-4 max-w-[1920px] mx-auto overflow-hidden">
|
||||
<div className="flex flex-col flex-1 min-h-0 p-4 md:p-6 space-y-4 max-w-[1920px] mx-auto overflow-hidden">
|
||||
{/* Top Header Bar */}
|
||||
<div className="flex flex-wrap items-center justify-between gap-4 p-4 bg-white dark:bg-slate-900/90 backdrop-blur-md border border-slate-200 dark:border-slate-800 rounded-2xl shadow-lg dark:shadow-xl">
|
||||
{/* Left: Title, OF Selector & Phase Filter */}
|
||||
|
||||
Reference in New Issue
Block a user