Contact form initial updates
This commit is contained in:
parent
c309fa1eee
commit
90b7b0b785
|
|
@ -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()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,20 @@
|
|||
<?php
|
||||
/**
|
||||
* ============================================
|
||||
* File: Router.php
|
||||
* Path: /app/Core/
|
||||
* Purpose: Core router handling HTTP method–specific 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 = [];
|
||||
|
|
@ -18,60 +22,59 @@ class Router
|
|||
/**
|
||||
* 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.
|
||||
* 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)
|
||||
{
|
||||
$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";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue