Add files via upload
This commit is contained in:
29 files changed
+5979
No files matched your search
@@ -0,0 +1,4 @@
|
||||
This repository is for IPT222 project.
|
||||
|
||||
Members:
|
||||
Babiano, De Vera, De Chavez, Garcia, Hernandez, and Jordan
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 |
@@ -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);
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
@@ -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>
|
||||
@@ -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());
|
||||
}
|
||||
?>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
?>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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>© <?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>
|
||||
@@ -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">
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,2 @@
|
||||
crischarles - passwordword
|
||||
crischarlesvendor - password123
|
||||
+267
@@ -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 */;
|
||||
Reference in new issue
Block a user