Add contact form functionality and enhance logo styles
This commit is contained in:
parent
236e64a2cc
commit
04c59f7d7a
|
@ -0,0 +1,54 @@
|
||||||
|
import { Resend } from 'resend';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cloudflare Pages Function - /api/send-email
|
||||||
|
*/
|
||||||
|
export async function onRequestPost(context) {
|
||||||
|
const { name, email, subject, message } = await context.request.json();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch("https://api.mailersend.com/v1/email", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer " + context.env.MAILERSEND_API_KEY,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
from: {
|
||||||
|
email: "daniel@laforceit.com",
|
||||||
|
name: "Daniel LaForce"
|
||||||
|
},
|
||||||
|
to: [
|
||||||
|
{
|
||||||
|
email: "daniel@laforceit.com",
|
||||||
|
name: "Daniel LaForce"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
subject: `[Argobox] ${subject}`,
|
||||||
|
html: `
|
||||||
|
<h2>New Contact Message</h2>
|
||||||
|
<p><strong>Name:</strong> ${name}</p>
|
||||||
|
<p><strong>Email:</strong> ${email}</p>
|
||||||
|
<p><strong>Message:</strong><br>${message.replace(/\n/g, "<br>")}</p>
|
||||||
|
`,
|
||||||
|
reply_to: [
|
||||||
|
{
|
||||||
|
email,
|
||||||
|
name
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error("MailerSend Error:", await response.json());
|
||||||
|
return new Response(JSON.stringify({ error: "Failed to send email" }), { status: 500 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify({ success: true }), { status: 200 });
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Unexpected Error:", err);
|
||||||
|
return new Response(JSON.stringify({ error: "Unexpected server error" }), { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
<!-- CSS -->
|
<!-- CSS -->
|
||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
<link rel="stylesheet" href="test-styles.css">
|
|
||||||
|
|
||||||
<!-- Font Awesome -->
|
<!-- Font Awesome -->
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
|
||||||
|
@ -41,8 +40,7 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<a href="#home">
|
<a href="#home">
|
||||||
<span class="logo-text">LaForceIT</span>
|
<span class="logo-text-glow">LaForceIT</span><span class="logo-dot-glow">.com</span>
|
||||||
<span class="logo-dot">.com</span>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-menu">
|
<div class="nav-menu">
|
||||||
|
|
|
@ -294,8 +294,8 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<a href="index.html">
|
<a href="index.html">
|
||||||
<span class="logo-text">Argobox</span>
|
<span class="logo-text-glow">LaForceIT</span>
|
||||||
<span class="logo-dot">.com</span>
|
<span class="logo-dot-glow">.com</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-menu">
|
<div class="nav-menu">
|
||||||
|
@ -805,8 +805,8 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="footer-content">
|
<div class="footer-content">
|
||||||
<div class="footer-logo">
|
<div class="footer-logo">
|
||||||
<span class="logo-text">Argobox</span>
|
<span class="logo-text-glow">LaForceIT</span>
|
||||||
<span class="logo-dot">.com</span>
|
<span class="logo-dot-glow">.com</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer-links">
|
<div class="footer-links">
|
||||||
|
|
37
script.js
37
script.js
|
@ -394,11 +394,14 @@ function updateMetrics() {
|
||||||
setInterval(updateMetricValues, 5000);
|
setInterval(updateMetricValues, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize contact form handling
|
||||||
|
*/
|
||||||
/**
|
/**
|
||||||
* Initialize contact form handling
|
* Initialize contact form handling
|
||||||
*/
|
*/
|
||||||
function initFormHandling(form) {
|
function initFormHandling(form) {
|
||||||
form.addEventListener('submit', async function(e) {
|
form.addEventListener('submit', async function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const submitButton = form.querySelector('button[type="submit"]');
|
const submitButton = form.querySelector('button[type="submit"]');
|
||||||
|
@ -406,20 +409,34 @@ function initFormHandling(form) {
|
||||||
submitButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Sending...';
|
submitButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Sending...';
|
||||||
submitButton.disabled = true;
|
submitButton.disabled = true;
|
||||||
|
|
||||||
|
const formData = {
|
||||||
|
name: form.elements['name'].value,
|
||||||
|
email: form.elements['email'].value,
|
||||||
|
subject: form.elements['subject'].value,
|
||||||
|
message: form.elements['message'].value
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Simulated form submission - in production replace with actual API call
|
const res = await fetch("/api/send-email", {
|
||||||
// const formData = new FormData(form);
|
method: "POST",
|
||||||
// const formValues = Object.fromEntries(formData.entries());
|
headers: {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
body: JSON.stringify(formData)
|
||||||
|
});
|
||||||
|
|
||||||
// Simulated API response delay
|
const data = await res.json();
|
||||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
||||||
|
|
||||||
// Success message
|
if (data.success) {
|
||||||
alert('Thank you for your message! I will get back to you soon.');
|
alert("Thank you for your message! I will get back to you soon.");
|
||||||
form.reset();
|
form.reset();
|
||||||
|
} else {
|
||||||
|
alert("Failed to send message. Please try again or contact me directly.");
|
||||||
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error);
|
console.error("Error:", error);
|
||||||
alert('Failed to send message. Please try again or contact me directly via email.');
|
alert("Something went wrong while sending your message.");
|
||||||
} finally {
|
} finally {
|
||||||
submitButton.innerHTML = originalButtonText;
|
submitButton.innerHTML = originalButtonText;
|
||||||
submitButton.disabled = false;
|
submitButton.disabled = false;
|
||||||
|
|
35
styles.css
35
styles.css
|
@ -215,7 +215,8 @@ section {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
background: linear-gradient(135deg, #3b82f6, #2563eb);
|
background: linear-gradient(135deg, #3b82f6, #2563eb);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
text-shadow: 0 0 8px rgba(59, 130, 246, 0.5);
|
text-shadow: 0 0 8px rgba(59, 130, 246, 0.5);
|
||||||
}
|
}
|
||||||
|
@ -1506,3 +1507,35 @@ section {
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
LaForceIT.com Logo Styling
|
||||||
|
============================ */
|
||||||
|
|
||||||
|
.logo-text-glow {
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
background: linear-gradient(90deg, var(--accent), var(--accent-darker));
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
text-shadow: 0 0 6px rgba(59, 130, 246, 0.5);
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-dot-glow {
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
margin-left: 2px;
|
||||||
|
text-shadow: 0 0 3px rgba(255, 255, 255, 0.3);
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-text-glow:hover,
|
||||||
|
.logo-dot-glow:hover {
|
||||||
|
text-shadow: 0 0 10px rgba(59, 130, 246, 0.8), 0 0 8px rgba(255, 255, 255, 0.3);
|
||||||
|
transform: scale(1.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
/* Test CSS file to confirm changes are working */
|
|
||||||
|
|
||||||
/* Save this as test-styles.css in your repository root */
|
|
||||||
|
|
||||||
/* Logo Styles - Enhanced Version */
|
|
||||||
.logo {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo a {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
text-decoration: none;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo-text {
|
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
background: linear-gradient(90deg, #ff0000 0%, #ff6e00 50%, #ffa500 100%);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
color: transparent;
|
|
||||||
position: relative;
|
|
||||||
text-shadow: 0 0 15px rgba(255, 150, 100, 0.2);
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo-dot {
|
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
color: #ff6e00;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Logo with tech icon detail - using different brackets to be obviously visible */
|
|
||||||
.logo a::before {
|
|
||||||
content: "[ ";
|
|
||||||
font-family: 'JetBrains Mono', monospace;
|
|
||||||
color: #ff6e00;
|
|
||||||
font-weight: bold;
|
|
||||||
opacity: 0.8;
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo a::after {
|
|
||||||
content: " ]";
|
|
||||||
font-family: 'JetBrains Mono', monospace;
|
|
||||||
color: #ff6e00;
|
|
||||||
font-weight: bold;
|
|
||||||
opacity: 0.8;
|
|
||||||
margin-left: 2px;
|
|
||||||
}
|
|
Loading…
Reference in New Issue