Skip to content
Open

pr #90

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
Empty file.
Empty file.
32 changes: 32 additions & 0 deletions pages/api/users/change-password.ts
Original file line number Diff line number Diff line change
@@ -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 });
}
}
26 changes: 26 additions & 0 deletions pages/api/users/update.ts
Original file line number Diff line number Diff line change
@@ -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 });
}
}
105 changes: 94 additions & 11 deletions pages/settings.tsx
Original file line number Diff line number Diff line change
@@ -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 <div>You need to be signed in to view this page.</div>;
}

const renderActiveComponent = () => {
switch (activeComponent) {
case 'editProfile':
return (
<Form onSubmit={profileForm.handleSubmit(handleProfileUpdate)}>
{/* Profile update fields */}
<Button type="submit">Update Profile</Button>
</Form>
);
case 'changePassword':
return (
<Form onSubmit={passwordForm.handleSubmit(handlePasswordChange)}>
{/* Password change fields */}
<Button type="submit">Change Password</Button>
</Form>
);
case 'emailNotifications':
return (
<Form
onSubmit={notificationsForm.handleSubmit(
handleNotificationsChange
)}>
{/* Email notifications settings fields */}
<Button type="submit">Save Preferences</Button>
</Form>
);
default:
return <div>Select a setting to edit</div>;
}
};

return (
<div>
{session && (
<>
<div>You have signed in as {session.user?.email}</div>
<button onClick={() => signOut()}>Sign out</button>
</>
)}
</div>
<SettingsContainer>
<Sidebar>
<SidebarItem
onClick={() => setActiveComponent('editProfile')}
isActive={activeComponent === 'editProfile'}>
Edit Profile
</SidebarItem>
<SidebarItem
onClick={() => setActiveComponent('changePassword')}
isActive={activeComponent === 'changePassword'}>
Change Password
</SidebarItem>
<SidebarItem
onClick={() => setActiveComponent('emailNotifications')}
isActive={activeComponent === 'emailNotifications'}>
Email Notifications
</SidebarItem>
<SignOutButton onClick={() => signOut()}>Sign out</SignOutButton>
</Sidebar>

<ContentArea>
<SettingsH1>Settings</SettingsH1>
{renderActiveComponent()}
</ContentArea>
</SettingsContainer>
);
};

export default SettingsPage;

// perform automatic redirection to login page if user not logged in.
export { getServerSideProps } from '@/lib/getServerSideProps';
export { getServerSideProps };
100 changes: 100 additions & 0 deletions styles/settings.styles.tsx
Original file line number Diff line number Diff line change
@@ -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;
`;