major fix
This commit is contained in:
1 parent
b78fbcd833
commit
c9f38f568f
14 files changed
+678
-1076
No files matched your search
@@ -1,9 +1,5 @@
|
||||
MYSQL_DATABASE="railway"
|
||||
MYSQL_PUBLIC_URL="mysql://root:eIXppNyuzdrfoijMvKHncPsJOicPuUkf@switchback.proxy.rlwy.net:16829/railway"
|
||||
MYSQL_ROOT_PASSWORD="eIXppNyuzdrfoijMvKHncPsJOicPuUkf"
|
||||
MYSQL_URL="mysql://root:eIXppNyuzdrfoijMvKHncPsJOicPuUkf@mysql.railway.internal:3306/railway"
|
||||
MYSQLDATABASE="railway"
|
||||
MYSQLHOST="mysql.railway.internal"
|
||||
MYSQLPASSWORD="eIXppNyuzdrfoijMvKHncPsJOicPuUkf"
|
||||
MYSQLDATABASE="unimarket"
|
||||
MYSQLHOST="127.0.0.1"
|
||||
MYSQLPASSWORD=""
|
||||
MYSQLPORT="3306"
|
||||
MYSQLUSER="root"
|
||||
@@ -0,0 +1,75 @@
|
||||
# Fix database connection and route navigation
|
||||
|
||||
## Context
|
||||
|
||||
Two unrelated defects are breaking the app on Laragon (Windows, Apache, PHP, MySQL/MariaDB):
|
||||
|
||||
1. **Database connection fails.** `config/database.php` reads `MYSQLHOST`/`MYSQLUSER`/`MYSQLPASSWORD`/etc. via `getenv()`. PHP under Apache/CGI on Laragon does **not** expose a project `.env` file to `getenv()` automatically — only the real OS environment. There is no `vlucas/phpdotenv` or `apache_setenv` call. The `.env` file at the project root is therefore ignored, so `getenv("MYSQLHOST")` returns `false`, and the PDO DSN is malformed (`host=;dbname=unimarket;port=3306;…`).
|
||||
2. **Broken navigation links.** `index.php` links to `/public/customer/products/browse.php` and `/public/owner/dashboard.php`, but the actual folders live at `/customer/…` and `/owner/…` (no `public/` prefix). `includes/sidebar.php` references a `BASE_URL` constant that is never defined anywhere. Header/sidebar links will render as `/owner/products/list.php` (no host) or as the literal text `BASE_URLowner/…`.
|
||||
|
||||
The `.env` file is otherwise correct: `MYSQLHOST=127.0.0.1`, `MYSQLUSER=root`, `MYSQLPASSWORD=` (empty), `MYSQLPORT=3306`, `MYSQLDATABASE=unimarket`. Database `unimarket` is created by `unimarket.sql`.
|
||||
|
||||
## Decisions
|
||||
|
||||
- **DB fix approach:** Add a small inline parser for `.env` in `config/database.php` (no new dependency). On first call it loads `/path/to/project/.env`, sets values into `$_SERVER`, `$_ENV`, and `putenv()`, then continues to use `getenv()`. This is the minimum change that keeps `getenv()` calls working everywhere else and avoids pulling in Composer.
|
||||
- **Routes approach:** Fix the offending links to use the real paths (`/customer/…`, `/owner/…`, `/admin/…`) and define `BASE_URL` once. Do **not** rename folders or add a `public/` rewrite — that conflicts with the `guide.txt` layout.
|
||||
- `Unimarket/includes/sidebar.php` is a duplicate/stale file; we will not edit it (it is not referenced by any page). It is flagged in the risks so the team can delete it.
|
||||
|
||||
## Tasks
|
||||
|
||||
### 1. `config/database.php` — load `.env` before reading env vars
|
||||
- Add a function `loadEnv($path)` that:
|
||||
- Returns silently if file missing or unreadable.
|
||||
- Skips blank lines and `#` comments.
|
||||
- For `KEY=value` lines, calls `putenv("$KEY=$value")`, sets `$_ENV[$KEY]`, and `$_SERVER[$KEY]`.
|
||||
- Honors double-quoted values (strips quotes) and leaves empty values as `""`.
|
||||
- Call `loadEnv(__DIR__ . '/../.env')` before the `getenv()` reads.
|
||||
- Keep existing `try/catch` so a real connection failure still shows the message.
|
||||
|
||||
### 2. `index.php` — fix two hero buttons
|
||||
- Line 153: `/public/customer/products/browse.php` → `/customer/products/browse.php`
|
||||
- Line 155: `/public/owner/dashboard.php` → `/owner/dashboard.php`
|
||||
|
||||
### 3. `includes/sidebar.php` — define `BASE_URL` and fix trailing slashes
|
||||
- At the top of the file (before any output), add a guard that defines `BASE_URL` if not already set:
|
||||
```php
|
||||
if (!defined('BASE_URL')) { define('BASE_URL', '/'); }
|
||||
```
|
||||
- Note: header.php links use absolute paths starting with `/` already, so sidebar is the only place that needs the constant. The current three links render as `/owner/products/list.php` etc., which is what we want.
|
||||
- (Optional but recommended) Remove the third link to `owner/reports.php` because `owner/reports.php` does **not** exist in the repo (see Risks). Decision: keep it for now — out of scope; this task is "fix what is broken", not "remove features".
|
||||
|
||||
### 4. `Unimarket/includes/sidebar.php` — flag as stale
|
||||
- Do not edit. List in Open Questions so the team decides whether to delete it.
|
||||
|
||||
## Files to change
|
||||
|
||||
- `config/database.php` — add `loadEnv()` and call it
|
||||
- `index.php` — two href fixes
|
||||
- `includes/sidebar.php` — add `BASE_URL` guard
|
||||
|
||||
## Out of scope
|
||||
|
||||
- `Unimarket/includes/sidebar.php` (duplicate, not referenced anywhere)
|
||||
- Missing `owner/reports.php`, `owner/manage_orders.php`, `admin/reports.php` — those are separate feature gaps, not routing bugs
|
||||
- Composer / phpdotenv adoption
|
||||
- CSRF enforcement gaps and other security items
|
||||
- `.htaccess` or `public/` rewrite
|
||||
|
||||
## Validation
|
||||
|
||||
Manual smoke test on Laragon (`http://unimarket.test` or `http://localhost/Unimarket/`):
|
||||
|
||||
1. Hit `/index.php` — page loads, no `Database connection failed` banner.
|
||||
2. Trending Products section renders up to 6 cards from the `products` table.
|
||||
3. From a guest session, both header "Login"/"Register" links open the auth pages.
|
||||
4. Log in as an owner; click "Go to Dashboard" hero button — lands on `/owner/dashboard.php` (not 404).
|
||||
5. Log in as a customer; click "Browse Products" — lands on `/customer/products/browse.php`.
|
||||
6. From the owner sidebar, "Products" and "Orders" links open their list pages without "BASE_URL" appearing in the URL or the rendered HTML.
|
||||
7. Confirm by viewing source of any owner page that no literal string `BASE_URL` appears in `href` attributes.
|
||||
|
||||
## Risks / open questions
|
||||
|
||||
- **Stale duplicate file:** `Unimarket/includes/sidebar.php` mirrors `includes/sidebar.php` and still uses `BASE_URL`. Recommend deleting the entire `Unimarket/` subfolder — confirm with team before doing so.
|
||||
- **Empty `MYSQLPASSWORD`:** Laragon default MySQL root has no password; the `getenv("MYSQLPASSWORD") ?: ''` works once `.env` is loaded. If a teammate's MySQL root *does* have a password, they must set `MYSQLPASSWORD="theirpass"` in `.env`.
|
||||
- **`owner/reports.php` referenced but absent:** clicking the "Reports" sidebar link will 404. Flagged for the team; not fixed here.
|
||||
- **No tests exist** in the repo, so validation is manual only.
|
||||
@@ -0,0 +1,14 @@
|
||||
# DESIGN
|
||||
- tailwindcss cdn
|
||||
- motion
|
||||
- e-commerce design
|
||||
- make it simple and premium
|
||||
- responsive
|
||||
|
||||
# LANDING PAGE
|
||||
- fix font and colors (background , card)
|
||||
- do not add margin in hero and final CTA left and right
|
||||
|
||||
# LOGO TAB TITLE LOGO, HEADER & FOOTER
|
||||
- make the logo black in light theme
|
||||
- make the logo white in dark theme
|
||||
@@ -1,20 +0,0 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="<?php echo BASE_URL; ?>owner/products/list.php">
|
||||
<i class="fas fa-box me-2"></i>Products
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="<?php echo BASE_URL; ?>owner/orders/list.php">
|
||||
<i class="fas fa-shopping-cart me-2"></i>Orders
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="<?php echo BASE_URL; ?>owner/reports.php">
|
||||
<i class="fas fa-chart-bar me-2"></i>Reports
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M331.8 504.4C331.1 487.5 339.7 471.7 354.2 463C368.7 454.4 386.7 454.5 401.2 463.2C415.6 471.9 424.1 487.8 423.3 504.7C424 521.6 415.4 537.4 400.9 546.1C386.4 554.7 368.4 554.6 353.9 545.9C339.5 537.2 331 521.3 331.8 504.4zM169.4 458.9C152.6 458.2 136.7 466.7 128.1 481.2C119.5 495.7 119.6 513.7 128.3 528.1C137 542.6 152.9 551 169.7 550.2C186.5 550.9 202.4 542.4 211 527.9C219.6 513.4 219.5 495.4 210.8 481C202.1 466.5 186.2 458.1 169.4 458.9zM461.1 188.9C158.9 188.9 81.9 176.1 0 89.7C34.4 141.4 53.3 238.6 373.1 233.9C706.4 228.9 503.1 320 443.9 422.8C630.6 256.1 763.3 188.9 461.1 188.9z"/></svg>
|
||||
|
After Width: | Height: | Size: 671 B |
Binary file not shown.
|
Before Width: | Height: | Size: 2.6 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 169 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.9 MiB |
@@ -1,4 +1,27 @@
|
||||
<?php
|
||||
function loadEnv($path) {
|
||||
if (!is_readable($path)) return;
|
||||
$lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
if ($lines === false) return;
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if ($line === '' || $line[0] === '#') continue;
|
||||
if (strpos($line, '=') === false) continue;
|
||||
list($key, $value) = explode('=', $line, 2);
|
||||
$key = trim($key);
|
||||
$value = trim($value);
|
||||
if (strlen($value) >= 2 && $value[0] === '"' && substr($value, -1) === '"') {
|
||||
$value = substr($value, 1, -1);
|
||||
}
|
||||
if ($key === '') continue;
|
||||
putenv("$key=$value");
|
||||
$_ENV[$key] = $value;
|
||||
$_SERVER[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
loadEnv(__DIR__ . '/../.env');
|
||||
|
||||
$host = getenv("MYSQLHOST");
|
||||
$db = getenv("MYSQLDATABASE");
|
||||
$user = getenv("MYSQLUSER");
|
||||
|
||||
+81
-53
@@ -1,53 +1,81 @@
|
||||
</main>
|
||||
|
||||
<footer style="background-color: var(--primary-dark); color: var(--light-text); padding: 40px 0; margin-top: 40px;">
|
||||
<div class="container" style="background: transparent; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; border: none; margin: 0 auto; padding: 0 30px;">
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 30px;">
|
||||
<div>
|
||||
<h3 style="margin-bottom: 15px; color: var(--light-text);">UniMarket</h3>
|
||||
<p>Your university's premier marketplace for buying and selling products within the campus community.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 style="margin-bottom: 15px; color: var(--light-text);">Quick Links</h3>
|
||||
<ul style="list-style: none;">
|
||||
<li style="margin-bottom: 8px;"><a href="/index.php" style="color: var(--light-text); text-decoration: none;">Home</a></li>
|
||||
<?php if (!isLoggedIn()): ?>
|
||||
<li style="margin-bottom: 8px;"><a href="/auth/login.php" style="color: var(--light-text); text-decoration: none;">Login</a></li>
|
||||
<li style="margin-bottom: 8px;"><a href="/auth/register.php" style="color: var(--light-text); text-decoration: none;">Register</a></li>
|
||||
<?php else: ?>
|
||||
<?php if (isCustomer()): ?>
|
||||
<li style="margin-bottom: 8px;"><a href="/customer/products/browse.php" style="color: var(--light-text); text-decoration: none;">Browse Products</a></li>
|
||||
<li style="margin-bottom: 8px;"><a href="/customer/profile.php" style="color: var(--light-text); text-decoration: none;">My Profile</a></li>
|
||||
<?php else: ?>
|
||||
<li style="margin-bottom: 8px;"><a href="/owner/dashboard.php" style="color: var(--light-text); text-decoration: none;">Dashboard</a></li>
|
||||
<li style="margin-bottom: 8px;"><a href="/owner/products/add.php" style="color: var(--light-text); text-decoration: none;">Add Product</a></li>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 style="margin-bottom: 15px; color: var(--light-text);">Contact</h3>
|
||||
<ul style="list-style: none;">
|
||||
<li style="margin-bottom: 8px;"><i class="fas fa-envelope" style="margin-right: 8px;"></i> contact@unimarket.edu</li>
|
||||
<li style="margin-bottom: 8px;"><i class="fas fa-phone" style="margin-right: 8px;"></i> (123) 456-7890</li>
|
||||
<li style="margin-bottom: 8px;"><i class="fas fa-map-marker-alt" style="margin-right: 8px;"></i> University Campus</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="border-top: 1px solid rgba(255,255,255,0.1); margin-top: 30px; padding-top: 20px; text-align: center;">
|
||||
<p>© <?php echo date('Y'); ?> UniMarket. All rights reserved.</p>
|
||||
<div style="margin-top: 15px;">
|
||||
<a href="#" style="color: var(--light-text); margin: 0 10px; font-size: 1.2rem;"><i class="fab fa-facebook"></i></a>
|
||||
<a href="#" style="color: var(--light-text); margin: 0 10px; font-size: 1.2rem;"><i class="fab fa-twitter"></i></a>
|
||||
<a href="#" style="color: var(--light-text); margin: 0 10px; font-size: 1.2rem;"><i class="fab fa-instagram"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/assets/js/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</main>
|
||||
|
||||
<footer class="bg-brand-background border-t border-brand-muted/20 py-20 px-6 transition-colors duration-300">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-12 mb-16">
|
||||
<!-- Brand -->
|
||||
<div class="col-span-1 md:col-span-1 space-y-6">
|
||||
<a href="/index.php" class="flex items-center gap-3 group">
|
||||
<img src="/assets/images/logo/logo.svg" alt="UniMarket Logo" class="h-7 w-auto transition-all dark:invert">
|
||||
<span class="serif text-xl font-semibold tracking-tight text-brand-text">UniMarket</span>
|
||||
</a>
|
||||
<p class="text-brand-muted font-light text-sm leading-relaxed max-w-xs">
|
||||
The university's premier exchange for students. Curated, secure, and community-driven.
|
||||
</p>
|
||||
<div class="flex gap-4 text-brand-muted">
|
||||
<a href="#" class="hover:text-brand-text transition-colors"><i class="fab fa-facebook-f"></i></a>
|
||||
<a href="#" class="hover:text-brand-text transition-colors"><i class="fab fa-twitter"></i></a>
|
||||
<a href="#" class="hover:text-brand-text transition-colors"><i class="fab fa-instagram"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Links -->
|
||||
<div class="space-y-6">
|
||||
<h4 class="serif text-lg text-brand-text">Navigation</h4>
|
||||
<ul class="space-y-3 text-sm font-medium text-brand-muted">
|
||||
<li><a href="/index.php" class="hover:text-brand-text transition-colors">Home</a></li>
|
||||
<?php if (!isLoggedIn()): ?>
|
||||
<li><a href="/auth/login.php" class="hover:text-brand-text transition-colors">Login</a></li>
|
||||
<li><a href="/auth/register.php" class="hover:text-brand-text transition-colors">Register</a></li>
|
||||
<?php else: ?>
|
||||
<?php if (isCustomer()): ?>
|
||||
<li><a href="/customer/products/browse.php" class="hover:text-brand-text transition-colors">Browse Products</a></li>
|
||||
<li><a href="/customer/profile.php" class="hover:text-brand-text transition-colors">My Profile</a></li>
|
||||
<?php else: ?>
|
||||
<li><a href="/owner/dashboard.php" class="hover:text-brand-text transition-colors">Dashboard</a></li>
|
||||
<li><a href="/owner/products/add.php" class="hover:text-brand-text transition-colors">Add Product</a></li>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Support -->
|
||||
<div class="space-y-6">
|
||||
<h4 class="serif text-lg text-brand-text">Support</h4>
|
||||
<ul class="space-y-3 text-sm font-medium text-brand-muted">
|
||||
<li class="flex items-center gap-3 hover:text-brand-text transition-colors cursor-pointer">
|
||||
<i class="fas fa-envelope w-4"></i> contact@unimarket.edu
|
||||
</li>
|
||||
<li class="flex items-center gap-3 hover:text-brand-text transition-colors cursor-pointer">
|
||||
<i class="fas fa-phone w-4"></i> (123) 456-7890
|
||||
</li>
|
||||
<li class="flex items-center gap-3 hover:text-brand-text transition-colors cursor-pointer">
|
||||
<i class="fas fa-map-marker-alt w-4"></i> University Campus
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Newsletter -->
|
||||
<div class="space-y-6">
|
||||
<h4 class="serif text-lg text-brand-text">Stay Updated</h4>
|
||||
<p class="text-brand-muted text-sm font-light leading-relaxed">Get notified about the latest campus arrivals.</p>
|
||||
<form class="flex gap-2">
|
||||
<input type="email" placeholder="Email address" class="bg-brand-surface border border-brand-muted/20 rounded-xl px-4 py-2 text-sm w-full focus:outline-none focus:ring-2 focus:ring-brand-primary transition-all text-brand-text">
|
||||
<button class="bg-brand-text text-brand-background px-4 py-2 rounded-xl text-sm font-medium hover:bg-brand-primary transition-all">Join</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-8 border-t border-brand-muted/20 flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<p class="text-brand-muted text-xs font-light">© <?php echo date('Y'); ?> UniMarket. All rights reserved.</p>
|
||||
<div class="flex gap-6 text-xs font-medium text-brand-muted">
|
||||
<a href="#" class="hover:text-brand-text transition-colors">Privacy Policy</a>
|
||||
<a href="#" class="hover:text-brand-text transition-colors">Terms of Service</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/assets/js/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
+166
-770
@@ -1,795 +1,191 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/auth_functions.php';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php echo isset($page_title) ? $page_title . ' - ' : ''; ?>UniMarket - University Marketplace</title>
|
||||
<link rel="stylesheet" href="/assets/css/style.css">
|
||||
<link rel="stylesheet" href="/assets/css/responsive.css">
|
||||
<link rel="icon" type="image/x-icon" href="/assets/images/logo/tab-logo.png">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<style>
|
||||
.logo{
|
||||
text-decoration: none;
|
||||
color: var(--light-text);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.logo img {
|
||||
height: 30px;
|
||||
width: auto;
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
/* Sticky header styles */
|
||||
header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
background: rgba(46, 125, 50, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
max-width: 100%;
|
||||
color: var(--light-text);
|
||||
padding: 15px 0;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
header .container {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
backdrop-filter: none;
|
||||
-webkit-backdrop-filter: none;
|
||||
border: none;
|
||||
margin: 0 auto;
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: 60px !important;
|
||||
}
|
||||
|
||||
/* Adjust mobile menu for fixed header */
|
||||
.mobile-menu {
|
||||
position: fixed;
|
||||
top: 60px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
background: rgba(46, 125, 50, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
color: var(--light-text);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
transition: background-color 0.3s ease;
|
||||
height: 40px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
nav ul li a:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
nav ul li a i {
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.mobile-menu-toggle {
|
||||
display: none;
|
||||
color: var(--light-text);
|
||||
font-size: 1.5rem;
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.header-content nav ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-menu-toggle {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.mobile-menu {
|
||||
display: none;
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
.mobile-menu ul {
|
||||
list-style: none;
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mobile-menu ul li {
|
||||
margin: 0;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.mobile-menu ul li a {
|
||||
display: block;
|
||||
padding: 8px 15px;
|
||||
color: var(--light-text);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mobile-menu ul li a:hover {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add logout modal styles */
|
||||
.logout-modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 2000;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logout-modal-content {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
max-width: 400px;
|
||||
width: 90%;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.logout-modal h2 {
|
||||
margin-bottom: 20px;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.logout-modal-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 15px;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.logout-modal-buttons button {
|
||||
padding: 10px 25px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.logout-modal-buttons .btn-cancel {
|
||||
background: #e0e0e0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.logout-modal-buttons .btn-cancel:hover {
|
||||
background: #d0d0d0;
|
||||
}
|
||||
|
||||
.logout-modal-buttons .btn-confirm {
|
||||
background: #ff4444;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.logout-modal-buttons .btn-confirm:hover {
|
||||
background: #ff0000;
|
||||
}
|
||||
|
||||
/* Update notification styles */
|
||||
.notification-btn {
|
||||
position: relative;
|
||||
color: var(--light-text);
|
||||
text-decoration: none;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
height: 40px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.notification-btn:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.notification-btn i {
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.notification-badge {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
background-color: #ff4444;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
padding: 2px 6px;
|
||||
font-size: 0.7rem;
|
||||
display: none;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
.notification-badge.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.notification-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.notification-modal {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: calc(100% + 10px);
|
||||
right: 0;
|
||||
width: 350px;
|
||||
max-height: 80vh;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
z-index: 2000;
|
||||
animation: slideDown 0.2s ease;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
transform: translateY(-10px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.notification-modal::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: 20px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: white;
|
||||
transform: rotate(45deg);
|
||||
box-shadow: -2px -2px 5px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.notification-modal-content {
|
||||
background: white;
|
||||
padding: 0;
|
||||
border-radius: 8px;
|
||||
max-height: 80vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.notification-modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.notification-modal-header h2 {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.notification-modal-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
opacity: 0.8;
|
||||
transition: opacity 0.3s;
|
||||
padding: 5px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.notification-modal-close:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.notification-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.notification-list::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.notification-list::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
.notification-list::-webkit-scrollbar-thumb {
|
||||
background: #888;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.notification-list::-webkit-scrollbar-thumb:hover {
|
||||
background: #666;
|
||||
}
|
||||
|
||||
.notification-item {
|
||||
padding: 12px 15px;
|
||||
border-bottom: 1px solid #eee;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
<!-- The head section is handled by index.php for the landing page, but we maintain the logic here for internal pages -->
|
||||
<header class="fixed top-0 left-0 right-0 z-[1000] transition-all duration-300 glass border-b border-brand-muted/20">
|
||||
<div class="max-w-7xl mx-auto px-6 h-20 flex items-center justify-between">
|
||||
<!-- Logo -->
|
||||
<a href="/index.php" class="flex items-center gap-3 group transition-transform duration-300 active:scale-95">
|
||||
<img src="/assets/images/logo/logo.svg" alt="UniMarket Logo" class="h-8 w-auto transition-all dark:invert">
|
||||
<span class="serif text-xl font-semibold tracking-tight text-brand-text">UniMarket</span>
|
||||
</a>
|
||||
|
||||
.notification-item:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.notification-item.unread {
|
||||
background-color: #f0f7ff;
|
||||
}
|
||||
|
||||
.notification-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.notification-icon.ready {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
}
|
||||
|
||||
.notification-icon.completed {
|
||||
background-color: #e2e3e5;
|
||||
color: #383d41;
|
||||
}
|
||||
|
||||
.notification-icon.cancelled {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
|
||||
.notification-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.notification-title {
|
||||
font-weight: 500;
|
||||
margin-bottom: 4px;
|
||||
color: #333;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.notification-time {
|
||||
font-size: 0.8rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.notification-status {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.status-ready {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
background-color: #e2e3e5;
|
||||
color: #383d41;
|
||||
}
|
||||
|
||||
.status-cancelled {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
<!-- Desktop Navigation -->
|
||||
<nav class="hidden md:flex items-center gap-4">
|
||||
<!-- Theme Toggle -->
|
||||
<button onclick="toggleTheme()" class="p-2 rounded-full hover:bg-brand-surface transition-all text-brand-text" title="Toggle Theme">
|
||||
<i class="fas fa-moon dark:hidden"></i>
|
||||
<i class="fas fa-sun hidden dark:block"></i>
|
||||
</button>
|
||||
|
||||
.no-notifications {
|
||||
text-align: center;
|
||||
padding: 30px 20px;
|
||||
color: #666;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.no-notifications i {
|
||||
font-size: 1.8rem;
|
||||
color: #ccc;
|
||||
margin-bottom: 8px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.no-notifications p {
|
||||
margin: 0;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.notification-modal {
|
||||
position: fixed;
|
||||
top: 60px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
max-height: calc(100vh - 60px);
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.notification-modal::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.logout-link {
|
||||
color: var(--light-text) !important;
|
||||
transition: all 0.3s ease !important;
|
||||
background: none !important;
|
||||
background-color: transparent !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
height: 40px !important;
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
.logout-link:hover {
|
||||
background-color: rgba(255, 68, 68, 0.1) !important;
|
||||
color: #ff4444 !important;
|
||||
}
|
||||
|
||||
.logout-link i {
|
||||
width: 20px !important;
|
||||
text-align: center !important;
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Add logout modal HTML -->
|
||||
<div class="logout-modal" id="logoutModal">
|
||||
<div class="logout-modal-content">
|
||||
<h2>Confirm Logout</h2>
|
||||
<p>Are you sure you want to logout?</p>
|
||||
<div class="logout-modal-buttons">
|
||||
<button class="btn-cancel" onclick="closeLogoutModal()">Cancel</button>
|
||||
<button class="btn-confirm" onclick="confirmLogout()">Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<header>
|
||||
<div class="container header-content">
|
||||
<a href="/index.php" class="logo">
|
||||
<img src="/assets/images/logo/logo.png" alt="UniMarket Logo">
|
||||
</a>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<?php if (isLoggedIn()): ?>
|
||||
<?php if (isCustomer()): ?>
|
||||
<li><a href="/customer/products/browse.php"><i class="fas fa-search"></i> Browse</a></li>
|
||||
<li><a href="/customer/cart.php"><i class="fas fa-shopping-cart"></i> Cart</a></li>
|
||||
<li class="notification-container">
|
||||
<a href="#" onclick="openNotificationModal(); return false;" class="notification-btn">
|
||||
<i class="fas fa-bell"></i> Notifications
|
||||
<span class="notification-badge" id="notificationBadge"></span>
|
||||
</a>
|
||||
<div class="notification-modal" id="notificationModal">
|
||||
<div class="notification-modal-content">
|
||||
<div class="notification-modal-header">
|
||||
<h2><i class="fas fa-bell"></i> Notifications</h2>
|
||||
<button class="notification-modal-close" onclick="closeNotificationModal()">×</button>
|
||||
</div>
|
||||
<div class="notification-list" id="notificationList">
|
||||
<div class="no-notifications">
|
||||
<i class="fas fa-bell-slash"></i>
|
||||
<p>No notifications yet</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="flex items-center gap-1 text-sm font-medium text-brand-muted">
|
||||
<?php if (isLoggedIn()): ?>
|
||||
<?php if (isCustomer()): ?>
|
||||
<li><a href="/customer/products/browse.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Browse</a></li>
|
||||
<li><a href="/customer/cart.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Cart</a></li>
|
||||
<li class="relative group">
|
||||
<a href="#" onclick="openNotificationModal(); return false;" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all flex items-center gap-2">
|
||||
Notifications
|
||||
<span class="notification-badge" id="notificationBadge"></span>
|
||||
</a>
|
||||
<!-- Notification Modal -->
|
||||
<div class="absolute top-full right-0 mt-2 w-80 bg-brand-background rounded-3xl shadow-2xl border border-brand-muted/20 opacity-0 pointer-events-none translate-y-2 transition-all duration-300 z-[2000]" id="notificationModal">
|
||||
<div class="p-4 border-b border-brand-muted/10 flex justify-between items-center bg-brand-surface/50 rounded-t-3xl">
|
||||
<h2 class="font-semibold text-sm flex items-center gap-2 text-brand-text"><i class="fas fa-bell text-brand-primary"></i> Notifications</h2>
|
||||
<button onclick="closeNotificationModal()" class="text-brand-muted hover:text-brand-text">×</button>
|
||||
</div>
|
||||
</li>
|
||||
<li><a href="/customer/profile.php"><i class="fas fa-user"></i> Profile</a></li>
|
||||
<?php elseif (isAdmin()): ?>
|
||||
<li><a href="/admin/dashboard.php"><i class="fas fa-tachometer-alt"></i> Admin Dashboard</a></li>
|
||||
<li><a href="/admin/users/manage.php"><i class="fas fa-users"></i> Users</a></li>
|
||||
<li><a href="/admin/products/index.php"><i class="fas fa-box"></i> Products</a></li>
|
||||
<li><a href="/admin/orders/manage.php"><i class="fas fa-shopping-cart"></i> Orders</a></li>
|
||||
<?php else: ?>
|
||||
<li><a href="/owner/dashboard.php"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li>
|
||||
<li><a href="/owner/products/list.php"><i class="fas fa-box-open"></i> Products</a></li>
|
||||
<?php endif; ?>
|
||||
<li><a href="#" onclick="openLogoutModal(); return false;" class="logout-link"><i class="fas fa-sign-out-alt"></i> Logout</a></li>
|
||||
<div class="max-h-[400px] overflow-y-auto p-2" id="notificationList">
|
||||
<div class="py-10 text-center text-brand-muted text-xs italic">No notifications yet</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li><a href="/customer/profile.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Profile</a></li>
|
||||
<?php elseif (isAdmin()): ?>
|
||||
<li><a href="/admin/dashboard.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Admin</a></li>
|
||||
<li><a href="/admin/users/manage.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Users</a></li>
|
||||
<li><a href="/admin/products/index.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Products</a></li>
|
||||
<li><a href="/admin/orders/manage.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Orders</a></li>
|
||||
<?php else: ?>
|
||||
<li><a href="/index.php"><i class="fas fa-home"></i> Home</a></li>
|
||||
<li><a href="/auth/login.php"><i class="fas fa-sign-in-alt"></i> Login</a></li>
|
||||
<li><a href="/auth/register.php"><i class="fas fa-user-plus"></i> Register</a></li>
|
||||
<li><a href="/owner/dashboard.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Dashboard</a></li>
|
||||
<li><a href="/owner/products/list.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Products</a></li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<?php if (isLoggedIn()): ?>
|
||||
<div class="mobile-menu-toggle" style="display: none;">
|
||||
<i class="fas fa-bars"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<?php if (isLoggedIn()): ?>
|
||||
<style>
|
||||
.mobile-menu {
|
||||
display: none;
|
||||
background-color: var(--primary-dark);
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
.mobile-menu ul {
|
||||
list-style: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mobile-menu ul li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.mobile-menu ul li a {
|
||||
color: var(--light-text);
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.mobile-menu-toggle {
|
||||
color: var(--light-text);
|
||||
font-size: 1.5rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.header-content nav ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-menu-toggle {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="mobile-menu" id="mobileMenu">
|
||||
<div class="container">
|
||||
<ul>
|
||||
<?php if (isCustomer()): ?>
|
||||
<li><a href="/customer/products/browse.php"><i class="fas fa-search"></i> Browse</a></li>
|
||||
<li><a href="/customer/cart.php"><i class="fas fa-shopping-cart"></i> Cart</a></li>
|
||||
<li class="notification-container">
|
||||
<a href="#" onclick="openNotificationModal(); return false;" class="notification-btn">
|
||||
<i class="fas fa-bell"></i> Notifications
|
||||
<span class="notification-badge" id="notificationBadge"></span>
|
||||
</a>
|
||||
<div class="notification-modal" id="notificationModal">
|
||||
<div class="notification-modal-content">
|
||||
<div class="notification-modal-header">
|
||||
<h2><i class="fas fa-bell"></i> Notifications</h2>
|
||||
<button class="notification-modal-close" onclick="closeNotificationModal()">×</button>
|
||||
</div>
|
||||
<div class="notification-list" id="notificationList">
|
||||
<div class="no-notifications">
|
||||
<i class="fas fa-bell-slash"></i>
|
||||
<p>No notifications yet</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<li>
|
||||
<a href="#" onclick="openLogoutModal(); return false;" class="px-4 py-2 rounded-full bg-brand-text text-brand-background hover:bg-brand-primary transition-all ml-2">Logout</a>
|
||||
</li>
|
||||
<li><a href="/customer/profile.php"><i class="fas fa-user"></i> Profile</a></li>
|
||||
<?php elseif (isAdmin()): ?>
|
||||
<li><a href="/admin/dashboard.php"><i class="fas fa-tachometer-alt"></i> Admin Dashboard</a></li>
|
||||
<li><a href="/admin/users/manage.php"><i class="fas fa-users"></i> Users</a></li>
|
||||
<li><a href="/admin/products/index.php"><i class="fas fa-box"></i> Products</a></li>
|
||||
<li><a href="/admin/orders/manage.php"><i class="fas fa-shopping-cart"></i> Orders</a></li>
|
||||
<?php else: ?>
|
||||
<li><a href="/owner/dashboard.php"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li>
|
||||
<li><a href="/owner/products/list.php"><i class="fas fa-box-open"></i> Products</a></li>
|
||||
<li><a href="/index.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Home</a></li>
|
||||
<li><a href="/auth/login.php" class="px-4 py-2 rounded-full hover:bg-brand-surface hover:text-brand-text transition-all">Login</a></li>
|
||||
<li><a href="/auth/register.php" class="px-4 py-2 rounded-full bg-brand-text text-brand-background hover:bg-brand-primary transition-all ml-2">Join Now</a></li>
|
||||
<?php endif; ?>
|
||||
<li><a href="#" onclick="openLogoutModal(); return false;" class="logout-link"><i class="fas fa-sign-out-alt"></i> Logout</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Mobile Toggle -->
|
||||
<button class="md:hidden p-2 text-slate-600 hover:text-black transition-colors" id="mobileMenuToggle">
|
||||
<i class="fas fa-bars text-xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<div class="hidden md:hidden absolute top-20 left-0 right-0 bg-white border-b border-slate-100 z-[999] animate-in slide-in-from-top duration-300" id="mobileMenu">
|
||||
<ul class="flex flex-col p-6 gap-4 text-sm font-medium text-slate-600">
|
||||
<?php if (isLoggedIn()): ?>
|
||||
<?php if (isCustomer()): ?>
|
||||
<li><a href="/customer/products/browse.php" class="block py-2">Browse</a></li>
|
||||
<li><a href="/customer/cart.php" class="block py-2">Cart</a></li>
|
||||
<li><a href="/customer/profile.php" class="block py-2">Profile</a></li>
|
||||
<?php elseif (isAdmin()): ?>
|
||||
<li><a href="/admin/dashboard.php" class="block py-2">Admin Dashboard</a></li>
|
||||
<li><a href="/admin/users/manage.php" class="block py-2">Users</a></li>
|
||||
<li><a href="/admin/products/index.php" class="block py-2">Products</a></li>
|
||||
<li><a href="/admin/orders/manage.php" class="block py-2">Orders</a></li>
|
||||
<?php else: ?>
|
||||
<li><a href="/owner/dashboard.php" class="block py-2">Dashboard</a></li>
|
||||
<li><a href="/owner/products/list.php" class="block py-2">Products</a></li>
|
||||
<?php endif; ?>
|
||||
<li><a href="#" onclick="openLogoutModal(); return false;" class="block py-2 text-red-500 font-semibold">Logout</a></li>
|
||||
<?php else: ?>
|
||||
<li><a href="/index.php" class="block py-2">Home</a></li>
|
||||
<li><a href="/auth/login.php" class="block py-2">Login</a></li>
|
||||
<li><a href="/auth/register.php" class="block py-2 font-semibold text-black">Join Now</a></li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Logout Modal -->
|
||||
<div class="fixed inset-0 z-[2000] hidden items-center justify-center bg-black/40 backdrop-blur-sm p-6" id="logoutModal">
|
||||
<div class="bg-white w-full max-w-sm rounded-3xl p-8 text-center shadow-2xl animate-in zoom-in-95 duration-200">
|
||||
<div class="w-16 h-16 bg-red-50 text-red-500 rounded-full flex items-center justify-center mx-auto mb-6 text-2xl">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
</div>
|
||||
<h2 class="serif text-2xl mb-2">Confirm Logout</h2>
|
||||
<p class="text-muted text-sm mb-8">Are you sure you want to leave your session?</p>
|
||||
<div class="flex gap-3">
|
||||
<button onclick="closeLogoutModal()" class="flex-1 py-3 rounded-xl bg-slate-100 text-slate-600 font-medium hover:bg-slate-200 transition-all">Cancel</button>
|
||||
<button onclick="confirmLogout()" class="flex-1 py-3 rounded-xl bg-black text-white font-medium hover:bg-red-600 transition-all">Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('mobileMenuToggle')?.addEventListener('click', () => {
|
||||
const menu = document.getElementById('mobileMenu');
|
||||
menu.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
function openLogoutModal() { document.getElementById('logoutModal').style.display = 'flex'; }
|
||||
function closeLogoutModal() { document.getElementById('logoutModal').style.display = 'none'; }
|
||||
function confirmLogout() { window.location.href = '/auth/logout.php'; }
|
||||
|
||||
<script>
|
||||
document.querySelector('.mobile-menu-toggle').addEventListener('click', function() {
|
||||
const menu = document.getElementById('mobileMenu');
|
||||
menu.style.display = menu.style.display === 'block' ? 'none' : 'block';
|
||||
});
|
||||
document.getElementById('logoutModal')?.addEventListener('click', (e) => {
|
||||
if (e.target === document.getElementById('logoutModal')) closeLogoutModal();
|
||||
});
|
||||
|
||||
// Add logout modal functions
|
||||
function openLogoutModal() {
|
||||
document.getElementById('logoutModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
function closeLogoutModal() {
|
||||
document.getElementById('logoutModal').style.display = 'none';
|
||||
}
|
||||
|
||||
function confirmLogout() {
|
||||
window.location.href = '/auth/logout.php';
|
||||
}
|
||||
|
||||
// Close modal when clicking outside
|
||||
document.getElementById('logoutModal').addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
closeLogoutModal();
|
||||
function openNotificationModal() {
|
||||
const modal = document.getElementById('notificationModal');
|
||||
modal.classList.remove('opacity-0', 'pointer-events-none', 'translate-y-2');
|
||||
modal.classList.add('opacity-100', 'pointer-events-auto', 'translate-y-0');
|
||||
loadNotifications();
|
||||
|
||||
const close = (e) => {
|
||||
if (!modal.contains(e.target) && !e.target.closest('.notification-btn')) {
|
||||
closeNotificationModal();
|
||||
document.removeEventListener('click', close);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
|
||||
<main class="container">
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Remove the scroll event listener that was causing the hover effect
|
||||
});
|
||||
</script>
|
||||
};
|
||||
setTimeout(() => document.addEventListener('click', close), 10);
|
||||
}
|
||||
|
||||
<script>
|
||||
// Notification Modal Functions
|
||||
function openNotificationModal() {
|
||||
const modal = document.getElementById('notificationModal');
|
||||
modal.style.display = 'block';
|
||||
loadNotifications();
|
||||
|
||||
// Close modal when clicking outside
|
||||
document.addEventListener('click', function closeModal(e) {
|
||||
if (!modal.contains(e.target) && !e.target.closest('.notification-btn')) {
|
||||
modal.style.display = 'none';
|
||||
document.removeEventListener('click', closeModal);
|
||||
}
|
||||
});
|
||||
}
|
||||
function closeNotificationModal() {
|
||||
const modal = document.getElementById('notificationModal');
|
||||
modal.classList.add('opacity-0', 'pointer-events-none', 'translate-y-2');
|
||||
modal.classList.remove('opacity-100', 'pointer-events-auto', 'translate-y-0');
|
||||
}
|
||||
|
||||
function closeNotificationModal() {
|
||||
document.getElementById('notificationModal').style.display = 'none';
|
||||
}
|
||||
function loadNotifications() {
|
||||
const list = document.getElementById('notificationList');
|
||||
const badge = document.getElementById('notificationBadge');
|
||||
if(!list) return;
|
||||
|
||||
function loadNotifications() {
|
||||
const notificationList = document.getElementById('notificationList');
|
||||
const badge = document.getElementById('notificationBadge');
|
||||
|
||||
fetch('/customer/notifications.php')
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
if (data.notifications.length === 0) {
|
||||
notificationList.innerHTML = `
|
||||
<div class="no-notifications">
|
||||
<i class="fas fa-bell-slash"></i>
|
||||
<p>No notifications yet</p>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
notificationList.innerHTML = data.notifications.map(notification => `
|
||||
<div class="notification-item ${notification.unread ? 'unread' : ''}">
|
||||
<div class="notification-icon ${notification.status}">
|
||||
<i class="fas ${notification.status === 'ready' ? 'fa-check-circle' :
|
||||
notification.status === 'completed' ? 'fa-check-double' :
|
||||
'fa-times-circle'}"></i>
|
||||
fetch('/customer/notifications.php')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.error) throw new Error(data.error);
|
||||
if (data.notifications.length === 0) {
|
||||
list.innerHTML = '<div class="py-10 text-center text-slate-400 text-xs italic">No notifications yet</div>';
|
||||
} else {
|
||||
list.innerHTML = data.notifications.map(n => `
|
||||
<div class="p-3 border-b border-slate-50 last:border-0 hover:bg-slate-50 transition-colors cursor-pointer ${n.unread ? 'bg-blue-50/30' : ''}">
|
||||
<div class="flex gap-3">
|
||||
<div class="w-8 h-8 rounded-full flex items-center justify-center text-xs ${n.status === 'ready' ? 'bg-emerald-100 text-emerald-700' : n.status === 'completed' ? 'bg-slate-200 text-slate-700' : 'bg-red-100 text-red-700'}">
|
||||
<i class="fas ${n.status === 'ready' ? 'fa-check-circle' : n.status === 'completed' ? 'fa-check-double' : 'fa-times-circle'}"></i>
|
||||
</div>
|
||||
<div class="notification-content">
|
||||
<div class="notification-title">${notification.title}</div>
|
||||
<div class="notification-time">${notification.time}</div>
|
||||
<span class="notification-status status-${notification.status}">
|
||||
${notification.status.charAt(0).toUpperCase() + notification.status.slice(1)}
|
||||
</span>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-xs font-medium text-slate-900 truncate">${n.title}</p>
|
||||
<div class="flex justify-between items-center mt-1">
|
||||
<span class="text-[10px] text-slate-400">${n.time}</span>
|
||||
<span class="text-[10px] px-1.5 py-0.5 rounded-md font-semibold uppercase tracking-wider ${n.status === 'ready' ? 'bg-emerald-50 text-emerald-600' : n.status === 'completed' ? 'bg-slate-100 text-slate-600' : 'bg-red-50 text-red-600'}">${n.status}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
// Update badge
|
||||
if (data.unread_count > 0) {
|
||||
badge.textContent = data.unread_count;
|
||||
badge.classList.add('show');
|
||||
} else {
|
||||
badge.classList.remove('show');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
notificationList.innerHTML = `
|
||||
<div class="no-notifications">
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
<p>Error loading notifications: ${error.message}</p>
|
||||
<p>Please try again later</p>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
}
|
||||
}
|
||||
if (data.unread_count > 0) {
|
||||
badge.textContent = data.unread_count;
|
||||
badge.className = 'absolute -top-1 -right-1 w-4 h-4 bg-red-500 text-white text-[10px] flex items-center justify-center rounded-full';
|
||||
} else {
|
||||
badge.className = 'hidden';
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
list.innerHTML = `<div class="p-6 text-center text-xs text-red-400">Error: ${err.message}</div>`;
|
||||
});
|
||||
}
|
||||
|
||||
// Load notifications every 30 seconds if user is logged in
|
||||
<?php if (isLoggedIn()): ?>
|
||||
setInterval(loadNotifications, 30000);
|
||||
<?php endif; ?>
|
||||
</script>
|
||||
<?php if (isLoggedIn()): ?>
|
||||
setInterval(loadNotifications, 30000);
|
||||
<?php endif; ?>
|
||||
</script>
|
||||
|
||||
<main class="container mx-auto px-6 pt-24">
|
||||
@@ -1,15 +1,18 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="<?php echo BASE_URL; ?>owner/products/list.php">
|
||||
<a class="nav-link" href="<?php if (!defined('BASE_URL')) { define('BASE_URL', '/'); } ?>
|
||||
<?php echo BASE_URL; ?>owner/products/list.php">
|
||||
<i class="fas fa-box me-2"></i>Products
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="<?php echo BASE_URL; ?>owner/orders/list.php">
|
||||
<a class="nav-link" href="<?php if (!defined('BASE_URL')) { define('BASE_URL', '/'); } ?>
|
||||
<?php echo BASE_URL; ?>owner/orders/list.php">
|
||||
<i class="fas fa-shopping-cart me-2"></i>Orders
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="<?php echo BASE_URL; ?>owner/reports.php">
|
||||
<a class="nav-link" href="<?php if (!defined('BASE_URL')) { define('BASE_URL', '/'); } ?>
|
||||
<?php echo BASE_URL; ?>owner/reports.php">
|
||||
<i class="fas fa-chart-bar me-2"></i>Reports
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -1,249 +1,335 @@
|
||||
<?php
|
||||
require_once 'includes/auth_functions.php';
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>UniMarket - University Marketplace</title>
|
||||
<link rel="stylesheet" href="/assets/css/style.css">
|
||||
<link rel="stylesheet" href="/assets/css/responsive.css">
|
||||
<link rel="icon" type="image/png" href="/assets/images/logo/tab-logo.png">
|
||||
<style>
|
||||
header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
background: rgba(46, 125, 50, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
}
|
||||
<title>UniMarket | Premium Campus Exchange</title>
|
||||
|
||||
.hero {
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('/assets/images/hero/hero-bg.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
color: var(--light-text);
|
||||
padding: 120px 0;
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
position: relative;
|
||||
}
|
||||
<!-- Tailwind CSS CDN (must come BEFORE any Tailwind config) -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
|
||||
.hero .container {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
backdrop-filter: none;
|
||||
-webkit-backdrop-filter: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3.5rem;
|
||||
margin-bottom: 20px;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.hero p {
|
||||
font-size: 1.3rem;
|
||||
max-width: 800px;
|
||||
margin: 0 auto 30px;
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.hero .btn {
|
||||
padding: 12px 30px;
|
||||
font-size: 1.1rem;
|
||||
margin: 0 10px;
|
||||
transition: all 0.3s ease;
|
||||
background-color: transparent;
|
||||
border: 2px solid var(--light-text);
|
||||
color: var(--light-text);
|
||||
}
|
||||
|
||||
.hero .btn:hover {
|
||||
background-color: var(--light-text);
|
||||
color: var(--primary-color);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
<!-- Google Fonts: Playfair Display (Serif) & Inter (Sans) -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Playfair+Display:wght@600;700&display=swap" rel="stylesheet">
|
||||
|
||||
.hero .btn-secondary {
|
||||
background-color: transparent;
|
||||
border: 2px solid var(--light-text);
|
||||
}
|
||||
<!-- Font Awesome for high-quality icons -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
.hero .btn-secondary:hover {
|
||||
background-color: var(--light-text);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.features {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 30px;
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.05);
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 3rem;
|
||||
color: var(--primary-color);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
margin-bottom: 15px;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
background-color: #f5f5f5;
|
||||
padding: 60px 0;
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.trending-products {
|
||||
margin: 60px 0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<?php include 'includes/header.php'; ?>
|
||||
|
||||
<div class="hero">
|
||||
<div class="container">
|
||||
<h1>Welcome to UniMarket</h1>
|
||||
<p>The University Marketplace for Affordable Student Essentials, Books, Supplies & Campus Merchandise.</p>
|
||||
<?php if (!isLoggedIn()): ?>
|
||||
<div>
|
||||
<a href="/auth/register.php" class="btn" style="margin-right: 10px;">Join Now</a>
|
||||
<a href="/auth/login.php" class="btn btn-secondary">Sign In</a>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div>
|
||||
<?php if (isCustomer()): ?>
|
||||
<a href="/public/customer/products/browse.php" class="btn">Browse Products</a>
|
||||
<?php else: ?>
|
||||
<a href="/public/owner/dashboard.php" class="btn">Go to Dashboard</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="features">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🛍️</div>
|
||||
<h3>Campus Marketplace</h3>
|
||||
<p>Buy and sell products exclusively within your university community.</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🔄</div>
|
||||
<h3>Easy Pickup</h3>
|
||||
<p>Schedule convenient on-campus pickup times for your orders.</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🛒</div>
|
||||
<h3>Secure Transactions</h3>
|
||||
<p>Safe and reliable transactions between students and campus vendors.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
// Display trending products (only for customers or guests)
|
||||
if (!isLoggedIn() || isCustomer()) {
|
||||
require_once 'config/database.php';
|
||||
|
||||
$stmt = $pdo->query("SELECT * FROM products ORDER BY created_at DESC LIMIT 6");
|
||||
$trending_products = $stmt->fetchAll();
|
||||
|
||||
if (!empty($trending_products)) {
|
||||
echo '<div class="trending-products">';
|
||||
echo '<h2 class="section-title">Trending Products</h2>';
|
||||
echo '<div class="product-grid">';
|
||||
|
||||
foreach ($trending_products as $product) {
|
||||
echo '<div class="product-card"">';
|
||||
echo '<div class="product-image">';
|
||||
if ($product['image_path']) {
|
||||
echo '<img src="/uploads/products/'.$product['image_path'].'" alt="'.htmlspecialchars($product['name']).'">';
|
||||
} else {
|
||||
echo '<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #999;">No Image</div>';
|
||||
<!-- Tailwind config (set BEFORE Tailwind finishes processing) -->
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['Inter', 'sans-serif'],
|
||||
serif: ['Playfair Display', 'serif'],
|
||||
},
|
||||
colors: {
|
||||
brand: {
|
||||
primary: 'var(--color-primary)',
|
||||
secondary: 'var(--color-secondary)',
|
||||
accent: 'var(--color-accent)',
|
||||
background: 'var(--color-background)',
|
||||
surface: 'var(--color-surface)',
|
||||
text: 'var(--color-text)',
|
||||
muted: 'var(--color-muted)',
|
||||
border: 'var(--color-border)',
|
||||
}
|
||||
}
|
||||
echo '</div>';
|
||||
echo '<div class="product-info">';
|
||||
echo '<h3 class="product-title">'.htmlspecialchars($product['name']).'</h3>';
|
||||
echo '<p class="product-price">₱'.number_format($product['price'], 2).'</p>';
|
||||
|
||||
if (isLoggedIn()) {
|
||||
echo '<a href="/customer/products/view.php?id='.$product['product_id'].'" class="btn" style="display: block; text-align: center;">';
|
||||
echo '<i class="fas fa-eye"></i> View Details';
|
||||
echo '</a>';
|
||||
} else {
|
||||
echo '<a href="/auth/login.php" class="btn" style="display: block; text-align: center;">Login to Purchase</a>';
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
echo '<div style="text-align: center; margin-top: 30px;">';
|
||||
echo '<a href="/customer/products/browse.php" class="btn">View All Products</a>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="cta-section">
|
||||
<div class="container">
|
||||
<h2>Ready to join the campus marketplace?</h2>
|
||||
<p style="max-width: 600px; margin: 0 auto 30px;">Whether you're looking to buy or sell, UniMarket connects you with your university community.</p>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
:root[data-theme="light"] {
|
||||
--color-primary: #006400;
|
||||
--color-secondary: #ffffff;
|
||||
--color-accent: #064e3b;
|
||||
--color-background: #ffffff;
|
||||
--color-surface: #f8fafc;
|
||||
--color-text: #0f172a;
|
||||
--color-muted: #64748b;
|
||||
--color-border: #e2e8f0;
|
||||
}
|
||||
:root[data-theme="dark"] {
|
||||
--color-primary: #006400;
|
||||
--color-secondary: #000000;
|
||||
--color-accent: #064e3b;
|
||||
--color-background: #000000;
|
||||
--color-surface: #0f172a;
|
||||
--color-text: #f8fafc;
|
||||
--color-muted: #94a3b8;
|
||||
--color-border: #334155;
|
||||
}
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
background-color: var(--color-background);
|
||||
color: var(--color-text);
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
}
|
||||
.serif { font-family: 'Playfair Display', serif; }
|
||||
|
||||
.glass {
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.18);
|
||||
}
|
||||
[data-theme="dark"] .glass {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.hero-overlay {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
}
|
||||
[data-theme="dark"] .hero-overlay {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const theme = localStorage.getItem('theme') || 'light';
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
})();
|
||||
function toggleTheme() {
|
||||
const current = document.documentElement.getAttribute('data-theme');
|
||||
const next = current === 'light' ? 'dark' : 'light';
|
||||
document.documentElement.setAttribute('data-theme', next);
|
||||
localStorage.setItem('theme', next);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body class="antialiased">
|
||||
<?php include 'includes/header.php'; ?>
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="relative min-h-screen flex items-center px-6 py-24 overflow-hidden">
|
||||
<!-- Background Image with Overlay -->
|
||||
<div class="absolute inset-0 -z-10">
|
||||
<img src="/assets/images/hero/hero-bg.jpg" class="w-full h-full object-cover" alt="Campus Background">
|
||||
<div class="absolute inset-0 hero-overlay"></div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-7xl mx-auto w-full grid grid-cols-1 lg:grid-cols-2 gap-12 items-center relative z-10">
|
||||
<!-- Content Column -->
|
||||
<div class="text-left space-y-8" id="hero-text">
|
||||
<div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-brand-primary/10 text-brand-primary text-xs font-semibold uppercase tracking-wider border border-brand-primary/20">
|
||||
<i class="fas fa-sparkles"></i> Exclusive Student Marketplace
|
||||
</div>
|
||||
<h1 class="serif text-5xl md:text-7xl lg:text-8xl tracking-tight leading-[1.1] text-brand-text">
|
||||
Elevating the <span class="text-brand-primary italic">Campus</span><br>Exchange Experience.
|
||||
</h1>
|
||||
<p class="text-lg md:text-xl text-brand-muted max-w-xl font-light leading-relaxed">
|
||||
A curated marketplace for student essentials. Minimalist, secure, and designed exclusively for the university community.
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row items-start sm:items-center gap-4 pt-4">
|
||||
<?php if (!isLoggedIn()): ?>
|
||||
<a href="/auth/register.php" class="px-8 py-4 bg-brand-text text-brand-background rounded-full hover:bg-brand-primary transition-all duration-300 w-full sm:w-auto font-medium shadow-lg shadow-black/20 flex items-center justify-center gap-2">
|
||||
Join the Community <i class="fas fa-arrow-right text-xs"></i>
|
||||
</a>
|
||||
<a href="/auth/login.php" class="px-8 py-4 border border-brand-muted/30 rounded-full hover:bg-brand-surface transition-all duration-300 w-full sm:w-auto font-medium text-center text-brand-text">Sign In</a>
|
||||
<?php else: ?>
|
||||
<?php if (isCustomer()): ?>
|
||||
<a href="/customer/products/browse.php" class="px-8 py-4 bg-brand-text text-brand-background rounded-full hover:bg-brand-primary transition-all duration-300 w-full sm:w-auto font-medium flex items-center justify-center gap-2">
|
||||
Browse Collection <i class="fas fa-shopping-bag text-xs"></i>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<a href="/owner/dashboard.php" class="px-8 py-4 bg-brand-text text-brand-background rounded-full hover:bg-brand-primary transition-all duration-300 w-full sm:w-auto font-medium flex items-center justify-center gap-2">
|
||||
Manage Shop <i class="fas fa-store text-xs"></i>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Visual/Stats Column -->
|
||||
<div class="hidden lg:grid grid-cols-2 gap-6" id="hero-visuals">
|
||||
<div class="p-8 bg-white/60 dark:bg-brand-surface/60 backdrop-blur-md rounded-3xl border border-white/40 dark:border-brand-border shadow-sm space-y-4">
|
||||
<div class="w-10 h-10 bg-emerald-100 dark:bg-emerald-900/30 text-brand-accent dark:text-brand-primary rounded-xl flex items-center justify-center text-lg shadow-inner">
|
||||
<i class="fas fa-shield-halved"></i>
|
||||
</div>
|
||||
<h3 class="serif text-xl text-brand-text">Secure Trade</h3>
|
||||
<p class="text-brand-muted text-sm font-light">Verified university accounts ensure safety for every exchange.</p>
|
||||
</div>
|
||||
<div class="p-8 bg-white/60 dark:bg-brand-surface/60 backdrop-blur-md rounded-3xl border border-white/40 dark:border-brand-border shadow-sm space-y-4">
|
||||
<div class="w-10 h-10 bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400 rounded-xl flex items-center justify-center text-lg shadow-inner">
|
||||
<i class="fas fa-location-dot"></i>
|
||||
</div>
|
||||
<h3 class="serif text-xl text-brand-text">Easy Pickup</h3>
|
||||
<p class="text-brand-muted text-sm font-light">Coordinate fast, free pickups at designated campus spots.</p>
|
||||
</div>
|
||||
<div class="p-8 bg-white/60 dark:bg-brand-surface/60 backdrop-blur-md rounded-3xl border border-white/40 dark:border-brand-border shadow-sm space-y-4">
|
||||
<div class="w-10 h-10 bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400 rounded-xl flex items-center justify-center text-lg shadow-inner">
|
||||
<i class="fas fa-book-open"></i>
|
||||
</div>
|
||||
<h3 class="serif text-xl text-brand-text">Student Focus</h3>
|
||||
<p class="text-brand-muted text-sm font-light">Books, supplies, and gear curated by students, for students.</p>
|
||||
</div>
|
||||
<div class="p-8 bg-white/60 dark:bg-brand-surface/60 backdrop-blur-md rounded-3xl border border-white/40 dark:border-brand-border shadow-sm space-y-4">
|
||||
<div class="w-10 h-10 bg-emerald-100 dark:bg-emerald-900/30 text-brand-accent dark:text-brand-primary rounded-xl flex items-center justify-center text-lg shadow-inner">
|
||||
<i class="fas fa-leaf"></i>
|
||||
</div>
|
||||
<h3 class="serif text-xl text-brand-text">Eco-Friendly</h3>
|
||||
<p class="text-brand-muted text-sm font-light">Reduce waste by recycling campus essentials efficiently.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Value Propositions -->
|
||||
<section class="py-24 px-6 bg-brand-surface transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto">
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-16">
|
||||
<div class="space-y-4 group">
|
||||
<div class="w-14 h-14 bg-brand-background rounded-2xl flex items-center justify-center shadow-sm text-xl mb-6 transition-all duration-300 group-hover:bg-brand-primary group-hover:text-brand-background group-hover:rotate-3 text-brand-primary">
|
||||
<i class="fas fa-store"></i>
|
||||
</div>
|
||||
<h3 class="serif text-2xl text-brand-text">Curated Marketplace</h3>
|
||||
<p class="text-brand-muted font-light leading-relaxed">Exclusive access to university-verified products and student essentials.</p>
|
||||
</div>
|
||||
<div class="space-y-4 group">
|
||||
<div class="w-14 h-14 bg-brand-background rounded-2xl flex items-center justify-center shadow-sm text-xl mb-6 transition-all duration-300 group-hover:bg-brand-primary group-hover:text-brand-background group-hover:rotate-3 text-brand-primary">
|
||||
<i class="fas fa-calendar-check"></i>
|
||||
</div>
|
||||
<h3 class="serif text-2xl text-brand-text">Intuitive Pickup</h3>
|
||||
<p class="text-brand-muted font-light leading-relaxed">Seamless on-campus coordination designed for the student schedule.</p>
|
||||
</div>
|
||||
<div class="space-y-4 group">
|
||||
<div class="w-14 h-14 bg-brand-background rounded-2xl flex items-center justify-center shadow-sm text-xl mb-6 transition-all duration-300 group-hover:bg-brand-primary group-hover:text-brand-background group-hover:rotate-3 text-brand-primary">
|
||||
<i class="fas fa-handshake"></i>
|
||||
</div>
|
||||
<h3 class="serif text-2xl text-brand-text">Trust-Based Trade</h3>
|
||||
<p class="text-brand-muted font-light leading-relaxed">Safe, community-driven transactions within a secure university environment.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Trending Section -->
|
||||
<?php
|
||||
$trending_products = [];
|
||||
try {
|
||||
if (!isLoggedIn() || isCustomer()) {
|
||||
require_once 'config/database.php';
|
||||
if (isset($pdo)) {
|
||||
$stmt = $pdo->query("SELECT * FROM products ORDER BY created_at DESC LIMIT 6");
|
||||
$trending_products = $stmt->fetchAll();
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("Trending products error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
if (!empty($trending_products)): ?>
|
||||
<section class="py-24 px-6">
|
||||
<div class="max-w-6xl mx-auto">
|
||||
<div class="flex items-end justify-between mb-12">
|
||||
<div class="text-left">
|
||||
<h2 class="serif text-4xl mb-2 text-brand-text">Latest Arrivals</h2>
|
||||
<p class="text-brand-muted font-light">Freshly listed essentials from your peers.</p>
|
||||
</div>
|
||||
<a href="/customer/products/browse.php" class="hidden md:block text-sm font-medium underline underline-offset-4 hover:text-brand-accent transition-colors">View all products →</a>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<?php foreach ($trending_products as $product): ?>
|
||||
<div class="group relative bg-brand-background border border-brand-border rounded-3xl p-4 hover:shadow-xl transition-all duration-500 glass">
|
||||
<div class="aspect-square rounded-2xl overflow-hidden bg-brand-surface mb-6">
|
||||
<?php if (!empty($product['image_path'])): ?>
|
||||
<img src="/uploads/products/<?= htmlspecialchars($product['image_path']) ?>" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-700" alt="<?= htmlspecialchars($product['name']) ?>">
|
||||
<?php else: ?>
|
||||
<div class="w-full h-full flex items-center justify-center text-brand-muted italic">No image available</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="px-2">
|
||||
<h3 class="text-lg font-medium mb-1 text-brand-text"><?= htmlspecialchars($product['name']) ?></h3>
|
||||
<p class="text-brand-accent font-semibold mb-4">₱<?= number_format($product['price'], 2) ?></p>
|
||||
<?php if (isLoggedIn()): ?>
|
||||
<a href="/customer/products/view.php?id=<?= $product['product_id'] ?>" class="block w-full py-3 text-center bg-brand-surface rounded-xl text-sm font-medium hover:bg-brand-text hover:text-brand-background transition-all duration-300">View Details</a>
|
||||
<?php else: ?>
|
||||
<a href="/auth/login.php" class="block w-full py-3 text-center bg-brand-surface rounded-xl text-sm font-medium hover:bg-brand-text hover:text-brand-background transition-all duration-300">Login to Purchase</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Final CTA -->
|
||||
<section class="py-24 px-6 bg-brand-text text-brand-background text-center transition-colors duration-300">
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<h2 class="serif text-4xl md:text-5xl mb-6">Join the inner circle of campus trade.</h2>
|
||||
<p class="text-brand-muted font-light mb-10 text-lg">Simpler, cleaner, and faster. The way university shopping should be.</p>
|
||||
<?php if (!isLoggedIn()): ?>
|
||||
<a href="/auth/register.php" class="btn">Get Started</a>
|
||||
<a href="/auth/register.php" class="px-10 py-4 bg-brand-background text-brand-text rounded-full font-medium hover:bg-brand-primary hover:text-brand-background transition-all duration-300">Get Started</a>
|
||||
<?php else: ?>
|
||||
<?php if (isCustomer()): ?>
|
||||
<a href="/customer/products/browse.php" class="btn">Browse Products</a>
|
||||
<a href="/customer/products/browse.php" class="px-10 py-4 bg-brand-background text-brand-text rounded-full font-medium hover:bg-brand-primary hover:text-brand-background transition-all duration-300">Browse Products</a>
|
||||
<?php else: ?>
|
||||
<a href="/owner/products/add.php" class="btn">Add New Product</a>
|
||||
<a href="/owner/products/add.php" class="px-10 py-4 bg-brand-background text-brand-text rounded-full font-medium hover:bg-brand-primary hover:text-brand-background transition-all duration-300">List a Product</a>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<?php include 'includes/footer.php'; ?>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const heroText = document.getElementById('hero-text');
|
||||
const heroVisuals = document.getElementById('hero-visuals');
|
||||
|
||||
if (heroText) {
|
||||
heroText.style.opacity = '0';
|
||||
heroText.style.transform = 'translateX(-50px)';
|
||||
heroText.style.transition = 'all 1s ease-out';
|
||||
setTimeout(() => {
|
||||
heroText.style.opacity = '1';
|
||||
heroText.style.transform = 'translateX(0)';
|
||||
}, 100);
|
||||
}
|
||||
|
||||
if (heroVisuals) {
|
||||
heroVisuals.style.opacity = '0';
|
||||
heroVisuals.style.transform = 'translateX(50px)';
|
||||
heroVisuals.style.transition = 'all 1s ease-out 0.3s';
|
||||
setTimeout(() => {
|
||||
heroVisuals.style.opacity = '1';
|
||||
heroVisuals.style.transform = 'translateX(0)';
|
||||
}, 100);
|
||||
}
|
||||
|
||||
const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' };
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.style.opacity = '1';
|
||||
entry.target.style.transform = 'translateY(0)';
|
||||
}
|
||||
});
|
||||
}, observerOptions);
|
||||
|
||||
document.querySelectorAll('section').forEach(el => {
|
||||
if (el.id === 'hero-text' || el.id === 'hero-visuals') return;
|
||||
el.style.opacity = '0';
|
||||
el.style.transform = 'translateY(40px)';
|
||||
el.style.transition = 'opacity 1s ease-out, transform 1s ease-out';
|
||||
observer.observe(el);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user