[
'page_title' => 'Διαχείριση Προϊόντων - Hockey CMS',
'header_title' => 'Διαχείριση Προϊόντων',
'attr_cat_title' => 'Χαρακτηριστικά Κατηγορίας',
'attr_placeholder' => 'π.χ. συμπληρώστε τιμή...',
'edit_prod_title' => 'Επεξεργασία Προϊόντος #',
'add_prod_title' => 'Προσθήκη Νέου Προϊόντος',
'prod_title' => 'Τίτλος Προϊόντος *',
'category' => 'Κατηγορία *',
'select_cat' => '-- Επίλεξε --',
'sku' => 'Κωδικός / Αύξων Αριθμός (SKU)',
'price' => 'Τιμή (€) *',
'stock' => 'Απόθεμα',
'status' => 'Κατάσταση',
'status_avail' => 'Διαθέσιμο (Available)',
'status_sold' => 'Πουλήθηκε (Sold)',
'status_hidden' => 'Απόκρυψη',
'seller_assign' => 'Ιδιοκτήτης / Πωλητής *',
'tags' => 'Ετικέτες Αναζήτησης (Tags)',
'tags_placeholder' => 'Πληκτρολογήστε λέξη και πατήστε Enter...',
'tags_hint' => 'Πατήστε Enter ή Κόμμα (,) για να δημιουργήσετε tag.',
'desc' => 'Περιγραφή',
'photo' => 'Κεντρική Φωτογραφία',
'photo_hint_edit' => '(Αφήστε το κενό αν δεν θέλετε να την αλλάξετε)',
'photo_hint_add' => '(Αυτόματο resize)',
'btn_update' => 'Ενημέρωση',
'btn_add' => 'Προσθήκη',
'btn_cancel' => 'Ακύρωση',
'list_title' => 'Λίστα Προϊόντων',
'th_id_sku' => 'ID / SKU',
'th_photo' => 'Φωτογραφία',
'th_title' => 'Τίτλος / Tags',
'th_cat' => 'Κατηγορία',
'th_price' => 'Τιμή',
'th_stock' => 'Απόθεμα',
'th_status' => 'Κατάσταση',
'th_actions' => 'Ενέργειες',
'no_img' => 'No IMG',
'pcs' => 'τεμ.',
'btn_view' => 'Προβολή',
'btn_del' => 'Διαγραφή',
'confirm_del' => 'Είστε σίγουρος ότι θέλετε να διαγράψετε αυτό το προϊόν;',
'modal_id' => 'Κωδικός (ID):',
'modal_sku' => 'SKU:',
'modal_cat' => 'Κατηγορία:',
'modal_price' => 'Τιμή:',
'modal_stock' => 'Απόθεμα:',
'modal_status' => 'Κατάσταση:',
'modal_seller' => 'Πωλητής:',
'modal_tags' => 'Tags:',
'modal_desc' => 'Περιγραφή Αγγελίας:',
'modal_no_attrs' => 'Δεν υπάρχουν επιπλέον χαρακτηριστικά',
'msg_add_ok' => 'Το προϊόν προστέθηκε επιτυχώς!',
'msg_edit_ok' => 'Το προϊόν ενημερώθηκε επιτυχώς!',
'msg_err_req' => 'Παρακαλώ συμπληρώστε τα υποχρεωτικά πεδία.',
'msg_err_del_orders' => 'Δεν μπορείτε να διαγράψετε αυτό το προϊόν διότι υπάρχει στο ιστορικό παραγγελιών. Αν δεν θέλετε να φαίνεται, αλλάξτε την κατάστασή του σε "Απόκρυψη".',
'msg_del_ok' => 'Το προϊόν διαγράφηκε επιτυχώς!'
],
'en' => [
'page_title' => 'Products Management - Hockey CMS',
'header_title' => 'Products Management',
'attr_cat_title' => 'Category Attributes',
'attr_placeholder' => 'e.g. fill in value...',
'edit_prod_title' => 'Edit Product #',
'add_prod_title' => 'Add New Product',
'prod_title' => 'Product Title *',
'category' => 'Category *',
'select_cat' => '-- Select --',
'sku' => 'Code / Sequential (SKU)',
'price' => 'Price (€) *',
'stock' => 'Stock',
'status' => 'Status',
'status_avail' => 'Available',
'status_sold' => 'Sold',
'status_hidden' => 'Hidden',
'seller_assign' => 'Owner / Seller *',
'tags' => 'Search Tags',
'tags_placeholder' => 'Type a word and press Enter...',
'tags_hint' => 'Press Enter or Comma (,) to create a tag.',
'desc' => 'Description',
'photo' => 'Main Photo',
'photo_hint_edit' => '(Leave empty to keep current)',
'photo_hint_add' => '(Auto resize)',
'btn_update' => 'Update',
'btn_add' => 'Add',
'btn_cancel' => 'Cancel',
'list_title' => 'Products List',
'th_id_sku' => 'ID / SKU',
'th_photo' => 'Photo',
'th_title' => 'Title / Tags',
'th_cat' => 'Category',
'th_price' => 'Price',
'th_stock' => 'Stock',
'th_status' => 'Status',
'th_actions' => 'Actions',
'no_img' => 'No IMG',
'pcs' => 'pcs.',
'btn_view' => 'View',
'btn_del' => 'Delete',
'confirm_del' => 'Are you sure you want to delete this product?',
'modal_id' => 'ID:',
'modal_sku' => 'SKU:',
'modal_cat' => 'Category:',
'modal_price' => 'Price:',
'modal_stock' => 'Stock:',
'modal_status' => 'Status:',
'modal_seller' => 'Seller:',
'modal_tags' => 'Tags:',
'modal_desc' => 'Listing Description:',
'modal_no_attrs' => 'No additional attributes',
'msg_add_ok' => 'Product added successfully!',
'msg_edit_ok' => 'Product updated successfully!',
'msg_err_req' => 'Please fill in the required fields.',
'msg_err_del_orders' => 'Cannot delete product because it exists in order history. If you want to hide it, change status to "Hidden".',
'msg_del_ok' => 'Product deleted successfully!'
]
];
$t = $translations[$current_lang];
// --- 1. AJAX API: Φέρνει δυναμικά τα πεδία όταν αλλάζει η Κατηγορία ---
if (isset($_GET['ajax_get_attributes']) && isset($_GET['category_id'])) {
$cat_id = (int)$_GET['category_id'];
$product_id = isset($_GET['product_id']) ? (int)$_GET['product_id'] : 0;
$stmt = $pdo->prepare("SELECT attribute_group_id FROM categories WHERE id = ?");
$stmt->execute([$cat_id]);
$cat = $stmt->fetch();
if ($cat && $cat['attribute_group_id']) {
$attrStmt = $pdo->prepare("SELECT id, name, unit FROM attributes WHERE group_id = ? ORDER BY name");
$attrStmt->execute([$cat['attribute_group_id']]);
$attributes = $attrStmt->fetchAll();
$existing_values = [];
if ($product_id > 0) {
$valStmt = $pdo->prepare("SELECT attribute_id, value FROM product_attribute_values WHERE product_id = ?");
$valStmt->execute([$product_id]);
while ($vRow = $valStmt->fetch(PDO::FETCH_ASSOC)) {
$existing_values[$vRow['attribute_id']] = $vRow['value'];
}
}
if ($attributes) {
echo "
{$t['attr_cat_title']}
";
echo "";
foreach ($attributes as $attr) {
$val = isset($existing_values[$attr['id']]) ? htmlspecialchars($existing_values[$attr['id']]) : '';
echo "
";
echo "";
echo "";
echo "
";
}
echo "
";
}
}
exit;
}
// --- 2. AJAX API: Δημιουργία προτεινόμενου SKU (Πρόθεμα 3 Γράμματα + Αύξων) ---
if (isset($_GET['ajax_generate_sku']) && isset($_GET['category_id'])) {
$cat_id = (int)$_GET['category_id'];
$stmt = $pdo->prepare("SELECT name_en FROM categories WHERE id = ?");
$stmt->execute([$cat_id]);
$name_en = $stmt->fetchColumn();
if ($name_en) {
// Κρατάμε μόνο τα γράμματα από τα Αγγλικά
$clean_name = preg_replace('/[^a-zA-Z]/', '', $name_en);
$prefix = strtoupper(substr($clean_name, 0, 3));
if (empty($prefix)) { $prefix = 'CAT'; }
// Βρίσκουμε το μεγαλύτερο νούμερο με αυτό το πρόθεμα
$stmtSku = $pdo->prepare("SELECT sku FROM products WHERE sku LIKE ?");
$stmtSku->execute([$prefix . '-%']);
$skus = $stmtSku->fetchAll(PDO::FETCH_COLUMN);
$max = 0;
foreach ($skus as $s) {
$parts = explode('-', $s);
if (count($parts) > 1) {
$num = (int)end($parts);
if ($num > $max) { $max = $num; }
}
}
// Γεννάμε το νέο νούμερο με μηδενικά μπροστά (π.χ. 001, 002)
$next_num = str_pad($max + 1, 3, '0', STR_PAD_LEFT);
echo $prefix . '-' . $next_num;
}
exit;
}
header('Content-Type: text/html; charset=utf-8');
$message = '';
function resizeAndSaveImage($source_file, $target_file, $max_resolution = 800) {
$info = getimagesize($source_file);
if (!$info) return false;
$mime = $info['mime'];
switch ($mime) {
case 'image/jpeg': $image = imagecreatefromjpeg($source_file); break;
case 'image/png': $image = imagecreatefrompng($source_file); break;
case 'image/gif': $image = imagecreatefromgif($source_file); break;
default: return false;
}
$original_width = imagesx($image);
$original_height = imagesy($image);
$ratio = $max_resolution / max($original_width, $original_height);
$new_width = $original_width > $max_resolution ? round($original_width * $ratio) : $original_width;
$new_height = $original_height > $max_resolution ? round($original_height * $ratio) : $original_height;
$new_image = imagecreatetruecolor($new_width, $new_height);
if ($mime == 'image/png') {
imagealphablending($new_image, false);
imagesavealpha($new_image, true);
}
imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $original_width, $original_height);
imagejpeg($new_image, $target_file, 85);
imagedestroy($image);
imagedestroy($new_image);
return true;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$action = $_POST['action'];
$title = trim($_POST['title']);
$sku = trim($_POST['sku']);
$category_id = (int)$_POST['category_id'];
$price = (float)$_POST['price'];
$quantity = (int)$_POST['quantity'];
$status = $_POST['status'] ?? 'available';
$description = trim($_POST['description']);
$search_tags = trim($_POST['search_tags']);
$seller_id = isset($_POST['seller_id']) ? (int)$_POST['seller_id'] : $_SESSION['user_id'];
if (!empty($title) && !empty($category_id) && !empty($price)) {
try {
$pdo->beginTransaction();
$stmtGrp = $pdo->prepare("SELECT attribute_group_id FROM categories WHERE id = ?");
$stmtGrp->execute([$category_id]);
$group_id = $stmtGrp->fetchColumn();
if ($action == 'add_product') {
$stmt = $pdo->prepare("INSERT INTO products (seller_id, category_id, attribute_group_id, title, sku, description, search_tags, price, quantity, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$seller_id, $category_id, $group_id, $title, $sku, $description, $search_tags, $price, $quantity, $status]);
$product_id = $pdo->lastInsertId();
$message_text = $t['msg_add_ok'];
} elseif ($action == 'edit_product') {
$product_id = (int)$_POST['product_id'];
$stmt = $pdo->prepare("UPDATE products SET seller_id = ?, category_id = ?, attribute_group_id = ?, title = ?, sku = ?, description = ?, search_tags = ?, price = ?, quantity = ?, status = ? WHERE id = ?");
$stmt->execute([$seller_id, $category_id, $group_id, $title, $sku, $description, $search_tags, $price, $quantity, $status, $product_id]);
$delAttr = $pdo->prepare("DELETE FROM product_attribute_values WHERE product_id = ?");
$delAttr->execute([$product_id]);
$message_text = $t['msg_edit_ok'];
}
if (isset($_POST['attributes']) && is_array($_POST['attributes'])) {
$insAttr = $pdo->prepare("INSERT INTO product_attribute_values (product_id, attribute_id, value) VALUES (?, ?, ?)");
foreach ($_POST['attributes'] as $attr_id => $val) {
$val = trim($val);
if ($val !== '') {
$insAttr->execute([$product_id, $attr_id, $val]);
}
}
}
if (isset($_FILES['image']) && $_FILES['image']['error'] == 0) {
$upload_dir = '../uploads/equipment/';
if (!is_dir($upload_dir)) { mkdir($upload_dir, 0755, true); }
$filename = 'prod_' . $product_id . '_' . time() . '.jpg';
$target_path = $upload_dir . $filename;
if (resizeAndSaveImage($_FILES['image']['tmp_name'], $target_path)) {
$checkImg = $pdo->prepare("SELECT id FROM product_images WHERE product_id = ? AND is_primary = 1");
$checkImg->execute([$product_id]);
if ($checkImg->fetch()) {
$updImg = $pdo->prepare("UPDATE product_images SET image_path = ? WHERE product_id = ? AND is_primary = 1");
$updImg->execute(['uploads/equipment/' . $filename, $product_id]);
} else {
$insImg = $pdo->prepare("INSERT INTO product_images (product_id, image_path, is_primary) VALUES (?, ?, 1)");
$insImg->execute([$product_id, 'uploads/equipment/' . $filename]);
}
}
}
$pdo->commit();
$message = "{$message_text}
";
} catch (Exception $e) {
$pdo->rollBack();
$message = "Σφάλμα: " . $e->getMessage() . "
";
}
} else {
$message = "{$t['msg_err_req']}
";
}
}
if (isset($_GET['delete'])) {
$del_id = (int)$_GET['delete'];
$checkOrders = $pdo->prepare("SELECT COUNT(*) FROM order_items WHERE product_id = ?");
$checkOrders->execute([$del_id]);
if ($checkOrders->fetchColumn() > 0) {
$message = "{$t['msg_err_del_orders']}
";
} else {
try {
$pdo->beginTransaction();
$imgStmt = $pdo->prepare("SELECT image_path FROM product_images WHERE product_id = ?");
$imgStmt->execute([$del_id]);
$images = $imgStmt->fetchAll();
foreach ($images as $img) {
$imgPath = '../' . $img['image_path'];
if (file_exists($imgPath) && is_file($imgPath)) { @unlink($imgPath); }
}
$pdo->prepare("DELETE FROM product_attribute_values WHERE product_id = ?")->execute([$del_id]);
$pdo->prepare("DELETE FROM product_images WHERE product_id = ?")->execute([$del_id]);
$pdo->prepare("DELETE FROM products WHERE id = ?")->execute([$del_id]);
$pdo->commit();
$message = "{$t['msg_del_ok']}
";
} catch (Exception $e) {
$pdo->rollBack();
$message = "Σφάλμα: " . $e->getMessage() . "
";
}
}
}
$edit_product = null;
if (isset($_GET['edit'])) {
$edit_id = (int)$_GET['edit'];
$editStmt = $pdo->prepare("SELECT * FROM products WHERE id = ?");
$editStmt->execute([$edit_id]);
$edit_product = $editStmt->fetch(PDO::FETCH_ASSOC);
}
// Φόρτωση Κατηγοριών
$cat_col = ($current_lang === 'en') ? 'name_en' : 'name_el';
$categories = $pdo->query("SELECT id, IFNULL(NULLIF(name_en, ''), name_el) as name FROM categories ORDER BY sort_order ASC, name_el ASC")->fetchAll();
if ($current_lang === 'el') {
$categories = $pdo->query("SELECT id, name_el as name FROM categories ORDER BY sort_order ASC, name_el ASC")->fetchAll();
}
// Φόρτωση όλων των χρηστών & Έξυπνη Εύρεση Ονόματος/Επιθέτου
$all_users = $pdo->query("SELECT * FROM users ORDER BY username ASC")->fetchAll(PDO::FETCH_ASSOC);
$user_map = [];
foreach ($all_users as $u) {
$fName = $u['first_name'] ?? $u['name'] ?? $u['firstname'] ?? '';
$lName = $u['last_name'] ?? $u['surname'] ?? $u['lastname'] ?? '';
$fullName = trim($fName . ' ' . $lName);
$user_map[$u['id']] = $fullName ? $fullName . ' (' . $u['username'] . ')' : $u['username'];
}
// Λίστα προϊόντων
$products = $pdo->query("SELECT p.id, p.sku, p.title, p.description, p.search_tags, p.price, p.quantity, p.status, p.category_id, p.seller_id, p.created_at,
IFNULL(NULLIF(c.name_en, ''), c.name_el) as cat_name_en, c.name_el as cat_name_el, u.username, pi.image_path
FROM products p
LEFT JOIN categories c ON p.category_id = c.id
LEFT JOIN users u ON p.seller_id = u.id
LEFT JOIN product_images pi ON (p.id = pi.product_id AND pi.is_primary = 1)
ORDER BY p.id DESC")->fetchAll(PDO::FETCH_ASSOC);
$all_attrs = $pdo->query("SELECT pav.product_id, a.name, a.name_en, a.unit, pav.value
FROM product_attribute_values pav
JOIN attributes a ON pav.attribute_id = a.id")->fetchAll(PDO::FETCH_ASSOC);
$attrs_by_product = [];
foreach($all_attrs as $attr) {
$attr['display_name'] = ($current_lang === 'en' && !empty($attr['name_en'])) ? $attr['name_en'] : $attr['name'];
$attrs_by_product[$attr['product_id']][] = $attr;
}
foreach ($products as &$prod) {
$prod['cat_name'] = ($current_lang === 'en' && !empty($prod['cat_name_en'])) ? $prod['cat_name_en'] : $prod['cat_name_el'];
$prod['attributes'] = isset($attrs_by_product[$prod['id']]) ? $attrs_by_product[$prod['id']] : [];
$prod['seller_display'] = isset($user_map[$prod['seller_id']]) ? $user_map[$prod['seller_id']] : $prod['username'];
}
unset($prod);
?>
|
|
|
|
|
|
|
|
#
|
|
'.htmlspecialchars(trim($tg)).'';
}
?>
|
|
€ |
|
|
|