diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..efaa271 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,118 @@ + +:root { + --primary-color: #3E66F8; + --secondary-color: #FF6B6B; + --background-color: #F8F9FA; + --surface-color: #FFFFFF; + --text-color: #212529; + --light-text-color: #6c757d; +} + +body { + font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + background-color: var(--background-color); + color: var(--text-color); +} + +.navbar-brand { + font-weight: bold; +} + +.hero { + background: linear-gradient(120deg, var(--primary-color), #2E52D9); + color: white; + padding: 6rem 0; + text-align: center; +} + +.hero h1 { + font-size: 3.5rem; + font-weight: 700; +} + +.hero p { + font-size: 1.25rem; + max-width: 600px; + margin: 1rem auto; +} + +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); + border-radius: 0.5rem; + padding: 0.75rem 1.5rem; + font-weight: 500; + transition: all 0.3s ease; +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.btn-secondary { + background-color: var(--secondary-color); + border-color: var(--secondary-color); + border-radius: 0.5rem; + padding: 0.75rem 1.5rem; + font-weight: 500; + transition: all 0.3s ease; +} + +.btn-secondary:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + + +.section { + padding: 5rem 0; +} + +.section-title { + text-align: center; + font-size: 2.5rem; + font-weight: 700; + margin-bottom: 3rem; +} + +.card { + border: none; + border-radius: 0.5rem; + box-shadow: 0 4px 25px rgba(0, 0, 0, 0.08); + transition: all 0.3s ease; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); +} + +.portfolio-card .card-img-top { + border-top-left-radius: 0.5rem; + border-top-right-radius: 0.5rem; +} + +.contact-form { + background: var(--surface-color); + padding: 3rem; + border-radius: 0.5rem; + box-shadow: 0 4px 25px rgba(0, 0, 0, 0.08); +} + +.form-control { + border-radius: 0.5rem; + padding: 0.75rem; +} + +.form-control:focus { + box-shadow: 0 0 0 0.25rem rgba(62, 102, 248, 0.25); + border-color: var(--primary-color); +} + +.footer { + background: var(--surface-color); + padding: 2rem 0; + text-align: center; + border-top: 1px solid #e9ecef; +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..855636e --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,64 @@ + +document.addEventListener('DOMContentLoaded', function () { + // Smooth scroll for navigation links + const navLinks = document.querySelectorAll('.nav-link'); + navLinks.forEach(link => { + if (link.hash !== '') { + link.addEventListener('click', function (e) { + e.preventDefault(); + const target = document.querySelector(this.hash); + if (target) { + window.scrollTo({ + top: target.offsetTop - 70, // Adjust for fixed navbar + behavior: 'smooth' + }); + } + }); + } + }); + + // Contact form submission + const contactForm = document.getElementById('contactForm'); + const toastContainer = document.getElementById('notificationToast'); + const toastBody = document.querySelector('#notificationToast .toast-body'); + const toast = new bootstrap.Toast(toastContainer); + + if (contactForm) { + contactForm.addEventListener('submit', function (e) { + e.preventDefault(); + const formData = new FormData(this); + const submitButton = this.querySelector('button[type="submit"]'); + submitButton.disabled = true; + submitButton.innerHTML = ' Sending...'; + + fetch('contact_handler.php', { + method: 'POST', + body: formData + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + toastBody.textContent = 'Message sent successfully! Thank you.'; + toastContainer.classList.remove('bg-danger'); + toastContainer.classList.add('bg-success'); + contactForm.reset(); + } else { + toastBody.textContent = data.error || 'An unknown error occurred.'; + toastContainer.classList.remove('bg-success'); + toastContainer.classList.add('bg-danger'); + } + toast.show(); + }) + .catch(error => { + toastBody.textContent = 'A network error occurred. Please try again.'; + toastContainer.classList.remove('bg-success'); + toastContainer.classList.add('bg-danger'); + toast.show(); + }) + .finally(() => { + submitButton.disabled = false; + submitButton.innerHTML = 'Send Message'; + }); + }); + } +}); diff --git a/contact_handler.php b/contact_handler.php new file mode 100644 index 0000000..31f01f1 --- /dev/null +++ b/contact_handler.php @@ -0,0 +1,107 @@ +exec("CREATE TABLE IF NOT EXISTS contact_submissions ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + subject VARCHAR(255) NOT NULL, + message TEXT NOT NULL, + submitted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )"); +} catch (PDOException $e) { + error_log("Database schema creation failed: " . $e->getMessage()); + echo json_encode(['success' => false, 'error' => 'Could not initialize database. Please try again later.']); + exit; +} + +// --- Form Submission Handling --- +if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + echo json_encode(['success' => false, 'error' => 'Invalid request method.']); + exit; +} + +// --- Input Validation --- +$name = trim($_POST['name'] ?? ''); +$email = trim($_POST['email'] ?? ''); +$subject = trim($_POST['subject'] ?? ''); +$message = trim($_POST['message'] ?? ''); + +if (empty($name) || empty($email) || empty($subject) || empty($message)) { + echo json_encode(['success' => false, 'error' => 'Please fill out all fields.']); + exit; +} + +if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { + echo json_encode(['success' => false, 'error' => 'Please provide a valid email address.']); + exit; +} + +// --- Store in Database --- +try { + $stmt = $pdo->prepare("INSERT INTO contact_submissions (name, email, subject, message) VALUES (?, ?, ?, ?)"); + $stmt->execute([$name, $email, $subject, $message]); +} catch (PDOException $e) { + error_log("Database insert failed: " . $e->getMessage()); + echo json_encode(['success' => false, 'error' => 'Could not save your message. Please try again later.']); + exit; +} + +// --- Send Email Notifications --- +$siteOwnerEmail = getenv('MAIL_TO') ?: (getenv('MAIL_FROM') ?: 'admin@example.com'); +$projectName = $_SERVER['PROJECT_NAME'] ?? 'Your Website'; + +// 1. Notification to Site Owner +$ownerSubject = "New Contact Form Submission: " . htmlspecialchars($subject); +$ownerHtmlBody = " +

New message from your website contact form:

+

Name: " . htmlspecialchars($name) . "

+

Email: " . htmlspecialchars($email) . "

+

Subject: " . htmlspecialchars($subject) . "

+

Message:

+

" . nl2br(htmlspecialchars($message)) . "

+"; +$ownerTextBody = "New message from your website contact form:\nName: $name\nEmail: $email\nSubject: $subject\nMessage:\n$message"; + +MailService::sendMail( + $siteOwnerEmail, + $ownerSubject, + $ownerHtmlBody, + $ownerTextBody, + ['reply_to' => $email] +); + +// 2. Auto-reply to Visitor +$visitorSubject = "Thank you for contacting " . $projectName; +$visitorHtmlBody = " +

Thank You For Your Message!

+

Hello " . htmlspecialchars($name) . ",

+

We have received your message and will get back to you as soon as possible.

+

Here is a copy of your submission:

+
+

Subject: " . htmlspecialchars($subject) . "

+

Message:

+

" . nl2br(htmlspecialchars($message)) . "

+
+

Best regards,
" . $projectName . "

+"; +$visitorTextBody = "Hello $name,\nThank you for your message! We have received it and will get back to you shortly.\n\nYour submission:\nSubject: $subject\nMessage: $message\n\nBest regards,\n" . $projectName; + +MailService::sendMail( + $email, + $visitorSubject, + $visitorHtmlBody, + $visitorTextBody +); + + +// --- Success Response --- +echo json_encode(['success' => true]); + diff --git a/index.php b/index.php index 7205f3d..17f209c 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,180 @@ - - + - - - New Style - - - - - - - - - - - - - - - - - - - + + + + + <?php echo htmlspecialchars($_SERVER['PROJECT_NAME'] ?? 'Personal Portfolio'); ?> + + + + + + + + + + + + + + + + + + + + + -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

+ + + + + +
+
+

Creative Developer & Designer

+

I build beautiful, functional, and user-centric web experiences.

+ View My Work +
+
+ + +
+
+

About Me

+
+
+ A portrait of John Doe +
+
+

Hello, I'm John Doe.

+

I am a passionate and results-oriented web developer with over 5 years of experience in creating dynamic websites and applications. My expertise lies in front-end technologies, but I am also proficient in back-end development, allowing me to build complete and robust solutions.

+

I believe in clean code, intuitive design, and the power of technology to solve real-world problems. When I'm not coding, I enjoy hiking, photography, and exploring new coffee shops.

+ +
+
+
+
+ + +
+
+

My Portfolio

+
+ +
+
+ Portfolio Project 1 +
+
Project One
+

A web application for managing tasks and boosting productivity. Built with modern JavaScript frameworks.

+ View Details +
+
+
+ +
+
+ Portfolio Project 2 +
+
Project Two
+

An e-commerce platform with a focus on user experience and a clean, minimalist design.

+ View Details +
+
+
+ +
+
+ Portfolio Project 3 +
+
Project Three
+

A corporate website redesign that resulted in a 40% increase in user engagement.

+ View Details +
+
+
+
+
+
+ + +
+
+

Get In Touch

+
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+
+
+
+ + +
+
+

© . All Rights Reserved.

+
+
+ + +
+
-
- + + + + - + \ No newline at end of file