You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

265 lines
9.6 KiB

  1. "use client";
  2. import Stack from "@mui/material/Stack";
  3. import Box from "@mui/material/Box";
  4. import Card from "@mui/material/Card";
  5. import CardContent from "@mui/material/CardContent";
  6. import Grid from "@mui/material/Grid";
  7. import TextField from "@mui/material/TextField";
  8. import Typography from "@mui/material/Typography";
  9. import { useFormContext } from "react-hook-form";
  10. import { useTranslation } from "react-i18next";
  11. import { useCallback, useState } from "react";
  12. import { PasswordInputs } from "@/app/api/user/actions";
  13. import { Visibility, VisibilityOff } from "@mui/icons-material";
  14. import {
  15. FormHelperText,
  16. IconButton,
  17. InputAdornment,
  18. createTheme,
  19. } from "@mui/material";
  20. import { ThemeProvider } from "../../../node_modules/@mui/system/index";
  21. import { PW_RULE_THEME as defaultTheme } from "@/theme/colorConst";
  22. import Check from "@mui/icons-material/Check";
  23. import Clear from "@mui/icons-material/Clear";
  24. import { PasswordRulesProps } from "./ChangePassword";
  25. const ChagnePasswordForm: React.FC<PasswordRulesProps> = ({ pwRules:rules }) => {
  26. const { t } = useTranslation("changePassword");
  27. const [showNewPassword, setShowNewPassword] = useState(false);
  28. const handleClickShowNewPassword = () => setShowNewPassword(!showNewPassword);
  29. const handleMouseDownNewPassword = () => setShowNewPassword(!showNewPassword);
  30. const [showPassword, setShowPassword] = useState(false);
  31. const handleClickShowPassword = () => setShowPassword(!showPassword);
  32. const handleMouseDownPassword = () => setShowPassword(!showPassword);
  33. const [helperTextColors, setHelperTextColors] = useState<string[]>([
  34. "red",
  35. "green",
  36. "blue",
  37. ]);
  38. const [inputValue, setInputValue] = useState("");
  39. const [theme, setTheme] =
  40. useState<ReturnType<typeof createTheme>>(defaultTheme);
  41. const pwlengthString = `${rules.min || 0}-${rules.max || " "} characters`
  42. let msgList = [
  43. pwlengthString,
  44. ]
  45. switch (true) {
  46. case rules.upperEng:
  47. msgList.push("Uppercase letters")
  48. case rules.lowerEng:
  49. msgList.push("Lowercase letters")
  50. case rules.number:
  51. msgList.push("Numbers")
  52. case rules.specialChar:
  53. msgList.push("Symbols")
  54. default:
  55. break
  56. }
  57. const {
  58. register,
  59. formState: { errors, defaultValues },
  60. control,
  61. reset,
  62. resetField,
  63. setValue,
  64. setError
  65. } = useFormContext<PasswordInputs>();
  66. const getColorFromInput = (
  67. inputValue: string,
  68. helperTextLines: string[]
  69. ): string[] => {
  70. // Determine the color for each line based on the input value
  71. return helperTextLines.map((_, index) => {
  72. if ((index === 0 && inputValue.length < rules.min) || inputValue.length > rules.max) {
  73. // testing length
  74. return "red";
  75. } else if (index === 1 && rules.upperEng &&!/[A-Z]/.test(inputValue)) {
  76. //testing for uppercase letters
  77. return "red";
  78. } else if (index === 2 && rules.lowerEng && !/[a-z]/.test(inputValue)) {
  79. //testing for lowercase letters
  80. return "red";
  81. } else if (index === 3 && rules.number && !/[0-9]/.test(inputValue)) {
  82. //testing for numbers
  83. return "red";
  84. } else if (index === 4 && rules.specialChar && !/[-!@#$%^&=+_*(),.?":{}|<>]/.test(inputValue)) {
  85. //testing for special characters
  86. return "red";
  87. } else {
  88. return "green";
  89. }
  90. });
  91. };
  92. if (!/[-!@#$%^&=+_*(),.?":{}|<>]/.test('12')) {
  93. console.log(!/[-!@#$%^&=+_*(),.?":{}|<>]/.test('12'))
  94. }
  95. const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  96. // Update the theme with the new color based on the input value
  97. const newInputValue = event.target.value;
  98. setInputValue(newInputValue);
  99. const newTheme = createTheme({
  100. ...theme,
  101. components: {
  102. MuiFormHelperText: {
  103. styleOverrides: {
  104. root: {
  105. color: getColorFromInput(newInputValue, msgList),
  106. fontFamily: "Roboto",
  107. "& .icon": {
  108. alignItems: "center",
  109. AlignHorizontalCenter: "center",
  110. marginRight: "4px",
  111. fontSize: "1rem", // Adjust the font size as needed
  112. },
  113. },
  114. },
  115. },
  116. },
  117. });
  118. setTheme(newTheme);
  119. };
  120. return (
  121. <Card sx={{ display: "block" }}>
  122. <CardContent component={Stack} spacing={4}>
  123. <Box>
  124. <Typography variant="overline" display="block" marginBlockEnd={1}>
  125. {t("Please Fill in All Fields")}
  126. </Typography>
  127. <Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
  128. <Grid item xs={6}>
  129. <TextField
  130. label={t("Input Old Password")}
  131. fullWidth
  132. type={showPassword ? "text" : "password"}
  133. InputProps={{
  134. endAdornment: (
  135. <InputAdornment position="end">
  136. <IconButton
  137. aria-label="toggle password visibility"
  138. onClick={handleClickShowPassword}
  139. onMouseDown={handleMouseDownPassword}
  140. >
  141. {showPassword ? <Visibility /> : <VisibilityOff />}
  142. </IconButton>
  143. </InputAdornment>
  144. ),
  145. }}
  146. {...register("password", {
  147. required: true,
  148. })}
  149. error={Boolean(errors.password)}
  150. helperText={
  151. Boolean(errors.password) &&
  152. (errors.password?.message
  153. ? t(errors.password.message)
  154. : t("Please input correct password"))
  155. }
  156. />
  157. </Grid>
  158. <Grid item xs={6} />
  159. <Grid item xs={6}>
  160. <ThemeProvider theme={theme}>
  161. <TextField
  162. label={t("Input New Password")}
  163. fullWidth
  164. type={showNewPassword ? "text" : "password"}
  165. InputProps={{
  166. endAdornment: (
  167. <InputAdornment position="end">
  168. <IconButton
  169. aria-label="toggle password visibility"
  170. onClick={handleClickShowNewPassword}
  171. onMouseDown={handleMouseDownNewPassword}
  172. >
  173. {showNewPassword ? <Visibility /> : <VisibilityOff />}
  174. </IconButton>
  175. </InputAdornment>
  176. ),
  177. }}
  178. {...register("newPassword")}
  179. onChange={handleInputChange}
  180. error={Boolean(errors.newPassword)}
  181. // error={Boolean(errors.newPassword)}
  182. helperText={msgList}
  183. FormHelperTextProps={{
  184. component: (props) => {
  185. return (
  186. <FormHelperText {...props}>
  187. {(props.children as string[]).map((line, index) => {
  188. console.log(index, getColorFromInput(inputValue, msgList)[index])
  189. return (
  190. <span
  191. key={index}
  192. style={{
  193. color: getColorFromInput(inputValue, msgList)[
  194. index
  195. ],
  196. }}
  197. >
  198. {getColorFromInput(inputValue, msgList)[index] ===
  199. "red" ? (
  200. <Clear className="icon" />
  201. ) : (
  202. <Check className="icon" color="success" />
  203. )}
  204. {line}
  205. {index <
  206. (props.children as string[]).length && (
  207. <br />
  208. )}
  209. </span>
  210. )}
  211. )}
  212. </FormHelperText>
  213. );
  214. },
  215. }}
  216. // (Boolean(errors.newPassword) &&
  217. // (errors.newPassword?.message
  218. // ? t(errors.newPassword.message)
  219. // : t("Please input correct newPassword")))
  220. />
  221. </ThemeProvider>
  222. </Grid>
  223. <Grid item xs={6}>
  224. <TextField
  225. label={t("Input New Password Again")}
  226. fullWidth
  227. type={showNewPassword ? "text" : "password"}
  228. InputProps={{
  229. endAdornment: (
  230. <InputAdornment position="end">
  231. <IconButton
  232. aria-label="toggle password visibility"
  233. onClick={handleClickShowNewPassword}
  234. onMouseDown={handleMouseDownNewPassword}
  235. >
  236. {showNewPassword ? <Visibility /> : <VisibilityOff />}
  237. </IconButton>
  238. </InputAdornment>
  239. ),
  240. }}
  241. {...register("newPasswordCheck")}
  242. error={Boolean(errors.newPassword)}
  243. helperText={
  244. Boolean(errors.newPassword) &&
  245. (errors.newPassword?.message
  246. ? t(errors.newPassword.message)
  247. : t("Please input correct newPassword"))
  248. }
  249. />
  250. </Grid>
  251. </Grid>
  252. </Box>
  253. </CardContent>
  254. </Card>
  255. );
  256. };
  257. export default ChagnePasswordForm;