Add files via upload

This commit is contained in:
ssbg04 authored and GitHub committed 2025-05-30 23:16:13 +08:00
commit 940dc4c250
29 files changed
+5979

No files matched your search

+4
View File
@@ -0,0 +1,4 @@
This repository is for IPT222 project.
Members:
Babiano, De Vera, De Chavez, Garcia, Hernandez, and Jordan
+48
View File
@@ -0,0 +1,48 @@
@media (max-width: 768px) {
.header-content {
flex-direction: column;
text-align: center;
}
nav ul {
margin-top: 15px;
justify-content: center;
}
nav ul li {
margin: 0 10px;
}
.dashboard-container {
grid-template-columns: 1fr;
}
.sidebar {
margin-bottom: 20px;
}
.product-grid {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
}
@media (max-width: 480px) {
.container {
width: 95%;
padding: 10px;
}
.product-grid {
grid-template-columns: 1fr;
}
.btn {
padding: 8px 15px;
font-size: 14px;
}
.table {
display: block;
overflow-x: auto;
}
}
+261
View File
@@ -0,0 +1,261 @@
:root {
--primary-color: #2e7d32;
--primary-light: #60ad5e;
--primary-dark: #005005;
--secondary-color: #f5f5f5;
--text-color: #333;
--light-text: #fff;
--error-color: #d32f2f;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: #f9f9f9;
color: var(--text-color);
line-height: 1.6;
}
.container {
width: 90%;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
background-color: var(--primary-color);
color: var(--light-text);
padding: 15px 0;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 24px;
font-weight: bold;
}
nav ul {
display: flex;
list-style: none;
}
nav ul li {
margin-left: 20px;
}
nav ul li a {
color: var(--light-text);
text-decoration: none;
font-weight: 500;
transition: opacity 0.3s;
}
nav ul li a:hover {
opacity: 0.8;
}
.btn {
display: inline-block;
padding: 10px 20px;
background-color: var(--primary-color);
color: var(--light-text);
border: none;
border-radius: 4px;
cursor: pointer;
text-decoration: none;
font-size: 16px;
transition: background-color 0.3s;
}
.btn:hover {
background-color: var(--primary-dark);
}
.btn-secondary {
background-color: #757575;
}
.btn-secondary:hover {
background-color: #616161;
}
.card {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
margin-bottom: 20px;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: 500;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
.form-group textarea {
min-height: 100px;
}
.alert {
padding: 15px;
margin-bottom: 20px;
border-radius: 4px;
}
.alert-success {
background-color: #dff0d8;
color: #3c763d;
}
.alert-error {
background-color: #f2dede;
color: #a94442;
}
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
margin-top: 20px;
}
.product-card {
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
transition: transform 0.3s, box-shadow 0.3s;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.product-image {
height: 200px;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.product-image img {
max-width: 100%;
max-height: 100%;
object-fit: cover;
}
.product-info {
padding: 15px;
}
.product-title {
font-size: 18px;
margin-bottom: 10px;
}
.product-price {
font-weight: bold;
color: var(--primary-color);
font-size: 20px;
margin-bottom: 10px;
}
/* Dashboard styles */
.dashboard-container {
display: grid;
grid-template-columns: 250px 1fr;
gap: 20px;
}
.sidebar {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
}
.sidebar ul {
list-style: none;
}
.sidebar ul li {
margin-bottom: 10px;
}
.sidebar ul li a {
color: var(--text-color);
text-decoration: none;
display: block;
padding: 8px 0;
transition: color 0.3s;
}
.sidebar ul li a:hover {
color: var(--primary-color);
}
.sidebar ul li a.active {
color: var(--primary-color);
font-weight: bold;
}
.main-content {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
}
/* Table styles */
.table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.table th,
.table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #ddd;
}
.table th {
background-color: #f5f5f5;
font-weight: 600;
}
.table tr:hover {
background-color: #f9f9f9;
}
/* Responsive styles are in responsive.css */
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

+425
View File
@@ -0,0 +1,425 @@
/**
* UniMarket - Main JavaScript File
* Handles frontend interactions, form validations, and UI enhancements
*/
document.addEventListener('DOMContentLoaded', function() {
// Mobile menu toggle functionality
const mobileMenuToggle = document.querySelector('.mobile-menu-toggle');
if (mobileMenuToggle) {
mobileMenuToggle.addEventListener('click', function() {
const menu = document.getElementById('mobileMenu');
if (menu) {
menu.style.display = menu.style.display === 'block' ? 'none' : 'block';
}
});
}
// Initialize all tooltips
initTooltips();
// Initialize all form validations
initFormValidations();
// Initialize product quantity controls
initQuantityControls();
// Initialize image preview for file uploads
initImagePreviews();
// Initialize date/time pickers
initDateTimePickers();
// Initialize cart interactions
if (document.querySelector('.cart-page')) {
initCartInteractions();
}
});
/**
* Initialize tooltips throughout the application
*/
function initTooltips() {
const tooltips = document.querySelectorAll('[data-tooltip]');
tooltips.forEach(tooltip => {
const tooltipText = tooltip.getAttribute('data-tooltip');
const tooltipElement = document.createElement('span');
tooltipElement.className = 'tooltip-text';
tooltipElement.textContent = tooltipText;
tooltip.appendChild(tooltipElement);
// Position tooltip on hover
tooltip.addEventListener('mouseenter', function() {
const rect = this.getBoundingClientRect();
tooltipElement.style.left = `${rect.width / 2}px`;
tooltipElement.style.top = `${rect.height + 5}px`;
tooltipElement.style.opacity = '1';
});
tooltip.addEventListener('mouseleave', function() {
tooltipElement.style.opacity = '0';
});
});
}
/**
* Initialize form validation handlers
*/
function initFormValidations() {
const forms = document.querySelectorAll('form[data-validate]');
forms.forEach(form => {
form.addEventListener('submit', function(e) {
let isValid = true;
const requiredFields = this.querySelectorAll('[required]');
requiredFields.forEach(field => {
if (!field.value.trim()) {
isValid = false;
field.classList.add('error');
// Create or show error message
let errorMsg = field.nextElementSibling;
if (!errorMsg || !errorMsg.classList.contains('error-message')) {
errorMsg = document.createElement('small');
errorMsg.className = 'error-message';
errorMsg.textContent = 'This field is required';
field.parentNode.insertBefore(errorMsg, field.nextSibling);
}
} else {
field.classList.remove('error');
const errorMsg = field.nextElementSibling;
if (errorMsg && errorMsg.classList.contains('error-message')) {
errorMsg.remove();
}
}
});
if (!isValid) {
e.preventDefault();
// Scroll to first error
const firstError = this.querySelector('.error');
if (firstError) {
firstError.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}
});
});
}
/**
* Initialize quantity controls for product pages
*/
function initQuantityControls() {
document.querySelectorAll('.quantity-control').forEach(control => {
const input = control.querySelector('.quantity-input');
const increment = control.querySelector('.quantity-increment');
const decrement = control.querySelector('.quantity-decrement');
increment.addEventListener('click', () => {
input.value = parseInt(input.value) + 1;
input.dispatchEvent(new Event('change'));
});
decrement.addEventListener('click', () => {
if (parseInt(input.value) > 1) {
input.value = parseInt(input.value) - 1;
input.dispatchEvent(new Event('change'));
}
});
// Validate input
input.addEventListener('change', () => {
if (parseInt(input.value) < 1) {
input.value = 1;
}
});
});
}
/**
* Initialize image previews for file uploads
*/
function initImagePreviews() {
document.querySelectorAll('.image-upload').forEach(upload => {
const input = upload.querySelector('input[type="file"]');
const preview = upload.querySelector('.image-preview');
const defaultText = upload.querySelector('.default-text');
if (input && preview) {
input.addEventListener('change', function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
preview.style.backgroundImage = `url(${e.target.result})`;
preview.classList.add('has-image');
if (defaultText) defaultText.style.display = 'none';
}
reader.readAsDataURL(file);
}
});
}
});
}
/**
* Initialize date/time pickers for pickup scheduling
*/
function initDateTimePickers() {
const datePickers = document.querySelectorAll('.date-picker');
if (datePickers.length > 0) {
// Load flatpickr if not already loaded
if (typeof flatpickr === 'undefined') {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/flatpickr';
script.onload = function() {
setupDateTimePickers();
};
document.head.appendChild(script);
const style = document.createElement('link');
style.rel = 'stylesheet';
style.href = 'https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css';
document.head.appendChild(style);
} else {
setupDateTimePickers();
}
}
function setupDateTimePickers() {
document.querySelectorAll('.date-picker').forEach(picker => {
flatpickr(picker, {
enableTime: picker.classList.contains('time-picker'),
dateFormat: picker.classList.contains('time-picker') ? "Y-m-d H:i" : "Y-m-d",
minDate: "today",
time_24hr: true
});
});
}
}
/**
* Initialize cart interactions
*/
function initCartInteractions() {
// Update cart item quantities
document.querySelectorAll('.cart-item-quantity').forEach(input => {
input.addEventListener('change', function() {
const form = this.closest('form');
if (form) {
form.submit();
}
});
});
// Handle remove item buttons
document.querySelectorAll('.remove-item-btn').forEach(button => {
button.addEventListener('click', function(e) {
if (!confirm('Are you sure you want to remove this item from your cart?')) {
e.preventDefault();
}
});
});
// Handle checkout button
const checkoutBtn = document.querySelector('.checkout-btn');
if (checkoutBtn) {
checkoutBtn.addEventListener('click', function(e) {
if (document.querySelector('.cart-item').length === 0) {
e.preventDefault();
alert('Your cart is empty. Please add items before checking out.');
}
});
}
}
/**
* AJAX helper function
*/
function makeRequest(url, method = 'GET', data = null) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
try {
resolve(JSON.parse(xhr.responseText));
} catch (e) {
resolve(xhr.responseText);
}
} else {
reject(xhr.statusText);
}
};
xhr.onerror = function() {
reject(xhr.statusText);
};
xhr.send(data ? JSON.stringify(data) : null);
});
}
/**
* Display flash messages
*/
function displayFlashMessages() {
const flashMessages = document.querySelector('.flash-messages');
if (flashMessages) {
setTimeout(() => {
flashMessages.style.opacity = '0';
setTimeout(() => {
flashMessages.remove();
}, 500);
}, 5000);
}
}
// Display flash messages when page loads
displayFlashMessages();
/**
* Debounce function for performance optimization
*/
function debounce(func, wait, immediate) {
let timeout;
return function() {
const context = this, args = arguments;
const later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
/**
* Throttle function for performance optimization
*/
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function() {
const context = this;
const args = arguments;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
}
}
// Add to cart functionality
document.querySelectorAll('.add-to-cart').forEach(button => {
button.addEventListener('click', function(e) {
e.preventDefault();
const productId = this.dataset.productId;
const quantity = this.closest('form')?.querySelector('input[name="quantity"]')?.value || 1;
makeRequest('/unimarket/ajax/add_to_cart.php', 'POST', {
product_id: productId,
quantity: quantity
})
.then(response => {
if (response.success) {
// Update cart count in header
const cartCount = document.querySelector('.cart-count');
if (cartCount) {
cartCount.textContent = response.cart_count;
cartCount.classList.add('pulse');
setTimeout(() => {
cartCount.classList.remove('pulse');
}, 500);
}
// Show success message
showToast('Item added to cart!');
} else {
showToast(response.message || 'Failed to add item to cart', 'error');
}
})
.catch(error => {
showToast('An error occurred. Please try again.', 'error');
});
});
});
/**
* Show toast notification
*/
function showToast(message, type = 'success') {
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
toast.textContent = message;
document.body.appendChild(toast);
setTimeout(() => {
toast.classList.add('show');
}, 10);
setTimeout(() => {
toast.classList.remove('show');
setTimeout(() => {
toast.remove();
}, 300);
}, 3000);
}
// Add CSS for toast notifications
const toastStyles = document.createElement('style');
toastStyles.textContent = `
.toast {
position: fixed;
bottom: 20px;
right: 20px;
padding: 15px 25px;
border-radius: 4px;
color: white;
background-color: #2e7d32;
box-shadow: 0 3px 10px rgba(0,0,0,0.2);
transform: translateY(100px);
opacity: 0;
transition: all 0.3s ease;
z-index: 1000;
}
.toast.show {
transform: translateY(0);
opacity: 1;
}
.toast-error {
background-color: #d32f2f;
}
.toast-success {
background-color: #2e7d32;
}
.pulse {
animation: pulse 0.5s;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
`;
document.head.appendChild(toastStyles);
+83
View File
@@ -0,0 +1,83 @@
<?php
require_once '../includes/auth_functions.php';
if (isLoggedIn()) {
header("Location: /unimarket/index.php");
exit();
}
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
require_once '../config/database.php';
$username = trim($_POST['username']);
$password = trim($_POST['password']);
if (empty($username) || empty($password)) {
$error = 'Please fill in all fields.';
} else {
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user_id'] = $user['user_id'];
$_SESSION['username'] = $user['username'];
$_SESSION['role'] = $user['role'];
if ($user['role'] === 'owner') {
header("Location: /unimarket/owner/dashboard.php");
} else {
header("Location: /unimarket/index.php");
}
exit();
} else {
$error = 'Invalid username or password.';
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
</head>
<body>
<?php include '../includes/header.php'; ?>
<div class="container">
<div class="card" style="max-width: 500px; margin: 50px auto;">
<h1 style="text-align: center; margin-bottom: 20px;">Login to UniMarket</h1>
<?php if ($error): ?>
<div class="alert alert-error"><?php echo $error; ?></div>
<?php endif; ?>
<form action="" method="POST">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit" class="btn">Login</button>
</form>
<p style="text-align: center; margin-top: 20px;">
Don't have an account? <a href="/unimarket/auth/register.php">Register here</a>
</p>
</div>
</div>
<?php include '../includes/footer.php'; ?>
</body>
</html>
+12
View File
@@ -0,0 +1,12 @@
<?php
require_once __DIR__ . '/../includes/auth_functions.php';
// Destroy the current session
destroySession();
// Set a success flash message
flashMessage('logout_success', 'You have been successfully logged out.');
// Redirect to the homepage with a success message
header("Location: /unimarket/index.php");
exit();
+325
View File
@@ -0,0 +1,325 @@
<?php
require_once '../includes/auth_functions.php';
if (isLoggedIn()) {
header("Location: /unimarket/index.php");
exit();
}
require_once '../config/database.php';
$errors = [];
$success = false;
// Form fields
$fields = [
'username' => '',
'email' => '',
'first_name' => '',
'last_name' => '',
'university_id' => '',
'phone' => '',
'role' => 'customer' // Default role
];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize and validate input
$fields['username'] = trim($_POST['username']);
$fields['email'] = trim($_POST['email']);
$fields['first_name'] = trim($_POST['first_name']);
$fields['last_name'] = trim($_POST['last_name']);
$fields['university_id'] = trim($_POST['university_id']);
$fields['phone'] = trim($_POST['phone']);
$fields['role'] = $_POST['role'] === 'owner' ? 'owner' : 'customer';
$password = trim($_POST['password']);
$confirm_password = trim($_POST['confirm_password']);
// Validate inputs
if (empty($fields['username'])) {
$errors['username'] = 'Username is required.';
} elseif (!preg_match('/^[a-zA-Z0-9_]{4,20}$/', $fields['username'])) {
$errors['username'] = 'Username must be 4-20 characters (letters, numbers, underscores).';
}
if (empty($fields['email'])) {
$errors['email'] = 'Email is required.';
} elseif (!filter_var($fields['email'], FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'Please enter a valid email address.';
}
if (empty($fields['first_name'])) {
$errors['first_name'] = 'First name is required.';
}
if (empty($fields['last_name'])) {
$errors['last_name'] = 'Last name is required.';
}
if (empty($fields['university_id'])) {
$errors['university_id'] = 'University ID is required.';
}
if (empty($password)) {
$errors['password'] = 'Password is required.';
} elseif (strlen($password) < 8) {
$errors['password'] = 'Password must be at least 8 characters.';
} elseif ($password !== $confirm_password) {
$errors['confirm_password'] = 'Passwords do not match.';
}
// Check if username or email already exists
if (empty($errors)) {
$stmt = $pdo->prepare("SELECT user_id FROM users WHERE username = ? OR email = ?");
$stmt->execute([$fields['username'], $fields['email']]);
if ($stmt->fetch()) {
$errors['general'] = 'Username or email already exists.';
}
}
// If no errors, create user
if (empty($errors)) {
try {
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("INSERT INTO users
(username, password, email, first_name, last_name, university_id, phone, role)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([
$fields['username'],
$hashed_password,
$fields['email'],
$fields['first_name'],
$fields['last_name'],
$fields['university_id'],
$fields['phone'],
$fields['role']
]);
// Create a cart for customers
if ($fields['role'] === 'customer') {
$user_id = $pdo->lastInsertId();
$stmt = $pdo->prepare("INSERT INTO cart (user_id) VALUES (?)");
$stmt->execute([$user_id]);
}
$success = true;
} catch (PDOException $e) {
$errors['general'] = 'Registration failed. Please try again.';
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<style>
.role-selector {
display: flex;
margin-bottom: 20px;
border: 1px solid #ddd;
border-radius: 4px;
overflow: hidden;
}
.role-option {
flex: 1;
text-align: center;
padding: 10px;
cursor: pointer;
transition: background-color 0.3s;
}
.role-option input {
display: none;
}
.role-option label {
display: block;
cursor: pointer;
}
.role-option:hover {
background-color: #f5f5f5;
}
.role-option.active {
background-color: var(--primary-color);
color: white;
}
.password-strength {
height: 5px;
background-color: #eee;
margin-top: 5px;
border-radius: 3px;
overflow: hidden;
}
.password-strength-bar {
height: 100%;
width: 0%;
background-color: #ff0000;
transition: width 0.3s, background-color 0.3s;
}
</style>
</head>
<body>
<?php include '../includes/header.php'; ?>
<div class="container">
<div class="card" style="max-width: 600px; margin: 50px auto;">
<h1 style="text-align: center; margin-bottom: 20px;">Create Your Account</h1>
<?php if ($success): ?>
<div class="alert alert-success">
Registration successful! You can now <a href="/unimarket/auth/login.php">login</a>.
</div>
<?php else: ?>
<?php if (isset($errors['general'])): ?>
<div class="alert alert-error"><?php echo $errors['general']; ?></div>
<?php endif; ?>
<form action="" method="POST" id="registrationForm">
<div class="role-selector">
<div class="role-option <?php echo $fields['role'] === 'customer' ? 'active' : ''; ?>">
<input type="radio" id="role_customer" name="role" value="customer" <?php echo $fields['role'] === 'customer' ? 'checked' : ''; ?>>
<label for="role_customer">I'm a Student</label>
</div>
<div class="role-option <?php echo $fields['role'] === 'owner' ? 'active' : ''; ?>">
<input type="radio" id="role_owner" name="role" value="owner" <?php echo $fields['role'] === 'owner' ? 'checked' : ''; ?>>
<label for="role_owner">I'm a Vendor</label>
</div>
</div>
<div class="form-group">
<label for="username">Username*</label>
<input type="text" id="username" name="username" value="<?php echo htmlspecialchars($fields['username']); ?>" required>
<?php if (isset($errors['username'])): ?>
<small style="color: var(--error-color);"><?php echo $errors['username']; ?></small>
<?php endif; ?>
</div>
<div class="form-group">
<label for="email">Email*</label>
<input type="email" id="email" name="email" value="<?php echo htmlspecialchars($fields['email']); ?>" required>
<?php if (isset($errors['email'])): ?>
<small style="color: var(--error-color);"><?php echo $errors['email']; ?></small>
<?php endif; ?>
</div>
<div class="form-group">
<label for="first_name">First Name*</label>
<input type="text" id="first_name" name="first_name" value="<?php echo htmlspecialchars($fields['first_name']); ?>" required>
<?php if (isset($errors['first_name'])): ?>
<small style="color: var(--error-color);"><?php echo $errors['first_name']; ?></small>
<?php endif; ?>
</div>
<div class="form-group">
<label for="last_name">Last Name*</label>
<input type="text" id="last_name" name="last_name" value="<?php echo htmlspecialchars($fields['last_name']); ?>" required>
<?php if (isset($errors['last_name'])): ?>
<small style="color: var(--error-color);"><?php echo $errors['last_name']; ?></small>
<?php endif; ?>
</div>
<div class="form-group">
<label for="university_id">University ID*</label>
<input type="text" id="university_id" name="university_id" value="<?php echo htmlspecialchars($fields['university_id']); ?>" required>
<?php if (isset($errors['university_id'])): ?>
<small style="color: var(--error-color);"><?php echo $errors['university_id']; ?></small>
<?php endif; ?>
</div>
<div class="form-group">
<label for="phone">Phone Number</label>
<input type="tel" id="phone" name="phone" value="<?php echo htmlspecialchars($fields['phone']); ?>">
</div>
<div class="form-group">
<label for="password">Password*</label>
<input type="password" id="password" name="password" required>
<div class="password-strength">
<div class="password-strength-bar" id="passwordStrengthBar"></div>
</div>
<?php if (isset($errors['password'])): ?>
<small style="color: var(--error-color);"><?php echo $errors['password']; ?></small>
<?php endif; ?>
</div>
<div class="form-group">
<label for="confirm_password">Confirm Password*</label>
<input type="password" id="confirm_password" name="confirm_password" required>
<?php if (isset($errors['confirm_password'])): ?>
<small style="color: var(--error-color);"><?php echo $errors['confirm_password']; ?></small>
<?php endif; ?>
</div>
<button type="submit" class="btn" style="width: 100%;">Register</button>
<p style="text-align: center; margin-top: 20px;">
Already have an account? <a href="/unimarket/auth/login.php">Login here</a>
</p>
</form>
<?php endif; ?>
</div>
</div>
<?php include '../includes/footer.php'; ?>
<script>
// Role selector styling
document.querySelectorAll('.role-option').forEach(option => {
option.addEventListener('click', function() {
document.querySelectorAll('.role-option').forEach(opt => {
opt.classList.remove('active');
});
this.classList.add('active');
this.querySelector('input').checked = true;
});
});
// Password strength indicator
const passwordInput = document.getElementById('password');
const strengthBar = document.getElementById('passwordStrengthBar');
passwordInput.addEventListener('input', function() {
const password = this.value;
let strength = 0;
if (password.length >= 8) strength += 1;
if (password.match(/[a-z]/)) strength += 1;
if (password.match(/[A-Z]/)) strength += 1;
if (password.match(/[0-9]/)) strength += 1;
if (password.match(/[^a-zA-Z0-9]/)) strength += 1;
const width = strength * 20;
let color;
if (strength <= 1) color = '#ff0000';
else if (strength <= 3) color = '#ff9900';
else color = '#00aa00';
strengthBar.style.width = width + '%';
strengthBar.style.backgroundColor = color;
});
// Form validation
document.getElementById('registrationForm').addEventListener('submit', function(e) {
const password = document.getElementById('password').value;
const confirmPassword = document.getElementById('confirm_password').value;
if (password !== confirmPassword) {
e.preventDefault();
alert('Passwords do not match!');
}
});
</script>
</body>
</html>
+13
View File
@@ -0,0 +1,13 @@
<?php
$host = 'localhost';
$dbname = 'unimarket';
$username = 'root';
$password = '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Database connection failed: " . $e->getMessage());
}
?>
+401
View File
@@ -0,0 +1,401 @@
<?php
require_once '../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotCustomer();
require_once '../config/database.php';
// Get cart items with product details
$stmt = $pdo->prepare("
SELECT ci.cart_item_id, p.product_id, p.name, p.price, ci.quantity, p.image_path, p.stock_quantity
FROM cart_items ci
JOIN products p ON ci.product_id = p.product_id
JOIN cart c ON ci.cart_id = c.cart_id
WHERE c.user_id = ?
");
$stmt->execute([$_SESSION['user_id']]);
$cart_items = $stmt->fetchAll();
// Calculate total
$total = 0;
foreach ($cart_items as $item) {
$total += $item['price'] * $item['quantity'];
}
// Handle quantity updates
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_quantity'])) {
$cart_item_id = (int)$_POST['cart_item_id'];
$quantity = (int)$_POST['quantity'];
// Validate quantity
$product = null;
foreach ($cart_items as $item) {
if ($item['cart_item_id'] == $cart_item_id) {
$product = $item;
break;
}
}
if ($product && $quantity > 0 && $quantity <= $product['stock_quantity']) {
$stmt = $pdo->prepare("UPDATE cart_items SET quantity = ? WHERE cart_item_id = ?");
$stmt->execute([$quantity, $cart_item_id]);
header("Location: /unimarket/customer/cart.php");
exit();
} else {
$error = $quantity <= 0 ? "Quantity must be at least 1" : "Only {$product['stock_quantity']} available in stock";
}
}
// Handle item removal
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['remove_item'])) {
$cart_item_id = (int)$_POST['cart_item_id'];
$stmt = $pdo->prepare("DELETE FROM cart_items WHERE cart_item_id = ?");
$stmt->execute([$cart_item_id]);
header("Location: /unimarket/customer/cart.php");
exit();
}
// Handle checkout
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['checkout'])) {
if (empty($cart_items)) {
$error = 'Your cart is empty.';
} else {
try {
$pdo->beginTransaction();
// Create order
$stmt = $pdo->prepare("INSERT INTO orders (customer_id, total_amount) VALUES (?, ?)");
$stmt->execute([$_SESSION['user_id'], $total]);
$order_id = $pdo->lastInsertId();
// Add order items and update stock
foreach ($cart_items as $item) {
$stmt = $pdo->prepare("INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?)");
$stmt->execute([$order_id, $item['product_id'], $item['quantity'], $item['price']]);
$stmt = $pdo->prepare("UPDATE products SET stock_quantity = stock_quantity - ? WHERE product_id = ?");
$stmt->execute([$item['quantity'], $item['product_id']]);
}
// Clear cart
$stmt = $pdo->prepare("DELETE ci FROM cart_items ci JOIN cart c ON ci.cart_id = c.cart_id WHERE c.user_id = ?");
$stmt->execute([$_SESSION['user_id']]);
$pdo->commit();
header("Location: /unimarket/customer/orders/view.php?order_id=$order_id");
exit();
} catch (Exception $e) {
$pdo->rollBack();
$error = 'An error occurred during checkout. Please try again.';
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your Cart - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.cart-container {
margin-top: 30px;
}
.cart-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
.cart-table th {
text-align: left;
padding: 12px;
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
}
.cart-table td {
padding: 12px;
border-bottom: 1px solid #eee;
vertical-align: middle;
}
.product-cell {
display: flex;
align-items: center;
}
.product-image {
width: 80px;
height: 80px;
margin-right: 15px;
background-color: #f9f9f9;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.product-image img {
max-width: 100%;
max-height: 100%;
}
.quantity-control {
display: flex;
align-items: center;
}
.quantity-control input {
width: 60px;
text-align: center;
margin: 0 5px;
padding: 5px;
}
.update-btn, .remove-btn {
padding: 5px 10px;
margin-left: 5px;
cursor: pointer;
}
.cart-summary {
background-color: #f9f9f9;
padding: 20px;
border-radius: 5px;
margin-top: 20px;
}
.summary-row {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.total-row {
font-weight: bold;
font-size: 1.1em;
border-top: 1px solid #ddd;
padding-top: 10px;
margin-top: 10px;
}
.checkout-btn {
width: 100%;
padding: 12px;
margin-top: 20px;
}
.empty-cart {
text-align: center;
padding: 50px;
background-color: #f9f9f9;
border-radius: 5px;
}
.stock-warning {
color: #e53935;
font-size: 0.9em;
margin-top: 5px;
}
@media (max-width: 768px) {
.cart-table thead {
display: none;
}
.cart-table tr {
display: block;
margin-bottom: 20px;
border: 1px solid #ddd;
border-radius: 5px;
}
.cart-table td {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: none;
}
.cart-table td::before {
content: attr(data-label);
font-weight: bold;
margin-right: 20px;
}
.product-cell {
flex-direction: column;
align-items: flex-start;
}
.product-image {
margin-bottom: 10px;
}
}
tbody td tr button{
background-color: green;
}
</style>
</head>
<body>
<?php include '../includes/header.php'; ?>
<div class="container cart-container">
<h1>Your Shopping Cart</h1>
<?php if (isset($error)): ?>
<div class="alert alert-error"><?php echo $error; ?></div>
<?php endif; ?>
<?php if (empty($cart_items)): ?>
<div class="empty-cart card">
<i class="fas fa-shopping-cart" style="font-size: 3em; color: #ccc; margin-bottom: 20px;"></i>
<h3>Your cart is empty</h3>
<p>Browse our products to add items to your cart</p>
<a href="/unimarket/customer/products/browse.php" class="btn">Continue Shopping</a>
</div>
<?php else: ?>
<table class="cart-table">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Subtotal</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($cart_items as $item): ?>
<tr>
<td data-label="Product">
<div class="product-cell">
<div class="product-image">
<?php if ($item['image_path']): ?>
<img src="/unimarket/assets/images/products/<?php echo $item['image_path']; ?>" alt="<?php echo htmlspecialchars($item['name']); ?>">
<?php else: ?>
<i class="fas fa-box-open" style="color: #ccc;"></i>
<?php endif; ?>
</div>
<div>
<h4><?php echo htmlspecialchars($item['name']); ?></h4>
<?php if ($item['quantity'] > $item['stock_quantity']): ?>
<p class="stock-warning">Only <?php echo $item['stock_quantity']; ?> available in stock</p>
<?php endif; ?>
</div>
</div>
</td>
<td data-label="Price">₱<?php echo number_format($item['price'], 2); ?></td>
<td data-label="Quantity">
<form method="POST" class="quantity-form">
<input type="hidden" name="cart_item_id" value="<?php echo $item['cart_item_id']; ?>">
<div class="quantity-control">
<button style="padding: 2px 5px;" type="button" class="quantity-decrement btn"><i class="fas fa-minus"></i></button>
<input type="number" name="quantity" value="<?php echo $item['quantity']; ?>" min="1" max="<?php echo $item['stock_quantity']; ?>">
<button style="padding: 2px 5px;" type="button" class="quantity-increment btn"><i class="fas fa-plus"></i></button>
</div>
<button style="padding: 2px 32px;" type="submit" name="update_quantity" class="update-btn btn">Update</button>
</form>
</td>
<td data-label="Subtotal">₱<?php echo number_format($item['price'] * $item['quantity'], 2); ?></td>
<td data-label="Action">
<form method="POST">
<input type="hidden" name="cart_item_id" value="<?php echo $item['cart_item_id']; ?>">
<button type="submit" name="remove_item" class="remove-btn btn">
<i class="fas fa-trash"></i> Remove
</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="cart-summary card">
<div class="summary-row">
<span>Subtotal:</span>
<span>₱<?php echo number_format($total, 2); ?></span>
</div>
<div class="summary-row">
<span>Estimated Shipping:</span>
<span>Free</span>
</div>
<div class="summary-row total-row">
<span>Total:</span>
<span>₱<?php echo number_format($total, 2); ?></span>
</div>
<form method="POST">
<button type="submit" name="checkout" class="checkout-btn btn">
<i class="fas fa-beat fa-shopping-bag"></i> Proceed to Checkout
</button>
</form>
</div>
<?php endif; ?>
</div>
<?php include '../includes/footer.php'; ?>
<script>
// Quantity increment/decrement buttons
document.querySelectorAll('.quantity-increment').forEach(button => {
button.addEventListener('click', function() {
const input = this.parentElement.querySelector('input');
const max = parseInt(input.getAttribute('max'));
const current = parseInt(input.value);
if (current < max) {
input.value = current + 1;
} else {
alert(`Only ${max} available in stock`);
}
});
});
document.querySelectorAll('.quantity-decrement').forEach(button => {
button.addEventListener('click', function() {
const input = this.parentElement.querySelector('input');
if (parseInt(input.value) > 1) {
input.value = parseInt(input.value) - 1;
}
});
});
// Quantity form submission
document.querySelectorAll('.quantity-form').forEach(form => {
form.addEventListener('submit', function(e) {
const input = this.querySelector('input[name="quantity"]');
const max = parseInt(input.getAttribute('max'));
const value = parseInt(input.value);
if (value < 1) {
e.preventDefault();
alert('Quantity must be at least 1');
input.focus();
} else if (value > max) {
e.preventDefault();
alert(`Only ${max} available in stock`);
input.focus();
}
});
});
// Remove item confirmation
document.querySelectorAll('button[name="remove_item"]').forEach(button => {
button.addEventListener('click', function(e) {
if (!confirm('Are you sure you want to remove this item from your cart?')) {
e.preventDefault();
}
});
});
</script>
</body>
</html>
+240
View File
@@ -0,0 +1,240 @@
<?php
require_once '../../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotCustomer();
require_once '../../config/database.php';
// Pagination variables
$current_page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$per_page = 10;
$offset = ($current_page - 1) * $per_page;
// Get total orders count
$count_stmt = $pdo->prepare("SELECT COUNT(*) FROM orders WHERE customer_id = ?");
$count_stmt->execute([$_SESSION['user_id']]);
$total_orders = $count_stmt->fetchColumn();
// Get orders with pagination
$stmt = $pdo->prepare("
SELECT o.order_id, o.order_date, o.total_amount, o.status, o.pickup_schedule
FROM orders o
WHERE o.customer_id = ?
ORDER BY o.order_date DESC
LIMIT ? OFFSET ?
");
$stmt->bindValue(1, $_SESSION['user_id'], PDO::PARAM_INT);
$stmt->bindValue(2, $per_page, PDO::PARAM_INT);
$stmt->bindValue(3, $offset, PDO::PARAM_INT);
$stmt->execute();
$orders = $stmt->fetchAll();
// Calculate total pages
$total_pages = ceil($total_orders / $per_page);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Orders - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.orders-container {
margin-top: 30px;
}
.orders-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.orders-table th, .orders-table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #eee;
}
.orders-table th {
background-color: #f5f5f5;
font-weight: 600;
}
.order-status {
display: inline-block;
padding: 5px 10px;
border-radius: 4px;
font-size: 0.9rem;
font-weight: 500;
}
.status-pending {
background-color: #fff3cd;
color: #856404;
}
.status-processing {
background-color: #cce5ff;
color: #004085;
}
.status-ready {
background-color: #d4edda;
color: #155724;
}
.status-completed {
background-color: #e2e3e5;
color: #383d41;
}
.status-cancelled {
background-color: #f8d7da;
color: #721c24;
}
.pagination {
display: flex;
justify-content: center;
margin-top: 30px;
gap: 5px;
}
.pagination a, .pagination span {
display: inline-block;
padding: 8px 15px;
border: 1px solid #ddd;
border-radius: 4px;
text-decoration: none;
color: var(--text-color);
}
.pagination a:hover {
background-color: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
.pagination .current {
background-color: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
.empty-orders {
text-align: center;
padding: 50px;
background-color: #f9f9f9;
border-radius: 8px;
}
@media (max-width: 768px) {
.orders-table {
display: block;
overflow-x: auto;
}
}
</style>
</head>
<body>
<?php include '../../includes/header.php'; ?>
<div class="container orders-container">
<h1>My Orders</h1>
<?php if (empty($orders)): ?>
<div class="empty-orders card">
<i class="fas fa-box-open" style="font-size: 3em; color: #ccc; margin-bottom: 20px;"></i>
<h3>You haven't placed any orders yet</h3>
<p>Start shopping to see your orders here</p>
<a href="/unimarket/customer/products/browse.php" class="btn">Browse Products</a>
</div>
<?php else: ?>
<table class="orders-table">
<thead>
<tr>
<th>Order #</th>
<th>Date</th>
<th>Total</th>
<th>Status</th>
<th>Pickup Schedule</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $order): ?>
<tr>
<td>
<a href="/unimarket/customer/orders/view.php?order_id=<?php echo $order['order_id']; ?>">
#<?php echo $order['order_id']; ?>
</a>
</td>
<td><?php echo date('M j, Y', strtotime($order['order_date'])); ?></td>
<td>$<?php echo number_format($order['total_amount'], 2); ?></td>
<td>
<?php
$status_class = '';
switch ($order['status']) {
case 'pending':
$status_class = 'status-pending';
break;
case 'processing':
$status_class = 'status-processing';
break;
case 'ready_for_pickup':
$status_class = 'status-ready';
break;
case 'completed':
$status_class = 'status-completed';
break;
case 'cancelled':
$status_class = 'status-cancelled';
break;
}
?>
<span class="order-status <?php echo $status_class; ?>">
<?php echo ucfirst(str_replace('_', ' ', $order['status'])); ?>
</span>
</td>
<td>
<?php if ($order['pickup_schedule']): ?>
<?php echo date('M j, Y g:i A', strtotime($order['pickup_schedule'])); ?>
<?php else: ?>
Not scheduled
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php if ($total_pages > 1): ?>
<div class="pagination">
<?php if ($current_page > 1): ?>
<a href="?page=1">First</a>
<a href="?page=<?php echo $current_page - 1; ?>">Prev</a>
<?php endif; ?>
<?php for ($i = max(1, $current_page - 2); $i <= min($current_page + 2, $total_pages); $i++): ?>
<?php if ($i == $current_page): ?>
<span class="current"><?php echo $i; ?></span>
<?php else: ?>
<a href="?page=<?php echo $i; ?>"><?php echo $i; ?></a>
<?php endif; ?>
<?php endfor; ?>
<?php if ($current_page < $total_pages): ?>
<a href="?page=<?php echo $current_page + 1; ?>">Next</a>
<a href="?page=<?php echo $total_pages; ?>">Last</a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php include '../../includes/footer.php'; ?>
</body>
</html>
+325
View File
@@ -0,0 +1,325 @@
<?php
require_once '../../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotCustomer();
require_once '../../config/database.php';
// Get order ID from URL
if (!isset($_GET['order_id'])) {
header("Location: /unimarket/customer/orders/list.php");
exit();
}
$order_id = (int)$_GET['order_id'];
// Verify order belongs to current user
$stmt = $pdo->prepare("SELECT customer_id FROM orders WHERE order_id = ?");
$stmt->execute([$order_id]);
$order_customer_id = $stmt->fetchColumn();
if ($order_customer_id != $_SESSION['user_id']) {
header("Location: /unimarket/customer/orders/list.php");
exit();
}
// Get order details
$stmt = $pdo->prepare("
SELECT o.order_id, o.order_date, o.total_amount, o.status, o.pickup_schedule
FROM orders o
WHERE o.order_id = ?
");
$stmt->execute([$order_id]);
$order = $stmt->fetch();
// Get order items
$stmt = $pdo->prepare("
SELECT oi.*, p.name, p.image_path, p.price
FROM order_items oi
JOIN products p ON oi.product_id = p.product_id
WHERE oi.order_id = ?
");
$stmt->execute([$order_id]);
$order_items = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Order Details - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.order-details-container {
margin-top: 30px;
}
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
}
.order-info {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
margin-bottom: 30px;
}
.info-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-top: 15px;
}
.info-item {
margin-bottom: 10px;
}
.info-label {
font-weight: 600;
color: #666;
margin-bottom: 5px;
}
.info-value {
font-size: 1.1rem;
}
.order-status {
display: inline-block;
padding: 8px 15px;
border-radius: 4px;
font-weight: 500;
}
.status-pending {
background-color: #fff3cd;
color: #856404;
}
.status-processing {
background-color: #cce5ff;
color: #004085;
}
.status-ready {
background-color: #d4edda;
color: #155724;
}
.status-completed {
background-color: #e2e3e5;
color: #383d41;
}
.status-cancelled {
background-color: #f8d7da;
color: #721c24;
}
.order-items {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
}
.items-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.items-table th, .items-table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #eee;
}
.items-table th {
background-color: #f5f5f5;
font-weight: 600;
}
.product-cell {
display: flex;
align-items: center;
}
.product-image {
width: 60px;
height: 60px;
margin-right: 15px;
background-color: #f9f9f9;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.product-image img {
max-width: 100%;
max-height: 100%;
}
.order-total {
text-align: right;
margin-top: 20px;
font-size: 1.2rem;
font-weight: 600;
}
.back-link {
display: inline-block;
margin-bottom: 20px;
color: var(--primary-color);
text-decoration: none;
}
.back-link:hover {
text-decoration: underline;
}
@media (max-width: 768px) {
.items-table {
display: block;
overflow-x: auto;
}
.product-cell {
flex-direction: column;
align-items: flex-start;
}
.product-image {
margin-bottom: 10px;
}
}
</style>
</head>
<body>
<?php include '../../includes/header.php'; ?>
<div class="container order-details-container">
<a href="/unimarket/customer/orders/list.php" class="back-link">
<i class="fas fa-arrow-left"></i> Back to Orders
</a>
<div class="order-header">
<h1>Order #<?php echo $order['order_id']; ?></h1>
<?php
$status_class = '';
switch ($order['status']) {
case 'pending':
$status_class = 'status-pending';
break;
case 'processing':
$status_class = 'status-processing';
break;
case 'ready_for_pickup':
$status_class = 'status-ready';
break;
case 'completed':
$status_class = 'status-completed';
break;
case 'cancelled':
$status_class = 'status-cancelled';
break;
}
?>
<span class="order-status <?php echo $status_class; ?>">
<?php echo ucfirst(str_replace('_', ' ', $order['status'])); ?>
</span>
</div>
<div class="order-info card">
<h2>Order Information</h2>
<div class="info-grid">
<div class="info-item">
<div class="info-label">Order Date</div>
<div class="info-value"><?php echo date('F j, Y g:i A', strtotime($order['order_date'])); ?></div>
</div>
<div class="info-item">
<div class="info-label">Order Status</div>
<div class="info-value">
<span class="order-status <?php echo $status_class; ?>">
<?php echo ucfirst(str_replace('_', ' ', $order['status'])); ?>
</span>
</div>
</div>
<div class="info-item">
<div class="info-label">Pickup Schedule</div>
<div class="info-value">
<?php if ($order['pickup_schedule']): ?>
<?php echo date('F j, Y g:i A', strtotime($order['pickup_schedule'])); ?>
<?php else: ?>
Not scheduled yet
<?php endif; ?>
</div>
</div>
<div class="info-item">
<div class="info-label">Payment Method</div>
<div class="info-value">Pay on Pickup</div>
</div>
</div>
</div>
<div class="order-items card">
<h2>Order Items</h2>
<table class="items-table">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Subtotal</th>
</tr>
</thead>
<tbody>
<?php foreach ($order_items as $item): ?>
<tr>
<td>
<div class="product-cell">
<div class="product-image">
<?php if ($item['image_path']): ?>
<img src="/unimarket/assets/images/products/<?php echo $item['image_path']; ?>" alt="<?php echo htmlspecialchars($item['name']); ?>">
<?php else: ?>
<i class="fas fa-box-open" style="color: #ccc;"></i>
<?php endif; ?>
</div>
<div>
<h4><?php echo htmlspecialchars($item['name']); ?></h4>
</div>
</div>
</td>
<td>₱<?php echo number_format($item['price'], 2); ?></td>
<td><?php echo $item['quantity']; ?></td>
<td>₱<?php echo number_format($item['price'] * $item['quantity'], 2); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="order-total">
<div style="margin-bottom: 10px;">Subtotal: ₱<?php echo number_format($order['total_amount'], 2); ?></div>
<div style="margin-bottom: 10px;">Shipping: Free</div>
<div style="font-size: 1.4rem;">Total: ₱<?php echo number_format($order['total_amount'], 2); ?></div>
</div>
</div>
</div>
<?php include '../../includes/footer.php'; ?>
</body>
</html>
+339
View File
@@ -0,0 +1,339 @@
<?php
require_once '../../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotCustomer();
require_once '../../config/database.php';
// Pagination variables
$current_page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$per_page = 12;
$offset = ($current_page - 1) * $per_page;
// Search and filter variables
$search_query = isset($_GET['search']) ? trim($_GET['search']) : '';
$category_filter = isset($_GET['category']) ? trim($_GET['category']) : '';
// Base query
$query = "SELECT * FROM products WHERE stock_quantity > 0";
$count_query = "SELECT COUNT(*) FROM products WHERE stock_quantity > 0";
$params = [];
// Add search condition
if (!empty($search_query)) {
$query .= " AND (name LIKE ? OR description LIKE ?)";
$count_query .= " AND (name LIKE ? OR description LIKE ?)";
$search_param = "%$search_query%";
array_push($params, $search_param, $search_param);
}
// Add category filter
if (!empty($category_filter)) {
$query .= " AND category = ?";
$count_query .= " AND category = ?";
array_push($params, $category_filter);
}
// Add sorting
$sort = isset($_GET['sort']) ? $_GET['sort'] : 'newest';
switch ($sort) {
case 'price_low':
$query .= " ORDER BY price ASC";
break;
case 'price_high':
$query .= " ORDER BY price DESC";
break;
case 'name':
$query .= " ORDER BY name ASC";
break;
default:
$query .= " ORDER BY created_at DESC";
break;
}
// Add pagination
$query .= " LIMIT ? OFFSET ?";
array_push($params, $per_page, $offset);
// Prepare and execute the query
$stmt = $pdo->prepare($query);
foreach ($params as $key => $value) {
$paramType = is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR;
$stmt->bindValue($key + 1, $value, $paramType);
}
$stmt->execute();
$products = $stmt->fetchAll();
// Get total count for pagination
$count_stmt = $pdo->prepare($count_query);
foreach (array_slice($params, 0, count($params) - 2) as $key => $value) {
$paramType = is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR;
$count_stmt->bindValue($key + 1, $value, $paramType);
}
$count_stmt->execute();
$total_products = $count_stmt->fetchColumn();
// Get all categories for filter dropdown
$categories = $pdo->query("SELECT DISTINCT category FROM products WHERE category IS NOT NULL AND category != '' ORDER BY category")->fetchAll();
// Calculate total pages
$total_pages = ceil($total_products / $per_page);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Browse Products - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<style>
.browse-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
}
.search-filter-container {
display: flex;
gap: 15px;
margin-bottom: 15px;
flex-wrap: wrap;
}
.search-box {
flex: 1;
min-width: 250px;
position: relative;
}
.search-box input {
width: 100%;
padding: 10px 15px;
padding-right: 40px;
border: 1px solid #ddd;
border-radius: 4px;
}
.search-box button {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
color: var(--primary-color);
}
.filter-dropdown {
min-width: 200px;
}
.filter-dropdown select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
.sort-dropdown {
min-width: 150px;
}
.pagination {
display: flex;
justify-content: center;
margin-top: 30px;
gap: 5px;
}
.pagination a, .pagination span {
display: inline-block;
padding: 8px 15px;
border: 1px solid #ddd;
border-radius: 4px;
text-decoration: none;
color: var(--text-color);
}
.pagination a:hover {
background-color: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
.pagination .current {
background-color: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
.no-products {
text-align: center;
padding: 40px;
background-color: #f9f9f9;
border-radius: 8px;
}
.product-card .stock-info {
color: #666;
font-size: 0.9rem;
margin-bottom: 10px;
}
.product-card .stock-low {
color: #e53935;
}
</style>
</head>
<body>
<?php include '../../includes/header.php'; ?>
<div class="container">
<div class="browse-header">
<h1>Browse Products</h1>
<div class="search-filter-container">
<form method="GET" class="search-box">
<input type="text" name="search" placeholder="Search products..." value="<?php echo htmlspecialchars($search_query); ?>">
<button type="submit"><i class="fas fa-search"></i></button>
</form>
<div class="filter-dropdown">
<select name="category" onchange="this.form.submit()" form="filter-form">
<option value="">All Categories</option>
<?php foreach ($categories as $category): ?>
<option value="<?php echo htmlspecialchars($category['category']); ?>" <?php echo $category_filter === $category['category'] ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($category['category']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="sort-dropdown">
<select name="sort" onchange="this.form.submit()" form="filter-form">
<option value="newest" <?php echo $sort === 'newest' ? 'selected' : ''; ?>>Newest First</option>
<option value="price_low" <?php echo $sort === 'price_low' ? 'selected' : ''; ?>>Price: Low to High</option>
<option value="price_high" <?php echo $sort === 'price_high' ? 'selected' : ''; ?>>Price: High to Low</option>
<option value="name" <?php echo $sort === 'name' ? 'selected' : ''; ?>>Name: A-Z</option>
</select>
</div>
<form id="filter-form" method="GET" style="display: none;">
<input type="hidden" name="search" value="<?php echo htmlspecialchars($search_query); ?>">
</form>
</div>
</div>
<?php if (empty($products)): ?>
<div class="no-products card">
<h3>No products found</h3>
<p>Try adjusting your search or filter criteria</p>
<a href="/unimarket/customer/products/browse.php" class="btn">Reset Filters</a>
</div>
<?php else: ?>
<div class="product-grid">
<?php foreach ($products as $product): ?>
<div class="product-card card">
<a style="color: black; text-decoration: none;" href="/unimarket/customer/products/view.php?id=<?php echo $product['product_id']; ?>">
<div class="product-image">
<?php if ($product['image_path']): ?>
<img src="/unimarket/assets/images/products/<?php echo $product['image_path']; ?>" alt="<?php echo htmlspecialchars($product['name']); ?>">
<?php else: ?>
<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #999;">
<i class="fas fa-box-open" style="font-size: 3rem;"></i>
</div>
<?php endif; ?>
</div>
<div class="product-info">
<h3 class="product-title"><?php echo htmlspecialchars($product['name']); ?></h3>
<p class="product-price">₱<?php echo number_format($product['price'], 2); ?></p>
<p class="stock-info <?php echo $product['stock_quantity'] < 5 ? 'stock-low' : ''; ?>">
<?php echo $product['stock_quantity'] < 5 ? 'Only ' . $product['stock_quantity'] . ' left!' : 'In stock'; ?>
</p>
<form action="/unimarket/customer/cart.php" method="POST">
<input type="hidden" name="product_id" value="<?php echo $product['product_id']; ?>">
<div style="display: flex; gap: 10px;">
<input style="text-align: center;" type="number" name="quantity" value="1" min="1" max="<?php echo $product['stock_quantity']; ?>" style="flex: 1;">
<button type="submit" name="add_to_cart" class="btn">Add to Cart</button>
</div>
</form>
</div>
</a>
</div>
<?php endforeach; ?>
</div>
<?php if ($total_pages > 1): ?>
<div class="pagination">
<?php if ($current_page > 1): ?>
<a href="?<?php echo buildQueryString(['page' => 1]); ?>">First</a>
<a href="?<?php echo buildQueryString(['page' => $current_page - 1]); ?>">Prev</a>
<?php endif; ?>
<?php for ($i = max(1, $current_page - 2); $i <= min($current_page + 2, $total_pages); $i++): ?>
<?php if ($i == $current_page): ?>
<span class="current"><?php echo $i; ?></span>
<?php else: ?>
<a href="?<?php echo buildQueryString(['page' => $i]); ?>"><?php echo $i; ?></a>
<?php endif; ?>
<?php endfor; ?>
<?php if ($current_page < $total_pages): ?>
<a href="?<?php echo buildQueryString(['page' => $current_page + 1]); ?>">Next</a>
<a href="?<?php echo buildQueryString(['page' => $total_pages]); ?>">Last</a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php include '../../includes/footer.php'; ?>
<script>
// Add to cart with quantity validation
document.querySelectorAll('form[action="/unimarket/customer/cart.php"]').forEach(form => {
form.addEventListener('submit', function(e) {
const quantityInput = this.querySelector('input[name="quantity"]');
const max = parseInt(quantityInput.getAttribute('max'));
const value = parseInt(quantityInput.value);
if (value < 1) {
e.preventDefault();
alert('Quantity must be at least 1');
quantityInput.focus();
} else if (value > max) {
e.preventDefault();
alert(`Only ${max} available in stock`);
quantityInput.focus();
}
});
});
// Helper function to build query string from current URL parameters
function buildQueryString(params) {
const searchParams = new URLSearchParams(window.location.search);
for (const key in params) {
if (params[key] !== undefined) {
searchParams.set(key, params[key]);
}
}
return searchParams.toString();
}
</script>
</body>
</html>
<?php
/**
* Helper function to build query string while preserving existing parameters
*/
function buildQueryString($new_params) {
$params = array_merge($_GET, $new_params);
return http_build_query($params);
}
?>
+306
View File
@@ -0,0 +1,306 @@
<?php
require_once '../../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotCustomer();
require_once '../../config/database.php';
// Check if product ID is provided
if (!isset($_GET['id'])) {
header("Location: /unimarket/customer/products/browse.php");
exit();
}
$product_id = (int)$_GET['id'];
// Get product details
$stmt = $pdo->prepare("SELECT p.*, u.username as seller_name
FROM products p
JOIN users u ON p.owner_id = u.user_id
WHERE p.product_id = ? AND p.stock_quantity > 0");
$stmt->execute([$product_id]);
$product = $stmt->fetch();
if (!$product) {
header("Location: /unimarket/customer/products/browse.php");
exit();
}
// Handle add to cart
$error_message = '';
$success_message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_to_cart'])) {
$quantity = (int)$_POST['quantity'];
if ($quantity < 1) {
$error_message = 'Quantity must be at least 1.';
} elseif ($quantity > $product['stock_quantity']) {
$error_message = "Only {$product['stock_quantity']} available in stock.";
} else {
try {
// Get or create cart for user
$stmt = $pdo->prepare("SELECT cart_id FROM cart WHERE user_id = ?");
$stmt->execute([$_SESSION['user_id']]);
$cart = $stmt->fetch();
if (!$cart) {
$stmt = $pdo->prepare("INSERT INTO cart (user_id) VALUES (?)");
$stmt->execute([$_SESSION['user_id']]);
$cart_id = $pdo->lastInsertId();
} else {
$cart_id = $cart['cart_id'];
}
// Check if product already in cart
$stmt = $pdo->prepare("SELECT * FROM cart_items WHERE cart_id = ? AND product_id = ?");
$stmt->execute([$cart_id, $product_id]);
$existing_item = $stmt->fetch();
if ($existing_item) {
// Update quantity if already in cart
$new_quantity = $existing_item['quantity'] + $quantity;
if ($new_quantity > $product['stock_quantity']) {
$error_message = "Cannot add more than available stock.";
} else {
$stmt = $pdo->prepare("UPDATE cart_items SET quantity = ? WHERE cart_item_id = ?");
$stmt->execute([$new_quantity, $existing_item['cart_item_id']]);
$success_message = 'Product quantity updated in cart!';
}
} else {
// Add new item to cart
$stmt = $pdo->prepare("INSERT INTO cart_items (cart_id, product_id, quantity) VALUES (?, ?, ?)");
$stmt->execute([$cart_id, $product_id, $quantity]);
$success_message = 'Product added to cart!';
}
} catch (PDOException $e) {
$error_message = 'Failed to add product to cart. Please try again.';
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo htmlspecialchars($product['name']); ?> - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.product-detail-container {
margin-top: 30px;
}
.product-main {
display: grid;
grid-template-columns: 1fr;
gap: 30px;
margin-bottom: 40px;
}
@media (min-width: 768px) {
.product-main {
grid-template-columns: 1fr 1fr;
}
}
.product-gallery {
background-color: #f9f9f9;
border-radius: 8px;
padding: 20px;
text-align: center;
}
.product-image {
max-width: 100%;
max-height: 400px;
margin-bottom: 20px;
}
.product-info {
padding: 20px;
}
.product-title {
font-size: 2rem;
margin-bottom: 10px;
color: var(--primary-dark);
}
.product-seller {
color: #666;
margin-bottom: 20px;
font-size: 1.1rem;
}
.product-price {
font-size: 1.8rem;
font-weight: bold;
color: var(--primary-color);
margin-bottom: 20px;
}
.product-stock {
margin-bottom: 20px;
font-size: 1.1rem;
}
.stock-high {
color: #2e7d32;
}
.stock-low {
color: #e53935;
}
.product-description {
margin-bottom: 30px;
line-height: 1.6;
}
.add-to-cart-form {
display: flex;
gap: 10px;
flex-wrap: wrap;
align-items: center;
}
.quantity-input {
width: 80px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
text-align: center;
}
.back-link {
display: inline-block;
margin-bottom: 20px;
color: var(--primary-color);
text-decoration: none;
}
.back-link:hover {
text-decoration: underline;
}
.product-meta {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-top: 30px;
padding-top: 30px;
border-top: 1px solid #eee;
}
.meta-item {
background-color: #f5f5f5;
padding: 15px;
border-radius: 8px;
}
.meta-label {
font-weight: 600;
color: #666;
margin-bottom: 5px;
}
</style>
</head>
<body>
<?php include '../../includes/header.php'; ?>
<div class="container product-detail-container">
<a href="/unimarket/customer/products/browse.php" class="back-link">
<i class="fas fa-arrow-left"></i> Back to Products
</a>
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo $success_message; ?></div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="alert alert-error"><?php echo $error_message; ?></div>
<?php endif; ?>
<div class="product-main card">
<div class="product-gallery">
<?php if ($product['image_path']): ?>
<img src="/unimarket/assets/images/products/<?php echo $product['image_path']; ?>"
alt="<?php echo htmlspecialchars($product['name']); ?>"
class="product-image">
<?php else: ?>
<div style="height: 400px; display: flex; align-items: center; justify-content: center;">
<i class="fas fa-box-open" style="font-size: 5rem; color: #ccc;"></i>
</div>
<?php endif; ?>
</div>
<div class="product-info">
<h1 class="product-title"><?php echo htmlspecialchars($product['name']); ?></h1>
<p class="product-seller">Sold by <?php echo htmlspecialchars($product['seller_name']); ?></p>
<p class="product-price">₱<?php echo number_format($product['price'], 2); ?></p>
<p class="product-stock <?php echo $product['stock_quantity'] < 5 ? 'stock-low' : 'stock-high'; ?>">
<?php if ($product['stock_quantity'] < 5): ?>
Only <?php echo $product['stock_quantity']; ?> left in stock!
<?php else: ?>
In stock (<?php echo $product['stock_quantity']; ?> available)
<?php endif; ?>
</p>
<div class="product-description">
<h3>Description</h3>
<p><?php echo nl2br(htmlspecialchars($product['description'])); ?></p>
</div>
<form method="POST" class="add-to-cart-form">
<input type="number" name="quantity" value="1" min="1" max="<?php echo $product['stock_quantity']; ?>"
class="quantity-input">
<button type="submit" name="add_to_cart" class="btn">
<i class="fas fa-shopping-cart"></i> Add to Cart
</button>
</form>
</div>
</div>
<div class="product-meta">
<div class="meta-item card">
<div class="meta-label">Category</div>
<div><?php echo $product['category'] ? htmlspecialchars($product['category']) : 'No category specified'; ?></div>
</div>
<div class="meta-item card">
<div class="meta-label">Pickup Information</div>
<div>Available for on-campus pickup</div>
</div>
<div class="meta-item card">
<div class="meta-label">Payment</div>
<div>Pay when you pickup</div>
</div>
</div>
</div>
<?php include '../../includes/footer.php'; ?>
<script>
// Quantity input validation
const quantityInput = document.querySelector('.quantity-input');
quantityInput.addEventListener('change', function() {
const max = parseInt(this.getAttribute('max'));
const value = parseInt(this.value);
if (value < 1) {
this.value = 1;
} else if (value > max) {
this.value = max;
alert(`Only ${max} available in stock`);
}
});
</script>
</body>
</html>
+544
View File
@@ -0,0 +1,544 @@
<?php
require_once '../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotCustomer();
require_once '../config/database.php';
// Initialize variables
$success_message = '';
$error_message = '';
$user = [];
$orders = [];
// Get user details
$stmt = $pdo->prepare("SELECT * FROM users WHERE user_id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
// Get recent orders
$stmt = $pdo->prepare("
SELECT o.order_id, o.order_date, o.total_amount, o.status, o.pickup_schedule
FROM orders o
WHERE o.customer_id = ?
ORDER BY o.order_date DESC
LIMIT 5
");
$stmt->execute([$_SESSION['user_id']]);
$orders = $stmt->fetchAll();
// Handle profile updates
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_profile'])) {
$first_name = trim($_POST['first_name']);
$last_name = trim($_POST['last_name']);
$email = trim($_POST['email']);
$phone = trim($_POST['phone']);
$university_id = trim($_POST['university_id']);
// Validate inputs
if (empty($first_name) || empty($last_name) || empty($email) || empty($university_id)) {
$error_message = 'Please fill in all required fields.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error_message = 'Please enter a valid email address.';
} else {
try {
// Check if email is already taken by another user
$stmt = $pdo->prepare("SELECT user_id FROM users WHERE email = ? AND user_id != ?");
$stmt->execute([$email, $_SESSION['user_id']]);
if ($stmt->fetch()) {
$error_message = 'This email is already registered to another account.';
} else {
// Update profile
$stmt = $pdo->prepare("
UPDATE users
SET first_name = ?, last_name = ?, email = ?, phone = ?, university_id = ?
WHERE user_id = ?
");
$stmt->execute([
$first_name,
$last_name,
$email,
$phone,
$university_id,
$_SESSION['user_id']
]);
$success_message = 'Profile updated successfully!';
// Refresh user data
$stmt = $pdo->prepare("SELECT * FROM users WHERE user_id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
}
} catch (PDOException $e) {
$error_message = 'An error occurred while updating your profile. Please try again.';
}
}
}
// Handle password changes
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['change_password'])) {
$current_password = $_POST['current_password'];
$new_password = $_POST['new_password'];
$confirm_password = $_POST['confirm_password'];
if (empty($current_password)) {
$error_message = 'Please enter your current password.';
} elseif (empty($new_password) || empty($confirm_password)) {
$error_message = 'Please enter and confirm your new password.';
} elseif ($new_password !== $confirm_password) {
$error_message = 'New passwords do not match.';
} elseif (strlen($new_password) < 8) {
$error_message = 'Password must be at least 8 characters long.';
} else {
// Verify current password
$stmt = $pdo->prepare("SELECT password FROM users WHERE user_id = ?");
$stmt->execute([$_SESSION['user_id']]);
$db_password = $stmt->fetchColumn();
if (password_verify($current_password, $db_password)) {
// Update password
$hashed_password = password_hash($new_password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("UPDATE users SET password = ? WHERE user_id = ?");
$stmt->execute([$hashed_password, $_SESSION['user_id']]);
$success_message = 'Password changed successfully!';
} else {
$error_message = 'Current password is incorrect.';
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Profile - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.profile-container {
display: grid;
grid-template-columns: 1fr;
gap: 30px;
margin-top: 30px;
}
@media (min-width: 992px) {
.profile-container {
grid-template-columns: 1fr 1fr;
}
}
.profile-section {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 25px;
}
.section-title {
font-size: 1.5rem;
margin-bottom: 20px;
color: var(--primary-color);
border-bottom: 2px solid var(--primary-light);
padding-bottom: 10px;
}
.profile-info {
display: grid;
grid-template-columns: 100px 1fr;
gap: 15px;
align-items: center;
margin-bottom: 20px;
}
.profile-avatar {
width: 100px;
height: 100px;
border-radius: 50%;
background-color: var(--primary-light);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 2.5rem;
}
.profile-details h3 {
margin-bottom: 5px;
font-size: 1.3rem;
}
.profile-details p {
color: #666;
margin-bottom: 5px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
}
.form-group input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
}
.btn-update {
background-color: var(--primary-color);
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s;
}
.btn-update:hover {
background-color: var(--primary-dark);
}
.orders-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.orders-table th, .orders-table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #eee;
}
.orders-table th {
background-color: #f5f5f5;
}
.order-status {
display: inline-block;
padding: 5px 10px;
border-radius: 4px;
font-size: 0.9rem;
font-weight: 500;
}
#orders-ids{
text-decoration: none;
}
#orders-ids:hover{
color: green;
text-decoration: underline;
}
.status-pending {
background-color: #fff3cd;
color: #856404;
}
.status-processing {
background-color: #cce5ff;
color: #004085;
}
.status-ready {
background-color: #d4edda;
color: #155724;
}
.status-completed {
background-color: #e2e3e5;
color: #383d41;
}
.status-cancelled {
background-color: #f8d7da;
color: #721c24;
}
.view-all {
display: block;
text-align: right;
margin-top: 15px;
color: var(--primary-color);
text-decoration: none;
}
.view-all:hover {
text-decoration: underline;
}
.password-strength {
height: 5px;
background-color: #eee;
margin-top: 5px;
border-radius: 3px;
overflow: hidden;
}
.password-strength-bar {
height: 100%;
width: 0%;
background-color: #ff0000;
transition: width 0.3s, background-color 0.3s;
}
@media (max-width: 768px) {
.profile-info {
grid-template-columns: 1fr;
text-align: center;
}
.profile-avatar {
margin: 0 auto;
}
.orders-table {
display: block;
overflow-x: auto;
}
}
</style>
</head>
<body>
<?php include '../includes/header.php'; ?>
<div class="container">
<h1>My Profile</h1>
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo $success_message; ?></div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="alert alert-error"><?php echo $error_message; ?></div>
<?php endif; ?>
<div class="profile-container">
<div class="profile-section">
<h2 class="section-title">Profile Information</h2>
<div class="profile-info">
<div class="profile-avatar">
<i class="fas fa-user"></i>
</div>
<div class="profile-details">
<h3><?php echo htmlspecialchars($user['first_name'] . ' ' . htmlspecialchars($user['last_name'])); ?></h3>
<p><?php echo htmlspecialchars($user['email']); ?></p>
<p>Member since <?php echo date('F Y', strtotime($user['created_at'])); ?></p>
</div>
</div>
<form method="POST">
<div class="form-group">
<label for="first_name">First Name</label>
<input type="text" id="first_name" name="first_name" value="<?php echo htmlspecialchars($user['first_name']); ?>" required>
</div>
<div class="form-group">
<label for="last_name">Last Name</label>
<input type="text" id="last_name" name="last_name" value="<?php echo htmlspecialchars($user['last_name']); ?>" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" value="<?php echo htmlspecialchars($user['email']); ?>" required>
</div>
<div class="form-group">
<label for="phone">Phone Number</label>
<input type="tel" id="phone" name="phone" value="<?php echo htmlspecialchars($user['phone']); ?>">
</div>
<div class="form-group">
<label for="university_id">University ID</label>
<input type="text" id="university_id" name="university_id" value="<?php echo htmlspecialchars($user['university_id']); ?>" required>
</div>
<button type="submit" name="update_profile" class="btn-update">Update Profile</button>
</form>
</div>
<div class="profile-section">
<h2 class="section-title">Change Password</h2>
<form method="POST">
<div class="form-group">
<label for="current_password">Current Password</label>
<input type="password" id="current_password" name="current_password" required>
</div>
<div class="form-group">
<label for="new_password">New Password</label>
<input type="password" id="new_password" name="new_password" required>
<div class="password-strength">
<div class="password-strength-bar" id="passwordStrengthBar"></div>
</div>
</div>
<div class="form-group">
<label for="confirm_password">Confirm New Password</label>
<input type="password" id="confirm_password" name="confirm_password" required>
</div>
<button type="submit" name="change_password" class="btn-update">Change Password</button>
</form>
<h2 class="section-title" style="margin-top: 40px;">Recent Orders</h2>
<?php if (empty($orders)): ?>
<p>You haven't placed any orders yet.</p>
<?php else: ?>
<table class="orders-table">
<thead>
<tr>
<th>Order #</th>
<th>Date</th>
<th>Total</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $order): ?>
<tr>
<td><a id="orders-ids" href="/unimarket/customer/orders/view.php?order_id=<?php echo $order['order_id']; ?>">#<?php echo $order['order_id']; ?></a></td>
<td><?php echo date('M j, Y', strtotime($order['order_date'])); ?></td>
<td>₱<?php echo number_format($order['total_amount'], 2); ?></td>
<td>
<?php
$status_class = '';
switch ($order['status']) {
case 'pending':
$status_class = 'status-pending';
break;
case 'processing':
$status_class = 'status-processing';
break;
case 'ready_for_pickup':
$status_class = 'status-ready';
break;
case 'completed':
$status_class = 'status-completed';
break;
case 'cancelled':
$status_class = 'status-cancelled';
break;
}
?>
<span class="order-status <?php echo $status_class; ?>">
<?php echo ucfirst(str_replace('_', ' ', $order['status'])); ?>
</span>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<a href="/unimarket/customer/orders/list.php" class="view-all">View all orders →</a>
<?php endif; ?>
</div>
</div>
</div>
<?php include '../includes/footer.php'; ?>
<script>
// Password strength indicator
const passwordInput = document.getElementById('new_password');
const strengthBar = document.getElementById('passwordStrengthBar');
passwordInput.addEventListener('input', function() {
const password = this.value;
let strength = 0;
if (password.length >= 8) strength += 1;
if (password.match(/[a-z]/)) strength += 1;
if (password.match(/[A-Z]/)) strength += 1;
if (password.match(/[0-9]/)) strength += 1;
if (password.match(/[^a-zA-Z0-9]/)) strength += 1;
const width = strength * 20;
let color;
if (strength <= 1) color = '#ff0000';
else if (strength <= 3) color = '#ff9900';
else color = '#00aa00';
strengthBar.style.width = width + '%';
strengthBar.style.backgroundColor = color;
});
// Form validation
document.querySelectorAll('form').forEach(form => {
form.addEventListener('submit', function(e) {
let isValid = true;
const requiredFields = this.querySelectorAll('[required]');
requiredFields.forEach(field => {
if (!field.value.trim()) {
isValid = false;
field.classList.add('error');
// Create or show error message
let errorMsg = field.nextElementSibling;
if (!errorMsg || !errorMsg.classList.contains('error-message')) {
errorMsg = document.createElement('small');
errorMsg.className = 'error-message';
errorMsg.textContent = 'This field is required';
field.parentNode.insertBefore(errorMsg, field.nextSibling);
}
} else {
field.classList.remove('error');
const errorMsg = field.nextElementSibling;
if (errorMsg && errorMsg.classList.contains('error-message')) {
errorMsg.remove();
}
}
});
// Password confirmation check
if (this.querySelector('#new_password') && this.querySelector('#confirm_password')) {
const newPassword = this.querySelector('#new_password').value;
const confirmPassword = this.querySelector('#confirm_password').value;
if (newPassword !== confirmPassword) {
isValid = false;
const confirmField = this.querySelector('#confirm_password');
confirmField.classList.add('error');
let errorMsg = confirmField.nextElementSibling;
if (!errorMsg || !errorMsg.classList.contains('error-message')) {
errorMsg = document.createElement('small');
errorMsg.className = 'error-message';
errorMsg.textContent = 'Passwords do not match';
confirmField.parentNode.insertBefore(errorMsg, confirmField.nextSibling);
}
}
}
if (!isValid) {
e.preventDefault();
// Scroll to first error
const firstError = this.querySelector('.error');
if (firstError) {
firstError.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}
});
});
</script>
</body>
</html>
+44
View File
@@ -0,0 +1,44 @@
/unimarket
│
├── assets/
│ ├── css/
│ │ ├── style.css okay na
│ │ └── responsive.css okay na
│ ├── js/
│ │ └── script.js okay na
│ └── images/
│ └── logo.png
│
├── config/
│ └── database.php okay na
│
├── includes/
│ ├── header.php okay na
│ ├── footer.php okay na
│ └── auth_functions.php okay na
│
├── owner/
│ ├── dashboard.php okay na
│ ├── products/
│ │ ├── add.php
│ │ ├── edit.php
│ │ └── list.php
│ └── orders/
│ ├── list.php
│ └── schedule_pickup.php
│
├── customer/
│ ├── profile.php okay na
│ ├── cart.php okay na
│ ├── orders/
│ │ ├── list.php
│ │ └── view.php
│ └── products/
│ └── browse.php okay na
│
├── auth/
│ ├── login.php okay na
│ ├── register.php okay na
│ └── logout.php okay na
│
└── index.php okay na
+242
View File
@@ -0,0 +1,242 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
require_once __DIR__ . '/../config/database.php';
/**
* Check if a user is logged in
* @return bool True if user is logged in, false otherwise
*/
function isLoggedIn() {
return isset($_SESSION['user_id']);
}
/**
* Check if the logged in user is an owner
* @return bool True if user is an owner, false otherwise
*/
function isOwner() {
return isLoggedIn() && $_SESSION['role'] === 'owner';
}
/**
* Check if the logged in user is a customer
* @return bool True if user is a customer, false otherwise
*/
function isCustomer() {
return isLoggedIn() && $_SESSION['role'] === 'customer';
}
/**
* Redirect to login page if not logged in
*/
function redirectIfNotLoggedIn() {
if (!isLoggedIn()) {
$_SESSION['redirect_url'] = $_SERVER['REQUEST_URI'];
header("Location: /unimarket/auth/login.php");
exit();
}
}
/**
* Redirect to homepage if not an owner
*/
function redirectIfNotOwner() {
if (!isOwner()) {
header("Location: /unimarket/index.php");
exit();
}
}
/**
* Redirect to homepage if not a customer
*/
function redirectIfNotCustomer() {
if (!isCustomer()) {
header("Location: /unimarket/index.php");
exit();
}
}
/**
* Get the current user's ID
* @return int|null User ID if logged in, null otherwise
*/
function getUserId() {
return $_SESSION['user_id'] ?? null;
}
/**
* Get the current user's role
* @return string|null User role if logged in, null otherwise
*/
function getUserRole() {
return $_SESSION['role'] ?? null;
}
/**
* Get the current user's username
* @return string|null Username if logged in, null otherwise
*/
function getUsername() {
return $_SESSION['username'] ?? null;
}
/**
* Verify if the provided password matches the user's password
* @param int $user_id User ID to verify
* @param string $password Password to verify
* @return bool True if password matches, false otherwise
*/
function verifyPassword($user_id, $password) {
global $pdo;
try {
$stmt = $pdo->prepare("SELECT password FROM users WHERE user_id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
return $user && password_verify($password, $user['password']);
} catch (PDOException $e) {
return false;
}
}
/**
* Update user's password
* @param int $user_id User ID
* @param string $new_password New password
* @return bool True if update was successful, false otherwise
*/
function updatePassword($user_id, $new_password) {
global $pdo;
try {
$hashed_password = password_hash($new_password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("UPDATE users SET password = ? WHERE user_id = ?");
return $stmt->execute([$hashed_password, $user_id]);
} catch (PDOException $e) {
return false;
}
}
/**
* Generate a CSRF token and store it in session
* @return string Generated CSRF token
*/
function generateCsrfToken() {
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
/**
* Verify a CSRF token
* @param string $token Token to verify
* @return bool True if token is valid, false otherwise
*/
function verifyCsrfToken($token) {
return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}
/**
* Check if the current user owns a specific product
* @param int $product_id Product ID to check
* @return bool True if user owns the product, false otherwise
*/
function ownsProduct($product_id) {
if (!isOwner()) return false;
global $pdo;
try {
$stmt = $pdo->prepare("SELECT product_id FROM products WHERE product_id = ? AND owner_id = ?");
$stmt->execute([$product_id, getUserId()]);
return (bool)$stmt->fetch();
} catch (PDOException $e) {
return false;
}
}
/**
* Check if the current user placed a specific order
* @param int $order_id Order ID to check
* @return bool True if user placed the order, false otherwise
*/
function placedOrder($order_id) {
if (!isCustomer()) return false;
global $pdo;
try {
$stmt = $pdo->prepare("SELECT order_id FROM orders WHERE order_id = ? AND customer_id = ?");
$stmt->execute([$order_id, getUserId()]);
return (bool)$stmt->fetch();
} catch (PDOException $e) {
return false;
}
}
/**
* Flash a message to display on the next page load
* @param string $key Message key
* @param string $message Message content
*/
function flashMessage($key, $message) {
$_SESSION['flash_messages'][$key] = $message;
}
/**
* Get and clear a flashed message
* @param string $key Message key
* @return string|null Message content if exists, null otherwise
*/
function getFlashMessage($key) {
if (isset($_SESSION['flash_messages'][$key])) {
$message = $_SESSION['flash_messages'][$key];
unset($_SESSION['flash_messages'][$key]);
return $message;
}
return null;
}
/**
* Initialize a user session after login
* @param array $user User data array (must contain user_id, username, and role)
*/
function initUserSession($user) {
$_SESSION['user_id'] = $user['user_id'];
$_SESSION['username'] = $user['username'];
$_SESSION['role'] = $user['role'];
// Regenerate session ID to prevent fixation
session_regenerate_id(true);
}
/**
* Destroy the current user session
*/
function destroySession() {
// Unset all session variables
$_SESSION = array();
// Delete session cookie
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(
session_name(),
'',
time() - 42000,
$params["path"],
$params["domain"],
$params["secure"],
$params["httponly"]
);
}
// Destroy the session
session_destroy();
}
+53
View File
@@ -0,0 +1,53 @@
</main>
<footer style="background-color: var(--primary-dark); color: var(--light-text); padding: 40px 0; margin-top: 40px;">
<div class="container">
<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="/unimarket/index.php" style="color: var(--light-text); text-decoration: none;">Home</a></li>
<?php if (!isLoggedIn()): ?>
<li style="margin-bottom: 8px;"><a href="/unimarket/auth/login.php" style="color: var(--light-text); text-decoration: none;">Login</a></li>
<li style="margin-bottom: 8px;"><a href="/unimarket/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="/unimarket/customer/products/browse.php" style="color: var(--light-text); text-decoration: none;">Browse Products</a></li>
<li style="margin-bottom: 8px;"><a href="/unimarket/customer/profile.php" style="color: var(--light-text); text-decoration: none;">My Profile</a></li>
<?php else: ?>
<li style="margin-bottom: 8px;"><a href="/unimarket/owner/dashboard.php" style="color: var(--light-text); text-decoration: none;">Dashboard</a></li>
<li style="margin-bottom: 8px;"><a href="/unimarket/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>&copy; <?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="/unimarket/assets/js/script.js"></script>
</body>
</html>
+120
View File
@@ -0,0 +1,120 @@
<?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="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<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: white;
}
</style>
</head>
<body>
<header>
<div class="container header-content">
<a href="/unimarket/index.php" class="logo">
<i class="fas fa-flip fa-store" style="margin-right: 10px; --fa-animation-duration: 10s;" ></i>UniMarket
</a>
<nav>
<ul>
<?php if (isLoggedIn()): ?>
<?php if (isCustomer()): ?>
<li><a href="/unimarket/customer/products/browse.php"><i class="fas fa-search"></i> Browse</a></li>
<li><a href="/unimarket/customer/cart.php"><i class="fas fa-shopping-cart"></i> Cart</a></li>
<li><a href="/unimarket/customer/profile.php"><i class="fas fa-user"></i> Profile</a></li>
<?php else: ?>
<li><a href="/unimarket/owner/dashboard.php"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li>
<li><a href="/unimarket/owner/products/list.php"><i class="fas fa-box-open"></i> Products</a></li>
<?php endif; ?>
<li><a href="/unimarket/auth/logout.php"><i class="fas fa-sign-out-alt"></i> Logout</a></li>
<?php else: ?>
<li><a href="/unimarket/index.php"><i class="fas fa-home"></i> Home</a></li>
<li><a href="/unimarket/auth/login.php"><i class="fas fa-sign-in-alt"></i> Login</a></li>
<li><a href="/unimarket/auth/register.php"><i class="fas fa-user-plus"></i> Register</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="/unimarket/customer/products/browse.php"><i class="fas fa-search"></i> Browse</a></li>
<li><a href="/unimarket/customer/cart.php"><i class="fas fa-shopping-cart"></i> Cart</a></li>
<li><a href="/unimarket/customer/profile.php"><i class="fas fa-user"></i> Profile</a></li>
<?php else: ?>
<li><a href="/unimarket/owner/dashboard.php"><i class="fas fa-tachometer-alt"></i> Dashboard</a></li>
<li><a href="/unimarket/owner/products/list.php"><i class="fas fa-box-open"></i> Products</a></li>
<?php endif; ?>
<li><a href="/unimarket/auth/logout.php"><i class="fas fa-sign-out-alt"></i> Logout</a></li>
</ul>
</div>
</div>
<script>
document.querySelector('.mobile-menu-toggle').addEventListener('click', function() {
const menu = document.getElementById('mobileMenu');
menu.style.display = menu.style.display === 'block' ? 'none' : 'block';
});
</script>
<?php endif; ?>
<main class="container">
+195
View File
@@ -0,0 +1,195 @@
<?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="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<style>
.hero {
background-color: var(--primary-color);
color: var(--light-text);
padding: 80px 0;
text-align: center;
margin-bottom: 40px;
}
.hero h1 {
font-size: 3rem;
margin-bottom: 20px;
}
.hero p {
font-size: 1.2rem;
max-width: 800px;
margin: 0 auto 30px;
}
.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>Your university's premier marketplace for buying and selling products within the campus community.</p>
<?php if (!isLoggedIn()): ?>
<div>
<a href="/unimarket/auth/register.php" class="btn" style="margin-right: 10px;">Join Now</a>
<a href="/unimarket/auth/login.php" class="btn btn-secondary">Sign In</a>
</div>
<?php else: ?>
<div>
<?php if (isCustomer()): ?>
<a href="/unimarket/customer/products/browse.php" class="btn">Browse Products</a>
<?php else: ?>
<a href="/unimarket/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="/unimarket/assets/images/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>';
}
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 '<form action="/unimarket/customer/cart.php" method="POST" style="display: flex;">';
echo '<input type="hidden" name="product_id" value="'.$product['product_id'].'">';
echo '<a style="display: flex;" href="/unimarket/customer/products/browse.php"><input type="number" name="quantity" value="1" min="1" style="width: 60px; margin-right: 10px;"></a>';
echo '<button type="submit" name="add_to_cart" class="btn" style="padding: 8px 15px;">Add to Cart</button>';
echo '</form>';
} else {
echo '<a href="/unimarket/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="/unimarket/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>
<?php if (!isLoggedIn()): ?>
<a href="/unimarket/auth/register.php" class="btn">Get Started</a>
<?php else: ?>
<?php if (isCustomer()): ?>
<a href="/unimarket/customer/products/browse.php" class="btn">Browse Products</a>
<?php else: ?>
<a href="/unimarket/owner/products/add.php" class="btn">Add New Product</a>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
<?php include 'includes/footer.php'; ?>
</body>
</html>
+112
View File
@@ -0,0 +1,112 @@
<?php
require_once '../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotOwner();
require_once '../config/database.php';
// Get owner's products count
$stmt = $pdo->prepare("SELECT COUNT(*) FROM products WHERE owner_id = ?");
$stmt->execute([$_SESSION['user_id']]);
$products_count = $stmt->fetchColumn();
// Get pending orders count
$stmt = $pdo->prepare("SELECT COUNT(*) FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
WHERE p.owner_id = ? AND o.status = 'pending'");
$stmt->execute([$_SESSION['user_id']]);
$pending_orders_count = $stmt->fetchColumn();
// Get recent orders
$stmt = $pdo->prepare("SELECT o.order_id, o.order_date, o.total_amount, o.status, u.username
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
JOIN users u ON o.customer_id = u.user_id
WHERE p.owner_id = ?
GROUP BY o.order_id
ORDER BY o.order_date DESC
LIMIT 5");
$stmt->execute([$_SESSION['user_id']]);
$recent_orders = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Owner Dashboard - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<style>
#order-number{
text-decoration: none;
}
#order-number:hover{
color: green;
text-decoration: underline;
}
</style>
</head>
<body>
<?php include '../includes/header.php'; ?>
<div class="container dashboard-container">
<div class="sidebar">
<h3>Owner Menu</h3>
<ul>
<li><a href="/unimarket/owner/dashboard.php" class="active">Dashboard</a></li>
<li><a href="/unimarket/owner/products/list.php">Products</a></li>
<li><a href="/unimarket/owner/products/add.php">Add Product</a></li>
<li><a href="/unimarket/owner/orders/list.php">Orders</a></li>
<li><a href="/unimarket/auth/logout.php">Logout</a></li>
</ul>
</div>
<div class="main-content">
<h1>Dashboard</h1>
<div class="card-grid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; margin: 20px 0;">
<div class="card">
<h3>Products</h3>
<p style="font-size: 24px; font-weight: bold; color: var(--primary-color);"><?php echo $products_count; ?></p>
</div>
<div class="card">
<h3>Pending Orders</h3>
<p style="font-size: 24px; font-weight: bold; color: var(--primary-color);"><?php echo $pending_orders_count; ?></p>
</div>
</div>
<h2>Recent Orders</h2>
<table class="table">
<thead>
<tr>
<th>Order ID</th>
<th>Customer</th>
<th>Date</th>
<th>Amount</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<?php foreach ($recent_orders as $order): ?>
<tr>
<td><a id="order-number" href="/unimarket/owner/orders/list.php?order_id=<?php echo $order['order_id']; ?>">#<?php echo $order['order_id']; ?></a></td>
<td><?php echo htmlspecialchars($order['username']); ?></td>
<td><?php echo date('M d, Y', strtotime($order['order_date'])); ?></td>
<td>₱<?php echo number_format($order['total_amount'], 2); ?></td>
<td><span class="status-badge"><?php echo ucfirst(str_replace('_', ' ', $order['status'])); ?></span></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php include '../includes/footer.php'; ?>
</body>
</html>
+194
View File
@@ -0,0 +1,194 @@
<?php
require_once '../../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotOwner();
require_once '../../config/database.php';
// Get all orders with customer info for products owned by this owner
$stmt = $pdo->prepare("
SELECT o.order_id, o.order_date, o.total_amount, o.status, o.pickup_schedule,
u.username AS customer_username, u.first_name, u.last_name
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
JOIN users u ON o.customer_id = u.user_id
WHERE p.owner_id = ?
GROUP BY o.order_id
ORDER BY o.order_date DESC
");
$stmt->execute([$_SESSION['user_id']]);
$orders = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Manage Orders - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.orders-container {
margin-top: 30px;
}
.orders-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.orders-table th, .orders-table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #eee;
}
.orders-table th {
background-color: #f5f5f5;
font-weight: 600;
}
.order-status {
display: inline-block;
padding: 5px 10px;
border-radius: 4px;
font-size: 0.9rem;
font-weight: 500;
}
.status-pending {
background-color: #fff3cd;
color: #856404;
}
.status-processing {
background-color: #cce5ff;
color: #004085;
}
.status-ready {
background-color: #d4edda;
color: #155724;
}
.status-completed {
background-color: #e2e3e5;
color: #383d41;
}
.status-cancelled {
background-color: #f8d7da;
color: #721c24;
}
.action-link {
color: var(--primary-color);
text-decoration: none;
margin-right: 10px;
}
.action-link:hover {
text-decoration: underline;
}
.empty-orders {
text-align: center;
padding: 50px;
background-color: #f9f9f9;
border-radius: 8px;
}
@media (max-width: 768px) {
.orders-table {
display: block;
overflow-x: auto;
}
}
</style>
</head>
<body>
<?php include '../../includes/header.php'; ?>
<div class="container orders-container">
<h1>Manage Orders</h1>
<?php if (empty($orders)): ?>
<div class="empty-orders card">
<i class="fas fa-box-open" style="font-size: 3em; color: #ccc; margin-bottom: 20px;"></i>
<h3>No orders yet</h3>
<p>Orders for your products will appear here</p>
</div>
<?php else: ?>
<table class="orders-table">
<thead>
<tr>
<th>Order #</th>
<th>Customer</th>
<th>Date</th>
<th>Total</th>
<th>Status</th>
<th>Pickup</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $order): ?>
<tr>
<td>#<?php echo $order['order_id']; ?></td>
<td><?php echo htmlspecialchars($order['first_name'] . ' ' . $order['last_name']); ?></td>
<td><?php echo date('M j, Y', strtotime($order['order_date'])); ?></td>
<td>₱<?php echo number_format($order['total_amount'], 2); ?></td>
<td>
<?php
$status_class = '';
switch ($order['status']) {
case 'pending':
$status_class = 'status-pending';
break;
case 'processing':
$status_class = 'status-processing';
break;
case 'ready_for_pickup':
$status_class = 'status-ready';
break;
case 'completed':
$status_class = 'status-completed';
break;
case 'cancelled':
$status_class = 'status-cancelled';
break;
}
?>
<span class="order-status <?php echo $status_class; ?>">
<?php echo ucfirst(str_replace('_', ' ', $order['status'])); ?>
</span>
</td>
<td>
<?php if ($order['pickup_schedule']): ?>
<?php echo date('M j, Y', strtotime($order['pickup_schedule'])); ?>
<?php else: ?>
Not scheduled
<?php endif; ?>
</td>
<td>
<a href="/unimarket/owner/orders/schedule_pickup.php?order_id=<?php echo $order['order_id']; ?>" class="action-link">
<i class="fas fa-calendar-alt"></i> Schedule
</a>
<a href="/unimarket/owner/orders/view.php?order_id=<?php echo $order['order_id']; ?>" class="action-link">
<i class="fas fa-eye"></i> View
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
<?php include '../../includes/footer.php'; ?>
</body>
</html>
+253
View File
@@ -0,0 +1,253 @@
<?php
require_once '../../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotOwner();
require_once '../../config/database.php';
// Check if order ID is provided
if (!isset($_GET['order_id'])) {
header("Location: /unimarket/owner/orders/list.php");
exit();
}
$order_id = (int)$_GET['order_id'];
// Verify order contains owner's products
$stmt = $pdo->prepare("
SELECT o.order_id
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
WHERE o.order_id = ? AND p.owner_id = ?
LIMIT 1
");
$stmt->execute([$order_id, $_SESSION['user_id']]);
$valid_order = $stmt->fetch();
if (!$valid_order) {
header("Location: /unimarket/owner/orders/list.php");
exit();
}
// Get order details
$stmt = $pdo->prepare("
SELECT o.*, u.username, u.first_name, u.last_name
FROM orders o
JOIN users u ON o.customer_id = u.user_id
WHERE o.order_id = ?
");
$stmt->execute([$order_id]);
$order = $stmt->fetch();
// Handle form submission
$success_message = '';
$error_message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pickup_date = $_POST['pickup_date'];
$pickup_time = $_POST['pickup_time'];
if (empty($pickup_date) || empty($pickup_time)) {
$error_message = 'Please select both date and time.';
} else {
$pickup_datetime = date('Y-m-d H:i:s', strtotime("$pickup_date $pickup_time"));
try {
$stmt = $pdo->prepare("UPDATE orders SET pickup_schedule = ?, status = 'ready_for_pickup' WHERE order_id = ?");
$stmt->execute([$pickup_datetime, $order_id]);
$success_message = 'Pickup scheduled successfully!';
$order['pickup_schedule'] = $pickup_datetime;
$order['status'] = 'ready_for_pickup';
} catch (PDOException $e) {
$error_message = 'Failed to schedule pickup. Please try again.';
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Schedule Pickup - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<style>
.schedule-container {
margin-top: 30px;
}
.order-card {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
margin-bottom: 30px;
}
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.customer-info {
margin-bottom: 20px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
}
.form-group input, .form-group select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
}
.datetime-fields {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
}
.btn-submit {
background-color: var(--primary-color);
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s;
}
.btn-submit:hover {
background-color: var(--primary-dark);
}
.back-link {
display: inline-block;
margin-bottom: 20px;
color: var(--primary-color);
text-decoration: none;
}
.back-link:hover {
text-decoration: underline;
}
@media (max-width: 768px) {
.datetime-fields {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<?php include '../../includes/header.php'; ?>
<div class="container schedule-container">
<a href="/unimarket/owner/orders/list.php" class="back-link">
<i class="fas fa-arrow-left"></i> Back to Orders
</a>
<h1>Schedule Pickup</h1>
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo $success_message; ?></div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="alert alert-error"><?php echo $error_message; ?></div>
<?php endif; ?>
<div class="order-card card">
<div class="order-header">
<h2>Order #<?php echo $order['order_id']; ?></h2>
<div>
<strong>Order Date:</strong> <?php echo date('M j, Y', strtotime($order['order_date'])); ?>
</div>
</div>
<div class="customer-info">
<h3>Customer Information</h3>
<p><strong>Name:</strong> <?php echo htmlspecialchars($order['first_name'] . ' ' . $order['last_name']); ?></p>
<p><strong>Username:</strong> <?php echo htmlspecialchars($order['username']); ?></p>
</div>
<form method="POST">
<div class="form-group">
<label>Current Pickup Schedule</label>
<p>
<?php if ($order['pickup_schedule']): ?>
<?php echo date('F j, Y g:i A', strtotime($order['pickup_schedule'])); ?>
<?php else: ?>
Not scheduled yet
<?php endif; ?>
</p>
</div>
<div class="form-group">
<label for="pickup_date">Pickup Date*</label>
<input type="date" id="pickup_date" name="pickup_date" required
min="<?php echo date('Y-m-d'); ?>">
</div>
<div class="form-group">
<label for="pickup_time">Pickup Time*</label>
<select id="pickup_time" name="pickup_time" required>
<option value="">Select a time</option>
<?php
// Generate time slots from 9AM to 5PM in 30-minute increments
$start = strtotime('09:00');
$end = strtotime('17:00');
for ($time = $start; $time <= $end; $time += 1800) {
$time_value = date('H:i', $time);
$time_display = date('g:i A', $time);
echo "<option value=\"$time_value\">$time_display</option>";
}
?>
</select>
</div>
<button type="submit" class="btn-submit">
<i class="fas fa-calendar-check"></i> Schedule Pickup
</button>
</form>
</div>
</div>
<?php include '../../includes/footer.php'; ?>
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script>
// Initialize date picker
flatpickr("#pickup_date", {
minDate: "today",
dateFormat: "Y-m-d",
disable: [
function(date) {
// Disable weekends
return (date.getDay() === 0 || date.getDay() === 6);
}
]
});
</script>
</body>
</html>
+437
View File
@@ -0,0 +1,437 @@
<?php
require_once '../../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotOwner();
require_once '../../config/database.php';
// Check if order ID is provided
if (!isset($_GET['order_id'])) {
header("Location: /unimarket/owner/orders/list.php");
exit();
}
$order_id = (int)$_GET['order_id'];
// Verify order contains owner's products
$stmt = $pdo->prepare("
SELECT o.order_id
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
WHERE o.order_id = ? AND p.owner_id = ?
LIMIT 1
");
$stmt->execute([$order_id, $_SESSION['user_id']]);
$valid_order = $stmt->fetch();
if (!$valid_order) {
header("Location: /unimarket/owner/orders/list.php");
exit();
}
// Get order details with proper null checks
$stmt = $pdo->prepare("
SELECT o.*,
COALESCE(u.username, 'N/A') AS username,
COALESCE(u.first_name, '') AS first_name,
COALESCE(u.last_name, '') AS last_name,
COALESCE(u.email, 'Not provided') AS email,
COALESCE(u.phone, 'Not provided') AS phone
FROM orders o
LEFT JOIN users u ON o.customer_id = u.user_id
WHERE o.order_id = ?
");
$stmt->execute([$order_id]);
$order = $stmt->fetch();
// Get order items for this owner's products
$stmt = $pdo->prepare("
SELECT oi.*, p.name, p.price, p.image_path
FROM order_items oi
JOIN products p ON oi.product_id = p.product_id
WHERE oi.order_id = ? AND p.owner_id = ?
");
$stmt->execute([$order_id, $_SESSION['user_id']]);
$order_items = $stmt->fetchAll();
// Calculate subtotal for owner's products
$subtotal = 0;
foreach ($order_items as $item) {
$subtotal += $item['price'] * $item['quantity'];
}
// Handle status update
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_status'])) {
$new_status = $_POST['status'];
try {
$stmt = $pdo->prepare("UPDATE orders SET status = ? WHERE order_id = ?");
$stmt->execute([$new_status, $order_id]);
// Refresh order data
$stmt = $pdo->prepare("
SELECT o.*,
COALESCE(u.username, 'N/A') AS username,
COALESCE(u.first_name, '') AS first_name,
COALESCE(u.last_name, '') AS last_name,
COALESCE(u.email, 'Not provided') AS email,
COALESCE(u.phone, 'Not provided') AS phone
FROM orders o
LEFT JOIN users u ON o.customer_id = u.user_id
WHERE o.order_id = ?
");
$stmt->execute([$order_id]);
$order = $stmt->fetch();
$success_message = 'Order status updated successfully!';
} catch (PDOException $e) {
$error_message = 'Failed to update order status. Please try again.';
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Order #<?php echo $order_id; ?> - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.order-detail-container {
margin-top: 30px;
}
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
}
.order-card {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
margin-bottom: 30px;
}
.customer-info {
margin-bottom: 30px;
}
.info-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-top: 15px;
}
.info-item {
margin-bottom: 10px;
}
.info-label {
font-weight: 600;
color: #666;
margin-bottom: 5px;
}
.info-value {
font-size: 1.1rem;
}
.order-status {
display: inline-block;
padding: 8px 15px;
border-radius: 4px;
font-weight: 500;
}
.status-pending {
background-color: #fff3cd;
color: #856404;
}
.status-processing {
background-color: #cce5ff;
color: #004085;
}
.status-ready {
background-color: #d4edda;
color: #155724;
}
.status-completed {
background-color: #e2e3e5;
color: #383d41;
}
.status-cancelled {
background-color: #f8d7da;
color: #721c24;
}
.items-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.items-table th, .items-table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #eee;
}
.items-table th {
background-color: #f5f5f5;
font-weight: 600;
}
.product-cell {
display: flex;
align-items: center;
}
.product-image {
width: 60px;
height: 60px;
margin-right: 15px;
background-color: #f9f9f9;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.product-image img {
max-width: 100%;
max-height: 100%;
}
.order-total {
text-align: right;
margin-top: 20px;
font-size: 1.2rem;
font-weight: 600;
}
.back-link {
display: inline-block;
margin-bottom: 20px;
color: var(--primary-color);
text-decoration: none;
}
.back-link:hover {
text-decoration: underline;
}
.status-form {
display: flex;
gap: 10px;
align-items: center;
margin-top: 20px;
}
.status-form select {
padding: 8px;
border-radius: 4px;
border: 1px solid #ddd;
}
@media (max-width: 768px) {
.items-table {
display: block;
overflow-x: auto;
}
.product-cell {
flex-direction: column;
align-items: flex-start;
}
.product-image {
margin-bottom: 10px;
}
.status-form {
flex-direction: column;
align-items: flex-start;
}
}
</style>
</head>
<body>
<?php include '../../includes/header.php'; ?>
<div class="container order-detail-container">
<a href="/unimarket/owner/orders/list.php" class="back-link">
<i class="fas fa-arrow-left"></i> Back to Orders
</a>
<div class="order-header">
<h1>Order #<?php echo $order_id; ?></h1>
<?php
$status_class = '';
switch ($order['status'] ?? '') {
case 'pending':
$status_class = 'status-pending';
break;
case 'processing':
$status_class = 'status-processing';
break;
case 'ready_for_pickup':
$status_class = 'status-ready';
break;
case 'completed':
$status_class = 'status-completed';
break;
case 'cancelled':
$status_class = 'status-cancelled';
break;
default:
$status_class = 'status-pending';
}
?>
<span class="order-status <?php echo $status_class; ?>">
<?php echo ucfirst(str_replace('_', ' ', $order['status'] ?? 'pending')); ?>
</span>
</div>
<?php if (isset($success_message)): ?>
<div class="alert alert-success"><?php echo $success_message; ?></div>
<?php endif; ?>
<?php if (isset($error_message)): ?>
<div class="alert alert-error"><?php echo $error_message; ?></div>
<?php endif; ?>
<div class="order-card card">
<h2>Customer Information</h2>
<div class="customer-info">
<div class="info-grid">
<div class="info-item">
<div class="info-label">Name</div>
<div class="info-value">
<?php
$first_name = $order['first_name'] ?? '';
$last_name = $order['last_name'] ?? '';
echo htmlspecialchars(trim("$first_name $last_name") ?: 'Not provided');
?>
</div>
</div>
<div class="info-item">
<div class="info-label">Username</div>
<div class="info-value"><?php echo htmlspecialchars($order['username'] ?? 'N/A'); ?></div>
</div>
<div class="info-item">
<div class="info-label">Email</div>
<div class="info-value"><?php echo htmlspecialchars($order['email'] ?? 'Not provided'); ?></div>
</div>
<div class="info-item">
<div class="info-label">Phone</div>
<div class="info-value"><?php echo htmlspecialchars($order['phone'] ?? 'Not provided'); ?></div>
</div>
</div>
</div>
<h2>Order Information</h2>
<div class="info-grid">
<div class="info-item">
<div class="info-label">Order Date</div>
<div class="info-value"><?php echo date('F j, Y g:i A', strtotime($order['order_date'])); ?></div>
</div>
<div class="info-item">
<div class="info-label">Order Status</div>
<div class="info-value">
<span class="order-status <?php echo $status_class; ?>">
<?php echo ucfirst(str_replace('_', ' ', $order['status'])); ?>
</span>
</div>
</div>
<div class="info-item">
<div class="info-label">Pickup Schedule</div>
<div class="info-value">
<?php if ($order['pickup_schedule']): ?>
<?php echo date('F j, Y g:i A', strtotime($order['pickup_schedule'])); ?>
<?php else: ?>
Not scheduled yet
<?php endif; ?>
</div>
</div>
</div>
<form method="POST" class="status-form">
<label for="status">Update Status:</label>
<select name="status" id="status">
<option value="pending" <?php echo $order['status'] === 'pending' ? 'selected' : ''; ?>>Pending</option>
<option value="processing" <?php echo $order['status'] === 'processing' ? 'selected' : ''; ?>>Processing</option>
<option value="ready_for_pickup" <?php echo $order['status'] === 'ready_for_pickup' ? 'selected' : ''; ?>>Ready for Pickup</option>
<option value="completed" <?php echo $order['status'] === 'completed' ? 'selected' : ''; ?>>Completed</option>
<option value="cancelled" <?php echo $order['status'] === 'cancelled' ? 'selected' : ''; ?>>Cancelled</option>
</select>
<button type="submit" name="update_status" class="btn">
<i class="fas fa-save"></i> Update
</button>
</form>
</div>
<div class="order-card card">
<h2>Order Items (Your Products)</h2>
<table class="items-table">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Subtotal</th>
</tr>
</thead>
<tbody>
<?php foreach ($order_items as $item): ?>
<tr>
<td>
<div class="product-cell">
<div class="product-image">
<?php if ($item['image_path']): ?>
<img src="/unimarket/assets/images/products/<?php echo $item['image_path']; ?>" alt="<?php echo htmlspecialchars($item['name']); ?>">
<?php else: ?>
<i class="fas fa-box-open" style="color: #ccc;"></i>
<?php endif; ?>
</div>
<div>
<h4><?php echo htmlspecialchars($item['name']); ?></h4>
</div>
</div>
</td>
<td>$<?php echo number_format($item['price'], 2); ?></td>
<td><?php echo $item['quantity']; ?></td>
<td>$<?php echo number_format($item['price'] * $item['quantity'], 2); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="order-total">
<div style="margin-bottom: 10px;">Subtotal: $<?php echo number_format($subtotal, 2); ?></div>
<div style="font-size: 1.4rem;">Total: $<?php echo number_format($subtotal, 2); ?></div>
</div>
</div>
</div>
<?php include '../../includes/footer.php'; ?>
</body>
</html>
+247
View File
@@ -0,0 +1,247 @@
<?php
require_once '../../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotOwner();
require_once '../../config/database.php';
$error_message = '';
$success_message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name']);
$description = trim($_POST['description']);
$price = trim($_POST['price']);
$category = trim($_POST['category']);
$stock_quantity = (int)$_POST['stock_quantity'];
// Validate inputs
if (empty($name) || empty($description) || empty($price) || empty($stock_quantity)) {
$error_message = 'Please fill in all required fields.';
} elseif (!is_numeric($price) || $price <= 0) {
$error_message = 'Please enter a valid price.';
} elseif ($stock_quantity < 0) {
$error_message = 'Stock quantity cannot be negative.';
} else {
try {
// Handle file upload
$image_path = null;
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
$upload_dir = '../../assets/images/products/';
$file_extension = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
$filename = uniqid() . '.' . $file_extension;
$destination = $upload_dir . $filename;
// Validate image
$allowed_types = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array(strtolower($file_extension), $allowed_types)) {
$error_message = 'Only JPG, JPEG, PNG, and GIF files are allowed.';
} elseif ($_FILES['image']['size'] > 5000000) { // 5MB max
$error_message = 'File size must be less than 5MB.';
} elseif (move_uploaded_file($_FILES['image']['tmp_name'], $destination)) {
$image_path = $filename;
} else {
$error_message = 'Failed to upload image.';
}
}
if (empty($error_message)) {
$pdo->beginTransaction();
$stmt = $pdo->prepare("
INSERT INTO products
(owner_id, name, description, price, category, stock_quantity, image_path)
VALUES (?, ?, ?, ?, ?, ?, ?)
");
$stmt->execute([
$_SESSION['user_id'],
$name,
$description,
$price,
$category,
$stock_quantity,
$image_path
]);
$pdo->commit();
$success_message = 'Product added successfully!';
// Clear form
$name = $description = $price = $category = '';
$stock_quantity = 0;
}
} catch (PDOException $e) {
$pdo->rollBack();
$error_message = 'Failed to add product. Please try again.';
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add Product - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.add-product-container {
margin-top: 30px;
}
.image-upload {
margin-bottom: 20px;
}
.image-preview {
width: 200px;
height: 200px;
background-color: #f5f5f5;
border: 1px dashed #ccc;
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
overflow: hidden;
}
.image-preview.has-image {
border: none;
}
.image-preview img {
max-width: 100%;
max-height: 100%;
}
.default-text {
color: #999;
text-align: center;
padding: 20px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
}
.form-group input,
.form-group textarea,
.form-group select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
}
.form-group textarea {
min-height: 100px;
}
.btn-submit {
background-color: var(--primary-color);
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s;
}
.btn-submit:hover {
background-color: var(--primary-dark);
}
</style>
</head>
<body>
<?php include '../../includes/header.php'; ?>
<div class="container add-product-container">
<h1>Add New Product</h1>
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo $success_message; ?></div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="alert alert-error"><?php echo $error_message; ?></div>
<?php endif; ?>
<form method="POST" enctype="multipart/form-data" class="card">
<div class="form-group image-upload">
<label>Product Image</label>
<input type="file" name="image" id="productImage" accept="image/*">
<div class="image-preview" id="imagePreview">
<div class="default-text">No image selected</div>
</div>
</div>
<div class="form-group">
<label for="name">Product Name*</label>
<input type="text" id="name" name="name" value="<?php echo htmlspecialchars($name ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="description">Description*</label>
<textarea id="description" name="description" required><?php echo htmlspecialchars($description ?? ''); ?></textarea>
</div>
<div class="form-group">
<label for="price">Price*</label>
<input type="number" id="price" name="price" step="0.01" min="0.01" value="<?php echo htmlspecialchars($price ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="category">Category</label>
<input type="text" id="category" name="category" value="<?php echo htmlspecialchars($category ?? ''); ?>">
</div>
<div class="form-group">
<label for="stock_quantity">Stock Quantity*</label>
<input type="number" id="stock_quantity" name="stock_quantity" min="0" value="<?php echo htmlspecialchars($stock_quantity ?? 0); ?>" required>
</div>
<button type="submit" class="btn-submit">Add Product</button>
</form>
</div>
<?php include '../../includes/footer.php'; ?>
<script>
// Image preview functionality
const productImage = document.getElementById('productImage');
const imagePreview = document.getElementById('imagePreview');
const defaultText = imagePreview.querySelector('.default-text');
productImage.addEventListener('change', function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
imagePreview.innerHTML = '';
const img = document.createElement('img');
img.src = e.target.result;
imagePreview.appendChild(img);
imagePreview.classList.add('has-image');
}
reader.readAsDataURL(file);
} else {
imagePreview.innerHTML = '<div class="default-text">No image selected</div>';
imagePreview.classList.remove('has-image');
}
});
</script>
</body>
</html>
+306
View File
@@ -0,0 +1,306 @@
<?php
require_once '../../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotOwner();
require_once '../../config/database.php';
// Check if product ID is provided
if (!isset($_GET['id'])) {
header("Location: /unimarket/owner/products/list.php");
exit();
}
$product_id = (int)$_GET['id'];
// Verify product belongs to current owner
$stmt = $pdo->prepare("SELECT * FROM products WHERE product_id = ? AND owner_id = ?");
$stmt->execute([$product_id, $_SESSION['user_id']]);
$product = $stmt->fetch();
if (!$product) {
header("Location: /unimarket/owner/products/list.php");
exit();
}
$error_message = '';
$success_message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name']);
$description = trim($_POST['description']);
$price = trim($_POST['price']);
$category = trim($_POST['category']);
$stock_quantity = (int)$_POST['stock_quantity'];
// Validate inputs
if (empty($name) || empty($description) || empty($price) || empty($stock_quantity)) {
$error_message = 'Please fill in all required fields.';
} elseif (!is_numeric($price) || $price <= 0) {
$error_message = 'Please enter a valid price.';
} elseif ($stock_quantity < 0) {
$error_message = 'Stock quantity cannot be negative.';
} else {
try {
$pdo->beginTransaction();
// Handle file upload if new image is provided
$image_path = $product['image_path'];
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
$upload_dir = '../../assets/images/products/';
$file_extension = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
$filename = uniqid() . '.' . $file_extension;
$destination = $upload_dir . $filename;
// Validate image
$allowed_types = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array(strtolower($file_extension), $allowed_types)) {
$error_message = 'Only JPG, JPEG, PNG, and GIF files are allowed.';
} elseif ($_FILES['image']['size'] > 5000000) { // 5MB max
$error_message = 'File size must be less than 5MB.';
} else {
// Delete old image if it exists
if ($image_path && file_exists($upload_dir . $image_path)) {
unlink($upload_dir . $image_path);
}
if (move_uploaded_file($_FILES['image']['tmp_name'], $destination)) {
$image_path = $filename;
} else {
$error_message = 'Failed to upload image.';
}
}
}
if (empty($error_message)) {
$stmt = $pdo->prepare("
UPDATE products
SET name = ?, description = ?, price = ?, category = ?, stock_quantity = ?, image_path = ?
WHERE product_id = ?
");
$stmt->execute([
$name,
$description,
$price,
$category,
$stock_quantity,
$image_path,
$product_id
]);
$pdo->commit();
$success_message = 'Product updated successfully!';
// Refresh product data
$stmt = $pdo->prepare("SELECT * FROM products WHERE product_id = ?");
$stmt->execute([$product_id]);
$product = $stmt->fetch();
}
} catch (PDOException $e) {
$pdo->rollBack();
$error_message = 'Failed to update product. Please try again.';
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Edit Product - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.edit-product-container {
margin-top: 30px;
}
.image-upload {
margin-bottom: 20px;
}
.image-preview {
width: 200px;
height: 200px;
background-color: #f5f5f5;
border: 1px dashed #ccc;
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
overflow: hidden;
}
.image-preview.has-image {
border: none;
}
.image-preview img {
max-width: 100%;
max-height: 100%;
}
.default-text {
color: #999;
text-align: center;
padding: 20px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
}
.form-group input,
.form-group textarea,
.form-group select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
}
.form-group textarea {
min-height: 100px;
}
.btn-submit {
background-color: var(--primary-color);
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s;
}
.btn-submit:hover {
background-color: var(--primary-dark);
}
.btn-delete {
background-color: #dc3545;
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s;
margin-left: 10px;
}
.btn-delete:hover {
background-color: #c82333;
}
.button-group {
display: flex;
justify-content: space-between;
}
</style>
</head>
<body>
<?php include '../../includes/header.php'; ?>
<div class="container edit-product-container">
<h1>Edit Product</h1>
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo $success_message; ?></div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="alert alert-error"><?php echo $error_message; ?></div>
<?php endif; ?>
<form method="POST" enctype="multipart/form-data" class="card">
<div class="form-group image-upload">
<label>Product Image</label>
<input type="file" name="image" id="productImage" accept="image/*">
<div class="image-preview" id="imagePreview">
<?php if ($product['image_path']): ?>
<img src="/unimarket/assets/images/products/<?php echo $product['image_path']; ?>" alt="<?php echo htmlspecialchars($product['name']); ?>">
<?php else: ?>
<div class="default-text">No image selected</div>
<?php endif; ?>
</div>
</div>
<div class="form-group">
<label for="name">Product Name*</label>
<input type="text" id="name" name="name" value="<?php echo htmlspecialchars($product['name']); ?>" required>
</div>
<div class="form-group">
<label for="description">Description*</label>
<textarea id="description" name="description" required><?php echo htmlspecialchars($product['description']); ?></textarea>
</div>
<div class="form-group">
<label for="price">Price*</label>
<input type="number" id="price" name="price" step="0.01" min="0.01" value="<?php echo htmlspecialchars($product['price']); ?>" required>
</div>
<div class="form-group">
<label for="category">Category</label>
<input type="text" id="category" name="category" value="<?php echo htmlspecialchars($product['category']); ?>">
</div>
<div class="form-group">
<label for="stock_quantity">Stock Quantity*</label>
<input type="number" id="stock_quantity" name="stock_quantity" min="0" value="<?php echo htmlspecialchars($product['stock_quantity']); ?>" required>
</div>
<div class="button-group">
<button type="submit" class="btn-submit">Update Product</button>
<a href="/unimarket/owner/products/delete.php?id=<?php echo $product_id; ?>" class="btn-delete" onclick="return confirm('Are you sure you want to delete this product?')">
<i class="fas fa-trash"></i> Delete
</a>
</div>
</form>
</div>
<?php include '../../includes/footer.php'; ?>
<script>
// Image preview functionality
const productImage = document.getElementById('productImage');
const imagePreview = document.getElementById('imagePreview');
productImage.addEventListener('change', function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
imagePreview.innerHTML = '';
const img = document.createElement('img');
img.src = e.target.result;
imagePreview.appendChild(img);
imagePreview.classList.add('has-image');
}
reader.readAsDataURL(file);
} else {
<?php if ($product['image_path']): ?>
imagePreview.innerHTML = '<img src="/unimarket/assets/images/products/<?php echo $product['image_path']; ?>" alt="<?php echo htmlspecialchars($product['name']); ?>">';
<?php else: ?>
imagePreview.innerHTML = '<div class="default-text">No image selected</div>';
imagePreview.classList.remove('has-image');
<?php endif; ?>
}
});
</script>
</body>
</html>
+181
View File
@@ -0,0 +1,181 @@
<?php
require_once '../../includes/auth_functions.php';
redirectIfNotLoggedIn();
redirectIfNotOwner();
require_once '../../config/database.php';
// Get all products for this owner
$stmt = $pdo->prepare("SELECT * FROM products WHERE owner_id = ? ORDER BY created_at DESC");
$stmt->execute([$_SESSION['user_id']]);
$products = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Products - UniMarket</title>
<link rel="stylesheet" href="/unimarket/assets/css/style.css">
<link rel="stylesheet" href="/unimarket/assets/css/responsive.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
.products-container {
margin-top: 30px;
}
.products-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
}
.products-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.products-table th, .products-table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #eee;
}
.products-table th {
background-color: #f5f5f5;
font-weight: 600;
}
.product-cell {
display: flex;
align-items: center;
}
.product-image {
width: 60px;
height: 60px;
margin-right: 15px;
background-color: #f9f9f9;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.product-image img {
max-width: 100%;
max-height: 100%;
}
.stock-low {
color: #e53935;
}
.action-link {
color: var(--primary-color);
text-decoration: none;
margin-right: 10px;
}
.action-link:hover {
text-decoration: underline;
}
.empty-products {
text-align: center;
padding: 50px;
background-color: #f9f9f9;
border-radius: 8px;
}
@media (max-width: 768px) {
.products-table {
display: block;
overflow-x: auto;
}
.product-cell {
flex-direction: column;
align-items: flex-start;
}
.product-image {
margin-bottom: 10px;
}
}
</style>
</head>
<body>
<?php include '../../includes/header.php'; ?>
<div class="container products-container">
<div class="products-header">
<h1>My Products</h1>
<a href="/unimarket/owner/products/add.php" class="btn">
<i class="fas fa-plus"></i> Add Product
</a>
</div>
<?php if (empty($products)): ?>
<div class="empty-products card">
<i class="fas fa-box-open" style="font-size: 3em; color: #ccc; margin-bottom: 20px;"></i>
<h3>You don't have any products yet</h3>
<p>Add your first product to start selling</p>
<a href="/unimarket/owner/products/add.php" class="btn">Add Product</a>
</div>
<?php else: ?>
<table class="products-table">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Stock</th>
<th>Category</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($products as $product): ?>
<tr>
<td>
<div class="product-cell">
<div class="product-image">
<?php if ($product['image_path']): ?>
<img src="/unimarket/assets/images/products/<?php echo $product['image_path']; ?>" alt="<?php echo htmlspecialchars($product['name']); ?>">
<?php else: ?>
<i class="fas fa-box-open" style="color: #ccc;"></i>
<?php endif; ?>
</div>
<div>
<h4><?php echo htmlspecialchars($product['name']); ?></h4>
<p><?php echo substr(htmlspecialchars($product['description']), 0, 50); ?>...</p>
</div>
</div>
</td>
<td>₱<?php echo number_format($product['price'], 2); ?></td>
<td class="<?php echo $product['stock_quantity'] < 5 ? 'stock-low' : ''; ?>">
<?php echo $product['stock_quantity']; ?>
</td>
<td><?php echo htmlspecialchars($product['category']); ?></td>
<td>
<a href="/unimarket/owner/products/edit.php?id=<?php echo $product['product_id']; ?>" class="action-link">
<i class="fas fa-edit"></i> Edit
</a>
<a href="/unimarket/owner/products/delete.php?id=<?php echo $product['product_id']; ?>" class="action-link" onclick="return confirm('Are you sure you want to delete this product?')">
<i class="fas fa-trash"></i> Delete
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
<?php include '../../includes/footer.php'; ?>
</body>
</html>
+2
View File
@@ -0,0 +1,2 @@
crischarles - passwordword
crischarlesvendor - password123
+267
View File
@@ -0,0 +1,267 @@
-- phpMyAdmin SQL Dump
-- version 5.2.1
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Generation Time: May 09, 2025 at 03:20 PM
-- Server version: 10.4.32-MariaDB
-- PHP Version: 8.2.12
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `unimarket`
--
-- --------------------------------------------------------
--
-- Table structure for table `cart`
--
CREATE TABLE `cart` (
`cart_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
--
-- Dumping data for table `cart`
--
INSERT INTO `cart` (`cart_id`, `user_id`, `created_at`) VALUES
(1, 1, '2025-05-09 10:11:49');
-- --------------------------------------------------------
--
-- Table structure for table `cart_items`
--
CREATE TABLE `cart_items` (
`cart_item_id` int(11) NOT NULL,
`cart_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`quantity` int(11) NOT NULL DEFAULT 1,
`added_at` timestamp NOT NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- --------------------------------------------------------
--
-- Table structure for table `orders`
--
CREATE TABLE `orders` (
`order_id` int(11) NOT NULL,
`customer_id` int(11) NOT NULL,
`order_date` timestamp NOT NULL DEFAULT current_timestamp(),
`total_amount` decimal(10,2) NOT NULL,
`status` enum('pending','processing','ready_for_pickup','completed','cancelled') DEFAULT 'pending',
`pickup_schedule` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- --------------------------------------------------------
--
-- Table structure for table `order_items`
--
CREATE TABLE `order_items` (
`item_id` int(11) NOT NULL,
`order_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`quantity` int(11) NOT NULL,
`price` decimal(10,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- --------------------------------------------------------
--
-- Table structure for table `products`
--
CREATE TABLE `products` (
`product_id` int(11) NOT NULL,
`owner_id` int(11) NOT NULL,
`name` varchar(100) NOT NULL,
`description` text DEFAULT NULL,
`price` decimal(10,2) NOT NULL,
`category` varchar(50) DEFAULT NULL,
`stock_quantity` int(11) NOT NULL DEFAULT 0,
`image_path` varchar(255) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
--
-- Dumping data for table `products`
--
INSERT INTO `products` (`product_id`, `owner_id`, `name`, `description`, `price`, `category`, `stock_quantity`, `image_path`, `created_at`, `updated_at`) VALUES
(1, 2, 'GARCIA', 'Nawawalan ng ID', 100.00, 'ID', 1, '681df946dcc9a.jpg', '2025-05-09 12:47:02', '2025-05-09 12:47:02');
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`user_id` int(11) NOT NULL,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(100) NOT NULL,
`role` enum('customer','owner') NOT NULL,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`phone` varchar(20) DEFAULT NULL,
`university_id` varchar(20) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`user_id`, `username`, `password`, `email`, `role`, `first_name`, `last_name`, `phone`, `university_id`, `created_at`) VALUES
(1, 'crischarles', '$2y$10$8ANjJj59KNpM1ToMniyamuWskxnnAj45nXZJSjhL8kKmsnHZDWXue', 'crischarlesgarcia345@gmail.com', 'customer', 'Cris Charles', 'Garcia', '09914970689', '23-10824', '2025-05-09 10:11:49'),
(2, 'crischarlesvendor', '$2y$10$f0ObqNbNpxNI2D1.xy/nguRjFlrnQyjS9pTzzLORL3TSmC2h4rXs.', 'crischarlesgarcia3456@gmail.com', 'owner', 'Cris Charles', 'Garcia', '09914970689', '23-10824', '2025-05-09 11:50:03');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `cart`
--
ALTER TABLE `cart`
ADD PRIMARY KEY (`cart_id`),
ADD UNIQUE KEY `user_id` (`user_id`);
--
-- Indexes for table `cart_items`
--
ALTER TABLE `cart_items`
ADD PRIMARY KEY (`cart_item_id`),
ADD UNIQUE KEY `cart_id` (`cart_id`,`product_id`),
ADD KEY `product_id` (`product_id`);
--
-- Indexes for table `orders`
--
ALTER TABLE `orders`
ADD PRIMARY KEY (`order_id`),
ADD KEY `customer_id` (`customer_id`);
--
-- Indexes for table `order_items`
--
ALTER TABLE `order_items`
ADD PRIMARY KEY (`item_id`),
ADD KEY `order_id` (`order_id`),
ADD KEY `product_id` (`product_id`);
--
-- Indexes for table `products`
--
ALTER TABLE `products`
ADD PRIMARY KEY (`product_id`),
ADD KEY `owner_id` (`owner_id`);
--
-- Indexes for table `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`user_id`),
ADD UNIQUE KEY `username` (`username`),
ADD UNIQUE KEY `email` (`email`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `cart`
--
ALTER TABLE `cart`
MODIFY `cart_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT for table `cart_items`
--
ALTER TABLE `cart_items`
MODIFY `cart_item_id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT for table `orders`
--
ALTER TABLE `orders`
MODIFY `order_id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT for table `order_items`
--
ALTER TABLE `order_items`
MODIFY `item_id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT for table `products`
--
ALTER TABLE `products`
MODIFY `product_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `cart`
--
ALTER TABLE `cart`
ADD CONSTRAINT `cart_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`);
--
-- Constraints for table `cart_items`
--
ALTER TABLE `cart_items`
ADD CONSTRAINT `cart_items_ibfk_1` FOREIGN KEY (`cart_id`) REFERENCES `cart` (`cart_id`),
ADD CONSTRAINT `cart_items_ibfk_2` FOREIGN KEY (`product_id`) REFERENCES `products` (`product_id`);
--
-- Constraints for table `orders`
--
ALTER TABLE `orders`
ADD CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`customer_id`) REFERENCES `users` (`user_id`);
--
-- Constraints for table `order_items`
--
ALTER TABLE `order_items`
ADD CONSTRAINT `order_items_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `orders` (`order_id`),
ADD CONSTRAINT `order_items_ibfk_2` FOREIGN KEY (`product_id`) REFERENCES `products` (`product_id`);
--
-- Constraints for table `products`
--
ALTER TABLE `products`
ADD CONSTRAINT `products_ibfk_1` FOREIGN KEY (`owner_id`) REFERENCES `users` (`user_id`);
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;