diff --git a/packages/console/src/hooks/use-console-routes/routes/organizations.tsx b/packages/console/src/hooks/use-console-routes/routes/organizations.tsx
index ae42dc98707..2bb58902607 100644
--- a/packages/console/src/hooks/use-console-routes/routes/organizations.tsx
+++ b/packages/console/src/hooks/use-console-routes/routes/organizations.tsx
@@ -1,8 +1,11 @@
import { condArray } from '@silverhand/essentials';
-import { type RouteObject } from 'react-router-dom';
+import { Navigate, type RouteObject } from 'react-router-dom';
import { isDevFeaturesEnabled } from '@/consts/env';
import OrganizationDetails from '@/pages/OrganizationDetails';
+import Members from '@/pages/OrganizationDetails/Members';
+import Settings from '@/pages/OrganizationDetails/Settings';
+import { OrganizationDetailsTabs } from '@/pages/OrganizationDetails/types';
import Organizations from '@/pages/Organizations';
export const organizations: RouteObject = {
@@ -14,6 +17,14 @@ export const organizations: RouteObject = {
path: 'template',
element: ,
},
- { path: ':id/*', element: }
+ {
+ path: ':id/*',
+ element: ,
+ children: [
+ { index: true, element: },
+ { path: OrganizationDetailsTabs.Settings, element: },
+ { path: OrganizationDetailsTabs.Members, element: },
+ ],
+ }
),
};
diff --git a/packages/console/src/pages/OrganizationDetails/Members/index.tsx b/packages/console/src/pages/OrganizationDetails/Members/index.tsx
index 537592bda05..cfcdcb4fe7c 100644
--- a/packages/console/src/pages/OrganizationDetails/Members/index.tsx
+++ b/packages/console/src/pages/OrganizationDetails/Members/index.tsx
@@ -1,6 +1,7 @@
-import { type UserWithOrganizationRoles, type Organization } from '@logto/schemas';
+import { type UserWithOrganizationRoles } from '@logto/schemas';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
+import { useOutletContext } from 'react-router-dom';
import useSWR from 'swr';
import Plus from '@/assets/icons/plus.svg';
@@ -19,17 +20,16 @@ import useActionTranslation from '@/hooks/use-action-translation';
import useApi, { type RequestError } from '@/hooks/use-api';
import { buildUrl } from '@/utils/url';
+import { type OrganizationDetailsOutletContext } from '../types';
+
import AddMembersToOrganization from './AddMembersToOrganization';
import EditOrganizationRolesModal from './EditOrganizationRolesModal';
import * as styles from './index.module.scss';
const pageSize = defaultPageSize;
-type Props = {
- organization: Organization;
-};
-
-function Members({ organization }: Props) {
+function Members() {
+ const { data: organization } = useOutletContext();
const api = useApi();
const [keyword, setKeyword] = useState('');
const [page, setPage] = useState(1);
diff --git a/packages/console/src/pages/OrganizationDetails/Settings/index.tsx b/packages/console/src/pages/OrganizationDetails/Settings/index.tsx
index b393543b1f9..a1489161fb4 100644
--- a/packages/console/src/pages/OrganizationDetails/Settings/index.tsx
+++ b/packages/console/src/pages/OrganizationDetails/Settings/index.tsx
@@ -2,6 +2,7 @@ import { type Organization } from '@logto/schemas';
import { useForm } from 'react-hook-form';
import { toast } from 'react-hot-toast';
import { useTranslation } from 'react-i18next';
+import { useOutletContext } from 'react-router-dom';
import DetailsForm from '@/components/DetailsForm';
import FormCard from '@/components/FormCard';
@@ -11,17 +12,10 @@ import TextInput from '@/ds-components/TextInput';
import useApi from '@/hooks/use-api';
import { trySubmitSafe } from '@/utils/form';
-type Props = {
- /**
- * Whether the organization is being deleted, this is used to disable the unsaved
- * changes alert modal.
- */
- isDeleting: boolean;
- data: Organization;
- onUpdated: (data: Organization) => void;
-};
+import { type OrganizationDetailsOutletContext } from '../types';
-function Settings({ isDeleting, data, onUpdated }: Props) {
+function Settings() {
+ const { isDeleting, data, onUpdated } = useOutletContext();
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const {
register,
diff --git a/packages/console/src/pages/OrganizationDetails/index.tsx b/packages/console/src/pages/OrganizationDetails/index.tsx
index f7fd6db6aad..df01f929bea 100644
--- a/packages/console/src/pages/OrganizationDetails/index.tsx
+++ b/packages/console/src/pages/OrganizationDetails/index.tsx
@@ -1,9 +1,7 @@
import { type Organization } from '@logto/schemas';
import { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
-// FIXME: @gao
-// eslint-disable-next-line no-restricted-imports
-import { Navigate, Route, Routes, useParams } from 'react-router-dom';
+import { Outlet, useParams } from 'react-router-dom';
import useSWR from 'swr';
import Delete from '@/assets/icons/delete.svg';
@@ -23,15 +21,10 @@ import useTenantPathname from '@/hooks/use-tenant-pathname';
import Introduction from '../Organizations/Guide/Introduction';
-import Members from './Members';
-import Settings from './Settings';
import * as styles from './index.module.scss';
+import { OrganizationDetailsTabs, type OrganizationDetailsOutletContext } from './types';
const pathname = '/organizations';
-const tabs = Object.freeze({
- settings: 'settings',
- members: 'members',
-});
function OrganizationDetails() {
const { id } = useParams();
@@ -111,27 +104,22 @@ function OrganizationDetails() {
{t('organization_details.delete_confirmation')}
-
+
{t('general.settings_nav')}
-
+
{t('organizations.members')}
-
- } />
- mutate(data)}
- />
- }
- />
- } />
-
+ mutate(data),
+ } satisfies OrganizationDetailsOutletContext
+ }
+ />
>
)}
diff --git a/packages/console/src/pages/OrganizationDetails/types.ts b/packages/console/src/pages/OrganizationDetails/types.ts
new file mode 100644
index 00000000000..6eb9254cbe9
--- /dev/null
+++ b/packages/console/src/pages/OrganizationDetails/types.ts
@@ -0,0 +1,16 @@
+import { type Organization } from '@logto/schemas';
+
+export type OrganizationDetailsOutletContext = {
+ data: Organization;
+ /**
+ * Whether the organization is being deleted, this is used to disable the unsaved
+ * changes alert modal.
+ */
+ isDeleting: boolean;
+ onUpdated: (data: Organization) => void;
+};
+
+export enum OrganizationDetailsTabs {
+ Settings = 'settings',
+ Members = 'members',
+}