feature/admin-section #31
@ -688,68 +688,4 @@ Coordinates: ${product.hidden_coordinates}
|
||||
await this.bot.sendMessage(chatId, 'Error processing purchase. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
async showPurchases(msg) {
|
||||
const chatId = msg.chat.id;
|
||||
const userId = msg.from.id;
|
||||
|
||||
try {
|
||||
const user = await User.getById(userId);
|
||||
if (!user) {
|
||||
await this.bot.sendMessage(chatId, 'Profile not found. Please use /start to create one.');
|
||||
return;
|
||||
}
|
||||
|
||||
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 10
|
||||
`, [user.id]);
|
||||
|
||||
if (purchases.length === 0) {
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'You haven\'t made any purchases yet.',
|
||||
{
|
||||
reply_markup: {
|
||||
inline_keyboard: [[
|
||||
{text: '🛍 Browse Products', callback_data: 'shop_start'}
|
||||
]]
|
||||
}
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let message = '🛍 *Your Recent Purchases:*\n\n';
|
||||
|
||||
for (const purchase of purchases) {
|
||||
const date = new Date(purchase.purchase_date).toLocaleString();
|
||||
message += `📦 *${purchase.product_name}*\n`;
|
||||
message += `├ Quantity: ${purchase.quantity}\n`;
|
||||
message += `├ Total: $${purchase.total_price}\n`;
|
||||
message += `├ Location: ${purchase.country}, ${purchase.city}\n`;
|
||||
message += `├ Payment: ${purchase.wallet_type}\n`;
|
||||
message += `├ TX: \`${purchase.tx_hash}\`\n`;
|
||||
message += `└ Date: ${date}\n\n`;
|
||||
}
|
||||
|
||||
await this.bot.sendMessage(chatId, message, {
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: {
|
||||
inline_keyboard: [[
|
||||
{text: '🛍 Browse Products', callback_data: 'shop_start'}
|
||||
]]
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in showPurchases:', error);
|
||||
await this.bot.sendMessage(chatId, 'Error loading purchase history. Please try again.');
|
||||
}
|
||||
}
|
||||
}
|
197
src/handlers/userPurchaseHandler.js
Normal file
197
src/handlers/userPurchaseHandler.js
Normal 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);
|
||||
}
|
||||
}
|
10
src/index.js
10
src/index.js
@ -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') {
|
||||
|
Loading…
Reference in New Issue
Block a user