Migration to astro #1

Merged
shiseri merged 6 commits from astro-migration into main 2026-07-29 18:59:27 +03:00
9 changed files with 187 additions and 31 deletions
Showing only changes of commit b010563b62 - Show all commits

View file

@ -1,4 +1,4 @@
import React, { useState, useRef } from "react";
import React, { useState, useRef, useEffect } from "react";
import axios from "axios";
import { useTranslation } from "react-i18next";
import "./contact-form.style.scss";
@ -9,6 +9,28 @@ import YellowPlanet from "../../assets/images/main/contact-form/Planet Yellow.sv
import FormInput from "../form-input/form-input.component";
import CustomButton from "../custom-button/custom-button.component";
const verifyCaptcha = async (captchaToken) => {
const keyId = "8e5272fb9c08";
try {
const response = await axios.post(
`https://cap.midcreative.eu/${keyId}/siteverify`,
{
response: captchaToken,
},
{
headers: {
"Content-Type": "application/json",
},
}
);
return response.data.success;
} catch (error) {
console.error("Captcha verification failed:", error);
return false;
}
};
const newPost = async (data) => {
return axios
.post("https://midcreative.eu/mail/", data, {
@ -17,7 +39,10 @@ const newPost = async (data) => {
},
})
.then((res) => true)
.catch((err) => err);
.catch((err) => {
console.error("Form submission error:", err);
return false;
});
};
const ContactForm = () => {
@ -34,6 +59,8 @@ const ContactForm = () => {
const [success, setSuccess] = useState();
const [error, setError] = useState();
const [captchaToken, setCaptchaToken] = useState(null);
const [captchaError, setCaptchaError] = useState(false);
const setName = (name) => {
setFormData({ ...formData, name: name });
@ -53,21 +80,69 @@ const ContactForm = () => {
phoneInputRef.current.clean();
};
const handlePost = (e) => {
useEffect(() => {
const handleCaptchaCompleted = (event) => {
if (event.detail && event.detail.token) {
setCaptchaToken(event.detail.token);
setCaptchaError(false);
}
};
const captchaWidget = document.querySelector('cap-widget');
if (captchaWidget) {
captchaWidget.addEventListener('cap-completed', handleCaptchaCompleted);
}
return () => {
if (captchaWidget) {
captchaWidget.removeEventListener('cap-completed', handleCaptchaCompleted);
}
};
}, []);
const handlePost = async (e) => {
e.preventDefault();
newPost(formData).then((res) => {
if (res === true) {
if (!captchaToken) {
setCaptchaError(true);
return;
}
const isCaptchaValid = await verifyCaptcha(captchaToken);
if (!isCaptchaValid) {
setCaptchaError(true);
setCaptchaToken(null);
const captchaWidget = document.querySelector('cap-widget');
if (captchaWidget && captchaWidget.reset) {
captchaWidget.reset();
}
return;
}
try {
const response = await newPost(formData);
if (response === true) {
cleanFields();
setError(false);
setSuccess(true);
setCaptchaToken(null);
setCaptchaError(false);
const captchaWidget = document.querySelector('cap-widget');
if (captchaWidget && captchaWidget.reset) {
captchaWidget.reset();
}
setTimeout(() => setSuccess(false), 6000);
} else {
cleanFields();
setError(true);
setSuccess(false);
}
});
} catch (err) {
console.error("Form submission failed:", err);
setError(true);
setSuccess(false);
}
};
return (
@ -113,6 +188,16 @@ const ContactForm = () => {
required
/>
<cap-widget
data-cap-api-endpoint="https://cap.midcreative.eu/8e5272fb9c08/api/"
></cap-widget>
{captchaError && (
<p className="error" style={{ marginTop: '10px' }}>
{t("contacts.captchaError") || "Please complete the captcha"}
</p>
)}
<CustomButton text={t("contacts.send")} />
</form>
</div>

View file

@ -1,7 +1,9 @@
import React from "react";
import { Link } from "gatsby";
import "./footer.style.scss";
import { useTranslation } from "react-i18next";
import { getLocalizedPath } from "../../utils/navigation";
import Contacts from "../contacts/contacts.component";
import TopLine from "../../assets/images/main/footer/top-line.png";
@ -27,21 +29,21 @@ const MidFooter = () => {
</div>
<nav>
<h6>{t("footer.navigation")}</h6>
<a href="#top" className="gray mobile">
<Link to={getLocalizedPath("/#top")} className="gray mobile">
{t("menu.home")}
</a>
<a href="#services" className="gray">
</Link>
<Link to={getLocalizedPath("/#services")} className="gray">
{t("menu.services")}
</a>
<a href="#about-us" className="gray">
</Link>
<Link to={getLocalizedPath("/#about-us")} className="gray">
{t("menu.about_us")}
</a>
<a href="#projects" className="gray">
</Link>
<Link to={getLocalizedPath("/#projects")} className="gray">
{t("menu.portfolio")}
</a>
<a href="#contact-us" className="gray">
</Link>
<Link to={getLocalizedPath("/#contact-us")} className="gray">
{t("menu.contact_us")}
</a>
</Link>
</nav>
<div>
<img src={Logo} alt="" />

View file

@ -4,6 +4,7 @@ import { Link } from "gatsby";
import { useTranslation } from "react-i18next";
import LanguageSwitch from "../language-switch/language-switch.component";
import { getLocalizedPath } from "../../utils/navigation";
import Logo from "../../assets/images/main/header/logo.svg";
import Logo2 from "../../assets/images/main/footer/logo.svg";
@ -64,10 +65,10 @@ const MidHeader = () => {
<img src={Logo} alt="MID" />
</div>
<nav className="navigation">
<Link to="/#services">{t("menu.services")}</Link>
<Link to="/#about-us">{t("menu.about_us")}</Link>
<Link to="/#projects">{t("menu.portfolio")}</Link>
<Link to="/#contact-us">{t("menu.contact_us")}</Link>
<Link to={getLocalizedPath("/#services")}>{t("menu.services")}</Link>
<Link to={getLocalizedPath("/#about-us")}>{t("menu.about_us")}</Link>
<Link to={getLocalizedPath("/#projects")}>{t("menu.portfolio")}</Link>
<Link to={getLocalizedPath("/#contact-us")}>{t("menu.contact_us")}</Link>
<LanguageSwitch />
</nav>
@ -91,11 +92,11 @@ const MidHeader = () => {
<img src={Logo2} alt="MID Creative Digital Agency" />
<nav className="navigation">
<a href="#top">{t("menu.home")}</a>
<a href="#services">{t("menu.services")}</a>
<a href="#about-us">{t("menu.about_us")}</a>
<a href="#projects">{t("menu.portfolio")}</a>
<a href="#contact-us">{t("menu.contact_us")}</a>
<Link to={getLocalizedPath("/#top")}>{t("menu.home")}</Link>
<Link to={getLocalizedPath("/#services")}>{t("menu.services")}</Link>
<Link to={getLocalizedPath("/#about-us")}>{t("menu.about_us")}</Link>
<Link to={getLocalizedPath("/#projects")}>{t("menu.portfolio")}</Link>
<Link to={getLocalizedPath("/#contact-us")}>{t("menu.contact_us")}</Link>
</nav>
<div className="header-contacts">

View file

@ -1,4 +1,5 @@
import React from "react";
import { navigate } from "gatsby";
import i18n from "../../i18n";
import "./language-switch.style.scss";
@ -6,6 +7,13 @@ import "./language-switch.style.scss";
const LanguageSwitch = ({ t }) => {
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
// Navigate to the appropriate route
if (lng === "lv") {
navigate("/lv");
} else {
navigate("/");
}
};
return (

View file

@ -33,6 +33,10 @@ export const Seo = ({ title, description, pathname, children }) => {
gtag('config', 'G-8M9CZ79T4L');
`}
</Script>
<Script
src="https://cap.midcreative.eu/8e5272fb9c08/widget.js"
strategy="idle"
/>
{children}
</>
);

View file

@ -18,10 +18,13 @@ i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
resources,
lng: "en", // language to use, more information here: https://www.i18next.com/overview/configuration-options#languages-namespaces-resources
// you can use the i18n.changeLanguage function to change the language manually: https://www.i18next.com/overview/api#changelanguage
// if you're using a language detector, do not define the lng option
lng: typeof window !== "undefined" && window.location.pathname.startsWith("/lv") ? "lv" : "en", // Detect language from URL
fallbackLng: "en", // use en if detected lng is not available
detection: {
// Disable automatic detection to respect URL-based language
order: ["path", "localStorage", "navigator"],
caches: ["localStorage"],
},
interpolation: {
escapeValue: false, // react already safes from xss

View file

@ -1,11 +1,18 @@
import * as React from "react";
import { useEffect } from "react";
import { Seo } from "../components/seo";
import i18n from "../i18n";
import "../assets/stylesheets/style.scss";
import MidMainPage from "../main/main.component";
const IndexPage = () => {
useEffect(() => {
// Ensure English is set for the root route
i18n.changeLanguage("en");
}, []);
return <MidMainPage></MidMainPage>;
};

View file

@ -91,7 +91,8 @@
"phone": "phone",
"send": "Send",
"success": "Thank you for sharing your contacts! We will get in touch!",
"error": "Looks like something went wrong, please try to reach us directly "
"error": "Looks like something went wrong, please try to reach us directly ",
"captchaError": "Please complete the captcha verification"
},
"privacy": {
"title": "Privacy Policy",
@ -144,5 +145,27 @@
"registration_nr": "Registration nr.",
"address": "Address",
"navigation": "Navigation"
},
"landingPromo": {
"title": "Professional Landing Page Development in Just 2 Business Days €150!",
"subtitle": "Looking to attract new customers quickly and effectively? Our experienced team specializes in creating efficient and modern landing pages that will help achieve your business goals.",
"whatYouGet": "What you get:",
"benefit1": "Customized landing page tailored to your brand and needs",
"benefit2": "Modern and user-friendly design",
"benefit3": "Mobile-responsive solution",
"benefit4": "Optimized page loading speed and SEO basics",
"benefit5": "Free consultation on content and structure creation",
"whyUs": "Why choose us:",
"feature1Title": "Fast Development",
"feature1": "Guaranteed delivery in just 2 business days",
"feature2Title": "Fixed Price",
"feature2": "€150 - no hidden costs",
"feature3Title": "Experienced Team",
"feature3": "Friendly and responsive team with website development experience",
"feature4Title": "Long-term Support",
"feature4": "Support even after page creation",
"ctaTitle": "Contact us today and get your new landing page in just two days!",
"ctaText": "Book a consultation we'll help bring your ideas to life!",
"ctaButton": "Contact Us"
}
}

View file

@ -91,12 +91,35 @@
"phone": "Telefons",
"send": "Nosūtīt",
"success": "Paldies ",
"error": "Izskatās, ka kautkas nestrādā :( Uzrakstiet mums uz "
"error": "Izskatās, ka kautkas nestrādā :( Uzrakstiet mums uz ",
"captchaError": "Lūdzu, aizpildiet captcha verifikāciju"
},
"footer": {
"company": "Kompānija",
"registration_nr": "Reģistrācijas nr.",
"address": "Adrese",
"navigation": "Navigācija"
},
"landingPromo": {
"title": "Profesionāla landing lapu izstrāde tikai 2 darba dienu laikā 150 €!",
"subtitle": "Vai vēlaties ātri un kvalitatīvi piesaistīt jaunus klientus? Mūsu pieredzējusī komanda specializējas efektīvu un modernu landing lapu izstrādē, kas palīdzēs sasniegt jūsu biznesa mērķus.",
"whatYouGet": "Ko jūs iegūstat:",
"benefit1": "Individuāli pielāgotu landing lapu atbilstoši jūsu zīmolam un vajadzībām",
"benefit2": "Mūsdienīgu un lietotājam draudzīgu dizainu",
"benefit3": "Mobilajām ierīcēm pielāgotu risinājumu",
"benefit4": "Optimizētu lapas ielādes ātrumu un SEO pamatus",
"benefit5": "Bezmaksas konsultāciju par satura un struktūras izveidi",
"whyUs": "Kāpēc izvēlēties mūs:",
"feature1Title": "Ātra izstrāde",
"feature1": "Garantēta izstrāde tikai 2 darba dienu laikā",
"feature2Title": "Fiksēta cena",
"feature2": "150 € - bez slēptām izmaksām",
"feature3Title": "Pieredzējuša komanda",
"feature3": "Draudzīga un atsaucīga komanda ar pieredzi mājaslapu izstrādē",
"feature4Title": "Ilgtermiņa atbalsts",
"feature4": "Atbalsts arī pēc lapas izveides",
"ctaTitle": "Sazinieties ar mums jau šodien un saņemiet savu jauno landing lapu tikai divu dienu laikā!",
"ctaText": "Piesakieties konsultācijai mēs palīdzēsim īstenot jūsu idejas!",
"ctaButton": "Sazināties ar mums"
}
}