Сделал форму обратной связи, отдельно сервер клиент работают хорошо. Но когда их объединил на одном хосте при нажатии отправить (заявка обратной связи на почту ) выходит ошибка. Ругается на строку в Hero.jsx const response = await fetch("/api/feedback", {
Серверная часть server.js
const express = require('express');
const nodemailer = require('nodemailer');
const server = express();
server.use(express.static(__dirname + '/public'));
server.use(express.json());
server.get('/', (req, res) => {
res.sendFile("public/index.html", { root: __dirname})
})
server.post("/api/feedback", async(req, res) => {
try {
const transporter = nodemailer.createTransport({
host: "smtp.mail.ru",
port: 465,
secure: true,
auth: {
user: "ya@mail.ru",
pass: "**********"
}
});
const { name, phone, message} = req.body;
await transporter.sendMail({
from: "ya@mail.ru",
to: "ya@mail.ru",
subject: "Тема письма",
text: `${name} ${phone} ${message}`,
html:
`
<p>${name}</p>
<p>${phone}</p>
<p>${message}</p>
`
});
return res.status(200).send({
status: 200,
message: 'Успешня отправка'
})
} catch (e) {
return res.status(500).send({
status:500,
message: 'Ошибка при запросе'
});
}
})
server.listen(5000, () => {
console.log('listening on port 5000');
})
script.js
const FEEDBACK_FORM = document.querySelector('#feedback-form');
function sendFeedback(feedback) {
fetch("/api/feedback" , {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(feedback),
}).then((response)=>response.json()).then(data => {
console.log(data);
alert('Успешно');
}).catch((error) => {
console.error(error);
alert('Ошибка');
});
}
FEEDBACK_FORM.addEventListener('submit', (e) => {
e.preventDefault();
const feedbackFormData = new FormData(e.target);
console.log('feedbackFormData', feedbackFormData);
const feedback = Object.fromEntries(feedbackFormData);
console.log('feedback', feedback);
sendFeedback(feedback);
})
Клиентская часть Hero.jsx
import React, { useState } from "react";
import styles from "./Hero.module.css";
import { getImageUrl } from "../../utils";
export const Hero = () => {
const [isOpen, setIsOpen] = useState(false);
const [formData, setFormData] = useState({
name: "",
phone: "",
message: ""
});
const openModal = () => {
setIsOpen(true);
};
const closeModal = () => {
setIsOpen(false);
};
const handleCall = () => {
window.location.href = "tel:**************";
};
const handleFormSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch("/api/feedback", {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(formData),
});
if (response.ok) {
alert('Успешно');
setFormData({
name: "",
phone: "",
message: ""
});
} else {
alert('Ошибка');
}
} catch (error) {
console.error(error);
alert('Ошибка');
}
};
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prevData) => ({
...prevData,
[name]: value
}));
};
return (
<section className={styles.container}>
<div className={styles.content}>
<h1 className={styles.title}>*********</h1>
<p className={styles.description}>
«Ya»
</p>
<a href="tel:+**********" className={styles.contactBtn} onClick={handleCall}>
Позвонить
</a>
<button onClick={openModal} className={styles.contactBTN}>
Оставить заявку
</button>
{isOpen && (
<form onSubmit={handleFormSubmit}>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
placeholder="Имя"
/>
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleChange}
placeholder="Телефон"
/>
<textarea
name="message"
value={formData.message}
onChange={handleChange}
placeholder="Сообщение"
/>
<button type="submit">Отправить</button>
</form>
)}
</div>
<img
src={getImageUrl("hero/heroImage.png")}
alt="Hero image of me"
className={styles.heroImg}
/>
<div className={styles.topBlur} />
<div className={styles.bottomBlur} />
</section>
);
};
export default Hero;