-
Notifications
You must be signed in to change notification settings - Fork 2
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
In amazon s3 #55
In amazon s3 #55
Changes from 7 commits
d9a4d96
617e17b
8953d36
cd1ed58
d428c28
eaa8423
ca70fd7
56dbe8c
2095124
8227466
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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import React, { useState } from 'react'; | ||
import { useState, ChangeEvent } from 'react'; | ||
import Box from '@material-ui/core/Box'; | ||
import Button from '@material-ui/core/Button'; | ||
import CardHeader from '@material-ui/core/CardHeader'; | ||
|
@@ -7,48 +7,123 @@ import CardMedia from '@material-ui/core/CardMedia'; | |
import Typography from '@material-ui/core/Typography'; | ||
import DeleteOutlineIcon from '@material-ui/icons/DeleteOutline'; | ||
import { useAuth } from '../../context/useAuthContext'; | ||
import { useSnackBar } from '../../context/useSnackbarContext'; | ||
import { useUser } from '../../context/useUserContext'; | ||
|
||
import useStyles from './useStyles'; | ||
import uploadImagesAPI from '../../helpers/APICalls/uploadImages'; | ||
|
||
interface UploadImagesState { | ||
background: string | File; | ||
profile: string | File; | ||
} | ||
|
||
const ProfilePhoto = (): JSX.Element => { | ||
const [imgSrc, setImgSrc] = useState<string>(''); | ||
const [uploadImages, setUploadImages] = useState<UploadImagesState>({ | ||
background: '', | ||
profile: '', | ||
}); | ||
const { userState, dispatchUserContext } = useUser(); | ||
const classes = useStyles(); | ||
const { loggedInUser } = useAuth(); | ||
|
||
const handleImageUpload = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
if (event.target.files?.length) { | ||
const src = URL.createObjectURL(event.target.files[0]); | ||
setImgSrc(src); | ||
const { updateSnackBarMessage } = useSnackBar(); | ||
const handleImageUpload = (event: ChangeEvent<HTMLInputElement>): void => { | ||
if (userState.background === '' && event.target.files?.length) { | ||
const background = URL.createObjectURL(event.target.files[0]); | ||
dispatchUserContext({ type: 'UPLOAD_BACKGROUND', background }); | ||
// eslint-disable-next-line | ||
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. what is currently the eslint issue here? 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.
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. This is resolved when I store |
||
setUploadImages((prevState) => ({ ...prevState, background: event.target.files![0] })); | ||
} else if (userState.profile === '' && event.target.files?.length) { | ||
const profile = URL.createObjectURL(event.target.files[0]); | ||
dispatchUserContext({ type: 'UPLOAD_PROFILE', profile }); | ||
// eslint-disable-next-line | ||
setUploadImages((prevState) => ({ ...prevState, profile: event.target.files![0] })); | ||
} | ||
}; | ||
|
||
const handleDeleteIcon = (): void => { | ||
dispatchUserContext({ type: 'EMPTY_IMAGES' }); | ||
setUploadImages({ | ||
background: '', | ||
profile: '', | ||
}); | ||
}; | ||
|
||
const handleImageUploads = (): void => { | ||
if (!uploadImages.background && !uploadImages.profile) return; | ||
const formData = new FormData(); | ||
formData.set('background', uploadImages.background); | ||
formData.set('profile', uploadImages.profile); | ||
uploadImagesAPI(formData).then((data): void => { | ||
console.log(data); | ||
if (data.error) { | ||
updateSnackBarMessage(data.error); | ||
} else if (data.success) { | ||
updateSnackBarMessage(data.success); | ||
} else { | ||
// should not get here from backend but this catch is for an unknown issue | ||
console.error({ data }); | ||
updateSnackBarMessage('An unexpected error occurred. Please try again'); | ||
} | ||
}); | ||
}; | ||
|
||
return ( | ||
<> | ||
<CardHeader title="Profile Photo" component="h1" className={classes.cardHeader} /> | ||
<Box className={classes.mediaContainer}> | ||
<CardMedia | ||
className={classes.backgroundMedia} | ||
component="img" | ||
src={ | ||
userState.background | ||
? userState.background | ||
: `https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRmFJpMlEV-41ZFT8U7iUsMJzaXVIL_hAtT9A&usqp=CAU` | ||
} | ||
title="Background Picture" | ||
alt="Your Background" | ||
/> | ||
<CardMedia | ||
className={classes.media} | ||
component="img" | ||
src={imgSrc ? imgSrc : `https://robohash.org/${loggedInUser?.email}.png`} | ||
src={userState.profile ? userState.profile : `https://robohash.org/${loggedInUser?.email}.png`} | ||
title="User Profile Picture" | ||
alt="Your Profile" | ||
/> | ||
<Typography color="textSecondary"> | ||
Be sure to use a photo that | ||
<Box component="span" display="block"> | ||
clearly shows your face | ||
</Box> | ||
</Typography> | ||
</Box> | ||
<Typography color="textSecondary" className={classes.profileMediaInfo}> | ||
Be sure to use a photo that | ||
<Box component="span" display="block"> | ||
clearly shows your face | ||
</Box> | ||
</Typography> | ||
<CardContent className={classes.cardContent}> | ||
<Button variant="outlined" component="label" color="primary" className={classes.upload}> | ||
Upload a file from your device | ||
<input type="file" hidden accept="image/*" onChange={handleImageUpload} /> | ||
</Button> | ||
<Button type="button" disableFocusRipple disableRipple> | ||
<Box> | ||
<Button variant="outlined" component="label" color="primary" className={classes.upload}> | ||
{userState.background === '' | ||
? `Select Your Background Image` | ||
: userState.profile === '' | ||
? `Select Your Profile Image` | ||
: `Both Files are uploaded.`} | ||
<input type="file" hidden accept="image/*" onChange={handleImageUpload} /> | ||
</Button> | ||
</Box> | ||
<Button type="button" disableFocusRipple disableRipple onClick={handleDeleteIcon}> | ||
<DeleteOutlineIcon /> | ||
<Typography color="textSecondary">Delete photo</Typography> | ||
<Typography color="textSecondary">Delete photos</Typography> | ||
</Button> | ||
<Box textAlign="center"> | ||
<Button | ||
type="submit" | ||
size="large" | ||
variant="contained" | ||
color="primary" | ||
className={classes.submit} | ||
onClick={handleImageUploads} | ||
> | ||
Save | ||
</Button> | ||
</Box> | ||
</CardContent> | ||
</> | ||
); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { useReducer, useContext, createContext, FunctionComponent } from 'react'; | ||
|
||
interface IUserContext { | ||
background: string; | ||
profile: string; | ||
} | ||
|
||
type Action = | ||
| { type: 'UPLOAD_PROFILE'; profile: string } | ||
| { type: 'UPLOAD_BACKGROUND'; background: string } | ||
| { type: 'EMPTY_IMAGES' }; | ||
|
||
const userReducer = (state: IUserContext, action: Action) => { | ||
switch (action.type) { | ||
case 'UPLOAD_PROFILE': | ||
return { ...state, profile: action.profile }; | ||
case 'UPLOAD_BACKGROUND': | ||
return { ...state, background: action.background }; | ||
case 'EMPTY_IMAGES': | ||
return { ...state, background: '', profile: '' }; | ||
default: | ||
throw new Error(); | ||
} | ||
}; | ||
|
||
export const UserContext = createContext({}); | ||
|
||
export const UserProvider: FunctionComponent = ({ children }): JSX.Element => { | ||
const [userState, dispatchUserContext] = useReducer(userReducer, { | ||
background: '', | ||
profile: '', | ||
}); | ||
return <UserContext.Provider value={{ userState, dispatchUserContext }}>{children}</UserContext.Provider>; | ||
}; | ||
|
||
export function useUser(): any { | ||
return useContext(UserContext); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { S3UploadAPIData } from '../../interface/S3Upload'; | ||
import { FetchOptions } from '../../interface/FetchOptions'; | ||
|
||
const uploadImagesAPI = async (data: FormData): Promise<S3UploadAPIData> => { | ||
const fetchOptions: FetchOptions = { | ||
method: 'POST', | ||
headers: { | ||
Accept: 'application/json', | ||
}, | ||
body: data, | ||
credentials: 'include', | ||
}; | ||
return await fetch(`/upload/uploadimage`, fetchOptions) | ||
.then((res) => res.json()) | ||
.catch(() => ({ | ||
error: { message: 'Unable to connect to server. Please try again' }, | ||
})); | ||
}; | ||
|
||
export default uploadImagesAPI; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
export interface FetchOptions { | ||
method: string; | ||
headers?: { | ||
'Content-Type': string; | ||
}; | ||
body?: string; | ||
credentials: RequestCredentials; | ||
method: string; | ||
headers?: { | ||
Accept?: string; | ||
"Content-Type"?: string; | ||
}; | ||
body?: string | FormData; | ||
credentials: RequestCredentials; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export interface S3UploadAPIData { | ||
error?: string; | ||
success?: string; | ||
locationURls: { locationUrl: string; key: string; }[]; | ||
} |
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.
maybe store
event.target.files
in a variable - you're accessing it multiple times in this blockThere 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.
Sure, will do that.