Compare commits
No commits in common. "ai-dev" and "master" have entirely different histories.
@ -1,58 +0,0 @@
|
||||
<?php
|
||||
// api/pexels.php
|
||||
header('Content-Type: application/json');
|
||||
require_once __DIR__.'/../includes/pexels.php';
|
||||
|
||||
// Get comma-separated query names from the request
|
||||
$queries_str = $_GET['queries'] ?? '';
|
||||
if (empty($queries_str)) {
|
||||
echo json_encode(['error' => 'No queries provided.']);
|
||||
exit;
|
||||
}
|
||||
$queries = explode(',', $queries_str);
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($queries as $query) {
|
||||
$query = trim($query);
|
||||
if (empty($query)) continue;
|
||||
|
||||
// Define a local path for the image
|
||||
$local_path_dir = __DIR__ . '/../assets/images/corals';
|
||||
if (!is_dir($local_path_dir)) {
|
||||
mkdir($local_path_dir, 0775, true);
|
||||
}
|
||||
$image_filename = strtolower(str_replace(' ', '-', $query)) . '.jpg';
|
||||
$local_path = $local_path_dir . '/' . $image_filename;
|
||||
$relative_path = 'assets/images/corals/' . $image_filename;
|
||||
|
||||
// Serve cached image if it exists
|
||||
if (file_exists($local_path)) {
|
||||
$results[$query] = $relative_path . '?v=' . filemtime($local_path);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fetch from Pexels if not cached
|
||||
$search_query = $query . " coral";
|
||||
$url = 'https://api.pexels.com/v1/search?query=' . urlencode($search_query) . '&orientation=square&per_page=1&page=1';
|
||||
$data = pexels_get($url);
|
||||
|
||||
if ($data && !empty($data['photos'])) {
|
||||
$photo = $data['photos'][0];
|
||||
$src = $photo['src']['large'] ?? $photo['src']['medium'] ?? $photo['src']['original'];
|
||||
|
||||
if (download_to($src, $local_path)) {
|
||||
$results[$query] = $relative_path . '?v=' . time();
|
||||
} else {
|
||||
// Download failed, use a placeholder
|
||||
$results[$query] = 'https://picsum.photos/seed/' . urlencode($query) . '/600/600';
|
||||
}
|
||||
} else {
|
||||
// Pexels fetch failed, use a placeholder
|
||||
$results[$query] = 'https://picsum.photos/seed/' . urlencode($query) . '/600/600';
|
||||
}
|
||||
// Small delay to avoid hitting API rate limits too quickly
|
||||
usleep(200000); // 200ms
|
||||
}
|
||||
|
||||
echo json_encode($results);
|
||||
@ -1,116 +0,0 @@
|
||||
/* /workspace/assets/css/custom.css */
|
||||
:root {
|
||||
--primary: #00A99D;
|
||||
--secondary: #FFC107;
|
||||
--light: #F8F9FA;
|
||||
--dark: #212529;
|
||||
--surface: #FFFFFF;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
color: var(--dark);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary);
|
||||
border-color: var(--primary);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #007a70;
|
||||
border-color: #007a70;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: var(--secondary);
|
||||
border-color: var(--secondary);
|
||||
color: var(--dark);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: #e0a800;
|
||||
border-color: #e0a800;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.navbar {
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
|
||||
|
||||
section {
|
||||
padding: 5rem 0;
|
||||
}
|
||||
|
||||
.section-bg {
|
||||
background-color: var(--light);
|
||||
}
|
||||
|
||||
.card.coral-card {
|
||||
border: none;
|
||||
border-radius: 0.5rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.08);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.card.coral-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 25px rgba(0,0,0,0.12);
|
||||
}
|
||||
|
||||
.card-img-top-container {
|
||||
width: 100%;
|
||||
padding-top: 100%; /* 1:1 Aspect Ratio */
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-img-top {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover; /* Cover the container without stretching */
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.coral-price {
|
||||
color: var(--primary);
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 0.25rem rgba(0, 169, 157, 0.25);
|
||||
}
|
||||
|
||||
.footer {
|
||||
background-color: var(--dark);
|
||||
color: white;
|
||||
padding: 3rem 0;
|
||||
}
|
||||
|
||||
.toast-container {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 1055;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 62 KiB |
@ -1,205 +0,0 @@
|
||||
// assets/js/corals.js
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const corals = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'WWC OG Voodoo Magic Zoanthid',
|
||||
type: 'Zoanthid',
|
||||
color: 'Rainbow',
|
||||
price: 129.99,
|
||||
seller: 'World Wide Corals',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/wwc-og-voodoo-magic-zoanthid.jpg'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'TSA Bill Murray Acropora',
|
||||
type: 'SPS',
|
||||
color: 'Green',
|
||||
price: 249.99,
|
||||
seller: 'Top Shelf Aquatics',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/tsa-bill-murray-acropora.jpg'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'JF Jack-O-Lantern Leptoseris',
|
||||
type: 'LPS',
|
||||
color: 'Yellow',
|
||||
price: 89.99,
|
||||
seller: 'Jason Fox Signature Corals',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/jf-jack-o-lantern-leptoseris.jpg'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'RR USA Rainbow Splice Trachyphyllia',
|
||||
type: 'LPS',
|
||||
color: 'Rainbow',
|
||||
price: 399.99,
|
||||
seller: 'Reef Raft USA',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/rr-usa-rainbow-splice-trachyphyllia.jpg'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Godspawn Euphyllia',
|
||||
type: 'LPS',
|
||||
color: 'Green',
|
||||
price: 199.99,
|
||||
seller: 'World Wide Corals',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/godspawn-euphyllia.jpg'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'TGC Cherry Bomb Acropora',
|
||||
type: 'SPS',
|
||||
color: 'Red',
|
||||
price: 179.99,
|
||||
seller: 'The Coral Gorilla',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/tgc-cherry-bomb-acropora.jpg'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Bounce Mushroom',
|
||||
type: 'Mushroom',
|
||||
color: 'Pink',
|
||||
price: 450.00,
|
||||
seller: 'Top Shelf Aquatics',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/bounce-mushroom.jpg'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: 'Blue Hornets Zoanthid',
|
||||
type: 'Zoanthid',
|
||||
color: 'Blue',
|
||||
price: 49.99,
|
||||
seller: 'Jason Fox Signature Corals',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/blue-hornets-zoanthid.jpg'
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: 'Walt Disney Acropora',
|
||||
type: 'SPS',
|
||||
color: 'Rainbow',
|
||||
price: 299.99,
|
||||
seller: 'World Wide Corals',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/walt-disney-acropora.jpg'
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: 'Gold Torch Euphyllia',
|
||||
type: 'LPS',
|
||||
color: 'Yellow',
|
||||
price: 349.99,
|
||||
seller: 'Reef Raft USA',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/gold-torch-euphyllia.jpg'
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: 'Forest Fire Digitata',
|
||||
type: 'SPS',
|
||||
color: 'Green',
|
||||
price: 59.99,
|
||||
seller: 'Top Shelf Aquatics',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/forest-fire-digitata.jpg'
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: 'Grafted Cap Montipora',
|
||||
type: 'SPS',
|
||||
color: 'Red',
|
||||
price: 79.99,
|
||||
seller: 'The Coral Gorilla',
|
||||
seller_url: '#',
|
||||
image: 'assets/images/corals/grafted-cap-montipora.jpg'
|
||||
}
|
||||
];
|
||||
|
||||
const coralGrid = document.getElementById('coral-grid');
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
const filterType = document.getElementById('filterType');
|
||||
const filterColor = document.getElementById('filterColor');
|
||||
const priceRange = document.getElementById('priceRange');
|
||||
const priceValue = document.getElementById('priceValue');
|
||||
const noResults = document.getElementById('no-results');
|
||||
|
||||
const renderCorals = (filteredCorals) => {
|
||||
coralGrid.innerHTML = '';
|
||||
if (filteredCorals.length === 0) {
|
||||
noResults.style.display = 'block';
|
||||
} else {
|
||||
noResults.style.display = 'none';
|
||||
}
|
||||
|
||||
filteredCorals.forEach(coral => {
|
||||
const coralCard = `
|
||||
<div class="col-lg-3 col-md-4 col-sm-6 mb-4">
|
||||
<div class="card h-100 shadow-sm border-light-subtle">
|
||||
<div class="card-img-top-container">
|
||||
<img src="${coral.image}" class="card-img-top" alt="${coral.name}">
|
||||
</div>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h5 class="card-title fw-bold">${coral.name}</h5>
|
||||
<p class="card-text small text-muted">${coral.seller}</p>
|
||||
<div class="mt-auto">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="fw-bold text-primary fs-5">$${coral.price.toFixed(2)}</span>
|
||||
<a href="${coral.seller_url}" class="btn btn-sm btn-outline-primary">
|
||||
<i data-feather="shopping-cart" class="align-text-bottom"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent border-0 pt-0">
|
||||
<span class="badge bg-light text-dark me-1">${coral.type}</span>
|
||||
<span class="badge rounded-pill" style="background-color: ${coral.color.toLowerCase()}; color: ${['Yellow', 'Pink', 'White'].includes(coral.color) ? '#333' : 'white'};">${coral.color}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
coralGrid.innerHTML += coralCard;
|
||||
});
|
||||
feather.replace();
|
||||
};
|
||||
|
||||
const filterAndRender = () => {
|
||||
const searchTerm = searchInput.value.toLowerCase();
|
||||
const selectedType = filterType.value;
|
||||
const selectedColor = filterColor.value;
|
||||
const maxPrice = parseFloat(priceRange.value);
|
||||
|
||||
priceValue.textContent = maxPrice;
|
||||
|
||||
const filteredCorals = corals.filter(coral => {
|
||||
const nameMatch = coral.name.toLowerCase().includes(searchTerm);
|
||||
const typeMatch = selectedType ? coral.type === selectedType : true;
|
||||
const colorMatch = selectedColor ? coral.color === selectedColor : true;
|
||||
const priceMatch = coral.price <= maxPrice;
|
||||
return nameMatch && typeMatch && colorMatch && priceMatch;
|
||||
});
|
||||
|
||||
renderCorals(filteredCorals);
|
||||
};
|
||||
|
||||
// --- Initial Load ---
|
||||
priceValue.textContent = priceRange.value;
|
||||
filterAndRender();
|
||||
|
||||
// Event Listeners
|
||||
searchInput.addEventListener('keyup', filterAndRender);
|
||||
filterType.addEventListener('change', filterAndRender);
|
||||
filterColor.addEventListener('change', filterAndRender);
|
||||
priceRange.addEventListener('input', () => {
|
||||
priceValue.textContent = priceRange.value;
|
||||
});
|
||||
priceRange.addEventListener('change', filterAndRender);
|
||||
});
|
||||
@ -1,82 +0,0 @@
|
||||
// /workspace/assets/js/main.js
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Navbar scroll effect
|
||||
const navbar = document.querySelector('.navbar');
|
||||
if (navbar) {
|
||||
window.addEventListener('scroll', () => {
|
||||
if (window.scrollY > 50) {
|
||||
navbar.classList.add('scrolled');
|
||||
} else {
|
||||
navbar.classList.remove('scrolled');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Contact form submission
|
||||
const contactForm = document.getElementById('contactForm');
|
||||
if (contactForm) {
|
||||
contactForm.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
if (!this.checkValidity()) {
|
||||
e.stopPropagation();
|
||||
this.classList.add('was-validated');
|
||||
return;
|
||||
}
|
||||
this.classList.add('was-validated');
|
||||
|
||||
const submitBtn = this.querySelector('button[type="submit"]');
|
||||
const originalBtnText = submitBtn.innerHTML;
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Sending...';
|
||||
|
||||
const formData = new FormData(this);
|
||||
|
||||
fetch('contact.php', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
showToast('Success!', 'Your message has been sent. We will get back to you shortly.', 'success');
|
||||
contactForm.reset();
|
||||
contactForm.classList.remove('was-validated');
|
||||
} else {
|
||||
showToast('Error!', data.error || 'An unknown error occurred. Please try again.', 'danger');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
showToast('Error!', 'Could not reach the server. Please check your connection.', 'danger');
|
||||
})
|
||||
.finally(() => {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.innerHTML = originalBtnText;
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function showToast(title, message, type = 'info') {
|
||||
const toastContainer = document.getElementById('toast-container');
|
||||
if (!toastContainer) return;
|
||||
|
||||
const toastId = 'toast-' + Date.now();
|
||||
const toastHTML = `
|
||||
<div id="${toastId}" class="toast align-items-center text-white bg-${type} border-0" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
<strong>${title}</strong> ${message}
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
toastContainer.insertAdjacentHTML('beforeend', toastHTML);
|
||||
|
||||
const toastElement = document.getElementById(toastId);
|
||||
const toast = new bootstrap.Toast(toastElement, { delay: 5000 });
|
||||
toast.show();
|
||||
toastElement.addEventListener('hidden.bs.toast', () => {
|
||||
toastElement.remove();
|
||||
});
|
||||
}
|
||||
48
contact.php
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
// /workspace/contact.php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Basic validation
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$email = trim($_POST['email'] ?? '');
|
||||
$message = trim($_POST['message'] ?? '');
|
||||
|
||||
if (empty($name) || empty($email) || empty($message)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'All fields are required.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Invalid email format.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Use MailService
|
||||
require_once __DIR__ . '/mail/MailService.php';
|
||||
|
||||
// The recipient email address.
|
||||
// IMPORTANT: For a real application, this should come from a config file or environment variable,
|
||||
// not be hardcoded. Using the default from .env for this example.
|
||||
$to = getenv('MAIL_TO') ?: null; // Let MailService use its default if not set
|
||||
|
||||
$subject = 'New Contact Form Submission from Coral Hub';
|
||||
|
||||
$res = MailService::sendContactMessage($name, $email, $message, $to, $subject);
|
||||
|
||||
if (!empty($res['success'])) {
|
||||
echo json_encode(['success' => true, 'message' => 'Message sent successfully.']);
|
||||
} else {
|
||||
// Do not expose detailed mail errors to the client for security.
|
||||
// Log this error on the server in a real application.
|
||||
http_response_code(500);
|
||||
error_log('MailService Error: ' . ($res['error'] ?? 'Unknown error'));
|
||||
echo json_encode(['error' => 'Sorry, there was an issue sending your message. Please try again later.']);
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
// includes/pexels.php
|
||||
function pexels_key() {
|
||||
$k = getenv('PEXELS_KEY');
|
||||
return $k && strlen($k) > 0 ? $k : 'Vc99rnmOhHhJAbgGQoKLZtsaIVfkeownoQNbTj78VemUjKh08ZYRbf18';
|
||||
}
|
||||
function pexels_get($url) {
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [ 'Authorization: '. pexels_key() ],
|
||||
CURLOPT_TIMEOUT => 15,
|
||||
]);
|
||||
$resp = curl_exec($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($code >= 200 && $code < 300 && $resp) return json_decode($resp, true);
|
||||
return null;
|
||||
}
|
||||
function download_to($srcUrl, $destPath) {
|
||||
// Ensure the destination directory exists
|
||||
$dir = dirname($destPath);
|
||||
if (!is_dir($dir)) {
|
||||
if (!mkdir($dir, 0775, true)) {
|
||||
// Failed to create directory
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$data = @file_get_contents($srcUrl);
|
||||
if ($data === false) return false;
|
||||
|
||||
return file_put_contents($destPath, $data) !== false;
|
||||
}
|
||||
305
index.php
@ -1,186 +1,131 @@
|
||||
<!DOCTYPE html>
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
@ini_set('display_errors', '1');
|
||||
@error_reporting(E_ALL);
|
||||
@date_default_timezone_set('UTC');
|
||||
|
||||
$phpVersion = PHP_VERSION;
|
||||
$now = date('Y-m-d H:i:s');
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>Coral Hub - The Universal Coral Marketplace</title>
|
||||
<meta name="description" content="Find and buy corals from sellers worldwide. Coral Hub is your one-stop shop for every coral imaginable.">
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://your-domain.com/">
|
||||
<meta property="og:title" content="Coral Hub - The Universal Coral Marketplace">
|
||||
<meta property="og:description" content="Find and buy corals from sellers worldwide. Coral Hub is your one-stop shop for every coral imaginable.">
|
||||
<meta property="og:image" content="https://picsum.photos/seed/coralreef/1200/630">
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image">
|
||||
<meta property="twitter:url" content="https://your-domain.com/">
|
||||
<meta property="twitter:title" content="Coral Hub - The Universal Coral Marketplace">
|
||||
<meta property="twitter:description" content="Find and buy corals from sellers worldwide. Coral Hub is your one-stop shop for every coral imaginable.">
|
||||
<meta property="twitter:image" content="https://picsum.photos/seed/coralreef/1200/630">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&family=Poppins:wght@600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
|
||||
<!-- Custom CSS -->
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>New Style</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color-start: #6a11cb;
|
||||
--bg-color-end: #2575fc;
|
||||
--text-color: #ffffff;
|
||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
||||
animation: bg-pan 20s linear infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes bg-pan {
|
||||
0% { background-position: 0% 0%; }
|
||||
100% { background-position: 100% 100%; }
|
||||
}
|
||||
main {
|
||||
padding: 2rem;
|
||||
}
|
||||
.card {
|
||||
background: var(--card-bg-color);
|
||||
border: 1px solid var(--card-border-color);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.loader {
|
||||
margin: 1.25rem auto 1.25rem;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
||||
border-top-color: #fff;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
.hint {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px; height: 1px;
|
||||
padding: 0; margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap; border: 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 1rem;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
p {
|
||||
margin: 0.5rem 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
code {
|
||||
background: rgba(0,0,0,0.2);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
}
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Toast Container -->
|
||||
<div id="toast-container" class="toast-container"></div>
|
||||
|
||||
<!-- Header -->
|
||||
<!-- Navbar -->
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm sticky-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand fw-bold text-primary" href="index.php"><i data-feather="box" class="me-2"></i>Coral Hub</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="index.php">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="search.php">Search Corals</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#about">About</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#contact">Contact</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<!-- Hero Section -->
|
||||
<section class="py-5 text-center container-fluid" style="background: linear-gradient(135deg, rgba(0, 169, 157, 0.8) 0%, rgba(0, 194, 178, 0.7) 100%), url('https://picsum.photos/seed/coralreef/1600/900') no-repeat center center; background-size: cover;">
|
||||
<div class="row py-lg-5">
|
||||
<div class="col-lg-6 col-md-8 mx-auto">
|
||||
<h1 class="display-3 fw-bold text-white">All Corals. One Ocean.</h1>
|
||||
<p class="lead text-white-50 my-4">The ultimate marketplace for reef aquarists. Search thousands of corals from sellers worldwide.</p>
|
||||
<p>
|
||||
<a href="search.php" class="btn btn-primary my-2">Find Your Coral</a>
|
||||
<a href="#contact" class="btn btn-secondary my-2">Become a Seller</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- About Section -->
|
||||
<section id="about">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-6">
|
||||
<h2 class="mb-4">What is Coral Hub?</h2>
|
||||
<p class="lead">Tired of browsing dozens of websites to find that one specific coral? We are too.</p>
|
||||
<p>Coral Hub is a revolutionary platform that aggregates coral listings from online sellers and local stores into one massive, searchable library. Our mission is to make finding and buying the corals you love simple, fast, and efficient.</p>
|
||||
</div>
|
||||
<div class="col-lg-6 text-center">
|
||||
<img src="https://picsum.photos/seed/aquarium/500/500" class="img-fluid rounded-circle shadow" alt="A beautiful home reef aquarium.">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Portfolio Section -->
|
||||
<section id="portfolio" class="section-bg">
|
||||
<div class="container">
|
||||
<div class="text-center mb-5">
|
||||
<h2>Featured Corals</h2>
|
||||
<p class="lead">A glimpse of what you can find on Coral Hub.</p>
|
||||
</div>
|
||||
<div class="row g-4">
|
||||
<?php
|
||||
$corals = [
|
||||
['name' => 'Ultra Acropora', 'img_seed' => 'acropora', 'price' => '129.99', 'alt' => 'A beautiful Acropora coral fragment.'],
|
||||
['name' => 'Rainbow Zoanthids', 'img_seed' => 'zoanthid', 'price' => '79.50', 'alt' => 'A colony of colorful Zoanthid polyps.'],
|
||||
['name' => 'Flower Pot Goniopora', 'img_seed' => 'goniopora', 'price' => '99.00', 'alt' => 'A bright pink Goniopora coral.'],
|
||||
];
|
||||
foreach ($corals as $coral):
|
||||
?>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card coral-card h-100">
|
||||
<img src="https://picsum.photos/seed/<?php echo $coral['img_seed']; ?>/600/600" class="card-img-top" alt="<?php echo htmlspecialchars($coral['alt']); ?>">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><?php echo htmlspecialchars($coral['name']); ?></h5>
|
||||
<p class="card-text d-flex justify-content-between align-items-center">
|
||||
<span class="coral-price">$<?php echo $coral['price']; ?></span>
|
||||
<a href="#" class="btn btn-sm btn-secondary">View Seller</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section id="contact">
|
||||
<div class="container">
|
||||
<div class="text-center mb-5">
|
||||
<h2>Get In Touch</h2>
|
||||
<p class="lead">Have questions, feedback, or want to become a seller? Drop us a line!</p>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<form id="contactForm" class="needs-validation" novalidate>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name</label>
|
||||
<input type="text" class="form-control" id="name" name="name" required>
|
||||
<div class="invalid-feedback">Please enter your name.</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">Email address</label>
|
||||
<input type="email" class="form-control" id="email" name="email" required>
|
||||
<div class="invalid-feedback">Please enter a valid email address.</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="message" class="form-label">Message</label>
|
||||
<textarea class="form-control" id="message" name="message" rows="5" required></textarea>
|
||||
<div class="invalid-feedback">Please enter your message.</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-primary btn-lg">Send Message</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="footer">
|
||||
<div class="container text-center">
|
||||
<p>© <?php echo date('Y'); ?> Coral Hub. All Rights Reserved.</p>
|
||||
<p><a href="/privacy.php" class="text-white-50">Privacy Policy</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
|
||||
<!-- Custom JS -->
|
||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
|
||||
<!-- Feather Icons -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
||||
<script>
|
||||
feather.replace()
|
||||
</script>
|
||||
<main>
|
||||
<div class="card">
|
||||
<h1>Analyzing your requirements and generating your website…</h1>
|
||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||
<span class="sr-only">Loading…</span>
|
||||
</div>
|
||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWiZZy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
34
privacy.php
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
// /workspace/privacy.php
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Privacy Policy - Coral Hub</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body { padding-top: 2rem; padding-bottom: 2rem; }
|
||||
.container { max-width: 800px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Privacy Policy</h1>
|
||||
<p class="text-muted">Last updated: <?php echo date('F j, Y'); ?></p>
|
||||
<p>This is a placeholder for your privacy policy. You should replace this content with your own policy that details how you collect, use, and protect your users' data.</p>
|
||||
|
||||
<h2>Information We Collect</h2>
|
||||
<p>...</p>
|
||||
|
||||
<h2>How We Use Information</h2>
|
||||
<p>...</p>
|
||||
|
||||
<h2>Data Sharing</h2>
|
||||
<p>...</p>
|
||||
|
||||
<a href="/">Go back to the homepage</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
131
search.php
@ -1,131 +0,0 @@
|
||||
<?php
|
||||
// search.php
|
||||
$pageTitle = "Search Corals - Coral Hub";
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php echo $pageTitle; ?></title>
|
||||
<meta name="description" content="Search and filter through a vast collection of corals from sellers worldwide. Find your perfect coral at Coral Hub.">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&family=Open+Sans:wght@400;600&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Custom CSS -->
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
|
||||
<!-- Feather Icons -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
|
||||
<!-- Navbar -->
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm sticky-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand fw-bold text-primary" href="index.php"><i data-feather="box" class="me-2"></i>Coral Hub</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="index.php">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="search.php">Search Corals</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="index.php#about">About</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="index.php#contact">Contact</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="container my-5">
|
||||
<header class="text-center mb-5">
|
||||
<h1 class="display-4 fw-bold">Find Your Perfect Coral</h1>
|
||||
<p class="lead text-muted">Our entire collection at your fingertips.</p>
|
||||
</header>
|
||||
|
||||
<!-- Search and Filter Section -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-lg-8 mx-auto">
|
||||
<div class="input-group input-group-lg mb-3">
|
||||
<input type="text" id="searchInput" class="form-control" placeholder="Search by name, e.g., 'Zoanthid', 'Acropora'..." aria-label="Search for corals">
|
||||
<button class="btn btn-primary" type="button" id="searchButton"><i data-feather="search" class="align-text-bottom"></i></button>
|
||||
</div>
|
||||
<div class="row g-2">
|
||||
<div class="col-md-4">
|
||||
<select id="filterType" class="form-select">
|
||||
<option selected value="">All Types</option>
|
||||
<option value="SPS">SPS</option>
|
||||
<option value="LPS">LPS</option>
|
||||
<option value="Soft Coral">Soft Coral</option>
|
||||
<option value="Zoanthid">Zoanthid</option>
|
||||
<option value="Mushroom">Mushroom</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<select id="filterColor" class="form-select">
|
||||
<option selected value="">All Colors</option>
|
||||
<option value="Blue">Blue</option>
|
||||
<option value="Red">Red</option>
|
||||
<option value="Green">Green</option>
|
||||
<option value="Yellow">Yellow</option>
|
||||
<option value="Pink">Pink</option>
|
||||
<option value="Rainbow">Rainbow</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="range" class="form-range" id="priceRange" min="0" max="500" step="10">
|
||||
<div class="d-flex justify-content-between">
|
||||
<small>Price: $<span id="priceValue">0</span></small>
|
||||
<small>$500</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Coral Grid -->
|
||||
<div id="coral-grid" class="row g-4">
|
||||
<!-- Corals will be dynamically inserted here -->
|
||||
</div>
|
||||
<div id="no-results" class="text-center my-5" style="display: none;">
|
||||
<h3 class="fw-light">No Corals Found</h3>
|
||||
<p class="text-muted">Try adjusting your search or filters.</p>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="bg-white border-top py-4 mt-5">
|
||||
<div class="container text-center text-muted">
|
||||
<p class="mb-1">© <?php echo date("Y"); ?> Coral Hub. All Rights Reserved.</p>
|
||||
<p class="mb-0 small"><a href="privacy.php" class="text-muted">Privacy Policy</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
|
||||
<!-- Custom JS for Search -->
|
||||
<script src="assets/js/corals.js?v=<?php echo time(); ?>"></script>
|
||||
|
||||
<script>
|
||||
feather.replace()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||