-
-
Notifications
You must be signed in to change notification settings - Fork 24
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
feat(features): use stepper for congregation creation workflow #2900
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { SvgIcon, SxProps, Theme } from '@mui/material'; | ||
|
||
type IconProps = { | ||
color?: string; | ||
width?: number; | ||
height?: number; | ||
sx?: SxProps<Theme>; | ||
className?: string; | ||
}; | ||
|
||
const IconCongregationAccess = ({ | ||
color = '#222222', | ||
width = 24, | ||
height = 24, | ||
sx = {}, | ||
className, | ||
}: IconProps) => { | ||
return ( | ||
<SvgIcon | ||
className={`organized-icon-congregation-access ${className}`} | ||
sx={{ width: `${width}px`, height: `${height}px`, ...sx }} | ||
> | ||
<svg | ||
width="24" | ||
height="24" | ||
viewBox="0 0 24 24" | ||
fill="none" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<mask | ||
id="mask0_14912_258760" | ||
style={{ maskType: 'alpha' }} | ||
maskUnits="userSpaceOnUse" | ||
x="0" | ||
y="0" | ||
width="24" | ||
height="24" | ||
> | ||
<rect width="24" height="24" fill="#D9D9D9" /> | ||
</mask> | ||
<g mask="url(#mask0_14912_258760)"> | ||
<path | ||
d="M4 20.8941V9.6442L11.5 4L19 9.6442V11.7038H17.5V10.3942L11.5 5.87495L5.49998 10.3942V19.3942H7.69038C7.69038 19.672 7.69038 19.8787 7.69038 20.1364C7.69038 20.3942 7.69038 20.5998 7.69038 20.8941H4Z" | ||
fill={color} | ||
/> | ||
<path | ||
d="M10.5298 20.8008V19.3145H21.4702V20.8008H10.5298ZM11.2215 17.3124L10.4278 16.8284L10.8558 16.0266H10V15.0585H10.8558L10.4278 14.2848L11.2215 13.8008L11.6493 14.5824L12.0772 13.8008L12.8632 14.2848L12.4354 15.0585H13.2911V16.0266H12.4354L12.8632 16.8284L12.0772 17.3124L11.6493 16.5028L11.2215 17.3124ZM15.5722 17.3124L14.7785 16.8284L15.2065 16.0266H14.3507V15.0585H15.2065L14.7785 14.2848L15.5722 13.8008L16 14.5824L16.4278 13.8008L17.2215 14.2848L16.7935 15.0585H17.6493V16.0266H16.7935L17.2215 16.8284L16.4278 17.3124L16 16.5028L15.5722 17.3124ZM19.9228 17.3124L19.1368 16.8284L19.5646 16.0266H18.7089V15.0585H19.5646L19.1368 14.2848L19.9228 13.8008L20.3507 14.5824L20.7785 13.8008L21.5722 14.2848L21.1442 15.0585H22V16.0266H21.1442L21.5722 16.8284L20.7785 17.3124L20.3507 16.5028L19.9228 17.3124Z" | ||
fill={color} | ||
/> | ||
</g> | ||
</svg> | ||
</SvgIcon> | ||
); | ||
}; | ||
|
||
export default IconCongregationAccess; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,185 @@ | ||||||||||||||||||||||||||||||||||||||
import { Box } from '@mui/material'; | ||||||||||||||||||||||||||||||||||||||
import { IconCongregationAccess, IconError, IconLoading } from '@icons/index'; | ||||||||||||||||||||||||||||||||||||||
import { useAppTranslation } from '@hooks/index'; | ||||||||||||||||||||||||||||||||||||||
import useCongregationAccessCode from './useCongregationAccessCode'; | ||||||||||||||||||||||||||||||||||||||
import Button from '@components/button'; | ||||||||||||||||||||||||||||||||||||||
import Criteria from './criteria'; | ||||||||||||||||||||||||||||||||||||||
import InfoMessage from '@components/info-message'; | ||||||||||||||||||||||||||||||||||||||
import Markup from '@components/text_markup'; | ||||||||||||||||||||||||||||||||||||||
import TextField from '@components/textfield'; | ||||||||||||||||||||||||||||||||||||||
import Typography from '@components/typography'; | ||||||||||||||||||||||||||||||||||||||
import VipInfoTip from '@features/app_start/vip/vip_info_tip'; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
const CongregationAccessCode = () => { | ||||||||||||||||||||||||||||||||||||||
const { t } = useAppTranslation(); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
const { | ||||||||||||||||||||||||||||||||||||||
isLengthPassed, | ||||||||||||||||||||||||||||||||||||||
isNumberPassed, | ||||||||||||||||||||||||||||||||||||||
isLowerCasePassed, | ||||||||||||||||||||||||||||||||||||||
isUpperCasePassed, | ||||||||||||||||||||||||||||||||||||||
isSpecialSymbolPassed, | ||||||||||||||||||||||||||||||||||||||
isProcessing, | ||||||||||||||||||||||||||||||||||||||
hideMessage, | ||||||||||||||||||||||||||||||||||||||
message, | ||||||||||||||||||||||||||||||||||||||
title, | ||||||||||||||||||||||||||||||||||||||
variant, | ||||||||||||||||||||||||||||||||||||||
isMatch, | ||||||||||||||||||||||||||||||||||||||
setTmpAccessCode, | ||||||||||||||||||||||||||||||||||||||
setTmpAccessCodeVerify, | ||||||||||||||||||||||||||||||||||||||
tmpAccessCode, | ||||||||||||||||||||||||||||||||||||||
tmpAccessCodeVerify, | ||||||||||||||||||||||||||||||||||||||
btnActionDisabled, | ||||||||||||||||||||||||||||||||||||||
handleSetAccessCode, | ||||||||||||||||||||||||||||||||||||||
} = useCongregationAccessCode(); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||
<Box | ||||||||||||||||||||||||||||||||||||||
sx={{ | ||||||||||||||||||||||||||||||||||||||
display: 'flex', | ||||||||||||||||||||||||||||||||||||||
flexDirection: 'column', | ||||||||||||||||||||||||||||||||||||||
justifyContent: 'space-between', | ||||||||||||||||||||||||||||||||||||||
width: '100%', | ||||||||||||||||||||||||||||||||||||||
gap: '24px', | ||||||||||||||||||||||||||||||||||||||
flexGrow: 1, | ||||||||||||||||||||||||||||||||||||||
}} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
<Box | ||||||||||||||||||||||||||||||||||||||
sx={{ | ||||||||||||||||||||||||||||||||||||||
display: 'flex', | ||||||||||||||||||||||||||||||||||||||
flexDirection: 'column', | ||||||||||||||||||||||||||||||||||||||
height: '100%', | ||||||||||||||||||||||||||||||||||||||
width: '100%', | ||||||||||||||||||||||||||||||||||||||
}} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
<Markup | ||||||||||||||||||||||||||||||||||||||
content={t('tr_createAccessCodeDesc')} | ||||||||||||||||||||||||||||||||||||||
className="body-regular" | ||||||||||||||||||||||||||||||||||||||
color="var(--grey-400)" | ||||||||||||||||||||||||||||||||||||||
style={{ marginBottom: '24px' }} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
<Box | ||||||||||||||||||||||||||||||||||||||
sx={{ | ||||||||||||||||||||||||||||||||||||||
display: 'flex', | ||||||||||||||||||||||||||||||||||||||
padding: '8px 16px', | ||||||||||||||||||||||||||||||||||||||
alignItems: 'center', | ||||||||||||||||||||||||||||||||||||||
gap: '8px', | ||||||||||||||||||||||||||||||||||||||
borderRadius: 'var(--radius-l)', | ||||||||||||||||||||||||||||||||||||||
background: 'var(--orange-secondary)', | ||||||||||||||||||||||||||||||||||||||
marginBottom: '32px', | ||||||||||||||||||||||||||||||||||||||
}} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
<IconError color="var(--orange-dark)" /> | ||||||||||||||||||||||||||||||||||||||
<Typography className="body-regular" color="var(--orange-dark)"> | ||||||||||||||||||||||||||||||||||||||
{t('tr_congregationAccessCodeNotice')} | ||||||||||||||||||||||||||||||||||||||
</Typography> | ||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
<Box | ||||||||||||||||||||||||||||||||||||||
sx={{ | ||||||||||||||||||||||||||||||||||||||
display: 'flex', | ||||||||||||||||||||||||||||||||||||||
flexDirection: 'column', | ||||||||||||||||||||||||||||||||||||||
gap: '24px', | ||||||||||||||||||||||||||||||||||||||
alignItems: 'flex-start', | ||||||||||||||||||||||||||||||||||||||
alignSelf: 'stretch', | ||||||||||||||||||||||||||||||||||||||
width: '100%', | ||||||||||||||||||||||||||||||||||||||
}} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
<Box | ||||||||||||||||||||||||||||||||||||||
sx={{ | ||||||||||||||||||||||||||||||||||||||
display: 'flex', | ||||||||||||||||||||||||||||||||||||||
flexDirection: 'column', | ||||||||||||||||||||||||||||||||||||||
gap: '16px', | ||||||||||||||||||||||||||||||||||||||
width: '100%', | ||||||||||||||||||||||||||||||||||||||
}} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
<TextField | ||||||||||||||||||||||||||||||||||||||
type="password" | ||||||||||||||||||||||||||||||||||||||
label={t('tr_congregationAccessCodeCreate')} | ||||||||||||||||||||||||||||||||||||||
variant="outlined" | ||||||||||||||||||||||||||||||||||||||
autoComplete="off" | ||||||||||||||||||||||||||||||||||||||
value={tmpAccessCode} | ||||||||||||||||||||||||||||||||||||||
onChange={(e) => setTmpAccessCode(e.target.value)} | ||||||||||||||||||||||||||||||||||||||
startIcon={<IconCongregationAccess />} | ||||||||||||||||||||||||||||||||||||||
resetHelperPadding={true} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
<TextField | ||||||||||||||||||||||||||||||||||||||
type="password" | ||||||||||||||||||||||||||||||||||||||
label={t('tr_congregationAccessCodeVerify')} | ||||||||||||||||||||||||||||||||||||||
variant="outlined" | ||||||||||||||||||||||||||||||||||||||
autoComplete="off" | ||||||||||||||||||||||||||||||||||||||
value={tmpAccessCodeVerify} | ||||||||||||||||||||||||||||||||||||||
onChange={(e) => setTmpAccessCodeVerify(e.target.value)} | ||||||||||||||||||||||||||||||||||||||
startIcon={<IconCongregationAccess />} | ||||||||||||||||||||||||||||||||||||||
resetHelperPadding={true} | ||||||||||||||||||||||||||||||||||||||
helperText={ | ||||||||||||||||||||||||||||||||||||||
Comment on lines
+97
to
+116
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance password field security and user experience. Consider the following improvements:
<TextField
type="password"
label={t('tr_congregationAccessCodeCreate')}
variant="outlined"
- autoComplete="off"
+ autoComplete="new-password"
value={tmpAccessCode}
onChange={(e) => setTmpAccessCode(e.target.value)}
startIcon={<IconCongregationAccess />}
+ endIcon={<IconPasswordVisibility onClick={togglePasswordVisibility} />}
resetHelperPadding={true}
/>
|
||||||||||||||||||||||||||||||||||||||
<Box | ||||||||||||||||||||||||||||||||||||||
sx={{ | ||||||||||||||||||||||||||||||||||||||
padding: '8px 0px 0px 16px', | ||||||||||||||||||||||||||||||||||||||
display: 'flex', | ||||||||||||||||||||||||||||||||||||||
flexDirection: 'column', | ||||||||||||||||||||||||||||||||||||||
gap: '4px', | ||||||||||||||||||||||||||||||||||||||
}} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
<Criteria | ||||||||||||||||||||||||||||||||||||||
criteria={t('tr_congregationAccessCodeNoticeLength')} | ||||||||||||||||||||||||||||||||||||||
passed={isLengthPassed} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
<Criteria | ||||||||||||||||||||||||||||||||||||||
criteria={t('tr_encryptionCodeNoticeNumber')} | ||||||||||||||||||||||||||||||||||||||
passed={isNumberPassed} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
<Criteria | ||||||||||||||||||||||||||||||||||||||
criteria={t('tr_encryptionCodeNoticeLowerCase')} | ||||||||||||||||||||||||||||||||||||||
passed={isLowerCasePassed} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
<Criteria | ||||||||||||||||||||||||||||||||||||||
criteria={t('tr_encryptionCodeNoticeUpperCase')} | ||||||||||||||||||||||||||||||||||||||
passed={isUpperCasePassed} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
<Criteria | ||||||||||||||||||||||||||||||||||||||
criteria={t('tr_encryptionCodeNoticeSpecialSymbol')} | ||||||||||||||||||||||||||||||||||||||
passed={isSpecialSymbolPassed} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
<Criteria | ||||||||||||||||||||||||||||||||||||||
criteria={t('tr_encryptionCodeNoticeMatch')} | ||||||||||||||||||||||||||||||||||||||
passed={isMatch} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
<Button | ||||||||||||||||||||||||||||||||||||||
variant="main" | ||||||||||||||||||||||||||||||||||||||
sx={{ width: '100%' }} | ||||||||||||||||||||||||||||||||||||||
onClick={handleSetAccessCode} | ||||||||||||||||||||||||||||||||||||||
startIcon={ | ||||||||||||||||||||||||||||||||||||||
isProcessing ? <IconLoading width={22} height={22} /> : null | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
disabled={btnActionDisabled} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
{t('tr_congregationAccessCodeSet')} | ||||||||||||||||||||||||||||||||||||||
</Button> | ||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
<Box> | ||||||||||||||||||||||||||||||||||||||
<VipInfoTip variant="congregationCodes" /> | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
<Box id="onboarding-error" sx={{ display: 'none' }}> | ||||||||||||||||||||||||||||||||||||||
<InfoMessage | ||||||||||||||||||||||||||||||||||||||
variant={variant} | ||||||||||||||||||||||||||||||||||||||
messageIcon={<IconError />} | ||||||||||||||||||||||||||||||||||||||
messageHeader={title} | ||||||||||||||||||||||||||||||||||||||
message={message} | ||||||||||||||||||||||||||||||||||||||
onClose={hideMessage} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||
Comment on lines
+171
to
+179
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider using React state for error message visibility. Using -<Box id="onboarding-error" sx={{ display: 'none' }}>
+<Box sx={{ display: message ? 'block' : 'none' }}>
<InfoMessage
variant={variant}
messageIcon={<IconError />}
messageHeader={title}
message={message}
onClose={hideMessage}
/>
</Box> 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
export default CongregationAccessCode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Migration to useSetRecoilState is incomplete - Found legacy imports
The codebase still contains direct imports of
setIsAccountChoose
from the old location@services/recoil/app
in:src/features/app_start/shared/startup/useStartup.tsx
src/features/app_start/vip/signin/useSignin.tsx
These files need to be updated to use
useSetRecoilState(isAccountChooseState)
for consistency with the new pattern, as already implemented in other components likeuseTermsUse.tsx
anduseAccountChooser.tsx
.🔗 Analysis chain
LGTM! Verify state management changes across the application.
The switch to using
useSetRecoilState
hook directly is a good practice. However, let's verify that all components consuming these states are properly updated.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 383
Script:
Length of output: 474
Script:
Length of output: 3098