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_PASSWORD=76Avtostoperski76
|
||||||
SMTP_FROM=mailer@imk.mk
|
SMTP_FROM=mailer@imk.mk
|
||||||
FRONTEND_URL=https://imk.mk
|
FRONTEND_URL=https://imk.mk
|
||||||
|
ADMIN_EMAIL=petrovskidimitar@yandex.com
|
||||||
@ -49,7 +49,7 @@ export class AdminService {
|
|||||||
data: {
|
data: {
|
||||||
...createUserDto,
|
...createUserDto,
|
||||||
password: hashedPassword,
|
password: hashedPassword,
|
||||||
isAdmin: true,
|
isAdmin: createUserDto.isAdmin,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -97,6 +97,7 @@ export class AdminService {
|
|||||||
document.title,
|
document.title,
|
||||||
document.uploadedBy.name,
|
document.uploadedBy.name,
|
||||||
);
|
);
|
||||||
|
console.log('Document shared with user:', sharedWithUser.email);
|
||||||
|
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
import { Controller, Post, Body } from '@nestjs/common';
|
import { Controller, Post, Body } from '@nestjs/common';
|
||||||
import { EmailService } from './email.service';
|
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 {
|
export class EmailController {
|
||||||
constructor(private emailService: MailerService) {}
|
constructor(private emailService: EmailService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
async sendContactEmail(@Body() contactData: {
|
async sendContactEmail(@Body() contactData: {
|
||||||
@ -12,17 +17,20 @@ export class EmailController {
|
|||||||
email: string;
|
email: string;
|
||||||
message: string;
|
message: string;
|
||||||
}) {
|
}) {
|
||||||
await this.emailService.sendMail({
|
await this.emailService.sendContactEmail(
|
||||||
to: process.env.CONTACT_EMAIL,
|
contactData.name,
|
||||||
subject: `Contact Form: ${contactData.name}`,
|
contactData.email,
|
||||||
html: `
|
contactData.message
|
||||||
<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>
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
return { message: 'Contact form submitted successfully' };
|
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 { MailerModule } from '@nestjs-modules/mailer';
|
||||||
import { EmailService } from './email.service';
|
import { EmailService } from './email.service';
|
||||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
|
import { EmailController } from './email.controller';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -24,6 +25,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
|||||||
inject: [ConfigService],
|
inject: [ConfigService],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
controllers: [EmailController],
|
||||||
providers: [EmailService],
|
providers: [EmailService],
|
||||||
exports: [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';
|
import { MailerService } from '@nestjs-modules/mailer';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -13,7 +13,10 @@ export class EmailService {
|
|||||||
<h1>Welcome ${name}!</h1>
|
<h1>Welcome ${name}!</h1>
|
||||||
<p>Your account has been created successfully.</p>
|
<p>Your account has been created successfully.</p>
|
||||||
<p>You can now login to access your documents.</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, useEffect } from 'react';
|
||||||
import { useState } from 'react'
|
import axios from 'axios';
|
||||||
import { ChevronDownIcon } from '@heroicons/react/20/solid'
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Switch } from '@headlessui/react'
|
|
||||||
|
|
||||||
function classNames(...classes) {
|
|
||||||
return classes.filter(Boolean).join(' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Contact() {
|
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 (
|
useEffect(() => {
|
||||||
<div className="isolate bg-gray px-6 bg-gradient-to-b from-cyan-900 to-cyan-800 sm:py-32 lg:px-8">
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
<div
|
}, []);
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
|
|
||||||
|
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>
|
||||||
<div className="mx-auto max-w-2xl text-center mt-10">
|
</div>
|
||||||
<h2 className="text-3xl font-bold tracking-tight text-gray-900 sm:text-3xl">Пишете ни порака | Закажете средба</h2>
|
<div className="sm:col-span-2">
|
||||||
{/* <p className="mt-2 text-lg leading-8 text-gray-600">
|
<label htmlFor="email" className="block text-sm font-semibold leading-6 text-white">
|
||||||
take a wheel or let it slide
|
Емаил
|
||||||
|
</label>
|
||||||
</p> */}
|
<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>
|
</div>
|
||||||
<form action="https://formsubmit.co/taratur@gmail.com" method="POST" className="mx-auto mt-16 max-w-xl sm:mt-20">
|
</div>
|
||||||
<div className="grid grid-cols-1 gap-x-8 gap-y-6 sm:grid-cols-2">
|
<div className="sm:col-span-2">
|
||||||
<div>
|
<label htmlFor="message" className="block text-sm font-semibold leading-6 text-white">
|
||||||
<label htmlFor="first-name" className="block text-sm font-semibold leading-6 text-white">
|
Порака
|
||||||
Име
|
</label>
|
||||||
</label>
|
<div className="mt-2.5">
|
||||||
<div className="mt-2.5">
|
<textarea
|
||||||
<input
|
name="message"
|
||||||
type="text"
|
id="message"
|
||||||
name="first-name"
|
rows={4}
|
||||||
id="first-name"
|
value={formData.message}
|
||||||
autoComplete="given-name"
|
onChange={handleChange}
|
||||||
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"
|
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>
|
||||||
<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>
|
||||||
)
|
|
||||||
|
{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