diff --git a/src/api/Profile.ts b/src/api/Profile.ts index cc88bc691723631dbd114655fcf775ba90f5a494..4e5373f2097a73c98add7d9cb22caea7aa305399 100644 --- a/src/api/Profile.ts +++ b/src/api/Profile.ts @@ -13,3 +13,14 @@ export async function fetchUserDetail(username : string) { throw err; } } + +export async function putUserDetail(username : string, newUserDetail : UserInterface) { + try { + const API_URL = REST_URL + `/user/user-detail/${username}`; + const response = await axios.put<UserInterface>(API_URL, newUserDetail); + return response; + } catch(err) { + alert(err); + throw err; + } +} diff --git a/src/pages/Profile.tsx b/src/pages/Profile.tsx index 317dd300b55b44d16115ea99067f76708a7f8b7a..2e858efb6b37c677485ea1c67bd7301d86e9ec2d 100644 --- a/src/pages/Profile.tsx +++ b/src/pages/Profile.tsx @@ -4,25 +4,49 @@ import { Heading, Text, Stack, - Divider, - VStack, - HStack, useColorModeValue, Flex, Button, - useTab, + FormControl, + FormLabel, + Input, + FormErrorMessage, } from '@chakra-ui/react'; import React, { useEffect, useState } from 'react'; import UserInterface from '../interfaces/UserInterface'; -import { getUserDetail } from '../utils/Profile'; +import { changeUserDetail, getUserDetail } from '../utils/Profile'; import { getUser } from '../utils/LocalStorage'; +import { validateEmail } from '../utils/Login'; export default function Profile() { const username = getUser(); const [isEditing, setIsEditing] = useState(false); - const [userDetail, setUserDetail] = useState<UserInterface>(); + const [userDetail, setUserDetail] = useState<UserInterface>({username : "", + name : "", + email : "", + saldo : 0}); + const [currentEmail, setCurrentEmail] = useState(""); + const [emailValid, setEmailValid] = useState(true); + + function handleChange (event : React.ChangeEvent<HTMLInputElement>) { + const { name, value } = event.target; + setUserDetail((prevUserDetail) => ({ ...prevUserDetail, [name]: value })); + } + + function revalidateEmail() { + validateEmail(userDetail.email).then((available) => setEmailValid(available || (userDetail.email === currentEmail))); + } + + function handleSubmit(event : React.FormEvent<HTMLFormElement>) { + revalidateEmail(); + if(username && emailValid) { + changeUserDetail(username, userDetail); + } + setIsEditing(false); + event.preventDefault(); + } useEffect(() => { if(!username) { @@ -32,12 +56,13 @@ export default function Profile() { getUserDetail(username).then((res) => { console.log(res); setUserDetail(res.data); + setCurrentEmail(res.data.email); }); - }, [userDetail]); + }, [username]); return ( <Flex - h={'95vh'} + h={'110vh'} align={'center'} justify={'center'} bg={useColorModeValue('red.800', 'white')}> @@ -48,13 +73,66 @@ export default function Profile() { <Stack align={'center'}> {/* TODO : fetch real photo image */} <Avatar size="xl" name="John Doe" src="https://via.placeholder.com/150" /> + <Heading size="lg">{userDetail?.name}</Heading> {isEditing ? // TODO : edit photo logic - <Button>Edit Photo</Button> + <Button + bg={'blue.400'} + color={'white'} + _hover={{ + bg: 'blue.500', + }} + > + Edit Photo + </Button> : <></>} - <Heading size="lg">{userDetail?.name}</Heading> </Stack> + {isEditing ? + <Box + rounded={'lg'} + bg={useColorModeValue('white', 'gray.700')} + boxShadow={'lg'} + pl={8} + pr={8} + > + <form onSubmit={handleSubmit}> + <Stack spacing={4}> + <Text fontWeight="bold">Username:</Text> + <Text>{userDetail?.username}</Text> + <FormControl id="email" isRequired isInvalid={!emailValid} onBlur={revalidateEmail}> + <FormLabel>Email:</FormLabel> + <Input name="email" type="email" + value={userDetail.email} + onChange={handleChange} + borderColor={"black"} + /> + <FormErrorMessage>Email already used</FormErrorMessage> + </FormControl> + <FormControl id="name" isRequired> + <FormLabel>Name</FormLabel> + <Input name="name" type="text" + value={userDetail.name} + onChange={handleChange} + borderColor={"black"} + /> + </FormControl> + <Text fontWeight="bold">Saldo:</Text> + <Text>{userDetail?.saldo}</Text> + <Button + bg={'blue.400'} + color={'white'} + _hover={{ + bg: 'blue.500', + }} + type={"submit"} + > + Save Profile + </Button> + </Stack> + </form> + </Box> + : <Box rounded={'lg'} bg={useColorModeValue('white', 'gray.700')} @@ -62,6 +140,7 @@ export default function Profile() { pl={8} pr={8} > + <Stack spacing={4}> <Text fontWeight="bold">Username:</Text> <Text>{userDetail?.username}</Text> <Text fontWeight="bold">Email:</Text> @@ -70,11 +149,18 @@ export default function Profile() { <Text>{userDetail?.name}</Text> <Text fontWeight="bold">Saldo:</Text> <Text>{userDetail?.saldo}</Text> + <Button + bg={'blue.400'} + color={'white'} + _hover={{ + bg: 'blue.500', + }} + onClick={() => setIsEditing(true)}> + Edit Profile + </Button> + </Stack> </Box> - {isEditing ? - <Button></Button> - : - <Button></Button>} + } </Stack> </Flex> ); diff --git a/src/utils/Profile.ts b/src/utils/Profile.ts index ff2f169724e2c61fe65ca3767ef79a758632ff38..94949046441b022b1c5d33a86df765fb8f7c090f 100644 --- a/src/utils/Profile.ts +++ b/src/utils/Profile.ts @@ -1,8 +1,14 @@ import { fetchBalance, withdraw } from "../api/Balance"; -import { fetchUserDetail } from "../api/Profile"; +import { fetchUserDetail, putUserDetail } from "../api/Profile"; +import UserInterface from "../interfaces/UserInterface"; export async function getUserDetail(username : string) { const userDetail = await fetchUserDetail(username); return userDetail; } + +export async function changeUserDetail(username : string, newUserDetail : UserInterface) { + const responseString = await putUserDetail(username, newUserDetail); + return responseString; +}