Property contact form

This commit is contained in:
Brad Traversy
2024-07-14 08:08:35 -04:00
parent 95d2246e1a
commit f0f478dd64
3 changed files with 201 additions and 71 deletions
+39
View File
@@ -0,0 +1,39 @@
'use server';
import connectDB from '@/config/database';
import Message from '@/models/Message';
import { getSessionUser } from '@/utils/getSessionUser';
import { revalidatePath } from 'next/cache';
async function addMessage(previousState, formData) {
await connectDB();
const sessionUser = await getSessionUser();
if (!sessionUser || !sessionUser.user) {
return { error: 'You must be logged in to send a message' };
}
const { user } = sessionUser;
const recipient = formData.get('recipient');
if (user.id === recipient) {
return { error: 'You can not send a message to yourself' };
}
const newMessage = new Message({
sender: user.id,
recipient,
property: formData.get('property'),
name: formData.get('name'),
email: formData.get('email'),
phone: formData.get('phone'),
body: formData.get('message'),
});
await newMessage.save();
return { submitted: true };
}
export default addMessage;
+116 -71
View File
@@ -1,81 +1,126 @@
'use client';
import { useEffect } from 'react';
import { useFormState, useFormStatus } from 'react-dom';
import { useSession } from 'next-auth/react';
import { toast } from 'react-toastify';
import addMessage from '@/app/actions/addMessage';
import { FaPaperPlane } from 'react-icons/fa'; import { FaPaperPlane } from 'react-icons/fa';
const PropertyContactForm = ({ property }) => { const SubmitMessageButton = () => {
const status = useFormStatus();
return ( return (
<div className='bg-white p-6 rounded-lg shadow-md'> <button
<h3 className='text-xl font-bold mb-6'>Contact Property Manager</h3> className='bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-full w-full focus:outline-none focus:shadow-outline flex items-center justify-center'
<form> type='submit'
<div className='mb-4'> >
<label <FaPaperPlane className='mr-2' />{' '}
className='block text-gray-700 text-sm font-bold mb-2' {status.pending ? 'Sending...' : 'Send Message'}
htmlFor='name' </button>
> );
Name: };
</label>
const PropertyContactForm = ({ property }) => {
const { data: session } = useSession();
const [state, formAction] = useFormState(addMessage, {});
useEffect(() => {
if (state.error) toast.error(state.error);
if (state.submitted) toast.success('Message sent successfully');
}, [state]);
if (state.submitted) {
return (
<p className='text-green-500 mb-4'>
Your message has been sent successfully
</p>
);
}
return (
session && (
<div className='bg-white p-6 rounded-lg shadow-md'>
<h3 className='text-xl font-bold mb-6'>Contact Property Manager</h3>
<form action={formAction}>
<input <input
className='shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline' type='hidden'
id='name' id='property'
name='name' name='property'
type='text' defaultValue={property._id}
placeholder='Enter your name'
required
/> />
</div>
<div className='mb-4'>
<label
className='block text-gray-700 text-sm font-bold mb-2'
htmlFor='email'
>
Email:
</label>
<input <input
className='shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline' type='hidden'
id='email' id='recipient'
name='email' name='recipient'
type='email' defaultValue={property.owner}
placeholder='Enter your email'
required
/> />
</div> <div className='mb-4'>
<div className='mb-4'> <label
<label className='block text-gray-700 text-sm font-bold mb-2'
className='block text-gray-700 text-sm font-bold mb-2' htmlFor='name'
htmlFor='phone' >
> Name:
Phone: </label>
</label> <input
<input className='shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'
className='shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline' id='name'
id='phone' name='name'
name='phone' type='text'
type='text' placeholder='Enter your name'
placeholder='Enter your phone number' required
/> />
</div> </div>
<div className='mb-4'> <div className='mb-4'>
<label <label
className='block text-gray-700 text-sm font-bold mb-2' className='block text-gray-700 text-sm font-bold mb-2'
htmlFor='message' htmlFor='email'
> >
Message: Email:
</label> </label>
<textarea <input
className='shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 h-44 focus:outline-none focus:shadow-outline' className='shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'
id='message' id='email'
name='message' name='email'
placeholder='Enter your message' type='email'
></textarea> placeholder='Enter your email'
</div> required
<div> />
<button </div>
className='bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-full w-full focus:outline-none focus:shadow-outline flex items-center justify-center' <div className='mb-4'>
type='submit' <label
> className='block text-gray-700 text-sm font-bold mb-2'
<FaPaperPlane className='mr-2' /> Send Message htmlFor='phone'
</button> >
</div> Phone:
</form> </label>
</div> <input
className='shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'
id='phone'
name='phone'
type='text'
placeholder='Enter your phone number'
/>
</div>
<div className='mb-4'>
<label
className='block text-gray-700 text-sm font-bold mb-2'
htmlFor='message'
>
Message:
</label>
<textarea
className='shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 h-44 focus:outline-none focus:shadow-outline'
id='message'
name='message'
placeholder='Enter your message'
></textarea>
</div>
<div>
<SubmitMessageButton />
</div>
</form>
</div>
)
); );
}; };
export default PropertyContactForm; export default PropertyContactForm;
+46
View File
@@ -0,0 +1,46 @@
import { Schema, model, models } from 'mongoose';
const MessageSchema = new Schema(
{
sender: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
recipient: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
property: {
type: Schema.Types.ObjectId,
ref: 'Property',
required: true,
},
name: {
type: String,
required: [true, 'Name is required'],
},
email: {
type: String,
required: [true, 'Email is required'],
},
phone: {
type: String,
},
body: {
type: String,
},
read: {
type: Boolean,
default: false,
},
},
{
timestamps: true,
}
);
const Message = models.Message || model('Message', MessageSchema);
export default Message;