From f9810fa98d77f5f130967c50b4f4392a4ef842d6 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Mon, 9 Feb 2026 12:06:07 +0000 Subject: [PATCH] 1 --- assets/css/custom.css | 399 ++++-------------- assets/js/main.js | 130 +++--- db/config.php | 25 +- db/migrations/001_create_contact_requests.sql | 7 + index.php | 349 +++++++++------ process_contact.php | 44 ++ 6 files changed, 421 insertions(+), 533 deletions(-) create mode 100644 db/migrations/001_create_contact_requests.sql create mode 100644 process_contact.php diff --git a/assets/css/custom.css b/assets/css/custom.css index 65a1626..7f94136 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -1,346 +1,109 @@ +/* Professional Portfolio Styling */ :root { - --color-bg: #ffffff; - --color-text: #1a1a1a; - --color-primary: #2563EB; /* Vibrant Blue */ - --color-secondary: #000000; - --color-accent: #A3E635; /* Lime Green */ - --color-surface: #f8f9fa; - --font-heading: 'Space Grotesk', sans-serif; - --font-body: 'Inter', sans-serif; - --border-width: 2px; - --shadow-hard: 5px 5px 0px #000; - --shadow-hover: 8px 8px 0px #000; - --radius-pill: 50rem; - --radius-card: 1rem; + --primary: #1A1A1A; + --accent: #0066FF; + --bg-light: #F8F9FA; + --border: #E5E5E5; + --text-muted: #666666; } body { - font-family: var(--font-body); - background-color: var(--color-bg); - color: var(--color-text); - overflow-x: hidden; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + color: var(--primary); + line-height: 1.6; + scroll-behavior: smooth; } -h1, h2, h3, h4, h5, h6, .navbar-brand { - font-family: var(--font-heading); - letter-spacing: -0.03em; -} - -/* Utilities */ -.text-primary { color: var(--color-primary) !important; } -.bg-black { background-color: #000 !important; } -.text-white { color: #fff !important; } -.shadow-hard { box-shadow: var(--shadow-hard); } -.border-2-black { border: var(--border-width) solid #000; } -.py-section { padding-top: 5rem; padding-bottom: 5rem; } - -/* Navbar */ -.navbar { - background: rgba(255, 255, 255, 0.9); - backdrop-filter: blur(10px); - border-bottom: var(--border-width) solid transparent; - transition: all 0.3s; - padding-top: 1rem; - padding-bottom: 1rem; -} - -.navbar.scrolled { - border-bottom-color: #000; - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -.brand-text { - font-size: 1.5rem; - font-weight: 800; -} - -.nav-link { - font-weight: 500; - color: var(--color-text); - margin-left: 1rem; - position: relative; -} - -.nav-link:hover, .nav-link.active { - color: var(--color-primary); -} - -/* Buttons */ -.btn { +h1, h2, h3, h4 { font-weight: 700; - font-family: var(--font-heading); - padding: 0.8rem 2rem; - border-radius: var(--radius-pill); - border: var(--border-width) solid #000; - transition: all 0.2s cubic-bezier(0.25, 1, 0.5, 1); - box-shadow: var(--shadow-hard); + letter-spacing: -0.02em; } -.btn:hover { - transform: translate(-2px, -2px); - box-shadow: var(--shadow-hover); +.navbar { + border-bottom: 1px solid var(--border); + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); } -.btn:active { - transform: translate(2px, 2px); - box-shadow: 0 0 0 #000; +.hero { + padding: 120px 0 80px; + background: #ffffff; +} + +.hero h1 { + font-size: 4rem; + margin-bottom: 1.5rem; +} + +.section-padding { + padding: 100px 0; +} + +.bg-light { + background-color: var(--bg-light) !important; +} + +.card { + border: 1px solid var(--border); + border-radius: 4px; + transition: transform 0.2s ease, box-shadow 0.2s ease; + overflow: hidden; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); } .btn-primary { - background-color: var(--color-primary); - border-color: #000; - color: #fff; + background-color: var(--accent); + border-color: var(--accent); + border-radius: 4px; + padding: 0.75rem 1.5rem; + font-weight: 600; } -.btn-primary:hover { - background-color: #1d4ed8; - border-color: #000; - color: #fff; +.btn-outline-primary { + color: var(--accent); + border-color: var(--accent); + border-radius: 4px; } -.btn-outline-dark { - background-color: #fff; - color: #000; -} - -.btn-cta { - background-color: var(--color-accent); - color: #000; -} - -.btn-cta:hover { - background-color: #8cc629; - color: #000; -} - -/* Hero Section */ -.hero-section { - min-height: 100vh; - padding-top: 80px; -} - -.background-blob { - position: absolute; - border-radius: 50%; - filter: blur(80px); - opacity: 0.6; - z-index: 1; -} - -.blob-1 { - top: -10%; - right: -10%; - width: 600px; - height: 600px; - background: radial-gradient(circle, var(--color-accent), transparent); -} - -.blob-2 { - bottom: 10%; - left: -10%; - width: 500px; - height: 500px; - background: radial-gradient(circle, var(--color-primary), transparent); -} - -.highlight-text { - background: linear-gradient(120deg, transparent 0%, transparent 40%, var(--color-accent) 40%, var(--color-accent) 100%); - background-repeat: no-repeat; - background-size: 100% 40%; - background-position: 0 88%; - padding: 0 5px; -} - -.dot { color: var(--color-primary); } - -.badge-pill { - display: inline-block; - padding: 0.5rem 1rem; - border: 2px solid #000; - border-radius: 50px; - font-weight: 700; - background: #fff; - box-shadow: 4px 4px 0 #000; - font-family: var(--font-heading); - font-size: 0.9rem; -} - -/* Marquee */ -.marquee-container { - overflow: hidden; - white-space: nowrap; - border-top: 2px solid #000; - border-bottom: 2px solid #000; -} - -.rotate-divider { - transform: rotate(-2deg) scale(1.05); - z-index: 10; - position: relative; - margin-top: -50px; - margin-bottom: 30px; -} - -.marquee-content { - display: inline-block; - animation: marquee 20s linear infinite; - font-family: var(--font-heading); - font-weight: 700; - font-size: 1.5rem; - letter-spacing: 2px; -} - -@keyframes marquee { - 0% { transform: translateX(0); } - 100% { transform: translateX(-50%); } -} - -/* Portfolio Cards */ -.project-card { - border: 2px solid #000; - border-radius: var(--radius-card); - overflow: hidden; - background: #fff; - transition: transform 0.3s ease; - box-shadow: var(--shadow-hard); - height: 100%; - display: flex; - flex-direction: column; -} - -.project-card:hover { - transform: translateY(-10px); - box-shadow: 8px 8px 0 #000; -} - -.card-img-holder { - height: 250px; - display: flex; - align-items: center; - justify-content: center; - border-bottom: 2px solid #000; - position: relative; - font-size: 4rem; -} - -.placeholder-art { - transition: transform 0.3s ease; -} - -.project-card:hover .placeholder-art { - transform: scale(1.2) rotate(10deg); -} - -.bg-soft-blue { background-color: #e0f2fe; } -.bg-soft-green { background-color: #dcfce7; } -.bg-soft-purple { background-color: #f3e8ff; } -.bg-soft-yellow { background-color: #fef9c3; } - -.category-tag { - position: absolute; - top: 15px; - right: 15px; - background: #000; - color: #fff; - padding: 5px 12px; - border-radius: 20px; - font-size: 0.75rem; - font-weight: 700; -} - -.card-body { padding: 1.5rem; } - -.link-arrow { - text-decoration: none; - color: #000; - font-weight: 700; - display: inline-flex; - align-items: center; - margin-top: auto; -} - -.link-arrow i { transition: transform 0.2s; margin-left: 5px; } -.link-arrow:hover i { transform: translateX(5px); } - -/* About */ -.about-image-stack { - position: relative; - height: 400px; - width: 100%; -} - -.stack-card { - position: absolute; - width: 80%; - height: 100%; - border-radius: var(--radius-card); - border: 2px solid #000; - box-shadow: var(--shadow-hard); - left: 10%; - transform: rotate(-3deg); - background-size: cover; -} - -/* Forms */ .form-control { - border: 2px solid #000; - border-radius: 0.5rem; - padding: 1rem; - font-weight: 500; - background: #f8f9fa; + border-radius: 4px; + border: 1px solid var(--border); + padding: 0.75rem; } .form-control:focus { - box-shadow: 4px 4px 0 var(--color-primary); - border-color: #000; - background: #fff; + box-shadow: none; + border-color: var(--accent); } -/* Animations */ -.animate-up { - opacity: 0; - transform: translateY(30px); - animation: fadeUp 0.8s ease forwards; +.portfolio-img { + height: 250px; + background-color: #eee; + background-size: cover; + background-position: center; } -.delay-100 { animation-delay: 0.1s; } -.delay-200 { animation-delay: 0.2s; } +footer { + border-top: 1px solid var(--border); + padding: 40px 0; + font-size: 0.9rem; + color: var(--text-muted); +} -@keyframes fadeUp { - to { - opacity: 1; - transform: translateY(0); +/* Toast styling */ +.toast-container { + position: fixed; + top: 20px; + right: 20px; + z-index: 1060; +} + +@media (max-width: 768px) { + .hero h1 { + font-size: 2.5rem; } -} - -/* Social */ -.social-links a { - transition: transform 0.2s; - display: inline-block; -} -.social-links a:hover { - transform: scale(1.2) rotate(10deg); - color: var(--color-accent) !important; -} - -/* Responsive */ -@media (max-width: 991px) { - .rotate-divider { - transform: rotate(0); - margin-top: 0; - margin-bottom: 2rem; - } - - .hero-section { - padding-top: 120px; - text-align: center; - min-height: auto; - padding-bottom: 100px; - } - - .display-1 { font-size: 3.5rem; } - - .blob-1 { width: 300px; height: 300px; right: -20%; } - .blob-2 { width: 300px; height: 300px; left: -20%; } -} +} \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js index fdf2cfd..395208f 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,73 +1,73 @@ -document.addEventListener('DOMContentLoaded', () => { - - // Smooth scrolling for navigation links +document.addEventListener('DOMContentLoaded', function() { + const contactForm = document.getElementById('contactForm'); + const toastContainer = document.querySelector('.toast-container'); + + function showToast(message, isSuccess = true) { + const toastId = 'toast-' + Date.now(); + const toastHtml = ` + + `; + toastContainer.insertAdjacentHTML('beforeend', toastHtml); + const toastElement = document.getElementById(toastId); + const toast = new bootstrap.Toast(toastElement); + toast.show(); + + toastElement.addEventListener('hidden.bs.toast', () => { + toastElement.remove(); + }); + } + + if (contactForm) { + contactForm.addEventListener('submit', function(e) { + e.preventDefault(); + + const submitBtn = contactForm.querySelector('button[type="submit"]'); + const originalBtnText = submitBtn.innerHTML; + submitBtn.disabled = true; + submitBtn.innerHTML = ' Sending...'; + + const formData = new FormData(contactForm); + + fetch('process_contact.php', { + method: 'POST', + body: formData + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + showToast(data.message || 'Message sent successfully!'); + contactForm.reset(); + } else { + showToast(data.error || 'Something went wrong.', false); + } + }) + .catch(error => { + console.error('Error:', error); + showToast('Failed to connect to the server.', false); + }) + .finally(() => { + submitBtn.disabled = false; + submitBtn.innerHTML = originalBtnText; + }); + }); + } + + // Smooth scroll for nav links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); - const targetId = this.getAttribute('href'); - if (targetId === '#') return; - - const targetElement = document.querySelector(targetId); - if (targetElement) { - // Close mobile menu if open - const navbarToggler = document.querySelector('.navbar-toggler'); - const navbarCollapse = document.querySelector('.navbar-collapse'); - if (navbarCollapse.classList.contains('show')) { - navbarToggler.click(); - } - - // Scroll with offset - const offset = 80; - const elementPosition = targetElement.getBoundingClientRect().top; - const offsetPosition = elementPosition + window.pageYOffset - offset; - + const target = document.querySelector(this.getAttribute('href')); + if (target) { window.scrollTo({ - top: offsetPosition, - behavior: "smooth" + top: target.offsetTop - 70, + behavior: 'smooth' }); } }); }); - - // Navbar scroll effect - const navbar = document.querySelector('.navbar'); - window.addEventListener('scroll', () => { - if (window.scrollY > 50) { - navbar.classList.add('scrolled', 'shadow-sm', 'bg-white'); - navbar.classList.remove('bg-transparent'); - } else { - navbar.classList.remove('scrolled', 'shadow-sm', 'bg-white'); - navbar.classList.add('bg-transparent'); - } - }); - - // Intersection Observer for fade-up animations - const observerOptions = { - threshold: 0.1, - rootMargin: "0px 0px -50px 0px" - }; - - const observer = new IntersectionObserver((entries) => { - entries.forEach(entry => { - if (entry.isIntersecting) { - entry.target.classList.add('animate-up'); - entry.target.style.opacity = "1"; - observer.unobserve(entry.target); // Only animate once - } - }); - }, observerOptions); - - // Select elements to animate (add a class 'reveal' to them in HTML if not already handled by CSS animation) - // For now, let's just make sure the hero animations run. - // If we want scroll animations, we'd add opacity: 0 to elements in CSS and reveal them here. - // Given the request, the CSS animation I added runs on load for Hero. - // Let's make the project cards animate in. - - const projectCards = document.querySelectorAll('.project-card'); - projectCards.forEach((card, index) => { - card.style.opacity = "0"; - card.style.animationDelay = `${index * 0.1}s`; - observer.observe(card); - }); - -}); \ No newline at end of file +}); diff --git a/db/config.php b/db/config.php index 6250722..41e4f1f 100644 --- a/db/config.php +++ b/db/config.php @@ -1,17 +1,22 @@ PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - ]); + try { + $pdo = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8mb4', DB_USER, DB_PASS, [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + ]); + } catch (PDOException $e) { + error_log("Database connection failed: " . $e->getMessage()); + return null; + } } return $pdo; -} +} \ No newline at end of file diff --git a/db/migrations/001_create_contact_requests.sql b/db/migrations/001_create_contact_requests.sql new file mode 100644 index 0000000..0741031 --- /dev/null +++ b/db/migrations/001_create_contact_requests.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS contact_requests ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + message TEXT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); diff --git a/index.php b/index.php index 7205f3d..63be82f 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,219 @@ - - - New Style - - - - - - - - - - - - - - - - - - - + + + <?= htmlspecialchars($projectName) ?> + + + + + + + + + + + + + + + + + + + + -
-
-

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

-
-
- + + + + + +
+
+
+
+

Design. Build.
Deliver Value.

+

I help businesses grow by creating high-performance digital solutions tailored to their needs.

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

Selected Projects

+

A showcase of recent work across design and development.

+
+
+
+ +
+
+
+
+

Modern E-commerce

+

High-converting online store built with performance in mind.

+
+
+
+ +
+
+
+
+

SaaS Dashboard

+

Complex data visualization and management system.

+
+
+
+ +
+
+
+
+

Brand Identity

+

Complete visual design for a tech startup.

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

A bit about me

+

With over 5 years of experience in the digital space, I've had the privilege of working with a diverse range of clients, from startups to established brands. My approach is centered on understanding business goals and translating them into elegant, functional designs.

+

I specialize in full-stack development, user experience design, and digital strategy. When I'm not coding, I'm usually exploring new technologies or contributing to open-source projects.

+
+
+

15+

+ Projects +
+
+

10+

+ Clients +
+
+

5+

+ Years +
+
+
+
+
+
+

Core Skills

+
+ Web Development +
+
+
+
+
+ UI/UX Design +
+
+
+
+
+ Strategy +
+
+
+
+
+
+
+
+
+ + +
+
+
+
+

Get in Touch

+

Have a project in mind? Let's discuss how I can help.

+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+
+
+
+ + + + + +
+ + + + + - + \ No newline at end of file diff --git a/process_contact.php b/process_contact.php new file mode 100644 index 0000000..ed8fed6 --- /dev/null +++ b/process_contact.php @@ -0,0 +1,44 @@ + false, 'error' => 'Invalid request method.']); + exit; +} + +$name = trim($_POST['name'] ?? ''); +$email = trim($_POST['email'] ?? ''); +$message = trim($_POST['message'] ?? ''); + +if (empty($name) || empty($email) || empty($message)) { + echo json_encode(['success' => false, 'error' => 'All fields are required.']); + exit; +} + +if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { + echo json_encode(['success' => false, 'error' => 'Invalid email format.']); + exit; +} + +$db = db(); +if (!$db) { + echo json_encode(['success' => false, 'error' => 'Database connection failed.']); + exit; +} + +try { + $stmt = $db->prepare("INSERT INTO contact_requests (name, email, message) VALUES (?, ?, ?)"); + $stmt->execute([$name, $email, $message]); + + // Optional: Send email via MailService if configured + if (file_exists('mail/MailService.php')) { + require_once 'mail/MailService.php'; + // MailService::sendContactMessage($name, $email, $message); + } + + echo json_encode(['success' => true, 'message' => 'Thank you! Your message has been received.']); +} catch (PDOException $e) { + error_log("Database error: " . $e->getMessage()); + echo json_encode(['success' => false, 'error' => 'Failed to save your request. Please try again later.']); +}