From 1b5551aaed8c0258975934252646c85f612a6915 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Tue, 9 Sep 2025 18:50:56 +0000 Subject: [PATCH] v1 --- .env | 1 + assets/css/custom.css | 84 +++++++++ assets/js/main.js | 63 +++++++ index.php | 383 ++++++++++++++++++++++++++++-------------- mail/MailService.php | 39 ++++- mail/config.php | 5 + 6 files changed, 452 insertions(+), 123 deletions(-) create mode 100644 assets/css/custom.css create mode 100644 assets/js/main.js diff --git a/.env b/.env index 89d3816..39aae27 100644 --- a/.env +++ b/.env @@ -11,5 +11,6 @@ SMTP_USER=your_username SMTP_PASS=your_password # Email 'From' and 'Reply-To' Addresses +MAIL_TO=contact@avareed.design MAIL_FROM=you@example.com MAIL_FROM_NAME="Ava Reed Portfolio" diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..6bfd596 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,84 @@ + +/* Google Fonts */ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&family=Lato:wght@400;700&display=swap'); + +:root { + --primary-color: #0d6efd; + --secondary-color: #6c757d; + --background-color: #f8f9fa; + --surface-color: #ffffff; + --heading-font: 'Poppins', sans-serif; + --body-font: 'Lato', sans-serif; + --border-radius: 0.5rem; +} + +body { + font-family: var(--body-font); + background-color: var(--background-color); + color: #333; +} + +h1, h2, h3, h4, h5, h6 { + font-family: var(--heading-font); + font-weight: 600; +} + +.navbar { + transition: background-color 0.3s ease-in-out; +} + +.navbar-scrolled { + background-color: var(--surface-color); + box-shadow: 0 2px 4px rgba(0,0,0,0.05); +} + +.hero { + background: linear-gradient(45deg, #0d6efd, #7aaaff); + color: white; + padding: 8rem 0; +} + +.hero h1 { + font-size: 3.5rem; + font-weight: 700; +} + +.section { + padding: 4rem 0; +} + +.card { + border: none; + border-radius: var(--border-radius); + box-shadow: 0 4px 6px rgba(0,0,0,0.1); + transition: transform 0.2s ease-in-out; +} + +.card:hover { + transform: translateY(-5px); +} + +.form-control:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + border-color: #86b7fe; +} + +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); + border-radius: var(--border-radius); + padding: 0.75rem 1.5rem; + font-weight: 600; +} + +.avatar { + width: 96px; + height: 96px; + border-radius: 50%; +} + +.about-avatar { + width: 256px; + height: 256px; + border-radius: 50%; +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..3315690 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,63 @@ + +document.addEventListener('DOMContentLoaded', function () { + // Smooth scroll for anchor links + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function (e) { + e.preventDefault(); + document.querySelector(this.getAttribute('href')).scrollIntoView({ + behavior: 'smooth' + }); + }); + }); + + // Navbar scroll effect + const navbar = document.querySelector('.navbar'); + window.addEventListener('scroll', () => { + if (window.scrollY > 50) { + navbar.classList.add('navbar-scrolled'); + } else { + navbar.classList.remove('navbar-scrolled'); + } + }); + + // Contact form validation + const form = document.querySelector('#contactForm'); + const form = document.querySelector('#contactForm'); + if (form) { + form.addEventListener('submit', function(event) { + let isValid = true; + // Clear previous errors + document.querySelectorAll('.invalid-feedback').forEach(el => el.style.display = 'none'); + document.querySelectorAll('.form-control').forEach(el => el.classList.remove('is-invalid')); + + // Name validation + const name = document.querySelector('#name'); + if (name.value.trim() === '') { + isValid = false; + name.classList.add('is-invalid'); + document.querySelector('#nameError').style.display = 'block'; + } + + // Email validation + const email = document.querySelector('#email'); + const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!emailPattern.test(email.value)) { + isValid = false; + email.classList.add('is-invalid'); + document.querySelector('#emailError').style.display = 'block'; + } + + // Message validation + const message = document.querySelector('#message'); + if (message.value.trim() === '') { + isValid = false; + message.classList.add('is-invalid'); + document.querySelector('#messageError').style.display = 'block'; + } + + if (!isValid) { + event.preventDefault(); + } + }); + } +}); diff --git a/index.php b/index.php index e13ae95..9fe837b 100644 --- a/index.php +++ b/index.php @@ -1,131 +1,270 @@ 'success', 'text' => 'Thank you! Your message has been sent.']; + } else { + // For security, don't expose detailed error messages to the user. + error_log($result['error']); + $_SESSION['message_status'] = ['type' => 'danger', 'text' => 'Sorry, there was an error sending your message. Please try again later.']; + } + } else { + $_SESSION['message_status'] = ['type' => 'danger', 'text' => 'Invalid input. Please check your form entries.']; + } + + // Redirect to the same page to clear the POST data + header("Location: " . $_SERVER['PHP_SELF'] . "#contact"); + exit(); +} + +if (isset($_SESSION['message_status'])) { + $message_status = $_SESSION['message_status']; + unset($_SESSION['message_status']); +} ?> - + - - - New Style - - - - + + + Ava Reed | Creative Developer & Designer + + + + -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

Flatlogic AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

