작성
·
22
0
import React, { useState, useEffect } from "react";
import axios from "axios";
import { motion } from "framer-motion";
import { FiPhone, FiMail, FiMapPin } from "react-icons/fi";
import Swal from "sweetalert2";
import contactData from "../../Locale/contact.json"; // ✅ JSON 불러오기
const fadeInVariants = {
hidden: { opacity: 0, y: 30 },
visible: (i) => ({
opacity: 1,
y: 0,
transition: { duration: 0.6, delay: i * 0.2 },
}),
};
const buttonVariants = {
hover: { scale: 1.05, transition: { duration: 0.3 } },
tap: { scale: 0.95 },
};
const Contact = () => {
const [language, setLanguage] = useState(
localStorage.getItem("language") || "ko"
);
const [localizedData, setLocalizedData] = useState(contactData[language]);
const [forceRender, setForceRender] = useState(0); // ✅ 리렌더링 트리거를 위한 상태 추가
// ✅ `localStorage` 변경 감지 및 `forceRender` 상태 업데이트
useEffect(() => {
const handleLanguageChange = () => {
const newLanguage = localStorage.getItem("language") || "ko";
setLanguage(newLanguage);
setLocalizedData(contactData[newLanguage]);
setForceRender((prev) => prev + 1); // ✅ 리렌더링 강제 실행
};
window.addEventListener("storage", handleLanguageChange);
return () => {
window.removeEventListener("storage", handleLanguageChange);
};
}, []);
const getLocalizedText = (key) => {
const keys = key.split(".");
return keys.reduce((obj, k) => obj?.[k], localizedData) || key;
};
const [formData, setFormData] = useState({
name: "",
email: "",
phone: "",
message: "",
status: "in progress",
});
const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value,
});
};
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await axios.post(
"http://localhost:3000/api/contact",
formData
);
if (response.status === 201) {
Swal.fire({
icon: "success",
title: getLocalizedText("contact.alerts.success"),
confirmButtonColor: "#3085d6",
confirmButtonText: "확인",
});
setFormData({
name: "",
email: "",
phone: "",
message: "",
status: "in progress",
});
}
} catch (error) {
Swal.fire({
icon: "error",
title: getLocalizedText("contact.alerts.error"),
confirmButtonColor: "#d33",
confirmButtonText: "확인",
});
}
};
return (
<motion.div
key={language}
className="min-h-screen bg-white py-32"
initial="hidden"
animate="visible"
>
<motion.div
className="container mx-auto px-4 max-w-6xl"
variants={fadeInVariants}
custom={0}
>
<motion.div
className="text-center mb-16"
variants={fadeInVariants}
custom={1}
>
<h1 className="text-4xl lg:text-5xl font-bold text-gray-800 mb-6">
{getLocalizedText("contact.title")}
</h1>
<p className="text-xl text-gray-600 max-w-3xl mx-auto">
{getLocalizedText("contact.subtitle")}
</p>
</motion.div>
<motion.div
className="grid lg:grid-cols-2 gap-12 items-start"
variants={fadeInVariants}
custom={2}
>
<motion.div
className="bg-white rounded-2xl shadow-xl p-8"
variants={fadeInVariants}
custom={3}
>
<form onSubmit={handleSubmit}>
<div className="space-y-6">
{["name", "email", "phone"].map((field, index) => (
<motion.div
key={index}
variants={fadeInVariants}
custom={index + 4}
>
<label className="block text-gray-700 font-medium mb-2">
{getLocalizedText(`contact.form.${field}`)}
</label>
<input
type={field === "email" ? "email" : "text"}
name={field}
className="w-full p-4 py-3 rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all duration-300"
placeholder={getLocalizedText(
`contact.form.placeholders.${field}`
)}
required
value={formData[field]}
onChange={handleChange}
/>
</motion.div>
))}
<motion.div variants={fadeInVariants} custom={6}>
<label className="block text-gray-700 font-medium mb-2">
{getLocalizedText("contact.form.message")}
</label>
<textarea
name="message"
className="w-full p-4 py-3 rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all duration-300 h-40"
placeholder={getLocalizedText(
"contact.form.placeholders.message"
)}
required
value={formData.message}
onChange={handleChange}
/>
</motion.div>
<motion.button
className="w-full bg-blue-600 text-white py-4 rounded-lg font-medium hover:bg-blue-700 transition-colors duration-300"
variants={buttonVariants}
whileHover="hover"
whileTap="tap"
>
{getLocalizedText("contact.form.submit")}
</motion.button>
</div>
</form>
</motion.div>
{/* 연락처 정보 */}
<motion.div
className="space-y-8"
variants={fadeInVariants}
custom={7}
>
<motion.div
className="bg-white rounded-2xl shadow-lg p-8"
variants={fadeInVariants}
custom={8}
>
<h3 className="text-2xl font-bold text-gray-800 mb-6">
{getLocalizedText("contact.contact_info.title")}
</h3>
<div className="space-y-6">
{["phone", "email", "address"].map((key, index) => (
<motion.div
key={index}
className="flex items-center gap-4 p-4 border rounded-lg shadow-md hover:shadow-lg transition-all duration-300"
variants={fadeInVariants}
custom={index + 9}
>
{key === "phone" && (
<FiPhone className="text-blue-600 text-3xl" />
)}
{key === "email" && (
<FiMail className="text-blue-600 text-3xl" />
)}
{key === "address" && (
<FiMapPin className="text-blue-600 text-3xl" />
)}
<div>
<h4 className="text-lg font-semibold text-gray-800">
{getLocalizedText(`contact.contact_info.${key}.title`)}
</h4>
<p className="text-gray-600">
{getLocalizedText(`contact.contact_info.${key}.info`)}
</p>
<p className="text-sm text-gray-500">
{getLocalizedText(`contact.contact_info.${key}.desc`)}
</p>
</div>
</motion.div>
))}
</div>
</motion.div>
<motion.div
className="bg-white rounded-2xl shadow-lg overflow-hidden"
variants={fadeInVariants}
custom={10}
>
<iframe
src="
width="100%"
height="400"
loading="lazy"
className="w-full h-[400px] md:h-[600px] lg:h-[600px]"
></iframe>
</motion.div>
</motion.div>
</motion.div>
</motion.div>
</motion.div>
);
};
export default Contact;
gpt를 한 10번 돌려도 안고쳐져 져서 문의남깁니다선생님 ㅠㅠ
다른 페이지는 모두 변경완료 했습니다. 하지만 문의하기 페이지만 계속 새로고침 해야만 언어가 변경이 되네요.
왜그런지 자세히 알려주시면 감사하겠습니다..
(지도 src는 지웠습니다.)
답변