Skip to content

Commit

Permalink
nsc-events-nextjs_9_493_change-user-details (#497)
Browse files Browse the repository at this point in the history
* Separate first name and last name fields

* Add edit user details dialog

* Added functionality

* Small changes to UI
  • Loading branch information
intisarosman1 authored Jul 4, 2024
1 parent f1cf5cf commit d46407c
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 8 deletions.
26 changes: 20 additions & 6 deletions app/profile/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ import { Box, Button, Stack, Typography } from "@mui/material";
import React, { useEffect, useState } from "react";
import CurrentUserCard from "@/components/CurrentUserCard";
import { useRouter } from "next/navigation";
import EditUserDetailsDialog, { User } from "@/components/EditUserDetailsDialog";

interface User {
firstName: string;
lastName: string;
email: string;
pronouns: string
}
const URL = process.env.NSC_EVENTS_PUBLIC_API_URL || "http://localhost:3000/api";

const Profile = () => {
const [user, setUser] = useState<User>();
const [token, setToken] = useState<string | null>();
const [openEditDialog, setOpenEditDialog] = useState(false);
const router = useRouter();
const getUserFromId = async (userId: string) => {
const response = await fetch(`${URL}/users/find/${userId}`);
Expand All @@ -29,6 +26,18 @@ const Profile = () => {
const userId = getCurrentUserId();
getUserFromId(userId);
},[]);

const handleEditClick = () => {
setOpenEditDialog(true);
};

const handleCloseEditDialog = (updatedUser?: User) => {
setOpenEditDialog(false);
if (updatedUser) {
setUser(updatedUser);
}
};

if (token === null) {
return (
<Box sx={{ display: "flex", justifyContent: "center" }}>
Expand All @@ -45,16 +54,21 @@ const Profile = () => {
</Typography>
)
}

return (
<Box sx={{ display: "flex", justifyContent: "center" }}>
<Stack>
<Typography component="h1" variant="h4" sx={{ mt: 2, mb: 3 }}>
Welcome, { user?.firstName }
</Typography>
<CurrentUserCard user={user}/>
<Button onClick={handleEditClick} sx={{ mt: 2 }}>Edit Profile</Button>
<Button onClick={ () => router.replace('/auth/change-password') }>
Change Password
</Button>
{openEditDialog && (
<EditUserDetailsDialog open={openEditDialog} onClose={handleCloseEditDialog} user={user} />
)}
</Stack>
</Box>
);
Expand Down
7 changes: 5 additions & 2 deletions components/CurrentUserCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function CurrentUserCard({ user }: { user: CurrentUserCardProps }) {
return (
<Box
sx={{
border: '1px solid black',
border: '1px solid #ccc',
borderRadius: 1,
padding: 2,
display: 'flex',
Expand All @@ -28,7 +28,10 @@ function CurrentUserCard({ user }: { user: CurrentUserCardProps }) {
spacing={1}
>
<Typography variant="body1" gutterBottom>
Full Name: { user.firstName } { user.lastName }
First Name: { user.firstName }
</Typography>
<Typography variant="body1" gutterBottom>
Last Name: { user.lastName }
</Typography>
<Typography variant="body1" gutterBottom>
Email: { user.email }
Expand Down
116 changes: 116 additions & 0 deletions components/EditUserDetailsDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React, { useState, useEffect } from "react";
import { Dialog, DialogTitle, DialogContent, DialogActions, Button, TextField, Box } from "@mui/material";
import Snackbar from '@mui/material/Snackbar';
import Alert, { AlertColor } from '@mui/material/Alert';

interface EditUserDetailsDialogProps {
open: boolean;
onClose: (updatedUser?: User) => void;
user: User;
}

export interface User {
id: string;
firstName: string;
lastName: string;
email: string;
pronouns: string;
}

const EditUserDetailsDialog: React.FC<EditUserDetailsDialogProps> = ({ open, onClose, user }) => {
const [firstName, setFirstName] = useState(user.firstName);
const [lastName, setLastName] = useState(user.lastName);
const [pronouns, setPronouns] = useState(user.pronouns);
const [isUpdated, setIsUpdated] = useState(false);
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [snackbarMessage, setSnackbarMessage] = useState('');
const [snackbarSeverity, setSnackbarSeverity] = useState<AlertColor>('success');

useEffect(() => {
setFirstName(user.firstName);
setLastName(user.lastName);
setPronouns(user.pronouns);
setIsUpdated(false);
}, [user]);

const handleInputChange = (setter: React.Dispatch<React.SetStateAction<string>>, value: string, initialValue: string) => {
setter(value);
if (value !== initialValue) {
setIsUpdated(true);
} else {
setIsUpdated(false);
}
};

const handleSave = async () => {
const token = localStorage.getItem('token');
try {
const apiUrl = process.env.NSC_EVENTS_PUBLIC_API_URL || `http://localhost:3000/api`;
const response = await fetch(`${apiUrl}/users/update/${user.id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({ firstName, lastName, pronouns })
});
console.log(response.body)
if (response.ok) {
const updatedUser = await response.json();
setTimeout(() => onClose(updatedUser), 1000);
setSnackbarSeverity('success');
setSnackbarMessage('Profile updated successfully!');
setSnackbarOpen(true);
} else {
console.error('Failed to update profile:', response.statusText);
setSnackbarSeverity('error');
setSnackbarMessage('Failed to update profile');
setSnackbarOpen(true);
}
} catch (error) {
console.error('Error updating profile:', error);
setSnackbarSeverity('error');
setSnackbarMessage('Error updating profile');
}
setSnackbarOpen(true);
};

return (
<>
<Dialog open={open} onClose={() => onClose()}>
<DialogTitle>Edit Profile</DialogTitle>
<DialogContent>
<Box display="flex" flexDirection="column" gap={2} mt={2}>
<TextField
label="First Name"
value={firstName}
onChange={(e) => handleInputChange(setFirstName, e.target.value, user.firstName)}
/>
<TextField
label="Last Name"
value={lastName}
onChange={(e) => handleInputChange(setLastName, e.target.value, user.lastName)}
/>
<TextField
label="Pronouns"
value={pronouns}
onChange={(e) => handleInputChange(setPronouns, e.target.value, user.pronouns)}
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={() => onClose()}>Cancel</Button>
<Button onClick={handleSave} disabled={!isUpdated}>Save</Button>
</DialogActions>
</Dialog>
<Snackbar open={snackbarOpen} autoHideDuration={6000} onClose={() => setSnackbarOpen(false)}
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}>
<Alert onClose={() => setSnackbarOpen(false)} severity={snackbarSeverity} sx={{ width: '100%' }}>
{snackbarMessage}
</Alert>
</Snackbar>
</>
);
};

export default EditUserDetailsDialog;

0 comments on commit d46407c

Please sign in to comment.