purchase viewing #28

Merged
1323ed5 merged 1 commits from feature/user-section into main 2024-11-20 15:20:23 +00:00
2 changed files with 206 additions and 1 deletions

View File

@ -0,0 +1,197 @@
import db from '../config/database.js';
import User from '../models/User.js';
import WalletService from "../utils/walletService.js";
import config from "../config/config.js";
export default class UserPurchaseHandler {
constructor(bot) {
this.bot = bot;
this.userStates = new Map();
}
async viewPurchasePage(userId, page) {
try {
const limit = 10;
const offset = (page || 0) * limit;
const previousPage = page > 0 ? page - 1 : 0;
const nextPage = page + 1;
const purchases = await db.allAsync(`
SELECT
p.*,
pr.name as product_name,
pr.description,
l.country,
l.city,
l.district
FROM purchases p
JOIN products pr ON p.product_id = pr.id
JOIN locations l ON pr.location_id = l.id
WHERE p.user_id = ?
ORDER BY p.purchase_date DESC
LIMIT ?
OFFSET ?
`, [userId, limit, offset]);
if ((purchases.length === 0) && (page == 0)) {
return {
text: 'You haven\'t made any purchases yet.',
markup: [[
{text: '🛍 Browse Products', callback_data: 'shop_start'}
]]
}
}
if ((purchases.length === 0) && (page > 0)) {
return await this.viewPurchasePage(userId, previousPage);
}
const keyboard = {
inline_keyboard: [
...purchases.map(item => [{
text: `${item.product_name} [${new Date(item.purchase_date).toLocaleString()}]`,
callback_data: `view_purchase_${item.id}`
}]),
]
};
keyboard.inline_keyboard.push([
{text: `«`, callback_data: `list_purchases_${previousPage}`},
{text: `»`, callback_data: `list_purchases_${nextPage}`},
]);
keyboard.inline_keyboard.push([
{text: '🛍 Browse Products', callback_data: 'shop_start'}
]);
return {
text: `📦 Select purchase to view detailed information:`,
markup: keyboard
}
} catch (error) {
console.error('Error in showPurchases:', error);
return {text: 'Error loading purchase history. Please try again.'};
}
}
async handlePurchaseListPage(callbackQuery) {
const telegramId = callbackQuery.from.id;
const chatId = callbackQuery.message.chat.id;
const page = callbackQuery.data.replace('list_purchases_', '');
try {
const user = await User.getById(telegramId);
if (!user) {
await this.bot.sendMessage(chatId, 'User not found.');
return;
}
const {text, markup} = await this.viewPurchasePage(user.id, parseInt(page));
await this.bot.editMessageText(text, {
chat_id: chatId,
message_id: callbackQuery.message.message_id,
reply_markup: markup,
parse_mode: 'Markdown',
});
} catch (e) {
return;
}
}
async showPurchases(msg) {
// const userId = callbackQuery.from.id;
// const chatId = callbackQuery.message.chat.id;
const chatId = msg.chat.id;
const telegramId = msg.from.id;
try {
const user = await User.getById(telegramId);
if (!user) {
await this.bot.sendMessage(chatId, 'User not found.');
return;
}
const {text, markup} = await this.viewPurchasePage(user.id, 0);
await this.bot.sendMessage(chatId, text, {reply_markup: markup, parse_mode: 'Markdown'});
} catch (error) {
console.error('Error in handleSubcategorySelection:', error);
await this.bot.sendMessage(chatId, 'Error loading products. Please try again.');
}
}
async viewPurchase(callbackQuery) {
const chatId = callbackQuery.message.chat.id;
const purchaseId = callbackQuery.data.replace('view_purchase_', '');
const purchase = await db.getAsync(`
SELECT
p.*,
pr.name as product_name,
pr.description,
l.country,
l.city,
l.district
FROM purchases p
JOIN products pr ON p.product_id = pr.id
JOIN locations l ON pr.location_id = l.id
WHERE p.id = ?
`, [purchaseId]);
if (!purchase) {
await this.bot.sendMessage(chatId, "No such purchase");
return;
}
const product = await db.getAsync(
`SELECT * FROM products WHERE id = ?`,
[purchase.product_id]
);
if (!product) {
await this.bot.sendMessage(chatId, "No such product");
return;
}
let hiddenPhotoMessage;
if (product.hidden_photo_url) {
try {
hiddenPhotoMessage = await this.bot.sendPhoto(chatId, product.hidden_photo_url, {caption: 'Hidden photo'});
} catch (e) {
hiddenPhotoMessage = await this.bot.sendPhoto(chatId, "./corrupt-photo.jpg", {caption: 'Hidden photo'})
}
}
const message = `
📦 Purchase Details:
Name: ${purchase.product_name}
Quantity: ${purchase.quantity}
Total: $${purchase.total_price}
Location: ${purchase.country}, ${purchase.city}
Payment: ${purchase.wallet_type}
Date: ${new Date(purchase.purchase_date).toLocaleString()}
🔒 Private Information:
${product.private_data}
Hidden Location: ${product.hidden_description}
Coordinates: ${product.hidden_coordinates}
`;
const keyboard = {
inline_keyboard: [
[{text: "I've got it!", callback_data: "Asdasdasd"}],
[{text: "Contact support", url: config.SUPPORT_LINK}]
]
};
await this.bot.sendMessage(chatId, message, {reply_markup: keyboard});
await this.bot.deleteMessage(chatId, callbackQuery.message.message_id);
}
}

View File

@ -12,6 +12,7 @@ import ErrorHandler from './utils/errorHandler.js';
import User from './models/User.js';
import AdminUserLocationHandler from "./handlers/adminUserLocationHandler.js";
import AdminDumpHandler from "./handlers/adminDumpHandler.js";
import UserPurchaseHandler from "./handlers/userPurchaseHandler.js";
// Debug logging function
const logDebug = (action, functionName) => {
@ -41,6 +42,7 @@ const adminLocationHandler = new AdminLocationHandler(bot);
const adminUserLocationHandler = new AdminUserLocationHandler(bot);
const adminProductHandler = new AdminProductHandler(bot);
const adminDumpHandler = new AdminDumpHandler(bot);
const userPurchaseHandler = new UserPurchaseHandler(bot);
// Start command - Create user profile
bot.onText(/\/start/, async (msg) => {
@ -125,7 +127,7 @@ bot.on('message', async (msg) => {
await userWalletsHandler.showBalance(msg);
break;
case '🛍 Purchases':
await userProductHandler.showPurchases(msg);
await userPurchaseHandler.showPurchases(msg);
break;
case '📦 Manage Products':
if (adminHandler.isAdmin(msg.from.id)) {
@ -242,6 +244,12 @@ bot.on('callback_query', async (callbackQuery) => {
} else if (action.startsWith('pay_with_')) {
logDebug(action, 'handlePay');
await userProductHandler.handlePay(callbackQuery);
} else if (action.startsWith('list_purchases_')) {
logDebug(action, 'handlePurchaseListPage');
await userPurchaseHandler.handlePurchaseListPage(callbackQuery);
} else if (action.startsWith('view_purchase_')) {
logDebug(action, 'viewPurchase');
await userPurchaseHandler.viewPurchase(callbackQuery);
}
// Admin location management
else if (action === 'add_location') {