@oondemand/oon-core-front 0.4.3 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -539,11 +539,11 @@ var oonSystem = createOonSystem();
539
539
 
540
540
  // src/security/AuthProvider.tsx
541
541
  import {
542
- createContext as createContext3,
543
- useCallback as useCallback2,
544
- useContext as useContext3,
542
+ createContext as createContext4,
543
+ useCallback as useCallback3,
544
+ useContext as useContext4,
545
545
  useEffect as useEffect4,
546
- useState as useState4
546
+ useState as useState5
547
547
  } from "react";
548
548
 
549
549
  // src/security/ActivationProvider.tsx
@@ -598,9 +598,65 @@ function useActivation() {
598
598
  return context;
599
599
  }
600
600
 
601
- // src/security/AuthProvider.tsx
601
+ // src/security/TenantProvider.tsx
602
+ import {
603
+ createContext as createContext3,
604
+ useCallback as useCallback2,
605
+ useContext as useContext3,
606
+ useMemo as useMemo2,
607
+ useState as useState4
608
+ } from "react";
609
+ import { useQueryClient } from "@tanstack/react-query";
602
610
  import { jsx as jsx5 } from "react/jsx-runtime";
603
- var AuthContext = createContext3(null);
611
+ var TenantContext = createContext3(null);
612
+ function applyHeader(http, tenantId) {
613
+ if (tenantId) {
614
+ http.defaults.headers.common["x-oon-tenant-id"] = tenantId;
615
+ return;
616
+ }
617
+ delete http.defaults.headers.common["x-oon-tenant-id"];
618
+ }
619
+ function TenantProvider({ http, storage, children }) {
620
+ const queryClient = useQueryClient();
621
+ const [activeTenantId, setActiveTenantId] = useState4(() => storage.get());
622
+ const replaceTenant = useCallback2(
623
+ (tenantId) => {
624
+ const normalized2 = String(tenantId ?? "").trim() || null;
625
+ if (normalized2) storage.set(normalized2);
626
+ else storage.clear();
627
+ applyHeader(http, normalized2);
628
+ setActiveTenantId(normalized2);
629
+ queryClient.clear();
630
+ },
631
+ [http, queryClient, storage]
632
+ );
633
+ const value2 = useMemo2(
634
+ () => ({
635
+ activeTenantId,
636
+ switchTenant(tenantId) {
637
+ if (!tenantId?.trim()) throw new Error("tenantId \xE9 obrigat\xF3rio.");
638
+ replaceTenant(tenantId);
639
+ },
640
+ clearTenant() {
641
+ replaceTenant(null);
642
+ }
643
+ }),
644
+ [activeTenantId, replaceTenant]
645
+ );
646
+ return /* @__PURE__ */ jsx5(TenantContext.Provider, { value: value2, children });
647
+ }
648
+ function useOptionalOonTenant() {
649
+ return useContext3(TenantContext);
650
+ }
651
+ function useOonTenant() {
652
+ const value2 = useOptionalOonTenant();
653
+ if (!value2) throw new Error("useOonTenant deve ser usado dentro de TenantProvider.");
654
+ return value2;
655
+ }
656
+
657
+ // src/security/AuthProvider.tsx
658
+ import { jsx as jsx6 } from "react/jsx-runtime";
659
+ var AuthContext = createContext4(null);
604
660
  function errorStatus(error) {
605
661
  return error?.status;
606
662
  }