-
-
- + + + + + +
+
+

Ava Reed: Creative Developer & Designer

+

Building beautiful, functional websites and applications.

+ Contact Me +
+
+ +
+ +
+
+

Selected Work

+
+ +
+
+ Placeholder for project showcase item 1 +
+
Project One
+

A brief description of the project goes here.

+
+
+
+ +
+
+ Placeholder for project showcase item 2 +
+
Project Two
+

A brief description of the project goes here.

+
+
+
+ +
+
+ Placeholder for project showcase item 3 +
+
Project Three
+

A brief description of the project goes here.

+
+
+
+ +
+
+ Placeholder for project showcase item 4 +
+
Project Four
+

A brief description of the project goes here.

+
+
+
+ +
+
+ Placeholder for project showcase item 5 +
+
Project Five
+

A brief description of the project goes here.

+
+
+
+ +
+
+ Placeholder for project showcase item 6 +
+
Project Six
+

A brief description of the project goes here.

+
+
+
+
+
+
+ + +
+
+

What I Do

+
+
+
+
Web Design
+

Creating modern and responsive designs that are intuitive and user-friendly.

+
+
+
+
+
Web Development
+

Building fast, secure, and scalable web applications from the ground up.

+
+
+
+
+
UI/UX Consulting
+

Improving user satisfaction by enhancing the usability and accessibility of products.

+
+
+
+
+
+ + +
+
+

What Clients Say

+
+
+
+
+ Avatar of a satisfied client +
+

"Ava is a pleasure to work with. Her attention to detail is second to none."

+
Client One
+
+
+
+
+
+
+
+ Avatar of a satisfied client +
+

"The final product exceeded our expectations. Highly recommended!"

+
Client Two
+
+
+
+
+
+
+
+ + +
+
+
+
+ Headshot of Ava Reed +
+
+

About Me

+

I'm Ava Reed, a passionate developer and designer with a knack for creating elegant solutions in the least amount of time. I specialize in front-end development and love bringing ideas to life in the browser.

+

When I'm not coding, you can find me exploring new technologies, hiking, or enjoying a good cup of coffee.

+
+
+
+
+ + +
+
+

Let's Get in Touch

+
+
+ + + +
+
+ + +
Please enter your name.
+
+
+ + +
Please enter a valid email address.
+
+
+ + +
Please enter a message.
+
+ +
+
+
+
+
+
+ + + + + + + + diff --git a/mail/MailService.php b/mail/MailService.php index 0f655d5..8a2909a 100644 --- a/mail/MailService.php +++ b/mail/MailService.php @@ -144,7 +144,10 @@ class MailService } $transport = $cfg['transport'] ?? 'smtp'; - if ($transport === 'smtp' && class_exists('PHPMailer\\PHPMailer\\PHPMailer')) { + if ($transport === 'log') { + return self::sendViaLog($cfg, $name, $email, $message, $to, $subject); + } + if ($transport === 'smtp' && class_exists('PHPMailer\PHPMailer\PHPMailer')) { return self::sendViaPHPMailer($cfg, $name, $email, $message, $to, $subject); } @@ -152,6 +155,40 @@ class MailService return self::sendViaNativeMail($cfg, $name, $email, $message, $to, $subject); } + private static function sendViaLog(array $cfg, string $name, string $email, string $body, $to, string $subject) + { + $logPath = __DIR__ . '/../storage/logs/mail.log'; + $logDir = dirname($logPath); + if (!is_dir($logDir)) { + @mkdir($logDir, 0775, true); + } + + $toList = []; + if ($to) { + if (is_string($to)) $toList = array_map('trim', explode(',', $to)); + elseif (is_array($to)) $toList = $to; + } elseif (!empty(getenv('MAIL_TO'))) { + $toList = array_map('trim', explode(',', getenv('MAIL_TO'))); + } + if (empty($toList)) { + $toList[] = $cfg['from_email'] ?? 'no-reply@localhost'; + } + + $log_message = sprintf( + "[%s] MAIL: To: %s, Subject: %s, From: %s <%s>\n---\n%s\n---", + date('Y-m-d H:i:s'), + implode(', ', $toList), + $subject, + $name, + $email, + $body + ); + + $ok = @file_put_contents($logPath, $log_message, FILE_APPEND); + + return ['success' => $ok !== false]; + } + private static function sendViaPHPMailer(array $cfg, string $name, string $email, string $body, $to, string $subject) { $mail = new PHPMailer\PHPMailer\PHPMailer(true); diff --git a/mail/config.php b/mail/config.php index c0ad9b9..cec6d46 100644 --- a/mail/config.php +++ b/mail/config.php @@ -45,6 +45,11 @@ $smtp_secure = env_val('SMTP_SECURE', 'tls'); // tls | ssl | null $smtp_user = env_val('SMTP_USER'); $smtp_pass = env_val('SMTP_PASS'); +// If using SMTP but the host is the placeholder, fall back to 'log' transport +if ($transport === 'smtp' && $smtp_host === 'smtp.example.com') { + $transport = 'log'; +} + $from_email = env_val('MAIL_FROM', 'no-reply@localhost'); $from_name = env_val('MAIL_FROM_NAME', 'App'); $reply_to = env_val('MAIL_REPLY_TO');