contact form working
This commit is contained in:
parent
609475271e
commit
847ed031db
@ -17,3 +17,4 @@ SMTP_USER=mailer@imk.mk
|
||||
SMTP_PASSWORD=76Avtostoperski76
|
||||
SMTP_FROM=mailer@imk.mk
|
||||
FRONTEND_URL=https://imk.mk
|
||||
ADMIN_EMAIL=petrovskidimitar@yandex.com
|
||||
@ -49,7 +49,7 @@ export class AdminService {
|
||||
data: {
|
||||
...createUserDto,
|
||||
password: hashedPassword,
|
||||
isAdmin: true,
|
||||
isAdmin: createUserDto.isAdmin,
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -97,6 +97,7 @@ export class AdminService {
|
||||
document.title,
|
||||
document.uploadedBy.name,
|
||||
);
|
||||
console.log('Document shared with user:', sharedWithUser.email);
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
import { Controller, Post, Body } from '@nestjs/common';
|
||||
import { EmailService } from './email.service';
|
||||
import { MailerService } from '@nestjs-modules/mailer';
|
||||
// import { MailerService } from '@nestjs-modules/mailer';
|
||||
class ContactFormDto {
|
||||
name: string;
|
||||
email: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
@Controller('contact')
|
||||
@Controller('email')
|
||||
export class EmailController {
|
||||
constructor(private emailService: MailerService) {}
|
||||
constructor(private emailService: EmailService) {}
|
||||
|
||||
@Post()
|
||||
async sendContactEmail(@Body() contactData: {
|
||||
@ -12,17 +17,20 @@ export class EmailController {
|
||||
email: string;
|
||||
message: string;
|
||||
}) {
|
||||
await this.emailService.sendMail({
|
||||
to: process.env.CONTACT_EMAIL,
|
||||
subject: `Contact Form: ${contactData.name}`,
|
||||
html: `
|
||||
<h1>New Contact Form Submission</h1>
|
||||
<p><strong>From:</strong> ${contactData.name}</p>
|
||||
<p><strong>Email:</strong> ${contactData.email}</p>
|
||||
<p><strong>Message:</strong></p>
|
||||
<p>${contactData.message}</p>
|
||||
`,
|
||||
});
|
||||
await this.emailService.sendContactEmail(
|
||||
contactData.name,
|
||||
contactData.email,
|
||||
contactData.message
|
||||
);
|
||||
return { message: 'Contact form submitted successfully' };
|
||||
}
|
||||
@Post('contact')
|
||||
async handleContactForm(@Body() contactData: ContactFormDto) {
|
||||
await this.emailService.sendContactEmail(
|
||||
contactData.name,
|
||||
contactData.email,
|
||||
contactData.message
|
||||
);
|
||||
return { message: 'Thank you for your message. We will contact you soon.' };
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
||||
import { MailerModule } from '@nestjs-modules/mailer';
|
||||
import { EmailService } from './email.service';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { EmailController } from './email.controller';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -24,6 +25,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
],
|
||||
controllers: [EmailController],
|
||||
providers: [EmailService],
|
||||
exports: [EmailService],
|
||||
})
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, Post, Body } from '@nestjs/common';
|
||||
import { MailerService } from '@nestjs-modules/mailer';
|
||||
|
||||
@Injectable()
|
||||
@ -13,7 +13,10 @@ export class EmailService {
|
||||
<h1>Welcome ${name}!</h1>
|
||||
<p>Your account has been created successfully.</p>
|
||||
<p>You can now login to access your documents.</p>
|
||||
<p>Please use the following link to reset your password: </p>
|
||||
<p>Best regards,<br>IMK Team</p>
|
||||
`,
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -42,4 +45,30 @@ export class EmailService {
|
||||
`,
|
||||
});
|
||||
}
|
||||
async sendContactEmail(name: string, email: string, message: string) {
|
||||
// Send to admin
|
||||
await this.mailerService.sendMail({
|
||||
to: process.env.ADMIN_EMAIL,
|
||||
subject: `New Contact Form Submission from ${name}`,
|
||||
html: `
|
||||
<h2>New Contact Form Submission</h2>
|
||||
<p><strong>From:</strong> ${name}</p>
|
||||
<p><strong>Email:</strong> ${email}</p>
|
||||
<p><strong>Message:</strong></p>
|
||||
<p>${message}</p>
|
||||
`,
|
||||
});
|
||||
await this.mailerService.sendMail({
|
||||
to: email,
|
||||
subject: 'Thank you for contacting us',
|
||||
html: `
|
||||
<h2>Thank you for contacting us</h2>
|
||||
<p>Dear ${name},</p>
|
||||
<p>We have received your message and will get back to you soon.</p>
|
||||
<p>Your message:</p>
|
||||
<blockquote>${message}</blockquote>
|
||||
<p>Best regards,<br>IMK Team</p>
|
||||
`,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,115 +1,126 @@
|
||||
|
||||
import { useState } from 'react'
|
||||
import { ChevronDownIcon } from '@heroicons/react/20/solid'
|
||||
import { Switch } from '@headlessui/react'
|
||||
|
||||
function classNames(...classes) {
|
||||
return classes.filter(Boolean).join(' ')
|
||||
}
|
||||
import { useState, useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export default function Contact() {
|
||||
const [agreed, setAgreed] = useState(false)
|
||||
const navigate = useNavigate();
|
||||
const [formData, setFormData] = useState({
|
||||
name: '',
|
||||
email: '',
|
||||
message: ''
|
||||
});
|
||||
const [status, setStatus] = useState({ type: '', message: '' });
|
||||
|
||||
return (
|
||||
<div className="isolate bg-gray px-6 bg-gradient-to-b from-cyan-900 to-cyan-800 sm:py-32 lg:px-8">
|
||||
<div
|
||||
aria-hidden="true"
|
||||
>
|
||||
useEffect(() => {
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
}, []);
|
||||
|
||||
const handleChange = (e) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
[e.target.name]: e.target.value
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
setStatus({ type: 'loading', message: 'Sending...' });
|
||||
|
||||
try {
|
||||
await axios.post(`http://localhost:3000/email/contact`, formData);
|
||||
setStatus({
|
||||
type: 'success',
|
||||
message: 'Thank you for your message. We will contact you soon.'
|
||||
});
|
||||
setFormData({ name: '', email: '', message: '' });
|
||||
// Redirect to home page after 2 seconds
|
||||
setTimeout(() => {
|
||||
navigate('/');
|
||||
}, 2000);
|
||||
} catch (error) {
|
||||
setStatus({
|
||||
type: 'error',
|
||||
message: 'There was an error sending your message. Please try again.'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="isolate bg-gray-900 px-6 py-24 sm:py-32 lg:px-8">
|
||||
<div className="mx-auto max-w-2xl text-center">
|
||||
<h2 className="text-3xl font-bold tracking-tight text-white sm:text-4xl">Контактирајте нѐ</h2>
|
||||
<p className="mt-2 text-lg leading-8 text-gray-300">
|
||||
Имате прашања? Ние сме тука да помогнеме.
|
||||
</p>
|
||||
</div>
|
||||
<form onSubmit={handleSubmit} className="mx-auto mt-16 max-w-xl sm:mt-20">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-6 sm:grid-cols-2">
|
||||
<div className="sm:col-span-2">
|
||||
<label htmlFor="name" className="block text-sm font-semibold leading-6 text-white">
|
||||
Име и Презиме
|
||||
</label>
|
||||
<div className="mt-2.5">
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
id="name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="block w-full rounded-md border-0 bg-white/5 px-3.5 py-2 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-indigo-500 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="mx-auto max-w-2xl text-center mt-10">
|
||||
<h2 className="text-3xl font-bold tracking-tight text-gray-900 sm:text-3xl">Пишете ни порака | Закажете средба</h2>
|
||||
{/* <p className="mt-2 text-lg leading-8 text-gray-600">
|
||||
take a wheel or let it slide
|
||||
|
||||
</p> */}
|
||||
</div>
|
||||
<div className="sm:col-span-2">
|
||||
<label htmlFor="email" className="block text-sm font-semibold leading-6 text-white">
|
||||
Емаил
|
||||
</label>
|
||||
<div className="mt-2.5">
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="block w-full rounded-md border-0 bg-white/5 px-3.5 py-2 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-indigo-500 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
<form action="https://formsubmit.co/taratur@gmail.com" method="POST" className="mx-auto mt-16 max-w-xl sm:mt-20">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-6 sm:grid-cols-2">
|
||||
<div>
|
||||
<label htmlFor="first-name" className="block text-sm font-semibold leading-6 text-white">
|
||||
Име
|
||||
</label>
|
||||
<div className="mt-2.5">
|
||||
<input
|
||||
type="text"
|
||||
name="first-name"
|
||||
id="first-name"
|
||||
autoComplete="given-name"
|
||||
className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="last-name" className="block text-sm font-semibold leading-6 text-white">
|
||||
Презиме
|
||||
</label>
|
||||
<div className="mt-2.5">
|
||||
<input
|
||||
type="text"
|
||||
name="last-name"
|
||||
id="last-name"
|
||||
autoComplete="family-name"
|
||||
className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="sm:col-span-2">
|
||||
<label htmlFor="company" className="block text-sm font-semibold leading-6 text-white">
|
||||
Компанија
|
||||
</label>
|
||||
<div className="mt-2.5">
|
||||
<input
|
||||
type="text"
|
||||
name="company"
|
||||
id="company"
|
||||
autoComplete="organization"
|
||||
className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="sm:col-span-2">
|
||||
<label htmlFor="email" className="block text-sm font-semibold leading-6 text-white">
|
||||
Мејл
|
||||
</label>
|
||||
<div className="mt-2.5">
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
autoComplete="email"
|
||||
className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="sm:col-span-2">
|
||||
<label htmlFor="message" className="block text-sm font-semibold leading-6 text-white">
|
||||
Порака
|
||||
</label>
|
||||
<div className="mt-2.5">
|
||||
<textarea
|
||||
name="message"
|
||||
id="message"
|
||||
rows={4}
|
||||
className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
defaultValue={''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Switch.Group as="div" className="flex gap-x-4 sm:col-span-2">
|
||||
</Switch.Group>
|
||||
</div>
|
||||
<input type="hidden" name="_next" value="https://imk.mk/"></input>
|
||||
<div className="mt-10">
|
||||
<button
|
||||
type="submit"
|
||||
className="block w-full rounded-md bg-gray-500 px-3.5 py-2.5 text-center text-sm font-semibold text-white shadow-sm hover:bg-gray-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500"
|
||||
>
|
||||
Испрати
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div className="sm:col-span-2">
|
||||
<label htmlFor="message" className="block text-sm font-semibold leading-6 text-white">
|
||||
Порака
|
||||
</label>
|
||||
<div className="mt-2.5">
|
||||
<textarea
|
||||
name="message"
|
||||
id="message"
|
||||
rows={4}
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="block w-full rounded-md border-0 bg-white/5 px-3.5 py-2 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-indigo-500 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
{status.message && (
|
||||
<div className={`mt-4 text-center ${status.type === 'error' ? 'text-red-500' : 'text-green-500'}`}>
|
||||
{status.message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-10">
|
||||
<button
|
||||
type="submit"
|
||||
disabled={status.type === 'loading'}
|
||||
className="block w-full rounded-md bg-indigo-600 px-3.5 py-2.5 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{status.type === 'loading' ? 'Испраќање...' : 'Испрати Порака'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user