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', +}