diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/Button/button.styles.ts b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/Button/button.styles.ts new file mode 100644 index 00000000..242e50cc --- /dev/null +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/Button/button.styles.ts @@ -0,0 +1,7 @@ +import styled from "@emotion/styled"; +import { Button } from "@mui/material"; + +export const StyledButton = styled(Button)` + align-self: center; + text-transform: none; +`; diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/Button/button.tsx b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/Button/button.tsx new file mode 100644 index 00000000..9e5018fb --- /dev/null +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/Button/button.tsx @@ -0,0 +1,26 @@ +import { JSX } from "react"; +import { BUTTON_PROPS } from "../../../../../../../../styles/common/mui/button"; +import { useTerraSetUpUI } from "../../../../../../../../terra/setUpUI/provider/hook"; +import { STEPS_REGION_ID } from "../../constants"; +import { StyledButton } from "./button.styles"; +import { ButtonProps } from "./types"; + +export const Button = ({ + collapsible = false, +}: ButtonProps): JSX.Element | null => { + const { isOpen, onChange } = useTerraSetUpUI(); + + if (!collapsible) return null; + + return ( + + {isOpen ? "Save & continue later" : "Continue"} + + ); +}; diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/Button/types.ts b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/Button/types.ts new file mode 100644 index 00000000..a5110f42 --- /dev/null +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/Button/types.ts @@ -0,0 +1,3 @@ +export interface ButtonProps { + collapsible?: boolean; +} diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/formStep.styles.ts b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/formStep.styles.ts index cc289e8f..bddea5c7 100644 --- a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/formStep.styles.ts +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/formStep.styles.ts @@ -1,8 +1,26 @@ import styled from "@emotion/styled"; -import { SectionContent as DXSectionContent } from "../../terraSetUpForm.styles"; +import { PALETTE } from "../../../../../../../../styles/common/constants/palette"; +import { sectionPadding } from "../../../../../../../common/Section/section.styles"; -export const SectionContent = styled(DXSectionContent)` +export const Section = styled("div")` + ${sectionPadding}; + background-color: ${PALETTE.COMMON_WHITE}; + border-top: 1px solid ${PALETTE.SMOKE_MAIN}; + display: grid; + gap: 16px; + grid-template-columns: auto 1fr; +`; + +export const SectionContent = styled.div` + display: grid; gap: 2px; + grid-row: 1; + + .MuiTypography-body-400-2lines { + p { + margin: 0; + } + } .MuiTypography-body-500 { margin: 2px 0; diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/formStep.tsx b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/formStep.tsx index cc995218..3ae1f8f1 100644 --- a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/formStep.tsx +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/components/FormStep/formStep.tsx @@ -2,12 +2,8 @@ import { StepIcon, Typography } from "@mui/material"; import { JSX, ReactNode } from "react"; import { TYPOGRAPHY_PROPS } from "../../../../../../../../styles/common/mui/typography"; import { FormStatusCompletedIcon } from "../../../../../../../common/CustomIcon/components/FormStatusCompletedIcon/formStatusCompletedIcon"; -import { - Section, - SectionActions, - SectionStatus, -} from "../../terraSetUpForm.styles"; -import { SectionContent } from "./formStep.styles"; +import { SectionActions, SectionStatus } from "../../terraSetUpForm.styles"; +import { Section, SectionContent } from "./formStep.styles"; export interface FormStepProps { action: ReactNode; diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/constants.ts b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/constants.ts new file mode 100644 index 00000000..b50eaabd --- /dev/null +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/constants.ts @@ -0,0 +1,6 @@ +/** + * DOM id of the collapsible steps region. Used by the toggle button's + * `aria-controls` so assistive tech can associate the toggle with the + * region it expands/collapses. + */ +export const STEPS_REGION_ID = "terra-set-up-form-steps"; diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/stories/args.ts b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/stories/args.ts new file mode 100644 index 00000000..4babfb53 --- /dev/null +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/stories/args.ts @@ -0,0 +1,45 @@ +import { ComponentProps } from "react"; +import { AUTH_STATUS, AuthState } from "../../../../../../../auth/types/auth"; +import { REQUEST_STATUS } from "../../../../../../../terra/types/common"; +import { TerraProfileContextProps } from "../../../../../../../terra/types/context"; +import { TerraSetUpForm } from "../terraSetUpForm"; + +/** + * Authenticated, settled auth state — used so `TerraSetUpForm` doesn't bail + * early on its `isAuthenticated` / status guards. + */ +export const MOCK_AUTH_STATE: AuthState = { + isAuthenticated: true, + status: AUTH_STATUS.SETTLED, +}; + +/** + * Terra profile statuses where every onboarding step is supported but not yet + * complete — produces three incomplete steps in the rendered form. + */ +export const MOCK_TERRA_PROFILE_INCOMPLETE: TerraProfileContextProps = { + terraNIHProfileLoginStatus: { + isSuccess: false, + isSupported: true, + requestStatus: REQUEST_STATUS.COMPLETED, + response: undefined, + }, + terraProfileLoginStatus: { + isSuccess: false, + isSupported: true, + requestStatus: REQUEST_STATUS.COMPLETED, + response: undefined, + }, + terraTOSLoginStatus: { + isSuccess: false, + isSupported: true, + requestStatus: REQUEST_STATUS.COMPLETED, + response: undefined, + }, +}; + +export const DEFAULT_TERRA_SET_UP_FORM_ARGS: ComponentProps< + typeof TerraSetUpForm +> = { + collapsible: true, +}; diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/stories/constants.ts b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/stories/constants.ts new file mode 100644 index 00000000..f2fbc3ad --- /dev/null +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/stories/constants.ts @@ -0,0 +1,5 @@ +import { ComponentProps } from "react"; +import { TerraSetUpForm } from "../terraSetUpForm"; + +export const BOOLEAN_CONTROLS: (keyof ComponentProps)[] = + ["collapsible"]; diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/stories/terraSetUpForm.stories.tsx b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/stories/terraSetUpForm.stories.tsx new file mode 100644 index 00000000..4771a8aa --- /dev/null +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/stories/terraSetUpForm.stories.tsx @@ -0,0 +1,59 @@ +import { Box } from "@mui/material"; +import type { Meta, StoryObj } from "@storybook/nextjs-vite"; +import { ComponentProps, JSX } from "react"; +import { AuthContext } from "../../../../../../../auth/contexts/auth"; +import { CONTROL_TYPE } from "../../../../../../../storybook/controls/types"; +import { configureControls } from "../../../../../../../storybook/controls/utils"; +import { TerraProfileContext } from "../../../../../../../terra/context"; +import { TerraSetUpUIProvider } from "../../../../../../../terra/setUpUI/provider/provider"; +import { TerraSetUpForm } from "../terraSetUpForm"; +import { + DEFAULT_TERRA_SET_UP_FORM_ARGS, + MOCK_AUTH_STATE, + MOCK_TERRA_PROFILE_INCOMPLETE, +} from "./args"; +import { BOOLEAN_CONTROLS } from "./constants"; + +const meta: Meta = { + argTypes: { + ...configureControls>( + BOOLEAN_CONTROLS, + CONTROL_TYPE.BOOLEAN, + ), + }, + component: TerraSetUpForm, + decorators: [ + (Story): JSX.Element => ( + + + + + + + + + + ), + ], + parameters: { + layout: "fullscreen", + }, +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: DEFAULT_TERRA_SET_UP_FORM_ARGS, +}; + +export const NotCollapsible: Story = { + args: { ...DEFAULT_TERRA_SET_UP_FORM_ARGS, collapsible: false }, +}; diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/terraSetUpForm.styles.ts b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/terraSetUpForm.styles.ts index 76f465c5..0c65e0b3 100644 --- a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/terraSetUpForm.styles.ts +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/terraSetUpForm.styles.ts @@ -1,25 +1,16 @@ import styled from "@emotion/styled"; +import { Stack } from "@mui/material"; import { PALETTE } from "../../../../../../styles/common/constants/palette"; +import { FluidPaper } from "../../../../../common/Paper/components/FluidPaper/fluidPaper"; import { sectionPadding } from "../../../../../common/Section/section.styles"; -export const Section = styled("div")` - ${sectionPadding}; +export const StyledFluidPaper = styled(FluidPaper)` background-color: ${PALETTE.COMMON_WHITE}; - display: grid; - gap: 16px; - grid-template-columns: auto 1fr; `; -export const SectionContent = styled("div")` - display: grid; - gap: 4px; - grid-row: 1; - - .MuiTypography-body-400-2lines { - p { - margin: 0; - } - } +export const StyledStack = styled(Stack)` + ${sectionPadding}; + justify-content: space-between; `; export const SectionStatus = styled("div")` diff --git a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/terraSetUpForm.tsx b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/terraSetUpForm.tsx index cc44928f..46d51fb5 100644 --- a/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/terraSetUpForm.tsx +++ b/src/components/Export/components/ExportToTerra/components/TerraSetUpForm/terraSetUpForm.tsx @@ -1,4 +1,4 @@ -import { Typography } from "@mui/material"; +import { Collapse, Stack, Typography } from "@mui/material"; import { JSX } from "react"; import { useAuth } from "../../../../../../auth/hooks/useAuth"; import { AUTH_STATUS } from "../../../../../../auth/types/auth"; @@ -7,39 +7,47 @@ import { OnboardingStatus, useAuthenticationForm, } from "../../../../../../hooks/authentication/terra/useAuthenticationForm"; +import { STACK_PROPS } from "../../../../../../styles/common/mui/stack"; import { TYPOGRAPHY_PROPS } from "../../../../../../styles/common/mui/typography"; -import { - FluidPaper, - GridPaper, -} from "../../../../../common/Paper/paper.styles"; +import { useTerraSetUpUI } from "../../../../../../terra/setUpUI/provider/hook"; import { SectionTitle } from "../../../../../common/Section/components/SectionTitle/sectionTitle"; +import { Button } from "./components/Button/button"; import { AcceptTerraTOS } from "./components/FormStep/components/AcceptTerraTOS/acceptTerraTOS"; import { ConnectTerraToNIHAccount } from "./components/FormStep/components/ConnectTerraToNIHAccount/connectTerraToNIHAccount"; import { CreateTerraAccount } from "./components/FormStep/components/CreateTerraAccount/createTerraAccount"; -import { Section, SectionContent } from "./terraSetUpForm.styles"; +import { STEPS_REGION_ID } from "./constants"; +import { StyledFluidPaper, StyledStack } from "./terraSetUpForm.styles"; +import { TerraSetUpFormProps } from "./types"; -export const TerraSetUpForm = (): JSX.Element | null => { +export const TerraSetUpForm = ({ + collapsible = false, +}: TerraSetUpFormProps): JSX.Element | null => { const { authState: { isAuthenticated, status }, } = useAuth(); const { isComplete, onboardingStatusByStep } = useAuthenticationForm(); + const { isOpen } = useTerraSetUpUI(); + if (!isAuthenticated) return null; if (status === AUTH_STATUS.PENDING) return null; - return isComplete ? null : ( - - -
- - - - Follow these steps to unlock the full potential of the data - explorer. - - -
+ if (isComplete) return null; + + return ( + + + + + + Follow these steps to unlock the full potential of the data + explorer. + + + + + ); +} + +describe("TerraSetUpUIProvider", () => { + it("renders children with the initial open state", () => { + render( + + + , + ); + expect(screen.getByTestId(TEST_ID_STATE).textContent).toEqual(TEXT_OPEN); + }); + + it("toggles isOpen when onChange is invoked", () => { + render( + + + , + ); + + expect(screen.getByTestId(TEST_ID_STATE).textContent).toEqual(TEXT_OPEN); + + act(() => { + screen.getByTestId(TEST_ID_TOGGLE).click(); + }); + expect(screen.getByTestId(TEST_ID_STATE).textContent).toEqual(TEXT_CLOSED); + + act(() => { + screen.getByTestId(TEST_ID_TOGGLE).click(); + }); + expect(screen.getByTestId(TEST_ID_STATE).textContent).toEqual(TEXT_OPEN); + }); +});