diff --git a/src/handlers/adminHandlers/adminProductHandler.js b/src/handlers/adminHandlers/adminProductHandler.js index 263cb97..c7eddd9 100644 --- a/src/handlers/adminHandlers/adminProductHandler.js +++ b/src/handlers/adminHandlers/adminProductHandler.js @@ -821,51 +821,82 @@ export default class AdminProductHandler { } static async handleViewProduct(callbackQuery) { + if (!this.isAdmin(callbackQuery.from.id)) { + return; + } + const chatId = callbackQuery.message.chat.id; + const messageId = callbackQuery.message.message_id; const productId = callbackQuery.data.replace('view_product_', ''); - + try { - const product = await ProductService.getDetailedProductById(productId); - + const product = await ProductService.getDetailedProductById(productId) + if (!product) { throw new Error('Product not found'); } - + + const location = await LocationService.getLocationById(product.location_id); + + if (!location) { + throw new Error('Location not found'); + } + const message = ` - 📦 Product Details: - - Name: ${product.name} - Price: $${product.price} - Description: ${product.description} - Stock: ${product.quantity_in_stock} - Location: ${product.country}, ${product.city}, ${product.district} - Category: ${product.category_name} - - 🔒 Private Information: - ${product.private_data} - Hidden Location: ${product.hidden_description} - Coordinates: ${product.hidden_coordinates} - `; - +📦 Product Details: + +Name: ${product.name} +Price: $${product.price} +Description: ${product.description} +Stock: ${product.quantity_in_stock} +Location: ${location.country}, ${location.city}, ${location.district} +Category: ${product.category_name} +Subcategory: ${product.subcategory_name} + +🔒 Private Information: +${product.private_data} +Hidden Location: ${product.hidden_description} +Coordinates: ${product.hidden_coordinates} +`; + const keyboard = { inline_keyboard: [ [ - { text: '✏️ Edit', callback_data: `edit_product_${productId}` }, - { text: '❌ Delete', callback_data: `delete_product_${productId}` } + {text: '✏️ Edit', callback_data: `edit_product_${productId}`}, + {text: '❌ Delete', callback_data: `delete_product_${productId}`} ], - [{ text: '« Back', callback_data: `prod_category_${product.location_id}_${product.category_id}` }] + [{ + text: '« Back', + callback_data: `prod_subcategory_${product.location_id}_${product.category_id}_${product.subcategory_id}` + }] ] }; - - await bot.editMessageText( - message, - { - chat_id: chatId, - message_id: callbackQuery.message.message_id, - reply_markup: keyboard, - parse_mode: 'HTML' + + let photoMessage; + let hiddenPhotoMessage; + + // Send product photos + if (product.photo_url) { + try { + photoMessage = await bot.sendPhoto(chatId, product.photo_url, {caption: 'Public photo'}); + } catch (e) { + photoMessage = await bot.sendPhoto(chatId, "./corrupt-photo.jpg", {caption: 'Public photo'}) } - ); + } + if (product.hidden_photo_url) { + try { + hiddenPhotoMessage = await bot.sendPhoto(chatId, product.hidden_photo_url, {caption: 'Hidden photo'}); + } catch (e) { + hiddenPhotoMessage = await bot.sendPhoto(chatId, "./corrupt-photo.jpg", {caption: 'Hidden photo'}) + } + } + + userStates.set(chatId, { + msgToDelete: [photoMessage.message_id, hiddenPhotoMessage.message_id] + }) + + await bot.deleteMessage(chatId, messageId); + await bot.sendMessage(chatId, message, {reply_markup: keyboard}); } catch (error) { console.error('Error in handleViewProduct:', error); await bot.sendMessage(chatId, 'Error loading product details. Please try again.'); diff --git a/src/handlers/userHandlers/userProductHandler.js b/src/handlers/userHandlers/userProductHandler.js index 3eadb14..643064a 100644 --- a/src/handlers/userHandlers/userProductHandler.js +++ b/src/handlers/userHandlers/userProductHandler.js @@ -291,46 +291,78 @@ export default class UserProductHandler { static async handleProductSelection(callbackQuery) { const chatId = callbackQuery.message.chat.id; + const messageId = callbackQuery.message.message_id; const productId = callbackQuery.data.replace('shop_product_', ''); - + try { const product = await ProductService.getDetailedProductById(productId); - + if (!product) { throw new Error('Product not found'); } - + + // Delete the previous message + await bot.deleteMessage(chatId, messageId); + const message = ` - 📦 Product Details: - - Name: ${product.name} - Price: $${product.price} - Description: ${product.description} - Stock: ${product.quantity_in_stock} - Location: ${product.country}, ${product.city}, ${product.district} - Category: ${product.category_name} - - 🔒 Private Information: - ${product.private_data} - Hidden Location: ${product.hidden_description} - Coordinates: ${product.hidden_coordinates} - `; - +📦 ${product.name} + +💰 Price: $${product.price} +📝 Description: ${product.description} +📦 Available: ${product.quantity_in_stock} pcs + +Category: ${product.category_name} +Subcategory: ${product.subcategory_name} +`; + + let photoMessageId = null; + + // First send the photo if it exists + let photoMessage; + if (product.photo_url) { + try { + photoMessage = await bot.sendPhoto(chatId, product.photo_url, {caption: 'Public photo'}); + } catch (e) { + photoMessage = await bot.sendPhoto(chatId, "./corrupt-photo.jpg", {caption: 'Public photo'}) + } + } + const keyboard = { inline_keyboard: [ - [{ text: '« Back', callback_data: `shop_category_${product.location_id}_${product.category_id}` }] + [{text: '🛒 Buy Now', callback_data: `buy_product_${productId}`}], + [ + { + text: '➖', + callback_data: `decrease_quantity_${productId}`, + callback_game: {} // Initially disabled as quantity starts at 1 + }, + {text: '1', callback_data: 'current_quantity'}, + { + text: '➕', + callback_data: `increase_quantity_${productId}`, + callback_game: product.quantity_in_stock <= 1 ? {} : null // Disabled if stock is 1 or less + } + ], + [{ + text: `« Back to ${product.subcategory_name}`, + callback_data: `shop_subcategory_${product.location_id}_${product.category_id}_${product.subcategory_id}_${photoMessageId}` + }] ] }; - - await bot.editMessageText( - message, - { - chat_id: chatId, - message_id: callbackQuery.message.message_id, - reply_markup: keyboard, - parse_mode: 'HTML' - } - ); + + // Then send the message with controls + await bot.sendMessage(chatId, message, { + reply_markup: keyboard, + parse_mode: 'HTML' + }); + + // Store the current quantity and photo message ID in user state + userStates.set(chatId, { + action: 'buying_product', + productId, + quantity: 1, + photoMessageId + }); } catch (error) { console.error('Error in handleProductSelection:', error); await bot.sendMessage(chatId, 'Error loading product details. Please try again.'); diff --git a/src/services/productService.js b/src/services/productService.js index a79c4c1..06632ad 100644 --- a/src/services/productService.js +++ b/src/services/productService.js @@ -12,10 +12,9 @@ class ProductService { static async getDetailedProductById(productId) { return await db.getAsync( - `SELECT p.*, c.name as category_name, l.country, l.city, l.district + `SELECT p.*, c.name as category_name FROM products p JOIN categories c ON p.category_id = c.id - JOIN locations l ON p.location_id = l.id WHERE p.id = ?`, [productId] );