feat: adicionar módulo Metaset como iframe interno

- Cria página Metaset.tsx com iframe embutido
- Adiciona rota /metaset no App.tsx
- Adiciona item na navbar após Engenharia
- Mantém navegação suave sem sair da aplicação
- Inclui loading state e fallback para erro de iframe
This commit is contained in:
Jonas Pacheco 2026-04-08 14:26:32 -03:00
parent 2676b79f1f
commit bdb92c4135
3 changed files with 90 additions and 1 deletions

View File

@ -48,6 +48,7 @@ const TechnicalModule = lazy(() => import("@/pages/TechnicalModule"));
const SuppliersPortal = lazy(() => import("@/pages/SuppliersPortal")); const SuppliersPortal = lazy(() => import("@/pages/SuppliersPortal"));
const NPSSurvey = lazy(() => import("@/pages/NPSSurvey")); const NPSSurvey = lazy(() => import("@/pages/NPSSurvey"));
const EngineeringHub = lazy(() => import("@/pages/EngineeringHub")); const EngineeringHub = lazy(() => import("@/pages/EngineeringHub"));
const Metaset = lazy(() => import("@/pages/Metaset"));
const DocTypeBuilder = lazy(() => import("@/pages/DocTypeBuilder")); const DocTypeBuilder = lazy(() => import("@/pages/DocTypeBuilder"));
const PageBuilder = lazy(() => import("@/pages/PageBuilder")); const PageBuilder = lazy(() => import("@/pages/PageBuilder"));
const DevelopmentModule = lazy(() => import("@/pages/DevelopmentModule")); const DevelopmentModule = lazy(() => import("@/pages/DevelopmentModule"));
@ -123,6 +124,7 @@ function Router() {
<ProtectedRoute path="/suppliers" component={SuppliersPortal} /> <ProtectedRoute path="/suppliers" component={SuppliersPortal} />
<ProtectedRoute path="/nps" component={NPSSurvey} /> <ProtectedRoute path="/nps" component={NPSSurvey} />
<ProtectedRoute path="/engineering" component={EngineeringHub} /> <ProtectedRoute path="/engineering" component={EngineeringHub} />
<ProtectedRoute path="/metaset" component={Metaset} />
<ProtectedRoute path="/development" component={DevelopmentModule} /> <ProtectedRoute path="/development" component={DevelopmentModule} />
<ProtectedRoute path="/retail" component={ArcadiaRetail} /> <ProtectedRoute path="/retail" component={ArcadiaRetail} />
<ProtectedRoute path="/plus" component={() => { const [, nav] = useLocation(); useEffect(() => nav("/soe"), []); return null; }} /> <ProtectedRoute path="/plus" component={() => { const [, nav] = useLocation(); useEffect(() => nav("/soe"), []); return null; }} />

View File

@ -1,6 +1,6 @@
import { useLocation } from "wouter"; import { useLocation } from "wouter";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { Bot, Settings, MessageCircle, Zap, LayoutDashboard, Compass, Users, Ticket, LogOut, User, Shield, Receipt, Package, Rocket, Beaker, TrendingUp, MapPin, Droplets, Star, Database, Layout, Code, Code2, Store, Layers } from "lucide-react"; import { Bot, Settings, MessageCircle, Zap, LayoutDashboard, Compass, Users, Ticket, LogOut, User, Shield, Receipt, Package, Rocket, Beaker, TrendingUp, MapPin, Droplets, Star, Database, Layout, Code, Code2, Store, Layers, BarChart3 } from "lucide-react";
import browserIcon from "@assets/arcadia_branding/arcadia_suite_icon.png"; import browserIcon from "@assets/arcadia_branding/arcadia_suite_icon.png";
import { useAuth } from "@/hooks/use-auth"; import { useAuth } from "@/hooks/use-auth";
import { useNavigationTracking } from "@/hooks/use-navigation-tracking"; import { useNavigationTracking } from "@/hooks/use-navigation-tracking";
@ -171,6 +171,16 @@ function CompactNavigationBar() {
</div> </div>
<span className="hidden md:inline">Engenharia</span> <span className="hidden md:inline">Engenharia</span>
</div> </div>
<div
className="flex items-center gap-1 hover:bg-muted px-2 py-1.5 rounded cursor-pointer transition-colors flex-shrink-0"
onClick={() => navigateTo("/metaset", "Metaset")}
data-testid="bookmark-metaset"
>
<div className="w-4 h-4 bg-gradient-to-br from-green-500 to-emerald-700 rounded-sm flex items-center justify-center">
<BarChart3 className="w-2.5 h-2.5 text-white" />
</div>
<span className="hidden md:inline text-green-600 font-medium">Metaset</span>
</div>
</div> </div>
<div className="flex items-center gap-2 flex-shrink-0 border-l pl-3 ml-2"> <div className="flex items-center gap-2 flex-shrink-0 border-l pl-3 ml-2">

View File

@ -0,0 +1,77 @@
import { useState } from "react";
import { Loader2, AlertCircle, ExternalLink } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Alert, AlertDescription } from "@/components/ui/alert";
export default function Metaset() {
const [isLoading, setIsLoading] = useState(true);
const [hasError, setHasError] = useState(false);
return (
<div className="h-[calc(100vh-40px)] w-full flex flex-col bg-background">
{/* Header do módulo */}
<div className="h-10 border-b flex items-center px-4 justify-between bg-muted/30">
<div className="flex items-center gap-2">
<span className="font-semibold text-sm">Metaset BI</span>
</div>
<Button variant="ghost" size="sm" asChild>
<a
href="https://bi.onboardbi.com.br/"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-1"
>
<ExternalLink className="w-3 h-3" />
Abrir em nova aba
</a>
</Button>
</div>
{/* Container do iframe */}
<div className="flex-1 relative">
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-background z-10">
<div className="flex flex-col items-center gap-2">
<Loader2 className="w-8 h-8 animate-spin text-primary" />
<span className="text-sm text-muted-foreground">Carregando Metaset...</span>
</div>
</div>
)}
{hasError ? (
<div className="absolute inset-0 flex items-center justify-center p-4">
<Alert variant="destructive" className="max-w-md">
<AlertCircle className="h-4 w-4" />
<AlertDescription>
Não foi possível carregar o Metaset. O site pode não permitir embed em iframe.
<div className="mt-4">
<Button asChild>
<a
href="https://bi.onboardbi.com.br/"
target="_blank"
rel="noopener noreferrer"
>
Abrir Metaset em nova aba
</a>
</Button>
</div>
</AlertDescription>
</Alert>
</div>
) : (
<iframe
src="https://bi.onboardbi.com.br/"
className="w-full h-full border-0"
onLoad={() => setIsLoading(false)}
onError={() => {
setIsLoading(false);
setHasError(true);
}}
sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
title="Metaset BI"
/>
)}
</div>
</div>
);
}