diff --git a/govtool/frontend/src/App.tsx b/govtool/frontend/src/App.tsx index 13bc34a7d..c380c6664 100644 --- a/govtool/frontend/src/App.tsx +++ b/govtool/frontend/src/App.tsx @@ -32,6 +32,7 @@ import { import { SetupInterceptors } from "./services"; import { useGetVoterInfo, useWalletConnectionListener } from "./hooks"; import { RegisterAsSoleVoter } from "./pages/RegisterAsSoleVoter"; +import { CreateGovernanceAction } from "./pages/CreateGovernanceAction"; export default function App() { const { enable, setVoter, setIsDrepLoading } = useCardano(); @@ -115,6 +116,10 @@ export default function App() { element={} /> + } + /> } /> } /> >; - subtitle: string; + onChange: (newValue: string) => void; + subtitle?: string; title: string; tooltipText?: string; tooltipTitle?: string; @@ -76,13 +76,15 @@ export const ActionRadio: FC = ({ ...props }) => { )} - - {subtitle} - + {subtitle ? ( + + {subtitle} + + ) : null} ); diff --git a/govtool/frontend/src/components/molecules/BackToButton.tsx b/govtool/frontend/src/components/molecules/BackToButton.tsx new file mode 100644 index 000000000..e3a697d36 --- /dev/null +++ b/govtool/frontend/src/components/molecules/BackToButton.tsx @@ -0,0 +1,26 @@ +import { Box } from "@mui/material"; +import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos"; + +import { Typography } from "@atoms"; + +import { BackToLinkProps } from "./types"; + +export const BackToButton = ({ label, onClick, sx }: BackToLinkProps) => { + return ( + + + + {label} + + + ); +}; diff --git a/govtool/frontend/src/components/molecules/index.ts b/govtool/frontend/src/components/molecules/index.ts index 7b4c1668f..3afe1db00 100644 --- a/govtool/frontend/src/components/molecules/index.ts +++ b/govtool/frontend/src/components/molecules/index.ts @@ -1,4 +1,5 @@ export * from "./ActionCard"; +export * from "./BackToButton"; export * from "./CenteredBoxBottomButtons"; export * from "./CenteredBoxPageWrapper"; export * from "./DashboardActionCard"; diff --git a/govtool/frontend/src/components/molecules/types.ts b/govtool/frontend/src/components/molecules/types.ts new file mode 100644 index 000000000..6cafc8c4a --- /dev/null +++ b/govtool/frontend/src/components/molecules/types.ts @@ -0,0 +1,7 @@ +import { SxProps } from "@mui/material"; + +export type BackToLinkProps = { + label: string; + onClick: () => void; + sx?: SxProps; +}; diff --git a/govtool/frontend/src/components/organisms/BgCard.tsx b/govtool/frontend/src/components/organisms/BgCard.tsx index b430eb205..1995f06a3 100644 --- a/govtool/frontend/src/components/organisms/BgCard.tsx +++ b/govtool/frontend/src/components/organisms/BgCard.tsx @@ -89,7 +89,7 @@ export const BgCard = ({ flexDirection: "column", height: "auto", maxWidth: screenWidth > 768 ? 600 : undefined, - my: isMobile ? undefined : 3, + mb: isMobile ? undefined : 3, pb: isMobile ? undefined : 10, pt: isMobile ? 6 : 10, px: isMobile ? 2 : 18.75, diff --git a/govtool/frontend/src/components/organisms/ChooseGovernanceActionType.tsx b/govtool/frontend/src/components/organisms/ChooseGovernanceActionType.tsx new file mode 100644 index 000000000..91eec706e --- /dev/null +++ b/govtool/frontend/src/components/organisms/ChooseGovernanceActionType.tsx @@ -0,0 +1,70 @@ +import { Dispatch, SetStateAction } from "react"; + +import { ActionRadio, Spacer, Typography } from "@atoms"; +import { GOVERNANCE_ACTION_TYPES } from "@consts"; +import { + useCreateGovernanceActionForm, + useScreenDimension, + useTranslation, +} from "@hooks"; + +import { BgCard } from "./BgCard"; + +type ChooseGovernanceActionTypeProps = { + onClickCancel: () => void; + setStep: Dispatch>; +}; + +export const ChooseGovernanceActionType = ({ + onClickCancel, + setStep, +}: ChooseGovernanceActionTypeProps) => { + const { t } = useTranslation(); + const { isMobile } = useScreenDimension(); + const { getValues, setValue, watch } = useCreateGovernanceActionForm(); + + const isContinueButtonDisabled = !watch("type"); + + const onClickContinue = () => { + setStep(2); + }; + + // TODO: Add tooltips when they will be available + const renderGovernanceActionTypes = () => { + return GOVERNANCE_ACTION_TYPES.map((type, index) => { + const isChecked = getValues("type") === type; + return ( + <> + + {index + 1 < GOVERNANCE_ACTION_TYPES.length ? : null} + + ); + }); + }; + + const onChangeType = (value: string) => { + setValue("type", value); + }; + + return ( + + + {t("createGovernanceAction.chooseGATypeTitle")} + + + {renderGovernanceActionTypes()} + + + ); +}; diff --git a/govtool/frontend/src/components/organisms/RegisterAsdRepStepOne.tsx b/govtool/frontend/src/components/organisms/RegisterAsdRepStepOne.tsx index 3a68ce015..04598720a 100644 --- a/govtool/frontend/src/components/organisms/RegisterAsdRepStepOne.tsx +++ b/govtool/frontend/src/components/organisms/RegisterAsdRepStepOne.tsx @@ -14,8 +14,10 @@ import { import { BgCard } from "."; export const RegisterAsdRepStepOne = ({ + onClickCancel, setStep, }: { + onClickCancel: () => void; setStep: Dispatch>; }) => { const { t } = useTranslation(); @@ -35,6 +37,7 @@ export const RegisterAsdRepStepOne = ({ actionButtonLabel={t("continue")} backButtonLabel={t("cancel")} onClickActionButton={onClickContinue} + onClickBackButton={onClickCancel} sx={{ paddingBottom: isMobile ? undefined : 3 }} > diff --git a/govtool/frontend/src/components/organisms/index.ts b/govtool/frontend/src/components/organisms/index.ts index 9b7ee74ce..749a01357 100644 --- a/govtool/frontend/src/components/organisms/index.ts +++ b/govtool/frontend/src/components/organisms/index.ts @@ -1,4 +1,5 @@ export * from "./BgCard"; +export * from "./ChooseGovernanceActionType"; export * from "./ChooseStakeKeyPanel"; export * from "./ChooseWalletModal"; export * from "./ControlledField"; diff --git a/govtool/frontend/src/consts/governanceActionTypes.ts b/govtool/frontend/src/consts/governanceActionTypes.ts new file mode 100644 index 000000000..b3b6a8539 --- /dev/null +++ b/govtool/frontend/src/consts/governanceActionTypes.ts @@ -0,0 +1 @@ +export const GOVERNANCE_ACTION_TYPES = ["Info", "Treasury"]; diff --git a/govtool/frontend/src/consts/index.ts b/govtool/frontend/src/consts/index.ts index 65168f9c6..12f9ae298 100644 --- a/govtool/frontend/src/consts/index.ts +++ b/govtool/frontend/src/consts/index.ts @@ -1,3 +1,4 @@ +export * from "./governanceActionTypes"; export * from "./governanceActionsFilters"; export * from "./governanceActionsSorting"; export * from "./icons"; diff --git a/govtool/frontend/src/consts/paths.ts b/govtool/frontend/src/consts/paths.ts index 4ac0cbde2..f230747d5 100644 --- a/govtool/frontend/src/consts/paths.ts +++ b/govtool/frontend/src/consts/paths.ts @@ -1,4 +1,5 @@ export const PATHS = { + create_governance_action: "/create_governance_action", dashboard_governance_actions_action: "/connected/governance_actions/:proposalId", dashboard_governance_actions_category: diff --git a/govtool/frontend/src/hooks/forms/index.ts b/govtool/frontend/src/hooks/forms/index.ts index 2457ac6de..fe994e70b 100644 --- a/govtool/frontend/src/hooks/forms/index.ts +++ b/govtool/frontend/src/hooks/forms/index.ts @@ -1,3 +1,4 @@ +export * from "./useCreateGovernanceActionForm"; export * from "./useDelegateTodRepForm"; export * from "./useRegisterAsdRepFormContext"; export * from "./useUpdatedRepMetadataForm"; diff --git a/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts b/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts new file mode 100644 index 000000000..bb4335f71 --- /dev/null +++ b/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts @@ -0,0 +1,45 @@ +import { useCallback, useState } from "react"; +import { useFormContext } from "react-hook-form"; + +type createGovernanceActionValues = { + type: string; +}; + +export const defaulCreateGovernanceActionValues: createGovernanceActionValues = + { + type: "", + }; + +export const useCreateGovernanceActionForm = () => { + const [isLoading, setIsLoading] = useState(false); + + const { + control, + formState: { errors, isValid }, + getValues, + handleSubmit, + setValue, + watch, + } = useFormContext(); + + const onSubmit = useCallback(async (values: createGovernanceActionValues) => { + setIsLoading(true); + console.log(values); + try { + } catch (e: any) { + } finally { + setIsLoading(false); + } + }, []); + + return { + control, + errors, + getValues, + isLoading, + isValid, + setValue, + submitForm: handleSubmit(onSubmit), + watch, + }; +}; diff --git a/govtool/frontend/src/i18n/locales/en.ts b/govtool/frontend/src/i18n/locales/en.ts index 3c9d6e006..8483755e6 100644 --- a/govtool/frontend/src/i18n/locales/en.ts +++ b/govtool/frontend/src/i18n/locales/en.ts @@ -122,6 +122,10 @@ export const en = { youAreSoleVoterTitle: "You are a Sole Voter", }, }, + createGovernanceAction: { + chooseGATypeTitle: "Choose a Governance Action type", + title: "Create a Governance Action", + }, delegation: { description: "You can delegate your voting power to a DRep or to a pre-defined voting option.", @@ -277,6 +281,11 @@ export const en = { goToDashboard: "Go to Dashboard", oops: "Oops!", }, + createGovernanceAction: { + cancelModalDescription: + "If you return to the Dashboard, your information will not be saved.", + cancelModalTitle: "Do You Want to Cancel Registration ?", + }, delegation: { message: "The confirmation of your actual delegation might take a bit of time but you can track it using", @@ -292,6 +301,9 @@ export const en = { youAreAboutToOpen: "You are about to open an external link to:", }, registration: { + cancelTitle: "Do You Want to Abandon Registration ?", + cancelDescription: + "If you return to the Dashboard, your information will not be saved.", message: "The confirmation of your registration might take a bit of time but you can track it using", title: "Registration Transaction Submitted!", diff --git a/govtool/frontend/src/pages/CreateGovernanceAction.tsx b/govtool/frontend/src/pages/CreateGovernanceAction.tsx new file mode 100644 index 000000000..295dda462 --- /dev/null +++ b/govtool/frontend/src/pages/CreateGovernanceAction.tsx @@ -0,0 +1,85 @@ +import { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { FormProvider, useForm } from "react-hook-form"; +import { Box } from "@mui/material"; + +import { Background } from "@atoms"; +import { PATHS } from "@consts"; +import { useModal } from "@context"; +import { + defaulCreateGovernanceActionValues, + useScreenDimension, + useTranslation, +} from "@hooks"; +import { BackToButton } from "@molecules"; +import { + ChooseGovernanceActionType, + DashboardTopNav, + Footer, +} from "@organisms"; +import { checkIsWalletConnected } from "@utils"; + +export const CreateGovernanceAction = () => { + const navigate = useNavigate(); + const { t } = useTranslation(); + const { isMobile } = useScreenDimension(); + const { closeModal, openModal } = useModal(); + const [step, setStep] = useState(1); + + const methods = useForm({ + mode: "onBlur", + defaultValues: defaulCreateGovernanceActionValues, + }); + + useEffect(() => { + if (checkIsWalletConnected()) { + navigate(PATHS.home); + } + }, []); + + const onClickBackToDashboard = () => + openModal({ + type: "statusModal", + state: { + status: "warning", + message: t("modals.createGovernanceAction.cancelModalDescription"), + buttonText: t("modals.common.goToDashboard"), + title: t("modals.createGovernanceAction.cancelModalTitle"), + dataTestId: "cancel-governance-action-creation-modal", + onSubmit: backToDashboard, + }, + }); + + const backToDashboard = () => { + navigate(PATHS.dashboard); + closeModal(); + }; + + return ( + + + + + + {step === 1 && ( + + )} + + {isMobile &&