Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into search-issue-361
Browse files Browse the repository at this point in the history
  • Loading branch information
taoliu12 committed Oct 13, 2023
2 parents 920159b + 14e7f56 commit 4734ef0
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 83 deletions.
6 changes: 4 additions & 2 deletions client/src/components/BannerSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { Grid, Typography, Box } from '@mui/material';
import { makeStyles } from 'tss-react/mui';
import type { Theme } from '@mui/material/styles';
import MainImage from '../assets/banner-section-main.svg';
import CTAButton from './Buttons/CTAButton';
import { CTAHeroButton } from './Buttons/Button';
import { useHistory } from 'react-router-dom';

const useStyles = makeStyles()((theme: Theme) => ({
gridTitle: {
Expand Down Expand Up @@ -43,14 +44,15 @@ function BannerText() {

function BannerSection() {
const { classes } = useStyles();
const history = useHistory();

return (
<Box>
<Grid container spacing={3} sx={{ height: '600px' }}>
<Grid xs={6} item justifyContent="center" sx={{ display: 'flex' }}>
<Box sx={{ width: '550px', mt: '180px', mb: '66px', ml: '40px' }}>
<BannerText />
<CTAButton text="Join Now" />
<CTAHeroButton text="Join Now" onClick={() => history.push('/signup-citizen')} />
</Box>
</Grid>
<Grid
Expand Down
63 changes: 63 additions & 0 deletions client/src/components/Buttons/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { makeStyles } from 'tss-react/mui';
import { Button, Typography } from '@mui/material';
import theme from '../../theme';
import { ReactNode } from 'react';

const useStyles = makeStyles()(() => ({
CTAHeroButton: {
color: 'white',
backgroundColor: theme.palette.primary.main,
borderRadius: '10px',
fontWeight: 'semi-bold',
border: 'none',
'&:hover': {
backgroundColor: theme.palette.primary.main,
cursor: 'pointer',
},
},
primaryCTAButton: {
textTransform: 'capitalize',
backgroundColor: theme.palette.primary.main,
color: `${theme.palette.primary.contrastText}`,
borderRadius: '10px',
border: `1px solid ${theme.palette.primary.main}`,
marginLeft: '0px',
width: '100px',
'&:hover': {
color: `${theme.palette.text.primary}`,
},
},
}));

type Props = {
text: string;
onClick?: () => void;
children?: ReactNode;
};

export function CTAHeroButton({ text, onClick }: Props) {
const { classes } = useStyles();

return (
<button onClick={onClick} className={classes.CTAHeroButton}>
<Typography
sx={{
fontSize: '22px',
padding: '15px 25px 15px 25px',
}}
>
{text}
</Typography>
</button>
);
}

export function PrimaryCTAButton({ text, onClick, children }: Props) {
const { classes } = useStyles();
return (
<Button component="span" onClick={onClick} className={classes.primaryCTAButton}>
{text}
{children}
</Button>
);
}
43 changes: 0 additions & 43 deletions client/src/components/Buttons/CTAButton.tsx

This file was deleted.

15 changes: 12 additions & 3 deletions client/src/components/Forms/FileUploadInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { makeStyles } from 'tss-react/mui';
import { FormControl, FormLabel, Button } from '@mui/material';

import type { Theme } from '@mui/material/styles';
import { CTAHeroButton, PrimaryCTAButton } from '../Buttons/Button';

const useStyles = makeStyles()((theme: Theme) => ({
buttonText: {
Expand All @@ -20,6 +21,7 @@ type CustomProps = {
id: string;
label: string;
text: string;
buttonVariant?: 'CTAHeroButton' | 'primaryCTAButton';
onChange: (event: any) => void;
};

Expand All @@ -36,11 +38,18 @@ function FileUploadInput(props: CustomProps) {
id="raised-button-file"
multiple
type="file"
onChange={props.onChange}
/>
<label htmlFor="raised-button-file">
<Button component="span" className={classes.buttonText}>
{props.text}
</Button>
{props.buttonVariant === 'primaryCTAButton' ? (
<PrimaryCTAButton text={props.text}></PrimaryCTAButton>
) : props.buttonVariant === 'CTAHeroButton' ? (
<CTAHeroButton text={props.text}></CTAHeroButton>
) : (
<Button component="span" className={classes.buttonText}>
{props.text}
</Button>
)}
</label>
</FormControl>
);
Expand Down
21 changes: 6 additions & 15 deletions client/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import routes from '../routes/routes';
import { APP_API_BASE_URL } from '../configs';
import { UserAvatar } from './Users/UserAvatar';
import { ModalContext } from './../providers/ModalProvider';
import { PrimaryCTAButton } from './Buttons/Button';

const useStyles = makeStyles()(() => ({
home: {
Expand Down Expand Up @@ -74,18 +75,6 @@ const useStyles = makeStyles()(() => ({
logo: {
height: '30px',
},
signUpButton: {
textTransform: 'capitalize',
backgroundColor: theme.palette.primary.main,
color: `${theme.palette.primary.contrastText}`,
borderRadius: '10px',
border: `1px solid ${theme.palette.primary.main}`,
marginRight: '1.5em',
width: '100px',
'&:hover': {
color: `${theme.palette.text.primary}`,
},
},
signInButton: {
textTransform: 'capitalize',
backgroundColor: `${theme.palette.primary.contrastText}`,
Expand Down Expand Up @@ -500,9 +489,11 @@ function Header() {
</>
) : (
<>
<Button className={classes.signUpButton} onClick={() => handleoOpenModal('SignUp')}>
Join Now
</Button>
{/* TODO: Use () => handleoOpenModal('SignUp') when implemented */}
<PrimaryCTAButton
text="Join Now"
onClick={() => history.push('/signup-citizen')}
></PrimaryCTAButton>
<Button className={classes.signInButton} onClick={() => handleoOpenModal('SignIn')}>
Sign In
</Button>
Expand Down
23 changes: 22 additions & 1 deletion client/src/components/Users/Auth/SignUpCitizen/SignUpCitizen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ function SignupCitizen() {
const [activeStep, setActiveStep] = useState<number>(0);
const [formData, setFormData] = useState(initialFormData);
const [submitForm, setSubmitForm] = useState(false);
const [submitProfile, setSubmitProfile] = useState(false);
const [user, setUser] = useState(null);
const [errorMsg, setErrorMsg] = useState(null);
const [image, setImage] = useState<File | null>(null);

useEffect(() => {
if (user) {
Expand All @@ -56,16 +58,30 @@ function SignupCitizen() {
}
}, [submitForm]);

Check warning on line 59 in client/src/components/Users/Auth/SignUpCitizen/SignUpCitizen.tsx

View workflow job for this annotation

GitHub Actions / linting

React Hook useEffect has missing dependencies: 'formData' and 'registerUserMutation'. Either include them or remove the dependency array

useEffect(() => {
if (submitProfile) {
updateProfileMutation.mutate({ file: image!, userId: user!['id'] });
setSubmitProfile(false);
}
}, [submitProfile]);

Check warning on line 66 in client/src/components/Users/Auth/SignUpCitizen/SignUpCitizen.tsx

View workflow job for this annotation

GitHub Actions / linting

React Hook useEffect has missing dependencies: 'image', 'updateProfileMutation', and 'user'. Either include them or remove the dependency array

const registerUserMutation = useMutation({
mutationFn: Endpoints.userRegister,
onSuccess: ({ data: user }) => {
setUser(user);
setSubmitProfile(true);
},
onError: (error: AxiosError) => {
setErrorMsg(error?.response?.data?.message);
},
});

const updateProfileMutation = useMutation({
mutationFn: Endpoints.userUpdateProfile,
onSuccess: () => console.log('Profile updated!'),
onError: (error: AxiosError) => console.log(error),
});

const handleNext = (newFormData: {}, doSubmit = false) => {
setFormData((currFormData) => ({
...currFormData,
Expand Down Expand Up @@ -141,7 +157,12 @@ function SignupCitizen() {

{/* PAGE FOUR ######################################################## */}
{activeStep === 3 && (
<StepFour initData={formData} handleBack={handleBack} handleNext={handleNext} />
<StepFour
initData={formData}
handleBack={handleBack}
handleNext={handleNext}
setImage={setImage}
/>
)}

{/* PAGE FIVE ######################################################## */}
Expand Down
55 changes: 37 additions & 18 deletions client/src/components/Users/Auth/SignUpCitizen/StepFour.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import React, { useState } from 'react';
import { Avatar, Box, Button, Grid, TextField, Typography } from '@mui/material';
import { Alert, Avatar, Box, Button, Grid, TextField, Typography } from '@mui/material';

import { useStyles } from './styles/styles';
import { FileUploadInput } from '../../../Forms';

type TStepFourProps = {
initData: { bio: string };
handleBack: () => void;
handleNext: (formData: {}, submitForm?: boolean) => void;
setImage: (image: File | null) => void;
};

export default function StepFour({ initData, handleBack, handleNext }: TStepFourProps) {
export default function StepFour({ initData, handleBack, handleNext, setImage }: TStepFourProps) {
const { classes } = useStyles();
const [formData, setFormData] = useState(initData);
const [imageError, setImageError] = useState<'too-big' | 'unsupported-text' | ''>('');

const handleChange = (evt: React.ChangeEvent<HTMLInputElement>): void => {
const { name, value }: { name: string; value: string } = evt.target;
Expand All @@ -23,6 +26,22 @@ export default function StepFour({ initData, handleBack, handleNext }: TStepFour
});
};

const handleImageChange = (evt: React.ChangeEvent<HTMLInputElement>): void => {
if (!evt.target.files || evt.target.files.length === 0) {
return;
}
if (evt.target.files[0].size > 1000000) {
setImageError('too-big');
return;
}
if (!['image/jpeg', 'image/jpg', 'image/png', 'image/gif'].includes(evt.target.files[0].type)) {
setImageError('unsupported-text');
return;
}
setImageError('');
setImage(evt.target.files![0]);
};

const handleClickNext = () => {
handleNext(formData, true);
};
Expand All @@ -48,24 +67,24 @@ export default function StepFour({ initData, handleBack, handleNext }: TStepFour
</Typography>
<Grid item xs={12} sx={{ height: '50px' }} />
<Grid container item xs={12} lg={6} alignItems="center">
<Grid item xs={3}>
<Grid item xs={12}>
<Avatar sx={{ bgcolor: 'gray', width: 110, height: 110 }} />
</Grid>
<Grid item xs={3}>
<input accept="image/*" hidden id="upload-file" type="file" />
<label htmlFor="upload-file">
<Button
sx={{
backgroundColor: '#EF6A60',
color: 'white',
borderRadius: '4px',
padding: '10px',
}}
color="primary"
>
Upload
</Button>
</label>
<Grid item xs={12}>
<FileUploadInput
label=""
id="upload-file"
text="Upload"
onChange={handleImageChange}
buttonVariant="primaryCTAButton"
></FileUploadInput>
</Grid>
<Grid item xs={12}>
{imageError === 'too-big' ? (
<Alert severity="error">Please upload a file up to 1 megabyte in size.</Alert>
) : imageError === 'unsupported-text' ? (
<Alert severity="error">Supported files: jpeg, jpg png and gif</Alert>
) : null}
</Grid>
</Grid>
<Grid item xs={12} sx={{ height: '50px' }} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import axios from 'axios';

import { UserSignupData } from '../types/UserSignupData';
import { Profile, UserSignupData } from '../types/UserSignupData';

const client = axios.create({
baseURL: '/api',
Expand All @@ -27,6 +27,12 @@ const Endpoints = {
checkUserEmail: (userEmail: string) => {
return client.get(`/auth/user-email-exists/${userEmail}`);
},
userUpdateProfile: (profile: Profile) => {
const { file, userId } = profile;
const formData = new FormData();
formData.append('profile_image', file);
return client.put(`/auth/users/profile/${userId}`, formData);
},
};

export default Endpoints;
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@ export interface UserSignupData {
bio: string;
passwordConfirm: string;
}

export interface Profile {
file: File;
userId: number;
}

0 comments on commit 4734ef0

Please sign in to comment.