layout.tsx 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import React, { useMemo } from 'react';
  2. import type { ReactElement, ReactNode } from 'react';
  3. import { useTranslation } from 'next-i18next';
  4. import { useCustomTitle } from '~/pages/utils/page-title-customization';
  5. import { AdminPageFrame } from './AdminPageFrame';
  6. import type { AnyUnstatedContainer, AdminCommonProps } from './types';
  7. import { useUnstatedContainers } from './use-unstated-container';
  8. export interface AdminLayoutOptions<P extends AdminCommonProps> {
  9. title: string | ((props: P, t: (k: string) => string) => string);
  10. containerFactories?: Array<() => Promise<AnyUnstatedContainer>>;
  11. }
  12. export function createAdminPageLayout<P extends AdminCommonProps>(options: AdminLayoutOptions<P>) {
  13. return function getLayout(page: ReactElement<P>): ReactNode {
  14. const Wrapper: React.FC = () => {
  15. const { t } = useTranslation('admin');
  16. const rawTitle = typeof options.title === 'function' ? options.title(page.props, t) : options.title;
  17. const title = useCustomTitle(rawTitle);
  18. const factories = useMemo(() => options.containerFactories ?? [], []);
  19. const containers = useUnstatedContainers(factories);
  20. return (
  21. <AdminPageFrame
  22. title={title}
  23. componentTitle={rawTitle}
  24. isAccessDeniedForNonAdminUser={page.props.isAccessDeniedForNonAdminUser}
  25. containers={containers}
  26. >
  27. {page}
  28. </AdminPageFrame>
  29. );
  30. };
  31. return <Wrapper />;
  32. };
  33. }
  34. export default createAdminPageLayout;