Contact form initial updates

This commit is contained in:
essae 2025-05-10 16:55:50 -04:00
parent c309fa1eee
commit 90b7b0b785
6 changed files with 236 additions and 114 deletions

View File

@ -1,38 +1,88 @@
<?php
/**
* ============================================
* File: ContactController.php
* Path: /app/Controllers/ContactController.php
* Purpose: Handles form submissions from the Arsha contact form
* Version: 1.0
* Author: Wizdom Networks
* Usage: Routed via Router to handle POST /contact
* ============================================
*/
namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler;
use WizdomNetworks\WizeWeb\Core\View;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
class ContactController
{
public function index(): void
public function submit(): void
{
Logger::debug("ContactController::index() - Executing contact page rendering.");
try {
// Prepare data for the contact page
$data = [
'title' => 'Contact Us - Wizdom Networks',
'heroConfig' => [
'title' => 'Get in Touch',
'description' => 'Reach out to our team for inquiries and support.',
'image' => '/assets/images/contact-hero.jpg',
'cta' => ['text' => 'Send a Message', 'link' => '/contact'],
'style' => 'default',
'position' => 'top'
],
'content' => "<h1>Contact Us</h1>
<p>We're here to help. Send us a message and we'll get back to you as soon as possible.</p>"
];
// Sanitize and validate input
$firstName = trim($_POST['first_name'] ?? '');
$lastName = trim($_POST['last_name'] ?? '');
$email = trim($_POST['email'] ?? '');
$phone = trim($_POST['phone'] ?? '');
$message = trim($_POST['message'] ?? '');
if (!$firstName || !$lastName || !$email || !$phone || !$message) {
throw new \Exception("All fields except phone must be filled out.");
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \Exception("Invalid email address.");
}
// Store in database
$pdo = new \PDO($_ENV['DB_DSN'], $_ENV['DB_USER'], $_ENV['DB_PASS']);
$stmt = $pdo->prepare("INSERT INTO contact_messages (first_name, last_name, email, phone, message, ip_address, user_agent)
VALUES (?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([
$firstName,
$lastName,
$email,
$phone,
$message,
$_SERVER['REMOTE_ADDR'] ?? 'unknown',
$_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
]);
Logger::info("Contact form submitted by $firstName $lastName <$email>");
// Email notification
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = $_ENV['SMTP_HOST'];
$mail->Port = $_ENV['SMTP_PORT'];
$mail->SMTPAuth = $_ENV['SMTP_AUTH'] === 'true';
$mail->SMTPSecure = $_ENV['SMTP_ENCRYPTION'] !== 'none' ? $_ENV['SMTP_ENCRYPTION'] : '';
$mail->Username = $_ENV['SMTP_USERNAME'];
$mail->Password = $_ENV['SMTP_PASSWORD'];
$mail->setFrom($_ENV['SMTP_FROM_EMAIL'], $_ENV['SMTP_FROM_NAME']);
$mail->addAddress($_ENV['SALES_EMAILS'] ?? $_ENV['ADMIN_EMAILS']);
$mail->Subject = "New Contact Message from $firstName $lastName";
$mail->Body = "You received a message from: \n\n"
. "Name: $firstName $lastName\n"
. "Email: $email\n"
. "Phone: $phone\n"
. "Message:\n$message\n";
$mail->send();
http_response_code(200);
echo json_encode(['success' => true, 'message' => 'Thank you. We will be in touch.']);
Logger::debug("ContactController::index() - Data prepared successfully.");
View::render('pages/contact', $data);
Logger::info("ContactController::index() - Contact page rendered successfully.");
} catch (\Throwable $e) {
Logger::error("ContactController::index() - Error rendering contact page: " . $e->getMessage());
ErrorHandler::exception($e);
Logger::error("Contact form error: " . $e->getMessage());
ErrorHandler::handleException($e);
http_response_code(400);
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
}
}

View File

@ -1,77 +1,80 @@
<?php
/**
* ============================================
* File: Router.php
* Path: /app/Core/
* Purpose: Core router handling HTTP methodspecific route dispatching.
* Version: 1.1
* Author: Wizdom Networks
* Usage: Handles all GET/POST routing to controllers.
* ============================================
*/
namespace WizdomNetworks\WizeWeb\Core;
use WizdomNetworks\WizeWeb\Utils\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler;
/**
* Router Class
*
* Handles application routing by mapping URL paths to controller methods.
* Ensures all requests are routed through controllers and logs dispatch details.
*/
class Router
{
private array $routes = [];
/**
* Registers a new route.
*
* @param string $path The URL path.
* @param string $controller The fully qualified controller class name.
* @param string $method The method within the controller.
*
* @param string $path The URL path (e.g. /contact).
* @param string $controller The fully qualified controller class.
* @param string $method The method name in the controller.
* @param string $httpMethod HTTP method (GET, POST, etc.), defaults to GET.
*/
public function add(string $path, string $controller, string $method): void
public function add(string $path, string $controller, string $method, string $httpMethod = 'GET'): void
{
Logger::debug("Registering route: $path -> $controller::$method");
$this->routes[trim($path, '/')] = [$controller, $method];
$routeKey = strtoupper($httpMethod) . ':' . trim($path, '/');
Logger::debug("Registering route: [$httpMethod] $path -> $controller::$method");
$this->routes[$routeKey] = [$controller, $method];
}
/**
* Dispatches the request to the appropriate controller and method.
*
* @param string $path The requested URL path.
* Dispatch the request based on the path and HTTP method.
*
* @param string $path The requested path (from index.php).
*/
public function dispatch($path)
{
$path = trim($path, '/');
Logger::debug("Dispatching path: $path");
$httpMethod = $_SERVER['REQUEST_METHOD'];
$routeKey = $httpMethod . ':' . trim($path, '/');
if (isset($this->routes[$path])) {
[$controllerName, $method] = $this->routes[$path];
Logger::debug("Loading controller: $controllerName::$method");
Logger::debug("Dispatching [$httpMethod] $path");
if (isset($this->routes[$routeKey])) {
[$controllerName, $method] = $this->routes[$routeKey];
Logger::debug("Matched route -> $controllerName::$method");
try {
if (class_exists($controllerName)) {
$controller = new $controllerName();
if (method_exists($controller, $method)) {
Logger::info("Successfully dispatched: $controllerName::$method");
$controller->$method();
} else {
Logger::error("Method not found: $controllerName::$method");
throw new \Exception("Method $method not found in $controllerName");
}
} else {
Logger::error("Controller not found: $controllerName");
throw new \Exception("Controller $controllerName not found.");
if (!class_exists($controllerName)) {
throw new \Exception("Controller not found: $controllerName");
}
} //catch (\Throwable $e) {
//ErrorHandler::exception($e);
//Logger::error("Router dispatch error: " . $e->getMessage());
//echo "500 Internal Server Error";
catch (\Throwable $e) {
echo "<pre>";
echo "Exception: " . $e->getMessage() . "\n";
echo "File: " . $e->getFile() . "\n";
echo "Line: " . $e->getLine() . "\n";
echo "Trace:\n" . $e->getTraceAsString();
echo "</pre>";
exit;
$controller = new $controllerName();
if (!method_exists($controller, $method)) {
throw new \Exception("Method $method not found in $controllerName");
}
Logger::info("Executing controller: $controllerName::$method");
$controller->$method();
} catch (\Throwable $e) {
echo "<pre>";
echo "Exception: " . $e->getMessage() . "\n";
echo "File: " . $e->getFile() . "\n";
echo "Line: " . $e->getLine() . "\n";
echo "Trace:\n" . $e->getTraceAsString();
echo "</pre>";
exit;
}
} else {
Logger::error("Route not found: $path");
Logger::error("Route not found: [$httpMethod] $path");
http_response_code(404);
echo "404 Not Found";
}
}

View File

@ -0,0 +1,56 @@
document.addEventListener('DOMContentLoaded', function () {
const form = document.querySelector('.php-email-form');
if (!form) return;
const loading = document.createElement('div');
const errorMsg = document.createElement('div');
const successMsg = document.createElement('div');
loading.className = 'loading mt-3';
loading.textContent = 'Sending message...';
errorMsg.className = 'error-message mt-3';
errorMsg.style.display = 'none';
successMsg.className = 'sent-message mt-3';
successMsg.style.display = 'none';
form.appendChild(loading);
form.appendChild(errorMsg);
form.appendChild(successMsg);
loading.style.display = 'none';
form.addEventListener('submit', async function (e) {
e.preventDefault();
loading.style.display = 'block';
errorMsg.style.display = 'none';
successMsg.style.display = 'none';
const formData = new FormData(form);
try {
const response = await fetch(form.action, {
method: 'POST',
body: formData
});
const result = await response.json();
loading.style.display = 'none';
if (response.ok && result.success) {
successMsg.textContent = result.message || 'Your message was sent successfully.';
successMsg.style.display = 'block';
form.reset();
} else {
throw new Error(result.error || 'Submission failed.');
}
} catch (err) {
loading.style.display = 'none';
errorMsg.textContent = err.message || 'An unexpected error occurred.';
errorMsg.style.display = 'block';
}
});
});

View File

@ -4,22 +4,20 @@ ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// File: public/index.php
// Version: v1.1
// Version: v1.2
// Purpose: Application entry point with Arsha one-pager routing
// Project: Wizdom Networks Website
require_once __DIR__ . '/../vendor/autoload.php';
use Dotenv\Dotenv;
use WizdomNetworks\WizeWeb\Core\Router;
use WizdomNetworks\WizeWeb\Utils\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler;
use WizdomNetworks\WizeWeb\Controllers\LandingController;
// ✅ Load .env variables
use WizdomNetworks\WizeWeb\Controllers\ContactController; // <-- Missing
$dotenv = Dotenv::createImmutable(__DIR__ . '/../');
$dotenv->load();
@ -27,24 +25,26 @@ Logger::info("Bootstrapping application");
$router = new Router();
// ✅ Register new Arsha landing route
// Arsha landing routes
$router->add('', LandingController::class, 'index');
$router->add('/', LandingController::class, 'index');
$router->add('index.php', LandingController::class, 'index');
//$router->add('/', WizdomNetworks\WizeWeb\Controllers\LandingController::class, 'index');
// 🛑 Optional: Disable old route to avoid conflict
// use WizdomNetworks\WizeWeb\Controllers\HomeController;
//router->add('', HomeController::class, 'index');
// Contact form submission
$router->add('/contact', ContactController::class, 'submit', 'POST');
// DEBUG
//echo "<pre>";
//echo "REQUEST_URI: " . $_SERVER['REQUEST_URI'] . "\n";
//echo "Parsed path: " . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) . "\n";
//echo "Trimmed: " . trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/') . "\n";
//echo "</pre>";
//exit;
//END DEBUG
// Optional: fallback for /contact without leading slash (rare case)
// $router->add('contact', ContactController::class, 'submit', 'POST');
// Debug block — safe to leave commented
/*
echo "<pre>";
echo "REQUEST_URI: " . $_SERVER['REQUEST_URI'] . "\n";
echo "Parsed path: " . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) . "\n";
echo "Trimmed: " . trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/') . "\n";
echo "</pre>";
exit;
*/
$requestedPath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$router->dispatch($requestedPath);

View File

@ -82,6 +82,15 @@
<script src="/assets/vendor/isotope-layout/isotope.pkgd.min.js"></script>
<script src="/assets/vendor/swiper/swiper-bundle.min.js"></script>
<script src="/assets/vendor/waypoints/noframework.waypoints.js"></script>
<script>
if (document.querySelector('.php-email-form')) {
const script = document.createElement('script');
script.src = '/assets/js/contact-form.js';
document.body.appendChild(script);
}
</script>
<!-- Main JS File -->
<script src="/assets/js/main.js"></script>

View File

@ -709,39 +709,43 @@
</div>
<div class="col-lg-7">
<form action="forms/contact.php" method="post" class="php-email-form" data-aos="fade-up" data-aos-delay="200">
<div class="row gy-4">
<form action="/contact" method="POST" class="php-email-form">
<div class="col-md-6">
<label for="name-field" class="pb-2">Your Name</label>
<input type="text" name="name" id="name-field" class="form-control" required>
</div>
<div class="row">
<div class="col-md-6">
<label for="first_name" class="pb-2">First Name</label>
<input type="text" name="first_name" id="first_name" class="form-control" required>
</div>
<div class="col-md-6">
<label for="email-field" class="pb-2">Your Email</label>
<input type="email" class="form-control" name="email" id="email-field" required>
</div>
<div class="col-md-6">
<label for="last_name" class="pb-2">Last Name</label>
<input type="text" name="last_name" id="last_name" class="form-control" required>
</div>
</div>
<div class="col-md-12">
<label for="subject-field" class="pb-2">Subject</label>
<input type="text" class="form-control" name="subject" id="subject-field" required>
</div>
<div class="row mt-3">
<div class="col-md-6">
<label for="email" class="pb-2">Your Email</label>
<input type="email" name="email" id="email" class="form-control" required>
</div>
<div class="col-md-12">
<label for="message-field" class="pb-2">Message</label>
<textarea class="form-control" name="message" rows="10" id="message-field" required></textarea>
</div>
<div class="col-md-6">
<label for="phone" class="pb-2">Phone Number <small class="text-muted">(required to weed out spam)</small></label>
<input type="tel" name="phone" id="phone" class="form-control" required>
</div>
</div>
<div class="col-md-12 text-center">
<div class="loading">Loading</div>
<div class="error-message"></div>
<div class="sent-message">Your message has been sent. Thank you!</div>
<div class="form-group mt-3">
<label for="message" class="pb-2">Message</label>
<textarea name="message" id="message" rows="5" class="form-control" required></textarea>
</div>
<button type="submit">Send Message</button>
</div>
<div class="text-center mt-4">
<button type="submit">Send Message</button>
</div>
</form>
</div>
</form>
</div><!-- End Contact Form -->
</div>