@@ -648,20 +704,26 @@ function can(user, permission) {
648
704
  function AuthProvider({ http, storage, auth, loginUrl, children }) {
649
705
  const tokenParam = auth?.tokenParam ?? "code";
650
706
  const devToken = auth?.devToken?.trim() || null;
651
- const [user, setUser] = useState4(null);
652
- const [status, setStatus] = useState4("loading");
707
+ const [user, setUser] = useState5(null);
708
+ const [status, setStatus] = useState5("loading");
653
709
  const activation = useOptionalActivation();
654
- const redirectToExternalLogin = useCallback2(() => {
710
+ const tenantContext = useOptionalOonTenant();
711
+ const redirectToExternalLogin = useCallback3(() => {
655
712
  if (loginUrl) window.location.href = loginUrl;
656
713
  }, [loginUrl]);
657
- const applyUser = useCallback2((next) => {
714
+ const applyUser = useCallback3((next) => {
658
715
  setUser(next);
716
+ const tenant = next.tenant;
717
+ const resolvedTenantId = String(next.tenantId || tenant?.id || "").trim();
718
+ if (resolvedTenantId && tenantContext?.activeTenantId !== resolvedTenantId) {
719
+ tenantContext?.switchTenant(resolvedTenantId);
720
+ }
659
721
  const firstAccess = Boolean(
660
722
  next.mustChangePassword || next.firstAccessPending
661
723
  );
662
724
  setStatus(firstAccess ? "first-access" : "authenticated");
663
- }, []);
664
- const applyValidationError = useCallback2(
725
+ }, [tenantContext]);
726
+ const applyValidationError = useCallback3(
665
727
  (error) => {
666
728
  const currentStatus = errorStatus(error);
667
729
  setUser(null);
@@ -679,11 +741,11 @@ function AuthProvider({ http, storage, auth, loginUrl, children }) {
679
741
  },
680
742
  [storage, redirectToExternalLogin]
681
743
  );
682
- const validateSession = useCallback2(async () => {
744
+ const validateSession = useCallback3(async () => {
683
745
  const response = await http.get("/auth/validar-token");
684
746
  applyUser(response.data.usuario);
685
747
  }, [http, applyUser]);
686
- const retry = useCallback2(async () => {
748
+ const retry = useCallback3(async () => {
687
749
  setStatus("loading");
688
750
  try {
689
751
  await validateSession();
@@ -692,12 +754,14 @@ function AuthProvider({ http, storage, auth, loginUrl, children }) {
692
754
  throw error;
693
755
  }
694
756
  }, [validateSession, applyValidationError]);
695
- const login = useCallback2(
757
+ const login = useCallback3(
696
758
  async (email, password, tenantId) => {
697
759
  setStatus("loading");
698
760
  setUser(null);
699
761
  try {
700
762
  const normalizedTenantId = String(tenantId || "").trim();
763
+ if (normalizedTenantId) tenantContext?.switchTenant(normalizedTenantId);
764
+ else tenantContext?.clearTenant();
701
765
  const response = await http.post(
702
766
  "/auth/autenticar",
703
767
  {},
@@ -723,18 +787,19 @@ function AuthProvider({ http, storage, auth, loginUrl, children }) {
723
787
  throw error;
724
788
  }
725
789
  },
726
- [http, storage, validateSession, applyValidationError]
790
+ [http, storage, validateSession, applyValidationError, tenantContext]
727
791
  );
728
- const completeFirstAccess = useCallback2(async (password) => {
792
+ const completeFirstAccess = useCallback3(async (password) => {
729
793
  await http.post("/auth/first-access/password", { password });
730
794
  await validateSession();
731
795
  }, [http, validateSession]);
732
- const logout = useCallback2(() => {
796
+ const logout = useCallback3(() => {
733
797
  storage.clear();
798
+ tenantContext?.clearTenant();
734
799
  setUser(null);
735
800
  setStatus("unauthenticated");
736
801
  redirectToExternalLogin();
737
- }, [storage, redirectToExternalLogin]);
802
+ }, [storage, redirectToExternalLogin, tenantContext]);
738
803
  useEffect4(() => {
739
804
  let active = true;
740
805
  if (activation && !["active", "error"].includes(activation.status)) {
@@ -768,7 +833,7 @@ function AuthProvider({ http, storage, auth, loginUrl, children }) {
768
833
  const roles = roleCode ? [roleCode] : [];
769
834
  const capabilities = extractCapabilities(user);
770
835
  const permissions = explicitPermissions(user) ?? capabilities;
771
- const hasPermission = useCallback2(
836
+ const hasPermission = useCallback3(
772
837
  (permission) => can(user, permission),
773
838
  [user]
774
839
  );
@@ -785,67 +850,14 @@ function AuthProvider({ http, storage, auth, loginUrl, children }) {
785
850
  retry,
786
851
  logout
787
852
  };
788
- return /* @__PURE__ */ jsx5(AuthContext.Provider, { value: value2, children });
853
+ return /* @__PURE__ */ jsx6(AuthContext.Provider, { value: value2, children });
789
854
  }
790
855
  function useOonAuth() {
791
- const context = useContext3(AuthContext);
856
+ const context = useContext4(AuthContext);
792
857
  if (!context) throw new Error("useOonAuth deve ser usado dentro de <AuthProvider> (oonCoreFront.start).");
793
858
  return context;
794
859
  }
795
860
 
796
- // src/security/TenantProvider.tsx
797
- import {
798
- createContext as createContext4,
799
- useCallback as useCallback3,
800
- useContext as useContext4,
801
- useMemo as useMemo2,
802
- useState as useState5
803
- } from "react";
804
- import { useQueryClient } from "@tanstack/react-query";
805
- import { jsx as jsx6 } from "react/jsx-runtime";
806
- var TenantContext = createContext4(null);
807
- function applyHeader(http, tenantId) {
808
- if (tenantId) {
809
- http.defaults.headers.common["x-oon-tenant-id"] = tenantId;
810
- return;
811
- }
812
- delete http.defaults.headers.common["x-oon-tenant-id"];
813
- }
814
- function TenantProvider({ http, storage, children }) {
815
- const queryClient = useQueryClient();
816
- const [activeTenantId, setActiveTenantId] = useState5(() => storage.get());
817
- const replaceTenant = useCallback3(
818
- (tenantId) => {
819
- const normalized2 = String(tenantId ?? "").trim() || null;
820
- if (normalized2) storage.set(normalized2);
821
- else storage.clear();
822
- applyHeader(http, normalized2);
823
- setActiveTenantId(normalized2);
824
- queryClient.clear();
825
- },
826
- [http, queryClient, storage]
827
- );
828
- const value2 = useMemo2(
829
- () => ({
830
- activeTenantId,
831
- switchTenant(tenantId) {
832
- if (!tenantId?.trim()) throw new Error("tenantId \xE9 obrigat\xF3rio.");
833
- replaceTenant(tenantId);
834
- },
835
- clearTenant() {
836
- replaceTenant(null);
837
- }
838
- }),
839
- [activeTenantId, replaceTenant]
840
- );
841
- return /* @__PURE__ */ jsx6(TenantContext.Provider, { value: value2, children });
842
- }
843
- function useOonTenant() {
844
- const value2 = useContext4(TenantContext);
845
- if (!value2) throw new Error("useOonTenant deve ser usado dentro de TenantProvider.");
846
- return value2;
847
- }
848
-
849
861
  // src/app/OonProviders.tsx
850
862
  import { jsx as jsx7 } from "react/jsx-runtime";
851
863
  function OonProviders({
@@ -4939,7 +4951,7 @@ function Sidebar({ app, menu, registry }) {
4939
4951
  // package.json
4940
4952
  var package_default = {
4941
4953
  name: "@oondemand/oon-core-front",
4942
- version: "0.4.3",
4954
+ version: "0.4.4",
4943
4955
  repository: {
4944
4956
  type: "git",
4945
4957
  url: "git+https://github.com/oondemand/oon-platform.git",
@@ -5126,6 +5138,8 @@ function CoreTopbar({ app, menu }) {
5126
5138
  const settingsHref = resolveSettingsHref(
5127
5139
  menu.filter((item) => hasPermission(item.permissions))
5128
5140
  );
5141
+ const tenant = user?.tenant;
5142
+ const tenantLabel = String(tenant?.nome || tenant?.slug || "").trim();
5129
5143
  return /* @__PURE__ */ jsxs22(
5130
5144
  Flex14,
5131
5145
  {
@@ -5155,6 +5169,10 @@ function CoreTopbar({ app, menu }) {
5155
5169
  }
5156
5170
  ),
5157
5171
  /* @__PURE__ */ jsx31(Text22, { fontSize: "sm", fontWeight: "600", color: "#24323A", children: app.title ?? app.name }),
5172
+ tenantLabel ? /* @__PURE__ */ jsxs22(Text22, { fontSize: "xs", fontWeight: "600", color: "brand.600", lineHeight: "1.4", children: [
5173
+ "Tenant: ",
5174
+ tenantLabel
5175
+ ] }) : null,
5158
5176
  /* @__PURE__ */ jsxs22(Text22, { fontSize: "10px", color: "gray.600", lineHeight: "1.35", children: [
5159
5177
  "Central ",
5160
5178
  centralVersion,
@@ -5395,6 +5413,7 @@ import {
5395
5413
  Flex as Flex16,
5396
5414
  Heading as Heading12,
5397
5415
  Input as Input8,
5416
+ SimpleGrid as SimpleGrid5,
5398
5417
  Text as Text24,
5399
5418
  VStack as VStack4
5400
5419
  } from "@chakra-ui/react";
@@ -5468,7 +5487,7 @@ function LoginPage({ app }) {
5468
5487
  Box23,
5469
5488
  {
5470
5489
  width: "100%",
5471
- maxW: "440px",
5490
+ maxW: tenants.length > 1 ? "680px" : "440px",
5472
5491
  bg: "white",
5473
5492
  borderWidth: "1px",
5474
5493
  borderColor: "#E4EBEF",
@@ -5525,35 +5544,37 @@ function LoginPage({ app }) {
5525
5544
  )
5526
5545
  ] }),
5527
5546
  tenants.length > 1 ? /* @__PURE__ */ jsxs24(Box23, { children: [
5528
- /* @__PURE__ */ jsx35(Text24, { mb: 2, fontSize: "sm", fontWeight: "600", color: "#24323A", children: "Organiza\xE7\xE3o" }),
5529
- /* @__PURE__ */ jsxs24(
5530
- "select",
5531
- {
5532
- "aria-label": "Organiza\xE7\xE3o",
5533
- value: tenantId,
5534
- onChange: (event) => {
5535
- setTenantId(event.target.value);
5536
- setMessage(null);
5537
- },
5538
- required: true,
5539
- style: {
5540
- width: "100%",
5541
- minHeight: "40px",
5542
- padding: "0 12px",
5543
- border: "1px solid #CDD5DF",
5544
- borderRadius: "6px",
5545
- background: "white",
5546
- color: "#24323A"
5547
+ /* @__PURE__ */ jsx35(Text24, { mb: 3, fontSize: "sm", fontWeight: "600", color: "#24323A", children: "Escolha o tenant para acessar" }),
5548
+ /* @__PURE__ */ jsx35(SimpleGrid5, { columns: { base: 1, md: 2 }, gap: 3, children: tenants.map((tenant) => {
5549
+ const selected = tenantId === tenant.id;
5550
+ return /* @__PURE__ */ jsx35(
5551
+ Button16,
5552
+ {
5553
+ type: "button",
5554
+ variant: "outline",
5555
+ height: "auto",
5556
+ minH: "88px",
5557
+ justifyContent: "flex-start",
5558
+ whiteSpace: "normal",
5559
+ textAlign: "left",
5560
+ borderWidth: "2px",
5561
+ borderColor: selected ? "#39BFED" : "#D9E2E7",
5562
+ bg: selected ? "#EFFAFF" : "white",
5563
+ color: "#24323A",
5564
+ "aria-pressed": selected,
5565
+ onClick: () => {
5566
+ setTenantId(tenant.id);
5567
+ setMessage(null);
5568
+ },
5569
+ _hover: { borderColor: "#39BFED", bg: "#F6FCFE" },
5570
+ children: /* @__PURE__ */ jsxs24(VStack4, { align: "start", gap: 1, py: 3, children: [
5571
+ /* @__PURE__ */ jsx35(Text24, { fontWeight: "700", children: tenant.nome }),
5572
+ tenant.slug ? /* @__PURE__ */ jsx35(Text24, { fontSize: "xs", color: "gray.500", children: tenant.slug }) : null
5573
+ ] })
5547
5574
  },
5548
- children: [
5549
- /* @__PURE__ */ jsx35("option", { value: "", children: "Selecione uma organiza\xE7\xE3o" }),
5550
- tenants.map((tenant) => /* @__PURE__ */ jsxs24("option", { value: tenant.id, children: [
5551
- tenant.nome,
5552
- tenant.slug ? ` \u2014 ${tenant.slug}` : ""
5553
- ] }, tenant.id))
5554
- ]
5555
- }
5556
- )
5575
+ tenant.id
5576
+ );
5577
+ }) })
5557
5578
  ] }) : null
5558
5579
  ] }),
5559
5580
  message ? /* @__PURE__ */ jsx35(