contact poup updated in carees page
This commit is contained in:
parent
763c0df3c1
commit
0108118f2c
@ -7,8 +7,8 @@ import PageHeader from "@/components/common/PageHeader";
|
||||
import MetatronInitializer from "@/components/MetatronInitializer";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Top 5 SEO Trends for 2025 | Metatroncube",
|
||||
description: "Explore the latest SEO strategies for 2025. Stay ahead with insights from Metatroncube Software Solution.",
|
||||
title: "Web Dev, SEO & Digital Marketing Blog | Metatroncube",
|
||||
description: "Expert insights on web development, SEO strategies, and digital marketing trends. Actionable tips from Metatroncube Software Solutions in Waterloo, Canada.",
|
||||
alternates: {
|
||||
canonical: "/blog",
|
||||
},
|
||||
|
||||
@ -8,7 +8,7 @@ import AboutService from "@/components/services-digital-solutions/AboutService";
|
||||
import AboutThree from "@/components/home/AboutThree";
|
||||
import ProjectsSection from "@/components/home/ProjectsSection";
|
||||
import MetatronInitializer from "@/components/MetatronInitializer";
|
||||
import CareersForm from "@/components/careers/CareersForm";
|
||||
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Careers - Metatroncube Software Solution | Innovative & User-Centric Tech Services in Waterloo",
|
||||
@ -33,7 +33,7 @@ export default function CareersPage() {
|
||||
<AboutThree />
|
||||
<WhyChooseUs />
|
||||
<ProjectsSection />
|
||||
{/* <CareersForm /> */}
|
||||
|
||||
</main>
|
||||
<Footer1 />
|
||||
</>
|
||||
|
||||
@ -6841,7 +6841,7 @@ body {
|
||||
|
||||
.faq-one__accordion .accrodion {
|
||||
margin-bottom: 25px;
|
||||
border-radius: 70px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--pelocis-border-color, #DDDDDD);
|
||||
overflow: hidden;
|
||||
transition: all 400ms ease;
|
||||
@ -6921,10 +6921,14 @@ body {
|
||||
color: var(--pelocis-white, #fff);
|
||||
font-size: 10px;
|
||||
transition: all 400ms ease;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.faq-one__accordion .active .accrodion-title__icon {
|
||||
background-color: var(--pelocis-base, #3779b9);
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.faq-one__accordion .accrodion-content .inner {
|
||||
@ -9307,46 +9311,58 @@ body {
|
||||
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.form-label-custom-global {
|
||||
.form-label-custom-global,
|
||||
.form-label-custom {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.form-input-custom-global,
|
||||
.form-textarea-custom-global,
|
||||
.form-select-custom-styled-global {
|
||||
.form-select-custom-styled-global,
|
||||
.form-input,
|
||||
.form-select,
|
||||
.form-textarea {
|
||||
width: 100%;
|
||||
padding: 18px 25px;
|
||||
border: 1px solid #e2e8f0;
|
||||
background-color: #fff;
|
||||
padding: 15px 20px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 12px;
|
||||
outline: none;
|
||||
font-size: 15px;
|
||||
color: #1e293b;
|
||||
color: #fff;
|
||||
transition: all 0.3s ease;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.form-textarea-custom-global {
|
||||
min-height: 120px;
|
||||
.form-textarea-custom-global,
|
||||
.form-textarea {
|
||||
min-height: 100px;
|
||||
height: auto;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.form-input-custom-global:focus,
|
||||
.form-textarea-custom-global:focus,
|
||||
.form-select-custom-styled-global:focus {
|
||||
.form-select-custom-styled-global:focus,
|
||||
.form-input:focus,
|
||||
.form-textarea:focus,
|
||||
.form-select:focus {
|
||||
border-color: #3779b9;
|
||||
box-shadow: 0 0 0 4px rgba(55, 121, 185, 0.1);
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 0 0 4px rgba(55, 121, 185, 0.15);
|
||||
}
|
||||
|
||||
.submit-btn-custom-global {
|
||||
width: 100%;
|
||||
background: #3779b9 !important;
|
||||
color: #fff !important;
|
||||
padding: 20px 30px;
|
||||
padding: 18px 30px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-weight: 700;
|
||||
@ -9355,7 +9371,12 @@ body {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1.5px;
|
||||
font-size: 17px;
|
||||
box-shadow: 0 10px 20px rgba(99, 102, 241, 0.2);
|
||||
box-shadow: 0 10px 20px rgba(55, 121, 185, 0.2);
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.submit-btn-custom-global:hover {
|
||||
@ -16449,7 +16470,7 @@ h4.service-details__dynamic-content-erp {
|
||||
padding: 18px 24px;
|
||||
cursor: pointer;
|
||||
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
min-height: 70px;
|
||||
min-height: 40px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
@ -17346,9 +17367,6 @@ h4.service-details__dynamic-content-erp {
|
||||
}
|
||||
|
||||
.careers-popup-optimized .file-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
@ -17367,8 +17385,9 @@ h4.service-details__dynamic-content-erp {
|
||||
.careers-popup-optimized .form-panel {
|
||||
padding: 30px 45px 25px !important;
|
||||
background: #1a1f2b !important;
|
||||
overflow: hidden !important;
|
||||
/* Force no scroll on panel */
|
||||
overflow-y: auto !important;
|
||||
/* Allow internal scroll if needed as fallback */
|
||||
max-height: calc(100vh - 40px);
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-header {
|
||||
@ -17463,9 +17482,6 @@ h4.service-details__dynamic-content-erp {
|
||||
}
|
||||
|
||||
.careers-popup-optimized .file-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
@ -17552,125 +17568,240 @@ h4.service-details__dynamic-content-erp {
|
||||
.careers-popup-optimized {
|
||||
max-width: 600px !important;
|
||||
width: 90% !important;
|
||||
max-height: 95vh !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
/* No-scroll optimization: compress vertical rhythm */
|
||||
.careers-popup-optimized .form-panel {
|
||||
padding: 15px 30px 10px !important;
|
||||
padding: 10px 20px 10px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-header {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-input {
|
||||
padding: 10px 14px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-textarea {
|
||||
min-height: 60px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .g-recaptcha-container {
|
||||
transform: scale(0.8);
|
||||
margin: 5px 0 !important;
|
||||
}
|
||||
|
||||
.contact-popup-content .close-btn {
|
||||
position: absolute;
|
||||
top: 10px !important;
|
||||
right: 10px !important;
|
||||
background: #f3f4f6;
|
||||
border: none;
|
||||
width: 25px !important;
|
||||
height: 25px !important;
|
||||
border-radius: 50%;
|
||||
font-size: 16px !important;
|
||||
cursor: pointer;
|
||||
color: #1a1f2b;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s;
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
|
||||
/* 500-475px */
|
||||
@media (max-width: 500px) {
|
||||
.careers-popup-optimized {
|
||||
width: 95% !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-panel {
|
||||
padding: 12px 20px 8px !important;
|
||||
margin-bottom: 5px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-title {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-subtitle {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-label-custom {
|
||||
font-size: 9px !important;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .mt-3 {
|
||||
margin-top: 8px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 425px */
|
||||
@media (max-width: 425px) {
|
||||
.careers-popup-optimized .form-panel {
|
||||
padding: 10px 15px 5px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .g-recaptcha-container {
|
||||
transform: scale(0.75);
|
||||
}
|
||||
}
|
||||
|
||||
/* 320px - Small Mobile */
|
||||
@media (max-width: 320px) {
|
||||
.careers-popup-optimized .form-panel {
|
||||
padding: 8px 12px 5px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-title {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-subtitle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-label-custom {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hide labels, placeholders only to save vertical space */
|
||||
.careers-popup-optimized .form-input {
|
||||
padding: 8px 12px !important;
|
||||
font-size: 12px !important;
|
||||
.careers-popup-optimized .form-input,
|
||||
.careers-popup-optimized .form-select,
|
||||
.careers-popup-optimized .form-textarea {
|
||||
height: 33px !important;
|
||||
padding: 8px 15px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-textarea {
|
||||
min-height: 50px !important;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .g-recaptcha-container {
|
||||
transform: scale(0.65);
|
||||
margin: 3px 0 !important;
|
||||
transform: scale(0.7) !important;
|
||||
margin: 0 !important;
|
||||
height: 60px !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .submit-btn {
|
||||
padding: 12px !important;
|
||||
font-size: 13px !important;
|
||||
height: 50px !important;
|
||||
margin-top: 5px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 500-320px - Mobile */
|
||||
@media (max-width: 500px) {
|
||||
.careers-popup-optimized {
|
||||
width: 95% !important;
|
||||
max-height: 98vh !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-panel {
|
||||
padding: 8px 15px 5px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-label-custom {
|
||||
font-size: 11px !important;
|
||||
margin-bottom: 2px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .row.g-3 {
|
||||
--bs-gutter-y: 8px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .mt-3 {
|
||||
margin-top: 5px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .file-upload-styled {
|
||||
margin-bottom: 5px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .file-browse-btn {
|
||||
padding: 4px 10px !important;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-textarea {
|
||||
min-height: 50px !important;
|
||||
font-size: 12px !important;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .g-recaptcha-container {
|
||||
transform: scale(0.65);
|
||||
margin: 3px 0 !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .submit-btn {
|
||||
padding: 12px !important;
|
||||
font-size: 13px !important;
|
||||
margin-top: 5px !important;
|
||||
}
|
||||
|
||||
/* ── Height Based Responsiveness (No-Scroll Optimization) ── */
|
||||
@media (max-height: 600px) {
|
||||
.careers-popup-optimized .form-panel {
|
||||
padding: 8px 15px 5px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-header {
|
||||
margin-bottom: 5px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-title {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-label-custom {
|
||||
font-size: 9px !important;
|
||||
margin-bottom: 2px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-input,
|
||||
.careers-popup-optimized .form-select {
|
||||
height: 36px !important;
|
||||
padding: 4px 10px !important;
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-textarea {
|
||||
min-height: 36px !important;
|
||||
height: 36px !important;
|
||||
padding: 5px 10px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .file-upload-label {
|
||||
padding: 4px 10px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .file-browse-btn {
|
||||
padding: 2px 8px !important;
|
||||
font-size: 10px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .g-recaptcha-container {
|
||||
transform: scale(0.6) !important;
|
||||
transform-origin: center center;
|
||||
height: 48px !important;
|
||||
margin: 2px 0 !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .submit-btn {
|
||||
height: 38px !important;
|
||||
margin-top: 5px !important;
|
||||
font-size: 11px !important;
|
||||
padding: 5px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-height: 500px) {
|
||||
.careers-popup-optimized {
|
||||
border-radius: 12px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-panel {
|
||||
padding: 2px 10px 2px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-header {
|
||||
margin-bottom: 2px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-title {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-label-custom {
|
||||
font-size: 8px !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-input,
|
||||
.careers-popup-optimized .form-select,
|
||||
.careers-popup-optimized .form-textarea {
|
||||
height: 30px !important;
|
||||
min-height: 30px !important;
|
||||
padding: 2px 8px !important;
|
||||
font-size: 11px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .mt-3,
|
||||
.careers-popup-optimized .mt-1 {
|
||||
margin-top: 2px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .file-upload-label {
|
||||
padding: 2px 8px !important;
|
||||
border-width: 1px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .file-content i {
|
||||
font-size: 10px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .file-name-text {
|
||||
font-size: 10px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .file-browse-btn {
|
||||
padding: 2px 6px !important;
|
||||
font-size: 9px !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .g-recaptcha-container {
|
||||
transform: scale(0.5) !important;
|
||||
height: 38px !important;
|
||||
margin: 1px 0 !important;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .submit-btn {
|
||||
height: 32px !important;
|
||||
margin-top: 2px !important;
|
||||
font-size: 10px !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
/* Extreme optimization: hide labels for optional fields to save space */
|
||||
.careers-popup-optimized .form-field-wrapper .form-label-custom {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.careers-popup-optimized .optional-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-height: 400px) {
|
||||
.careers-popup-optimized .form-header {
|
||||
display: none;
|
||||
/* Hide header on very short screens to save space */
|
||||
}
|
||||
|
||||
.careers-popup-optimized .form-panel {
|
||||
padding-top: 20px !important;
|
||||
/* Room for close btn */
|
||||
}
|
||||
}
|
||||
@ -12,13 +12,9 @@ interface CareersContactPopupProps {
|
||||
}
|
||||
|
||||
const positions = [
|
||||
{ value: "Frontend Developer", label: "Website Development" },
|
||||
{ value: "Backend Developer", label: "Social Media Marketing" },
|
||||
{ value: "Full Stack Developer", label: "Search Engine Optimization" },
|
||||
{ value: "UI/UX Designer", label: "Mobile App Development" },
|
||||
{ value: "SEO Specialist", label: "UI/UX Designing" },
|
||||
{ value: "Digital Marketing Executive", label: "Graphic Designing" },
|
||||
{ value: "Other", label: "Other" },
|
||||
{ value: "Website Development", label: "Website Development" },
|
||||
{ value: "Social Media Marketing", label: "Social Media Marketing" },
|
||||
{ value: "Search Engine Optimization (SEO)", label: "Search Engine Optimization (SEO)" },
|
||||
];
|
||||
|
||||
const CareersContactPopup: React.FC<CareersContactPopupProps> = ({
|
||||
@ -26,12 +22,25 @@ const CareersContactPopup: React.FC<CareersContactPopupProps> = ({
|
||||
onClose,
|
||||
defaultPosition = "",
|
||||
}) => {
|
||||
// Helper to find match in positions array
|
||||
const getMatchedPosition = (val: string) => {
|
||||
if (!val) return "";
|
||||
const searchStr = val.toLowerCase();
|
||||
const found = positions.find(p =>
|
||||
p.label.toLowerCase() === searchStr ||
|
||||
p.value.toLowerCase() === searchStr ||
|
||||
searchStr.includes(p.label.toLowerCase()) ||
|
||||
p.label.toLowerCase().includes(searchStr)
|
||||
);
|
||||
return found ? found.value : val;
|
||||
};
|
||||
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [formData, setFormData] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
position: defaultPosition,
|
||||
position: getMatchedPosition(defaultPosition),
|
||||
message: "",
|
||||
});
|
||||
const [resumeFile, setResumeFile] = useState<File | null>(null);
|
||||
@ -48,7 +57,9 @@ const CareersContactPopup: React.FC<CareersContactPopupProps> = ({
|
||||
|
||||
// Sync position when defaultPosition changes (new card clicked)
|
||||
useEffect(() => {
|
||||
setFormData((prev) => ({ ...prev, position: defaultPosition }));
|
||||
if (defaultPosition) {
|
||||
setFormData((prev) => ({ ...prev, position: getMatchedPosition(defaultPosition) }));
|
||||
}
|
||||
}, [defaultPosition]);
|
||||
|
||||
// Close on ESC
|
||||
@ -127,17 +138,21 @@ const CareersContactPopup: React.FC<CareersContactPopupProps> = ({
|
||||
email: formData.email,
|
||||
phone: formData.phone,
|
||||
position: formData.position,
|
||||
message: `Position: ${formData.position}<br /><br />Phone: ${formData.phone}<br /><br />Message: ${formData.message || "No additional message."}`,
|
||||
message: `Full Name: ${formData.name}<br />Email Address: ${formData.email}<br />Phone Number: ${formData.phone}<br />Position: ${formData.position}<br /><br />Message: ${formData.message || "No additional message."}${resumeFile ? `<br /><br /><b>Resume attached:</b> ${resumeFile.name}` : ""}`,
|
||||
to: "info@metatroncubesolutions.com",
|
||||
senderName: "Metatroncube Careers Application",
|
||||
recaptchaToken: captchaToken,
|
||||
};
|
||||
|
||||
if (resumeBase64 && resumeFile) {
|
||||
// Extract raw base64 from data URI
|
||||
const base64Content = resumeBase64.split(",")[1];
|
||||
emailData.attachments = [
|
||||
{
|
||||
filename: resumeFile.name,
|
||||
path: resumeBase64,
|
||||
content: base64Content,
|
||||
contentType: resumeFile.type,
|
||||
encoding: 'base64',
|
||||
},
|
||||
];
|
||||
}
|
||||
@ -178,7 +193,7 @@ const CareersContactPopup: React.FC<CareersContactPopupProps> = ({
|
||||
}, [alert.show]);
|
||||
|
||||
const handleReset = () => {
|
||||
setFormData({ name: "", email: "", phone: "", position: defaultPosition, message: "" });
|
||||
setFormData({ name: "", email: "", phone: "", position: getMatchedPosition(defaultPosition), message: "" });
|
||||
setResumeFile(null);
|
||||
setResumeBase64(null);
|
||||
if (fileInputRef.current) fileInputRef.current.value = "";
|
||||
@ -275,7 +290,12 @@ const CareersContactPopup: React.FC<CareersContactPopupProps> = ({
|
||||
>
|
||||
<option value="">Select Position</option>
|
||||
{positions
|
||||
.filter(pos => !defaultPosition || pos.value === defaultPosition)
|
||||
.filter(pos => !defaultPosition ||
|
||||
pos.label === defaultPosition ||
|
||||
pos.value === defaultPosition ||
|
||||
defaultPosition.toLowerCase().includes(pos.label.toLowerCase()) ||
|
||||
pos.label.toLowerCase().includes(defaultPosition.toLowerCase())
|
||||
)
|
||||
.map((pos) => (
|
||||
<option key={pos.value} value={pos.value}>
|
||||
{pos.label}
|
||||
|
||||
@ -1,351 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import ReCAPTCHA from "react-google-recaptcha";
|
||||
import axios from "axios";
|
||||
|
||||
const CareersForm = () => {
|
||||
const sectionRef = useRef<HTMLDivElement>(null);
|
||||
const [formData, setFormData] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
position: "",
|
||||
message: "",
|
||||
});
|
||||
|
||||
const [resumeFile, setResumeFile] = useState<File | null>(null);
|
||||
const [resumeBase64, setResumeBase64] = useState<string | null>(null);
|
||||
|
||||
const [formErrors, setFormErrors] = useState<any>({});
|
||||
const [captchaToken, setCaptchaToken] = useState<string | null>(null);
|
||||
const [alert, setAlert] = useState({ show: false, type: "", message: "" });
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData((prev) => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.files && e.target.files.length > 0) {
|
||||
const file = e.target.files[0];
|
||||
|
||||
// Check file size (e.g., max 5MB)
|
||||
if (file.size > 5 * 1024 * 1024) {
|
||||
setFormErrors((prev: any) => ({ ...prev, resume: "File size should be less than 5MB." }));
|
||||
setResumeFile(null);
|
||||
setResumeBase64(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check file type
|
||||
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
|
||||
if (!allowedTypes.includes(file.type)) {
|
||||
setFormErrors((prev: any) => ({ ...prev, resume: "Only PDF and Word documents are allowed." }));
|
||||
setResumeFile(null);
|
||||
setResumeBase64(null);
|
||||
return;
|
||||
}
|
||||
|
||||
setResumeFile(file);
|
||||
setFormErrors((prev: any) => ({ ...prev, resume: undefined }));
|
||||
|
||||
// Convert to Base64 for email attachment
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = () => {
|
||||
setResumeBase64(reader.result as string);
|
||||
};
|
||||
reader.onerror = (error) => {
|
||||
console.error("Error reading file:", error);
|
||||
setFormErrors((prev: any) => ({ ...prev, resume: "Error reading file." }));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const handleCaptchaChange = (token: string | null) => {
|
||||
setCaptchaToken(token);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
const elements = entry.target.querySelectorAll(".wow");
|
||||
elements.forEach((el) => {
|
||||
const htmlEl = el as HTMLElement;
|
||||
const delay = htmlEl.dataset.wowDelay || "0ms";
|
||||
setTimeout(() => {
|
||||
htmlEl.classList.add("animated");
|
||||
|
||||
if (htmlEl.classList.contains("fadeInLeft")) {
|
||||
htmlEl.classList.add("fadeInLeft");
|
||||
} else if (htmlEl.classList.contains("fadeInRight")) {
|
||||
htmlEl.classList.add("fadeInRight");
|
||||
} else {
|
||||
htmlEl.classList.add("fadeInUp");
|
||||
}
|
||||
|
||||
htmlEl.style.visibility = "visible";
|
||||
}, parseInt(delay));
|
||||
});
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold: 0.1 }
|
||||
);
|
||||
|
||||
if (sectionRef.current) {
|
||||
observer.observe(sectionRef.current);
|
||||
}
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
const errors: any = {};
|
||||
if (!formData.name.trim()) errors.name = "Name is required.";
|
||||
if (!formData.email.trim()) errors.email = "Email is required.";
|
||||
if (!formData.phone.trim()) errors.phone = "Phone is required.";
|
||||
if (!formData.position.trim()) errors.position = "Please select a position.";
|
||||
if (!captchaToken) errors.captcha = "Please verify the CAPTCHA.";
|
||||
if (!resumeFile) errors.resume = "Please upload your resume.";
|
||||
|
||||
setFormErrors(errors);
|
||||
if (Object.keys(errors).length > 0) return;
|
||||
|
||||
setIsSubmitting(true);
|
||||
|
||||
const emailData: any = {
|
||||
...formData,
|
||||
message: `Position: ${formData.position}<br /><br />Phone: ${formData.phone}<br /><br />Message: ${formData.message || "No additional message."}`,
|
||||
to: "info@metatroncubesolutions.com",
|
||||
senderName: "Metatroncube Careers Application",
|
||||
recaptchaToken: captchaToken,
|
||||
};
|
||||
|
||||
// If the backend endpoint supports attachments via Nodemailer's "attachments" array matching to data URI paths
|
||||
if (resumeBase64 && resumeFile) {
|
||||
emailData.attachments = [
|
||||
{
|
||||
filename: resumeFile.name,
|
||||
path: resumeBase64
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await axios.post("https://mailserver.metatronnest.com/send", emailData, {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
setAlert({
|
||||
show: true,
|
||||
type: "success",
|
||||
message: res?.data?.message || "Application submitted successfully!",
|
||||
});
|
||||
|
||||
setFormData({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
position: "",
|
||||
message: "",
|
||||
});
|
||||
setResumeFile(null);
|
||||
setResumeBase64(null);
|
||||
// Reset file input value manually
|
||||
const fileInput = document.getElementById("resume-upload") as HTMLInputElement;
|
||||
if (fileInput) fileInput.value = "";
|
||||
|
||||
setCaptchaToken(null);
|
||||
setFormErrors({});
|
||||
} catch (error) {
|
||||
console.error("❌ Error sending email:", error);
|
||||
setAlert({
|
||||
show: true,
|
||||
type: "danger",
|
||||
message: "Failed to submit application. Please try again later.",
|
||||
});
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (alert.show) {
|
||||
const timer = setTimeout(() => {
|
||||
setAlert((prev) => ({ ...prev, show: false }));
|
||||
}, 5000);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}, [alert.show]);
|
||||
|
||||
return (
|
||||
<section ref={sectionRef} className="contact-one section-space-bottom" id="careers-form">
|
||||
|
||||
<div className="container contact-one__container wow fadeInUp" data-wow-delay="100ms">
|
||||
<div
|
||||
className="contact-one__wrapper"
|
||||
style={{ backgroundImage: "url(/assets/images/careers/right-bottom-element.webp)" }}
|
||||
>
|
||||
<div className="row">
|
||||
<div className="col-lg-6">
|
||||
<div className="contact-one__image-two">
|
||||
<img src="/assets/images/careers/left-img.webp" alt="Career Growth" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6">
|
||||
<div className="contact-one__content">
|
||||
<div className="sec-title text-left">
|
||||
<h6 className="sec-title__tagline">
|
||||
<span className="sec-title__tagline__left"></span>
|
||||
Join Our Team
|
||||
<span className="sec-title__tagline__right"></span>
|
||||
</h6>
|
||||
<h3 className="sec-title__title" style={{ color: "#fff" }}>
|
||||
Apply for your dream position today.
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
{alert.show && (
|
||||
<div className={`alert alert-${alert.type === 'danger' ? 'danger' : 'success'} mb-4`} style={{ padding: '15px', color: '#fff', backgroundColor: alert.type === 'danger' ? 'rgba(255, 107, 107, 0.2)' : 'rgba(76, 175, 80, 0.2)', border: alert.type === 'danger' ? '1px solid #ff6b6b' : '1px solid #4CAF50', borderRadius: '8px' }}>
|
||||
{alert.message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form className="contact-one__form form-one" onSubmit={handleSubmit}>
|
||||
<div className="form-one__group">
|
||||
<div className="mb-20">
|
||||
<label className="form-label">Full Name *</label>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
placeholder="Full Name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
className="form-input"
|
||||
suppressHydrationWarning={true}
|
||||
/>
|
||||
{formErrors.name && <small className="text-danger">{formErrors.name}</small>}
|
||||
</div>
|
||||
<div className="mb-20">
|
||||
<label className="form-label">Email Address *</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="Email Address"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
className="form-input"
|
||||
suppressHydrationWarning={true}
|
||||
/>
|
||||
{formErrors.email && <small className="text-danger">{formErrors.email}</small>}
|
||||
</div>
|
||||
<div className="mb-20">
|
||||
<label className="form-label">Phone Number *</label>
|
||||
<input
|
||||
type="tel"
|
||||
name="phone"
|
||||
placeholder="Phone Number"
|
||||
value={formData.phone}
|
||||
onChange={handleChange}
|
||||
className="form-input"
|
||||
suppressHydrationWarning={true}
|
||||
/>
|
||||
{formErrors.phone && <small className="text-danger">{formErrors.phone}</small>}
|
||||
</div>
|
||||
<div className="mb-20">
|
||||
<label className="form-label">Select Position *</label>
|
||||
<select
|
||||
name="position"
|
||||
value={formData.position}
|
||||
onChange={handleChange}
|
||||
className="form-select-custom"
|
||||
suppressHydrationWarning={true}
|
||||
>
|
||||
<option value="">Select Position</option>
|
||||
<option value="Frontend Developer">Website Development</option>
|
||||
<option value="Backend Developer">Social Media Marketing</option>
|
||||
<option value="Full Stack Developer">Search Engine Optimization</option>
|
||||
<option value="UI/UX Designer">Mobile App Development</option>
|
||||
<option value="SEO Specialist">UI/UX Designing</option>
|
||||
<option value="Digital Marketing Executive">Graphic Designing</option>
|
||||
<option value="Other">Other</option>
|
||||
</select>
|
||||
{formErrors.position && <small className="text-danger">{formErrors.position}</small>}
|
||||
</div>
|
||||
|
||||
<div className="form-one__control--full mb-20 mt-2">
|
||||
<label className="form-label">Upload Resume (PDF, DOC, DOCX) *</label>
|
||||
<div className="custom-file-upload">
|
||||
<input
|
||||
id="resume-upload"
|
||||
type="file"
|
||||
name="resume"
|
||||
accept=".pdf,.doc,.docx,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
||||
onChange={handleFileChange}
|
||||
className="hidden-file-input"
|
||||
suppressHydrationWarning={true}
|
||||
/>
|
||||
<label htmlFor="resume-upload" className="file-upload-label">
|
||||
<div className="file-upload-content">
|
||||
<i className="fa-solid fa-cloud-arrow-up"></i>
|
||||
<span className="file-name">
|
||||
{resumeFile ? resumeFile.name : "Choose your resume"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="file-upload-browse">
|
||||
Browse
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
{formErrors.resume && <small className="text-danger">{formErrors.resume}</small>}
|
||||
</div>
|
||||
|
||||
<div className="form-one__control--full mb-20">
|
||||
<label className="form-label">Cover Letter / Message (Optional)</label>
|
||||
<textarea
|
||||
name="message"
|
||||
placeholder="Write your message here..."
|
||||
rows={3}
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
className="form-textarea"
|
||||
suppressHydrationWarning={true}
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div className="form-one__control--full mb-3 mt-3">
|
||||
<ReCAPTCHA
|
||||
sitekey="6LekfpwrAAAAAOTwuP1d2gg-Fv9UEsAjE2gjOQJl"
|
||||
onChange={handleCaptchaChange}
|
||||
/>
|
||||
{formErrors.captcha && <small className="text-danger">{formErrors.captcha}</small>}
|
||||
</div>
|
||||
|
||||
|
||||
<div className="form-one__control--full">
|
||||
<button type="submit" className="submit-btn-custom-global" disabled={isSubmitting} suppressHydrationWarning={true}>
|
||||
<b>{isSubmitting ? "SUBMITTING..." : "SUBMIT APPLICATION"}</b>
|
||||
<span></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default CareersForm;
|
||||
@ -181,54 +181,53 @@ const ContactSection = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form className="contact-one__form form-one" onSubmit={handleSubmit}>
|
||||
<div className="form-one__group">
|
||||
<form className="contact-one__form form-one" onSubmit={handleSubmit}> <div className="form-one__group">
|
||||
<div className="mb-20">
|
||||
<label className="form-label">Full Name</label>
|
||||
<label className="form-label-custom">Full Name</label>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
placeholder="Full Name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
className="form-input"
|
||||
className="form-input-custom-global"
|
||||
suppressHydrationWarning={true}
|
||||
/>
|
||||
{formErrors.name && <small className="text-danger">{formErrors.name}</small>}
|
||||
</div>
|
||||
<div className="mb-20">
|
||||
<label className="form-label">Email Address</label>
|
||||
<label className="form-label-custom">Email Address</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="Email Address"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
className="form-input"
|
||||
className="form-input-custom-global"
|
||||
suppressHydrationWarning={true}
|
||||
/>
|
||||
{formErrors.email && <small className="text-danger">{formErrors.email}</small>}
|
||||
</div>
|
||||
<div className="mb-20">
|
||||
<label className="form-label">Phone Number</label>
|
||||
<label className="form-label-custom">Phone Number</label>
|
||||
<input
|
||||
type="text"
|
||||
name="phone"
|
||||
placeholder="Phone Number"
|
||||
value={formData.phone}
|
||||
onChange={handleChange}
|
||||
className="form-input"
|
||||
className="form-input-custom-global"
|
||||
suppressHydrationWarning={true}
|
||||
/>
|
||||
{formErrors.phone && <small className="text-danger">{formErrors.phone}</small>}
|
||||
</div>
|
||||
<div className="mb-20">
|
||||
<label className="form-label">Select Service</label>
|
||||
<label className="form-label-custom">Select Service</label>
|
||||
<select
|
||||
name="service"
|
||||
value={formData.service}
|
||||
onChange={handleChange}
|
||||
className="form-select-custom"
|
||||
className="form-select-custom-styled-global"
|
||||
suppressHydrationWarning={true}
|
||||
>
|
||||
<option value="">Select Service</option>
|
||||
@ -242,14 +241,14 @@ const ContactSection = () => {
|
||||
{formErrors.service && <small className="text-danger">{formErrors.service}</small>}
|
||||
</div>
|
||||
<div className="form-one__control--full mb-20">
|
||||
<label className="form-label">Write Message</label>
|
||||
<label className="form-label-custom">Write Message</label>
|
||||
<textarea
|
||||
name="message"
|
||||
placeholder="Write Message"
|
||||
rows={4}
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
className="form-textarea"
|
||||
className="form-textarea-custom-global"
|
||||
suppressHydrationWarning={true}
|
||||
></textarea>
|
||||
{formErrors.message && <small className="text-danger">{formErrors.message}</small>}
|
||||
|
||||
@ -53,7 +53,7 @@ const FaqPageSection = () => {
|
||||
<div className="section-title-wrapper">
|
||||
<div className="sec-title__shape"></div>
|
||||
<h6 className="sec-title__tagline">Digital Mastery Unlocked</h6>
|
||||
<h2 className="section-title mt-4" style={{ margin: 0 }}>Metatroncube FAQs: Web-Apps, SEO, & Digital Marketing</h2>
|
||||
<h2 className="sec-title__title" style={{ margin: 0 }}>Metatroncube FAQs: Web-Apps, SEO, & Digital Marketing</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6">
|
||||
|
||||
@ -10,7 +10,7 @@ const projectsData = [
|
||||
description: "5 Feb, 2025 | Full Time",
|
||||
image: "/assets/images/careers/4/web.webp",
|
||||
category: "web",
|
||||
link: "/services-digital-solutions/website-development-company"
|
||||
link: "#"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
@ -18,7 +18,7 @@ const projectsData = [
|
||||
description: "5 Feb, 2025 | Full Time",
|
||||
image: "/assets/images/careers/4/seo.webp",
|
||||
category: "seo",
|
||||
link: "/services-digital-solutions/search-engine-optimization-seo-content-writing"
|
||||
link: "#"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
@ -26,7 +26,7 @@ const projectsData = [
|
||||
description: "5 Feb, 2025 | Full Time",
|
||||
image: "/assets/images/careers/4/smm.webp",
|
||||
category: "dm",
|
||||
link: "/services-digital-solutions/digital-marketing-agency-in-canada"
|
||||
link: "#"
|
||||
}
|
||||
];
|
||||
|
||||
@ -126,30 +126,25 @@ const ProjectsSection = () => {
|
||||
|
||||
{filteredProjects.map((project) => (
|
||||
<div key={project.id} className="project-item">
|
||||
<div className="projects-one__card" onClick={(e) => openPopup(project.title, e)}>
|
||||
<div className="projects-one__card" style={{ cursor: 'pointer' }} onClick={(e) => openPopup(project.title, e)}>
|
||||
<img src={project.image} alt={project.title} />
|
||||
<div className="projects-one__card__hover d-flex">
|
||||
<div className="projects-one__card__hover-mask"></div>
|
||||
<div className="projects-one__card__hover-content-inner">
|
||||
<div className="projects-one__card__hover-text">
|
||||
<h3>
|
||||
<a
|
||||
href="#"
|
||||
onClick={(e) => openPopup(project.title, e)}
|
||||
>
|
||||
{project.title}
|
||||
</a>
|
||||
<h3 style={{ color: 'white' }}>
|
||||
{project.title}
|
||||
</h3>
|
||||
<p>{project.description}</p>
|
||||
</div>
|
||||
<div className="projects-one__card__hover-item"></div>
|
||||
<a
|
||||
href="#"
|
||||
<div
|
||||
className="projects-one__card__hover-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={(e) => openPopup(project.title, e)}
|
||||
>
|
||||
<i className="fa fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user