Skip to content
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

Profilepage #61

Merged
merged 12 commits into from
Apr 9, 2023
47 changes: 47 additions & 0 deletions src/components/profile/ChangePasswordForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from "react";
import { Button, Container, Typography } from "@mui/material";
import { useForm, FormProvider } from "react-hook-form";
import { FormField } from "@/components/shared/FormField";

export interface ChangePasswordFormData {
oldPassword: string;
newPassword: string;
confirmNewPassword: string;
}

interface ChangePasswordFormProps {
onSubmit: (data: ChangePasswordFormData) => void;
}

const ChangePasswordForm: React.FC<ChangePasswordFormProps> = ({ onSubmit }) => {
const methods = useForm<ChangePasswordFormData>();

return (
<Container maxWidth="sm">
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}>
<Typography variant="h6" sx={{ marginBottom: 1 }}>
Change Password
</Typography>
<FormField name="oldPassword" label="Old Password" type="password" />
<FormField name="newPassword" label="New Password" type="password" />
<FormField
name="confirmNewPassword"
label="Confirm New Password"
type="password"
/>
<Button
variant="contained"
color="warning"
type="submit"
sx={{ display: "block", margin: "0 auto", marginTop: 5 }}
>
Change
</Button>
</form>
</FormProvider>
</Container>
);
};

export default ChangePasswordForm;
46 changes: 46 additions & 0 deletions src/components/profile/EditableText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { useState } from "react";
import { Box, IconButton, InputBase, Typography } from "@mui/material";
import { Edit, Check } from "@mui/icons-material";

interface EditableTextProps {
label: string;
onSubmit: (value: string) => void;
placeholder: string;
}

const EditableText: React.FC<EditableTextProps> = ({
label,

onSubmit,
placeholder,
}) => {
const [value, setValue] = useState("");
const [isEditable, setIsEditable] = useState(false);

const handleIconClick = () => {
if (isEditable) {
onSubmit(value);
}
setIsEditable(!isEditable);
};

return (
<Box sx={{ display: "flex", alignItems: "center", color: "#FFFFFF" }}>
<Typography sx={{ marginRight: 1 }}>{label}:</Typography>
<InputBase
value={value}
onChange={(e) => setValue(e.target.value)}
readOnly={!isEditable}
multiline
placeholder={placeholder}
inputProps={{ style: { borderBottom: isEditable ? "2px solid blue" : "1px solid #F3FB8C" } }}
sx= { {color: isEditable ? "blue" : "#FFFFFF" } }
/>
<IconButton size="small" onClick={handleIconClick}>
{isEditable ? <Check /> : <Edit />}
</IconButton>
</Box>
);
};

export default EditableText;
78 changes: 78 additions & 0 deletions src/components/profile/ProfileInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React, { useState } from "react";
import { Box, TextField, Typography } from "@mui/material";
import { PersonOutline, PhoneIphone, EmailOutlined } from "@mui/icons-material";
import EditableText from "./EditableText";
import { FormField } from "../shared/FormField";

interface ProfileInfoProps {
name: string;
bio: string;
setBio: (bio: string) => void;
phoneNumber: string;
setPhoneNumber: (phoneNumber: string) => void;
email: string;
setEmail: (email: string) => void;
}

const ProfileInfo: React.FC<ProfileInfoProps> = ({
name,
bio,
setBio,
phoneNumber,
setPhoneNumber,
email,
setEmail,
}) => {
return (
<div>
<Typography variant="h2">{name}</Typography>
<TextField
name="bio"
label="Bio"
value={bio}
onChange={(e) => setBio(e.target.value)}
multiline
rows={4}
variant="outlined"
sx={{
color: "#fffff",
margin: 2,
width: "100%",
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "transparent",
},
"&:hover .MuiOutlinedInput-notchedOutline": {
borderColor: "transparent",
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderColor: "transparent",
},
}}
/>
<Box sx={{ display: "flex", alignItems: "center" , marginBottom: "2", justifyContent: "space-between"}}>
<PhoneIphone sx={{ margin: 3 }} />
<EditableText
label="Phone"
onSubmit={(value) => setPhoneNumber(value)}
placeholder="Enter your phone number..."
/>
</Box>

<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between"}}>
<EmailOutlined sx={{ margin: 3 , "&:hover .icon": {
visibility: "visible",
opacity: 1,
}}} />
<EditableText
label="Email"
onSubmit={(value) => setEmail(value)}
placeholder="Enter your email..."
/>
</Box>


</div>
);
};

export default ProfileInfo;
26 changes: 26 additions & 0 deletions src/components/profile/SideMenuButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";
import { Button } from "@mui/material";
import EditIcon from "@mui/icons-material/Edit";
import LockIcon from "@mui/icons-material/Lock";


interface SideMenuButtonProps {
showForm: boolean;
onClick: () => void;
}

