From df91fec966bc2c1bbd158e8bb93a3c23e4062914 Mon Sep 17 00:00:00 2001 From: Ellie Li Date: Sat, 20 Apr 2024 12:09:35 -0500 Subject: [PATCH] pr --- components/Settings/ChangePassword.tsx | 0 components/Settings/EditProfile.tsx | 0 components/Settings/EmailNotif.tsx | 0 pages/api/users/change-password.ts | 32 ++++++++ pages/api/users/update.ts | 26 ++++++ pages/settings.tsx | 105 ++++++++++++++++++++++--- styles/settings.styles.tsx | 100 +++++++++++++++++++++++ 7 files changed, 252 insertions(+), 11 deletions(-) create mode 100644 components/Settings/ChangePassword.tsx create mode 100644 components/Settings/EditProfile.tsx create mode 100644 components/Settings/EmailNotif.tsx create mode 100644 pages/api/users/change-password.ts create mode 100644 pages/api/users/update.ts create mode 100644 styles/settings.styles.tsx diff --git a/components/Settings/ChangePassword.tsx b/components/Settings/ChangePassword.tsx new file mode 100644 index 00000000..e69de29b diff --git a/components/Settings/EditProfile.tsx b/components/Settings/EditProfile.tsx new file mode 100644 index 00000000..e69de29b diff --git a/components/Settings/EmailNotif.tsx b/components/Settings/EmailNotif.tsx new file mode 100644 index 00000000..e69de29b diff --git a/pages/api/users/change-password.ts b/pages/api/users/change-password.ts new file mode 100644 index 00000000..fb56024c --- /dev/null +++ b/pages/api/users/change-password.ts @@ -0,0 +1,32 @@ +// /api/users/change-password.ts +import type { NextApiRequest, NextApiResponse } from 'next'; +import dbConnect from '@/lib/dbConnect'; +import Users from 'bookem-shared/src/models/Users'; +import { compare, hash } from 'bcrypt'; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method !== 'POST') { + return res.status(405).json({ message: 'Method Not Allowed' }); + } + + try { + const { oldPassword, newPassword } = JSON.parse(req.body); + await dbConnect(); + + const userId = 'the-authenticated-users-id'; // Replace with actual logic to retrieve user ID + const user = await Users.findById(userId); + + const passwordMatch = await compare(oldPassword, user.password); + if (!passwordMatch) { + return res.status(403).json({ message: 'Incorrect old password' }); + } + + const hashedNewPassword = await hash(newPassword, 12); + user.password = hashedNewPassword; + await user.save(); + + res.status(200).json({ message: 'Password changed successfully' }); + } catch (error) { + res.status(500).json({ message: 'An error occurred while changing the password.', error }); + } +} diff --git a/pages/api/users/update.ts b/pages/api/users/update.ts new file mode 100644 index 00000000..9f66929f --- /dev/null +++ b/pages/api/users/update.ts @@ -0,0 +1,26 @@ +// /api/users/update.ts +import type { NextApiRequest, NextApiResponse } from 'next'; +import dbConnect from '@/lib/dbConnect'; +import Users from 'bookem-shared/src/models/Users'; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method !== 'POST') { + return res.status(405).json({ message: 'Method Not Allowed' }); + } + + try { + const userUpdates = JSON.parse(req.body); + await dbConnect(); + + // Assuming you have a method to authenticate and get user ID + const userId = 'the-authenticated-users-id'; // Replace with actual logic to retrieve user ID + + const updateResult = await Users.findByIdAndUpdate(userId, userUpdates, { + new: true, + }); + + res.status(200).json({ message: 'User updated', user: updateResult }); + } catch (error) { + res.status(500).json({ message: 'An error occurred while updating the user.', error }); + } +} diff --git a/pages/settings.tsx b/pages/settings.tsx index 91caa012..382bd6d2 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -1,22 +1,105 @@ +import React, { useState } from 'react'; +import { useForm } from 'react-hook-form'; import { signOut, useSession } from 'next-auth/react'; -import React from 'react'; +import { getServerSideProps } from '@/lib/getServerSideProps'; +import { + SettingsContainer, + Form, + Button, + ErrorMsg, + Input, + Sidebar, + SidebarItem, // Make sure to remove this if you're importing ActiveSidebarItem separately + ContentArea, + SettingsH1, + SignOutButton, // Ensure this is imported +} from '@/styles/settings.styles'; const SettingsPage = () => { const { data: session } = useSession(); + // Added state to keep track of the active component + const [activeComponent, setActiveComponent] = useState('editProfile'); + + const profileForm = useForm(); + const passwordForm = useForm(); + const notificationsForm = useForm(); // Assuming you might have a form for this + + const handleProfileUpdate = async data => { + // Profile update logic... + }; + + const handlePasswordChange = async data => { + // Password change logic... + }; + + const handleNotificationsChange = async data => { + // Dummy function for email notifications changes + }; + + if (!session) { + return
You need to be signed in to view this page.
; + } + + const renderActiveComponent = () => { + switch (activeComponent) { + case 'editProfile': + return ( +
+ {/* Profile update fields */} + +
+ ); + case 'changePassword': + return ( +
+ {/* Password change fields */} + +
+ ); + case 'emailNotifications': + return ( +
+ {/* Email notifications settings fields */} + +
+ ); + default: + return
Select a setting to edit
; + } + }; return ( -
- {session && ( - <> -
You have signed in as {session.user?.email}
- - - )} -
+ + + setActiveComponent('editProfile')} + isActive={activeComponent === 'editProfile'}> + Edit Profile + + setActiveComponent('changePassword')} + isActive={activeComponent === 'changePassword'}> + Change Password + + setActiveComponent('emailNotifications')} + isActive={activeComponent === 'emailNotifications'}> + Email Notifications + + signOut()}>Sign out + + + + Settings + {renderActiveComponent()} + + ); }; export default SettingsPage; -// perform automatic redirection to login page if user not logged in. -export { getServerSideProps } from '@/lib/getServerSideProps'; +export { getServerSideProps }; diff --git a/styles/settings.styles.tsx b/styles/settings.styles.tsx new file mode 100644 index 00000000..f45ac44f --- /dev/null +++ b/styles/settings.styles.tsx @@ -0,0 +1,100 @@ +import styled, { css } from 'styled-components'; + +export const SettingsContainer = styled.div` + display: flex; + position: relative; + padding: 20px; + background: #fff; + border-radius: 8px; + max-width: 1200px; + margin: auto; +`; + +export const Button = styled.button` + padding: 10px 20px; + border: none; + background: #da4347; + color: white; + border-radius: 4px; + cursor: pointer; + margin-top: 10px; +`; + +export const SignOutButton = styled(Button)` + margin-top: 200px; +`; + +export const SettingsH1 = styled.h1` + position: absolute; + top: 10px; + left: 20px; + font-family: 'Inter', sans-serif; + font-size: 40px; + font-weight: 400; + line-height: 48px; + text-align: left; + color: #333; + margin-bottom: 20px; +`; + +export const Form = styled.form` + display: flex; + flex-direction: column; +`; + +export const Input = styled.input` + padding: 10px; + margin-bottom: 10px; + border: 1px solid #ccc; + border-radius: 4px; +`; + +export const ErrorMsg = styled.span` + color: red; + margin-bottom: 10px; +`; + +export const Sidebar = styled.div` + flex: 1; + border-right: 2px solid #ccc; + padding-right: 20px; + margin-top: 160px; +`; + +export const SidebarItem = styled.div<{ isActive?: boolean }>` + padding: 10px; + cursor: pointer; + border-radius: 10px; // Adjust this value to increase or decrease the roundness + &:hover { + background-color: #f0f0f0; + } + ${props => + props.isActive && + css` + background-color: darkgrey; + `} +`; + +export const ContentArea = styled.div` + flex: 3; + padding-left: 20px; +`; + +export const SectionTitle = styled.h2` + margin-top: 20px; + margin-bottom: 10px; + font-size: 24px; + color: #333; +`; + +export const ProfilePicture = styled.img` + width: 150px; + height: 150px; + border-radius: 75px; // Circular image + object-fit: cover; + margin-bottom: 20px; +`; + +export const ProfilePictureEdit = styled.input` + margin-bottom: 20px; +`;