Browse Source

refactor forgot-password

Yuki Takei 7 months ago
parent
commit
0fb8cdec6c

+ 36 - 32
apps/app/src/pages/forgot-password/index.page.tsx

@@ -1,24 +1,29 @@
 import React from 'react';
 
 import type { NextPage, GetServerSideProps, GetServerSidePropsContext } from 'next';
-import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
 import dynamic from 'next/dynamic';
 
 import { RawLayout } from '~/components/Layout/RawLayout';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
-import { useIsMailerSetup } from '~/stores-universal/context';
 
-import type { CommonProps } from './common-props';
-import { getNextI18NextConfig, getServerSideCommonProps } from './common-props';
+import type {
+  CommonEachProps,
+  CommonInitialProps,
+} from '../common-props';
+import {
+  getServerSideCommonEachProps, getServerSideCommonInitialProps, getServerSideI18nProps,
+} from '../common-props';
+import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
+
+import type { ServerConfigurationProps } from './types';
+import { useHydrateServerConfigurationAtoms } from './use-hydrate-server-configurations';
 
 const PasswordResetRequestForm = dynamic(() => import('~/client/components/PasswordResetRequestForm'), { ssr: false });
 
-type Props = CommonProps & {
-  isMailerSetup: boolean,
-};
+type Props = CommonInitialProps & CommonEachProps & ServerConfigurationProps;
 
 const ForgotPasswordPage: NextPage<Props> = (props: Props) => {
-  useIsMailerSetup(props.isMailerSetup);
+  useHydrateServerConfigurationAtoms(props.serverConfig);
 
   return (
     <RawLayout>
@@ -39,37 +44,36 @@ const ForgotPasswordPage: NextPage<Props> = (props: Props) => {
   );
 };
 
-// eslint-disable-next-line max-len
-async function injectNextI18NextConfigurations(context: GetServerSidePropsContext, props: Props, namespacesRequired?: string[] | undefined): Promise<void> {
-  const nextI18NextConfig = await getNextI18NextConfig(serverSideTranslations, context, namespacesRequired);
-  props._nextI18Next = nextI18NextConfig._nextI18Next;
-}
-
-const injectServerConfigurations = async(context: GetServerSidePropsContext, props: Props): Promise<void> => {
+const getServerSideConfigurationProps: GetServerSideProps<ServerConfigurationProps> = async(context: GetServerSidePropsContext) => {
   const req: CrowiRequest = context.req as CrowiRequest;
   const { crowi } = req;
   const { mailService } = crowi;
 
-  props.isMailerSetup = mailService.isMailerSetup;
+  return {
+    props: {
+      serverConfig: {
+        isMailerSetup: mailService.isMailerSetup,
+      },
+    },
+  };
 };
 
 export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
-  const result = await getServerSideCommonProps(context);
-
-  // check for presence
-  // see: https://github.com/vercel/next.js/issues/19271#issuecomment-730006862
-  if (!('props' in result)) {
-    throw new Error('invalid getSSP result');
-  }
-
-  const props: Props = result.props as Props;
-
-  injectServerConfigurations(context, props);
-  await injectNextI18NextConfigurations(context, props, ['translation', 'commons']);
-
-  return {
-    props,
-  };
+  const [
+    commonInitialResult,
+    commonEachResult,
+    serverConfigResult,
+    i18nPropsResult,
+  ] = await Promise.all([
+    getServerSideCommonInitialProps(context),
+    getServerSideCommonEachProps(context),
+    getServerSideConfigurationProps(context),
+    getServerSideI18nProps(context, ['translation', 'commons']),
+  ]);
+
+  return mergeGetServerSidePropsResults(commonInitialResult,
+    mergeGetServerSidePropsResults(commonEachResult,
+      mergeGetServerSidePropsResults(serverConfigResult, i18nPropsResult)));
 };
 
 export default ForgotPasswordPage;

+ 5 - 0
apps/app/src/pages/forgot-password/types.ts

@@ -0,0 +1,5 @@
+export type ServerConfigurationProps = {
+  serverConfig: {
+    isMailerSetup: boolean,
+  },
+}

+ 20 - 0
apps/app/src/pages/forgot-password/use-hydrate-server-configurations.ts

@@ -0,0 +1,20 @@
+import { useHydrateAtoms } from 'jotai/utils';
+
+import {
+  isMailerSetupAtom,
+} from '~/states/server-configurations';
+
+import type { ServerConfigurationProps } from './types';
+
+/**
+ * Hook for hydrating server configuration atoms with server-side data
+ * This should be called early in the app component to ensure atoms are properly initialized before rendering
+ */
+export const useHydrateServerConfigurationAtoms = (
+    serverConfig: ServerConfigurationProps['serverConfig'] | undefined,
+): void => {
+  // Hydrate server configuration atoms with server-side data
+  useHydrateAtoms(serverConfig == null ? [] : [
+    [isMailerSetupAtom, serverConfig.isMailerSetup],
+  ]);
+};

+ 9 - 0
apps/app/src/states/server-configurations/server-configurations.ts

@@ -46,6 +46,15 @@ export const useDefaultIndentSize = (): UseAtom<
   return useAtom(defaultIndentSizeAtom);
 };
 
+/**
+ * Atom for mailer setup status
+ */
+export const isMailerSetupAtom = atom<boolean>(false);
+
+export const useIsMailerSetup = (): UseAtom<typeof isMailerSetupAtom> => {
+  return useAtom(isMailerSetupAtom);
+};
+
 /**
  * Atom for search scope children as default
  */

+ 0 - 4
apps/app/src/stores-universal/context.tsx

@@ -22,10 +22,6 @@ export const useRegistrationWhitelist = (initialData?: Nullable<string[]>): SWRR
   return useContextSWR<Nullable<string[]>, Error>('registrationWhitelist', initialData);
 };
 
-export const useIsMailerSetup = (initialData?: boolean): SWRResponse<boolean, Error> => {
-  return useContextSWR('isMailerSetup', initialData);
-};
-
 export const useAuditLogEnabled = (initialData?: boolean): SWRResponse<boolean, Error> => {
   return useContextSWR<boolean, Error>('auditLogEnabled', initialData, { fallbackData: false });
 };