Profile & property listings
This commit is contained in:
+10
-35
@@ -231,39 +231,12 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="text-2xl mb-4"><span class="font-bold block">Name: </span> John Doe</h2>
|
<h2 class="text-2xl mb-4">
|
||||||
<h2 class="text-2xl"><span class="font-bold block">Email: </span> john@gmail.com</h2>
|
<span class="font-bold block">Name: </span> John Doe
|
||||||
|
</h2>
|
||||||
<!-- <form class="mb-10">
|
<h2 class="text-2xl">
|
||||||
<div class="text-lg font-semibold">
|
<span class="font-bold block">Email: </span> john@gmail.com
|
||||||
<p class="mb-5">
|
</h2>
|
||||||
<label class="block mb-2" for="name">Name:</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="name"
|
|
||||||
name="name"
|
|
||||||
value="John Doe"
|
|
||||||
class="border rounded-md px-2 py-1"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p class="mb-5">
|
|
||||||
<label class="block mb-2" for="email">Email:</label>
|
|
||||||
<input
|
|
||||||
type="email"
|
|
||||||
id="email"
|
|
||||||
name="email"
|
|
||||||
value="johndoe@example.com"
|
|
||||||
class="border rounded-md px-2 py-1"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
class="bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600"
|
|
||||||
>
|
|
||||||
Update
|
|
||||||
</button>
|
|
||||||
</div> -->
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md:w-3/4 md:pl-4">
|
<div class="md:w-3/4 md:pl-4">
|
||||||
@@ -281,7 +254,8 @@
|
|||||||
<p class="text-gray-600">Address: 123 Main St</p>
|
<p class="text-gray-600">Address: 123 Main St</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<a href="/add-property.html"
|
<a
|
||||||
|
href="/add-property.html"
|
||||||
class="bg-blue-500 text-white px-3 py-3 rounded-md mr-2 hover:bg-blue-600"
|
class="bg-blue-500 text-white px-3 py-3 rounded-md mr-2 hover:bg-blue-600"
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
@@ -307,7 +281,8 @@
|
|||||||
<p class="text-gray-600">Address: 456 Elm St</p>
|
<p class="text-gray-600">Address: 456 Elm St</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<a href="/add-property.html"
|
<a
|
||||||
|
href="/add-property.html"
|
||||||
class="bg-blue-500 text-white px-3 py-3 rounded-md mr-2 hover:bg-blue-600"
|
class="bg-blue-500 text-white px-3 py-3 rounded-md mr-2 hover:bg-blue-600"
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import Image from 'next/image';
|
||||||
|
import connectDB from '@/config/database';
|
||||||
|
import Property from '@/models/Property';
|
||||||
|
import { getSessionUser } from '@/utils/getSessionUser';
|
||||||
|
import profileDefault from '@/assets/images/profile.png';
|
||||||
|
import ProfileProperties from '@/components/ProfileProperties';
|
||||||
|
import { convertToSerializeableObject } from '@/utils/convertToObject';
|
||||||
|
|
||||||
|
const ProfilePage = async () => {
|
||||||
|
await connectDB();
|
||||||
|
|
||||||
|
const sessionUser = await getSessionUser();
|
||||||
|
|
||||||
|
const { userId } = sessionUser;
|
||||||
|
|
||||||
|
if (!userId) {
|
||||||
|
throw new Error('User ID is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
const propertiesDocs = await Property.find({ owner: userId }).lean();
|
||||||
|
const properties = propertiesDocs.map(convertToSerializeableObject);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className='bg-blue-50'>
|
||||||
|
<div className='container m-auto py-24'>
|
||||||
|
<div className='bg-white px-6 py-8 mb-4 shadow-md rounded-md border m-4 md:m-0'>
|
||||||
|
<h1 className='text-3xl font-bold mb-4'>Your Profile</h1>
|
||||||
|
<div className='flex flex-col md:flex-row'>
|
||||||
|
<div className='md:w-1/4 mx-20 mt-10'>
|
||||||
|
<div className='mb-4'>
|
||||||
|
<Image
|
||||||
|
className='h-32 w-32 md:h-48 md:w-48 rounded-full mx-auto md:mx-0'
|
||||||
|
src={sessionUser.user.image || profileDefault}
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
alt='User'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className='text-2xl mb-4'>
|
||||||
|
<span className='font-bold block'>Name: </span>{' '}
|
||||||
|
{sessionUser.user.name}
|
||||||
|
</h2>
|
||||||
|
<h2 className='text-2xl'>
|
||||||
|
<span className='font-bold block'>Email: </span>{' '}
|
||||||
|
{sessionUser.user.email}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='md:w-3/4 md:pl-4'>
|
||||||
|
<h2 className='text-xl font-semibold mb-4'>Your Listings</h2>
|
||||||
|
{properties.length === 0 ? (
|
||||||
|
<p>You have no property listings</p>
|
||||||
|
) : (
|
||||||
|
<ProfileProperties properties={properties} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProfilePage;
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
'use client';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
const ProfileProperties = ({ properties: initialProperties }) => {
|
||||||
|
const [properties, setProperties] = useState(initialProperties);
|
||||||
|
return properties.map((property) => (
|
||||||
|
<div key={property._id} className='mb-10'>
|
||||||
|
<Link href={`/properties/${property._id}`}>
|
||||||
|
<Image
|
||||||
|
className='h-32 w-full rounded-md object-cover'
|
||||||
|
src={property.images[0]}
|
||||||
|
alt=''
|
||||||
|
width={500}
|
||||||
|
height={100}
|
||||||
|
priority={true}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
<div className='mt-2'>
|
||||||
|
<p className='text-lg font-semibold'>{property.name}</p>
|
||||||
|
<p className='text-gray-600'>
|
||||||
|
Address: {property.location.street} {property.location.city}{' '}
|
||||||
|
{property.location.state}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className='mt-2'>
|
||||||
|
<Link
|
||||||
|
href={`/properties/${property._id}/edit`}
|
||||||
|
className='bg-blue-500 text-white px-3 py-3 rounded-md mr-2 hover:bg-blue-600'
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Link>
|
||||||
|
<button
|
||||||
|
className='bg-red-500 text-white px-3 py-2 rounded-md hover:bg-red-600'
|
||||||
|
type='button'
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProfileProperties;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Converts a Mongoose lean document into a serializable plain JavaScript object.
|
||||||
|
*
|
||||||
|
* @param {Object} leanDocument - The Mongoose lean document to be converted.
|
||||||
|
* @returns {Object} A plain JavaScript object that is a serializable representation of the input document.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function convertToSerializeableObject(leanDocument) {
|
||||||
|
for (const key of Object.keys(leanDocument)) {
|
||||||
|
if (leanDocument[key].toJSON && leanDocument[key].toString)
|
||||||
|
leanDocument[key] = leanDocument[key].toString();
|
||||||
|
}
|
||||||
|
return leanDocument;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user