강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

신상님의 프로필 이미지
신상

작성한 질문수

gpt를 한 10번 돌려도 안고쳐져 져서 문의남깁니다선생님 ㅠㅠ

작성

·

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는 지웠습니다.)

답변

답변을 기다리고 있는 질문이에요
첫번째 답변을 남겨보세요!
신상님의 프로필 이미지
신상

작성한 질문수

질문하기