Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vote Context #568

Merged
merged 1 commit into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions govtool/frontend/src/components/atoms/TextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,27 @@ import { TextAreaProps } from "./types";
const TextAreaBase = styled(TextareaAutosize)(
() => `
font-family: "Poppins";
font-size: 16px;
font-weight: 400;
::placeholder {
font-family: "Poppins";
font-size: 16px;
font-weight: 400;
color: #a6a6a6;
}
`,
);

export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
({ errorMessage, maxLength = 500, onBlur, onFocus, ...props }, ref) => {
(
{
errorMessage,
maxLength = 500,
onBlur,
onFocus,
isModifiedLayout,
...props
},
ref,
) => {
const { isMobile } = useScreenDimension();
const textAraeRef = useRef<HTMLTextAreaElement>(null);

Expand Down Expand Up @@ -51,19 +59,32 @@ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
[handleBlur, handleFocus],
);

const getTexAreaHeight = () => {
if (isModifiedLayout && isMobile) return "312px";
if (isModifiedLayout) return "208px";
if (isMobile) return "104px";
return "128px";
};

return (
<TextAreaBase
style={{
border: `1px solid ${errorMessage ? "red" : "#6F99FF"}`,
backgroundColor: errorMessage ? "#FAEAEB" : "white",
borderRadius: "24px",
height: isMobile ? "104px" : "128px",
height: getTexAreaHeight(),
outline: "none",
padding: "12px 14px",
resize: "none",
}}
maxLength={maxLength}
ref={textAraeRef}
sx={{
fontSize: isModifiedLayout ? "12px" : "auto",
"&::placeholder": {
fontSize: isModifiedLayout ? "12px" : "16px",
},
}}
{...props}
/>
);
Expand Down
1 change: 1 addition & 0 deletions govtool/frontend/src/components/atoms/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export type FormHelpfulTextProps = {

export type TextAreaProps = TextareaAutosizeProps & {
errorMessage?: string;
isModifiedLayout?: boolean;
};

export type InfoTextProps = {
Expand Down
10 changes: 9 additions & 1 deletion govtool/frontend/src/components/molecules/Field/TextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaFieldProps>(
} as unknown as HTMLTextAreaElement),
[handleBlur, handleFocus],
);

const getCounterBottomSxValue = () => {
if (props.isModifiedLayout && errorMessage) return 30;
if (props.isModifiedLayout) return 10;
if (errorMessage) return 52.5;
return 35;
};

return (
<Box
sx={{
Expand Down Expand Up @@ -92,7 +100,7 @@ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaFieldProps>(
<Typography
color="#8E908E"
sx={{
bottom: errorMessage ? 52.5 : 35,
bottom: getCounterBottomSxValue(),
position: "absolute",
right: 15,
}}
Expand Down
205 changes: 104 additions & 101 deletions govtool/frontend/src/components/molecules/VoteActionForm.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
import {
useState,
useEffect,
useMemo,
useCallback,
Dispatch,
SetStateAction,
} from "react";
import { useState, useEffect, useMemo, Dispatch, SetStateAction } from "react";
import { useLocation } from "react-router-dom";
import { Box, Link } from "@mui/material";
import { Box } from "@mui/material";
import { Trans } from "react-i18next";

import { Button, LoadingButton, Radio, Spacer, Typography } from "@atoms";
import { ICONS } from "@consts";
import { Button, LoadingButton, Radio, Typography } from "@atoms";
import { orange } from "@consts";
import { useModal } from "@context";
import {
useScreenDimension,
useVoteActionForm,
useTranslation,
useGetVoterInfo,
} from "@hooks";
import { openInNewTab } from "@utils";

import { Trans } from "react-i18next";
import { ControlledField } from "../organisms";

// TODO: Decide with BE on how cast votes will be implemented
// and adjust accordingly the component below (UI is ready).
Expand All @@ -45,7 +35,12 @@ export const VoteActionForm = ({
abstainVotes,
isInProgress,
}: VoteActionFormProps) => {
const [isContext, setIsContext] = useState<boolean>(false);
const [voteContextText, setVoteContextText] = useState<string | undefined>();
const [voteContextHash, setVoteContextHash] = useState<string | undefined>();
const [voteContextUrl, setVoteContextUrl] = useState<string | undefined>();
const [showWholeVoteContext, setShowWholeVoteContext] =
useState<boolean>(false);

const { state } = useLocation();
const { isMobile } = useScreenDimension();
const { openModal } = useModal();
Expand All @@ -54,16 +49,19 @@ export const VoteActionForm = ({

const {
areFormErrors,
clearErrors,
confirmVote,
control,
errors,
isDirty,
isVoteLoading,
registerInput,
setValue,
vote,
} = useVoteActionForm();
} = useVoteActionForm(voteContextHash, voteContextUrl);

const setVoteContextData = (url: string, hash: string, text: string) => {
setVoteContextUrl(url);
setVoteContextHash(hash);
setVoteContextText(text);
};

useEffect(() => {
if (state && state.vote) {
Expand All @@ -75,14 +73,6 @@ export const VoteActionForm = ({
}
}, [state, voteFromEP, setValue]);

useEffect(() => {
clearErrors();
}, [isContext]);

const handleContext = useCallback(() => {
setIsContext((prev) => !prev);
}, []);

const renderCancelButton = useMemo(
() => (
<Button
Expand All @@ -108,7 +98,7 @@ export const VoteActionForm = ({
disabled={
(!areFormErrors && voteFromEP === vote) ||
areFormErrors ||
(!isContext && voteFromEP === vote)
voteFromEP === vote
}
isLoading={isVoteLoading}
variant="contained"
Expand Down Expand Up @@ -233,89 +223,102 @@ export const VoteActionForm = ({
{t("govActions.showVotes")}
</Button>
)}
{/* TODO: Change below into new voting context */}
<Box
alignItems="center"
data-testid="context-button"
display="flex"
flexDirection="row"
flexWrap="wrap"
justifyContent="center"
mb="15px"
mt="58px"
onClick={handleContext}
<Typography
variant="body1"
sx={{
textTransform: "uppercase",
fontSize: "14px",
color: orange.c400,
mt: 6,
}}
>
<p
style={{
cursor: "pointer",
fontFamily: "Poppins",
fontSize: 12,
fontWeight: 300,
lineHeight: "18px",
textAlign: "center",
margin: 0,
}}
>
{t("govActions.provideContext")}{" "}
<span style={{ fontSize: 12, fontWeight: 300 }}>
{t("govActions.optional")}
<img
alt="arrow"
src={ICONS.arrowDownIcon}
style={{
marginBottom: 2,
marginLeft: 12,
transform: `rotate(${!isContext ? "180deg" : "0"})`,
}}
/>
</span>
</p>
</Box>
{isContext && (
{t("optional")}
</Typography>
<Typography
variant="body2"
sx={{
textAlign: "center",
mt: "5px",
}}
>
{voteContextText
? t("govActions.contextAboutYourVote")
: t("govActions.youCanProvideContext")}
</Typography>
{voteContextText ? (
<Box
display="flex"
flexDirection="column"
flex={1}
sx={{
alignSelf: "stretch",
display: "flex",
flexDirection: "column",
mt: 2,
}}
>
<ControlledField.Input
{...{ control, errors }}
dataTestId="url-input"
name="url"
placeholder={t("forms.urlWithContextPlaceholder")}
/>
<Spacer y={1.5} />
<ControlledField.Input
{...{ control, errors }}
dataTestId="hash-input"
name="hash"
placeholder={t("forms.hashPlaceholder")}
/>
<Link
data-testid="how-to-create-link"
onClick={() =>
openInNewTab(
"https://docs.sanchogov.tools/faqs/how-to-create-a-metadata-anchor",
)
}
mt="12px"
mb={isMobile ? 2 : 6}
sx={{ cursor: "pointer" }}
textAlign="center"
visibility={!isContext ? "hidden" : "visible"}
<Typography
variant="body2"
sx={{
fontWeight: 400,
color: "neutralGray",
...(!showWholeVoteContext && {
overflow: "hidden",
textOverflow: "ellipsis",
display: "-webkit-box",
WebkitBoxOrient: "vertical",
WebkitLineClamp: 2,
}),
}}
>
<Typography color="primary" fontWeight={400} variant="body2">
{t("forms.howCreateUrlAndHash")}
{voteContextText}
</Typography>
<Button
onClick={() => {
setShowWholeVoteContext((prev) => !prev);
}}
sx={{
p: 0,
margin: "0 auto",
":hover": {
backgroundColor: "transparent",
},
}}
disableRipple
variant="text"
data-testid="external-modal-button"
>
<Typography
variant="body2"
sx={{
fontWeight: 400,
color: "primaryBlue",
borderBottom: "1px solid",
}}
>
{showWholeVoteContext ? t("showLess") : t("showMore")}
</Typography>
</Link>
</Button>
</Box>
) : (
<Button
variant="outlined"
onClick={() => {
openModal({
type: "voteContext",
state: {
onSubmit: setVoteContextData,
},
});
}}
sx={{
mt: "12px",
}}
>
{t("govActions.provideContextAboutYourVote")}
</Button>
)}
</Box>
<Typography
sx={{
mb: 1,
mb: 2,
mt: 3,
textAlign: "center",
visibility: state?.vote || voteFromEP ? "visible" : "hidden",
}}
Expand All @@ -341,7 +344,7 @@ export const VoteActionForm = ({
disabled={
!vote ||
state?.vote === vote ||
(isContext && areFormErrors && isDirty) ||
(areFormErrors && isDirty) ||
voteFromEP === vote
}
isLoading={isVoteLoading}
Expand Down
Loading
Loading