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 <?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; namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utils\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utils\ErrorHandler;
use WizdomNetworks\WizeWeb\Core\View;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
class ContactController class ContactController
{ {
public function index(): void public function submit(): void
{ {
Logger::debug("ContactController::index() - Executing contact page rendering.");
try { try {
// Prepare data for the contact page // Sanitize and validate input
$data = [ $firstName = trim($_POST['first_name'] ?? '');
'title' => 'Contact Us - Wizdom Networks', $lastName = trim($_POST['last_name'] ?? '');
'heroConfig' => [ $email = trim($_POST['email'] ?? '');
'title' => 'Get in Touch', $phone = trim($_POST['phone'] ?? '');
'description' => 'Reach out to our team for inquiries and support.', $message = trim($_POST['message'] ?? '');
'image' => '/assets/images/contact-hero.jpg',
'cta' => ['text' => 'Send a Message', 'link' => '/contact'], if (!$firstName || !$lastName || !$email || !$phone || !$message) {
'style' => 'default', throw new \Exception("All fields except phone must be filled out.");
'position' => 'top' }
],
'content' => "<h1>Contact Us</h1> if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
<p>We're here to help. Send us a message and we'll get back to you as soon as possible.</p>" 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) { } catch (\Throwable $e) {
Logger::error("ContactController::index() - Error rendering contact page: " . $e->getMessage()); Logger::error("Contact form error: " . $e->getMessage());
ErrorHandler::exception($e); ErrorHandler::handleException($e);
http_response_code(400);
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
} }
} }
} }

View File

@ -1,77 +1,80 @@
<?php <?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; namespace WizdomNetworks\WizeWeb\Core;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utils\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; 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 class Router
{ {
private array $routes = []; private array $routes = [];
/** /**
* Registers a new route. * Registers a new route.
* *
* @param string $path The URL path. * @param string $path The URL path (e.g. /contact).
* @param string $controller The fully qualified controller class name. * @param string $controller The fully qualified controller class.
* @param string $method The method within the controller. * @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"); $routeKey = strtoupper($httpMethod) . ':' . trim($path, '/');
$this->routes[trim($path, '/')] = [$controller, $method]; Logger::debug("Registering route: [$httpMethod] $path -> $controller::$method");
$this->routes[$routeKey] = [$controller, $method];
} }
/** /**
* Dispatches the request to the appropriate controller and method. * Dispatch the request based on the path and HTTP method.
* *
* @param string $path The requested URL path. * @param string $path The requested path (from index.php).
*/ */
public function dispatch($path) public function dispatch($path)
{ {
$path = trim($path, '/'); $httpMethod = $_SERVER['REQUEST_METHOD'];
Logger::debug("Dispatching path: $path"); $routeKey = $httpMethod . ':' . trim($path, '/');
if (isset($this->routes[$path])) { Logger::debug("Dispatching [$httpMethod] $path");
[$controllerName, $method] = $this->routes[$path];
Logger::debug("Loading controller: $controllerName::$method"); if (isset($this->routes[$routeKey])) {
[$controllerName, $method] = $this->routes[$routeKey];
Logger::debug("Matched route -> $controllerName::$method");
try { try {
if (class_exists($controllerName)) { if (!class_exists($controllerName)) {
$controller = new $controllerName(); throw new \Exception("Controller not found: $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.");
} }
} //catch (\Throwable $e) {
//ErrorHandler::exception($e); $controller = new $controllerName();
//Logger::error("Router dispatch error: " . $e->getMessage());
//echo "500 Internal Server Error"; if (!method_exists($controller, $method)) {
catch (\Throwable $e) { throw new \Exception("Method $method not found in $controllerName");
echo "<pre>"; }
echo "Exception: " . $e->getMessage() . "\n";
echo "File: " . $e->getFile() . "\n"; Logger::info("Executing controller: $controllerName::$method");
echo "Line: " . $e->getLine() . "\n"; $controller->$method();
echo "Trace:\n" . $e->getTraceAsString(); } catch (\Throwable $e) {
echo "</pre>"; echo "<pre>";
exit; echo "Exception: " . $e->getMessage() . "\n";
echo "File: " . $e->getFile() . "\n";
echo "Line: " . $e->getLine() . "\n";
echo "Trace:\n" . $e->getTraceAsString();
echo "</pre>";
exit;
} }
} else { } else {
Logger::error("Route not found: $path"); Logger::error("Route not found: [$httpMethod] $path");
http_response_code(404);
echo "404 Not Found"; 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); ini_set('display_startup_errors', 1);
error_reporting(E_ALL); error_reporting(E_ALL);
// File: public/index.php // File: public/index.php
// Version: v1.1 // Version: v1.2
// Purpose: Application entry point with Arsha one-pager routing // Purpose: Application entry point with Arsha one-pager routing
// Project: Wizdom Networks Website // Project: Wizdom Networks Website
require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../vendor/autoload.php';
use Dotenv\Dotenv; use Dotenv\Dotenv;
use WizdomNetworks\WizeWeb\Core\Router; use WizdomNetworks\WizeWeb\Core\Router;
use WizdomNetworks\WizeWeb\Utils\Logger; use WizdomNetworks\WizeWeb\Utils\Logger;
use WizdomNetworks\WizeWeb\Utils\ErrorHandler; use WizdomNetworks\WizeWeb\Utils\ErrorHandler;
use WizdomNetworks\WizeWeb\Controllers\LandingController; use WizdomNetworks\WizeWeb\Controllers\LandingController;
// ✅ Load .env variables use WizdomNetworks\WizeWeb\Controllers\ContactController; // <-- Missing
$dotenv = Dotenv::createImmutable(__DIR__ . '/../'); $dotenv = Dotenv::createImmutable(__DIR__ . '/../');
$dotenv->load(); $dotenv->load();
@ -27,24 +25,26 @@ Logger::info("Bootstrapping application");
$router = new Router(); $router = new Router();
// ✅ Register new Arsha landing route // Arsha landing routes
$router->add('', LandingController::class, 'index'); $router->add('', LandingController::class, 'index');
$router->add('/', LandingController::class, 'index'); $router->add('/', LandingController::class, 'index');
$router->add('index.php', 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 // Contact form submission
// use WizdomNetworks\WizeWeb\Controllers\HomeController; $router->add('/contact', ContactController::class, 'submit', 'POST');
//router->add('', HomeController::class, 'index');
// DEBUG // Optional: fallback for /contact without leading slash (rare case)
//echo "<pre>"; // $router->add('contact', ContactController::class, 'submit', 'POST');
//echo "REQUEST_URI: " . $_SERVER['REQUEST_URI'] . "\n";
//echo "Parsed path: " . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) . "\n"; // Debug block — safe to leave commented
//echo "Trimmed: " . trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/') . "\n"; /*
//echo "</pre>"; echo "<pre>";
//exit; echo "REQUEST_URI: " . $_SERVER['REQUEST_URI'] . "\n";
//END DEBUG 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); $requestedPath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$router->dispatch($requestedPath); $router->dispatch($requestedPath);

View File

@ -82,6 +82,15 @@
<script src="/assets/vendor/isotope-layout/isotope.pkgd.min.js"></script> <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/swiper/swiper-bundle.min.js"></script>
<script src="/assets/vendor/waypoints/noframework.waypoints.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 --> <!-- Main JS File -->
<script src="/assets/js/main.js"></script> <script src="/assets/js/main.js"></script>

View File

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