const SideMenuButton: React.FC<SideMenuButtonProps> = ({ showForm, onClick }) => {
return (
<Button
variant="contained"
color="warning"
onClick={onClick}
endIcon={showForm ? <LockIcon /> : <EditIcon />}
>
{showForm ? "Profile" : "Lock"}
</Button>

);
};

export default SideMenuButton;
12 changes: 12 additions & 0 deletions src/components/profile/avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";
import { Avatar } from "@mui/material";

interface ProfileAvatarProps {
src: string;
}

const ProfileAvatar: React.FC<ProfileAvatarProps> = ({ src }) => {
return <Avatar alt="Profile Picture" src={src} sx={{ width: 180, height: 180 }} />;
};

export default ProfileAvatar;
31 changes: 31 additions & 0 deletions src/components/profile/customButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react";
import { Button } from "@mui/material";
import { Lock, Add } from "@mui/icons-material";

interface SideMenuButtonProps {
onClick: () => void;
showForm: boolean;
}

const SideMenuButton: React.FC<SideMenuButtonProps> = ({ onClick, showForm }) => {
return (
<Button
variant="contained"
color="primary"
onClick={onClick}
sx={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
height: "100%",
width: "100%",
}}
>
{showForm ? <Add /> : <Lock />}
{showForm ? "Profile" : "Change Password"}
</Button>
);
};

export default SideMenuButton;
25 changes: 25 additions & 0 deletions src/components/profile/mainContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react";
import { Card, CardContent } from "@mui/material";

interface MainContentProps {
children: React.ReactNode;
}

const MainContent: React.FC<MainContentProps> = ({ children }) => {
return (
<Card
sx={{
height:'80vh',
backgroundColor: '#19053B',
color: '#ffffff',
border: 1,
marginLeft: 2,
marginTop: 2,
}}
>
<CardContent>{children}</CardContent>
</Card>
);
};

export default MainContent;
9 changes: 9 additions & 0 deletions src/components/shared/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {deleteUserData, selectUserData} from "@/store/slices/userSlice";
import {useAppDispatch} from "@/hooks/useAppHooks";
import {destroyCookie} from "nookies";
import {useRouter} from "next/router";
import { Box, Avatar, Typography } from '@mui/material';

const Header = () => {
const userData = useSelector(selectUserData);
Expand Down Expand Up @@ -36,6 +37,14 @@ const Header = () => {
<li>
<Link onClick={logout} href={'/'}>{userData.fullName} Logout</Link>
</li>
<li>
<Link href={'/profile'}>
<Box sx={{display: 'flex', flexDirection: 'row', alignItems:'center' }}>
<Avatar />
<Typography style={{paddingLeft:"5px" }}>Helen</Typography>
</Box>
</Link>
</li>
</ul>
) : (
<ul>
Expand Down
85 changes: 85 additions & 0 deletions src/pages/profile/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React, { useState } from "react";
import { Box, Grid, colors } from "@mui/material";
import MainLayout from "@/layouts/MainLayout";
import { NextPage } from "next";
import ProfileAvatar from "@/components/profile/avatar";
import ProfileInfo from "@/components/profile/ProfileInfo";
import ChangePasswordForm , { ChangePasswordFormData} from "@/components/profile/ChangePasswordForm";
import SideMenuButton from "@/components/profile/SideMenuButton";
import MainContent from "@/components/profile/mainContent";

const Profile: NextPage = () => {
const [showChangePasswordForm, setShowChangePasswordForm] = useState(false);
const handleButtonClick = () => {
setShowChangePasswordForm(!showChangePasswordForm);
};

const onSubmit = (data: ChangePasswordFormData) => {
console.log(data);
};

const [bio, setBio] = useState("Software Developer");
const [phoneNumber, setPhoneNumber] = useState("123-456-7890");
const [email, setEmail] = useState("[email protected]");

return (
<MainLayout>
<Box sx={{ bgcolor: '#120428' }}>

<Grid container>
<Grid item xs={1}>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "100vh",
}}
>
<SideMenuButton
showForm={showChangePasswordForm}
onClick={handleButtonClick}
/>
</Box>
</Grid>
<Grid item xs={11}>
<MainContent>
{!showChangePasswordForm && (
<>
<Box
sx={{
display: "flex",
alignItems: "center",
alignContent: "center",
justifyContent: "space-evenly",
flexDirection: "row",
marginTop: 5,
}}
>
<ProfileAvatar src={""} />
<ProfileInfo
name="John Doe"
bio={bio}
setBio={setBio}
phoneNumber={phoneNumber}
setPhoneNumber={setPhoneNumber}
email={email}
setEmail={setEmail}
/>
</Box>
</>
)}
{showChangePasswordForm && (
<ChangePasswordForm
onSubmit={onSubmit}
/>
)}
</MainContent>
</Grid>
</Grid>
</Box>
</MainLayout>
);
};

export default Profile;