Spaces:
Paused
Paused
| const { Scenes, Markup } = require('telegraf'); | |
| const Product = require('../../models/Product'); | |
| const Category = require('../../models/Category'); | |
| const userController = require('../../controllers/userController'); | |
| const addProductScene = new Scenes.WizardScene( | |
| 'ADD_PRODUCT_SCENE', | |
| // Step 1: Ask Category (First!) | |
| async (ctx) => { | |
| // Ensure localization logic | |
| if (!ctx.i18n) { | |
| const locales = require('../../locales'); | |
| const User = require('../../models/User'); | |
| const user = await User.findOne({ id: ctx.from.id }); | |
| ctx.i18n = locales[user ? user.language : 'uz']; | |
| } | |
| const i18n = ctx.i18n; | |
| // Init State | |
| ctx.wizard.state.product = { media: [] }; | |
| const categories = await Category.find(); | |
| let buttons = categories.map(c => c.name); | |
| buttons.push(i18n.admin.new_cat || "β Yangi Kategoriya"); | |
| buttons.push(i18n.btn_cancel || "β Bekor qilish"); | |
| // Filter out any undefined values to prevent crashes | |
| buttons = buttons.filter(b => b); | |
| ctx.reply(i18n.admin.enter_cat || "π Kategoriyani tanlang:", Markup.keyboard(buttons, { columns: 2 }).resize()); | |
| return ctx.wizard.next(); | |
| }, | |
| // Step 2: Handle Category -> Ask Name | |
| async (ctx) => { | |
| const i18n = ctx.i18n; | |
| const text = ctx.message?.text; | |
| if (text === i18n.btn_cancel) { | |
| ctx.scene.leave(); | |
| userController.start(ctx, i18n.cancel_process); | |
| return; | |
| } | |
| if (text === (i18n.admin.new_cat || "β Yangi Kategoriya")) { | |
| ctx.wizard.state.isNewCategory = true; | |
| ctx.reply(i18n.admin.enter_new_cat, Markup.keyboard([[i18n.btn_cancel]]).resize()); | |
| return ctx.wizard.selectStep(2); // Go to New Category Handler | |
| } | |
| // Validate Existing Category | |
| // We accept text input as category name too, or check against DB if strict | |
| ctx.wizard.state.product.category = text; | |
| ctx.reply(i18n.admin.add_product_title || "βοΈ Mahsulot nomini kiriting:", Markup.keyboard([[i18n.btn_cancel]]).resize()); | |
| return ctx.wizard.selectStep(3); // Go to Name Handler | |
| }, | |
| // Step 3: Handle New Category (If selected) -> Then Ask Name | |
| async (ctx) => { | |
| const i18n = ctx.i18n; | |
| const text = ctx.message?.text; | |
| if (text === i18n.btn_cancel) { | |
| ctx.scene.leave(); | |
| userController.start(ctx, i18n.cancel_process); | |
| return; | |
| } | |
| // Save New Category | |
| try { | |
| await new Category({ id: Date.now().toString(), name: text }).save(); | |
| ctx.reply(`${i18n.admin.new_cat}: ${text}`); | |
| ctx.wizard.state.product.category = text; | |
| ctx.reply(i18n.admin.add_product_title || "βοΈ Mahsulot nomini kiriting:", Markup.keyboard([[i18n.btn_cancel]]).resize()); | |
| return ctx.wizard.next(); | |
| } catch (e) { | |
| ctx.reply("Xatolik: " + e.message); | |
| return; | |
| } | |
| }, | |
| // Step 4: Handle Name -> Ask Condition | |
| (ctx) => { | |
| const i18n = ctx.i18n; | |
| if (ctx.message.text === i18n.btn_cancel) return ctx.scene.leave(); | |
| ctx.wizard.state.product.name = ctx.message.text; | |
| ctx.reply("π Mahsulot holatini tanlang:", Markup.keyboard([ | |
| ["π Yangi", "β»οΈ B/U"], | |
| [i18n.btn_cancel] | |
| ]).resize()); | |
| return ctx.wizard.next(); | |
| }, | |
| // Step 5: Handle Condition -> Ask Price | |
| (ctx) => { | |
| const i18n = ctx.i18n; | |
| const text = ctx.message.text; | |
| if (text === i18n.btn_cancel) { | |
| ctx.scene.leave(); | |
| userController.start(ctx, i18n.cancel_process); | |
| return; | |
| } | |
| if (text === "π Yangi") ctx.wizard.state.product.condition = "new"; | |
| else if (text === "β»οΈ B/U") ctx.wizard.state.product.condition = "used"; | |
| else return ctx.reply("Iltimos tugmani tanlang: Yangi yoki B/U"); | |
| ctx.reply(i18n.admin.enter_price, Markup.keyboard([[i18n.btn_cancel]]).resize()); | |
| return ctx.wizard.next(); | |
| }, | |
| // Step 6: Handle Price -> Ask Quantity | |
| (ctx) => { | |
| const i18n = ctx.i18n; | |
| if (ctx.message.text === i18n.btn_cancel) return ctx.scene.leave(); | |
| if (isNaN(ctx.message.text)) return ctx.reply(i18n.admin.error_num); | |
| ctx.wizard.state.product.price = parseInt(ctx.message.text); | |
| ctx.reply(i18n.admin.enter_qty, Markup.keyboard([[i18n.btn_cancel]]).resize()); | |
| return ctx.wizard.next(); | |
| }, | |
| // Step 7: Handle Quantity -> Ask Description | |
| (ctx) => { | |
| const i18n = ctx.i18n; | |
| if (ctx.message.text === i18n.btn_cancel) return ctx.scene.leave(); | |
| if (isNaN(ctx.message.text)) return ctx.reply(i18n.admin.error_num); | |
| ctx.wizard.state.product.quantity = parseInt(ctx.message.text); | |
| ctx.reply(i18n.admin.enter_desc, Markup.keyboard([[i18n.btn_cancel]]).resize()); | |
| return ctx.wizard.next(); | |
| }, | |
| // Step 8: Handle Description -> Ask Media | |
| (ctx) => { | |
| const i18n = ctx.i18n; | |
| if (ctx.message.text === i18n.btn_cancel) return ctx.scene.leave(); | |
| ctx.wizard.state.product.description = ctx.message.text; | |
| ctx.reply(i18n.admin.media_prompt, Markup.keyboard([i18n.admin.media_done, i18n.btn_cancel]).resize()); | |
| return ctx.wizard.next(); | |
| }, | |
| // Step 9: Handle Media Loop | |
| async (ctx) => { | |
| const i18n = ctx.i18n; | |
| const msg = ctx.message; | |
| if (msg.text === i18n.btn_cancel) { | |
| ctx.scene.leave(); | |
| userController.start(ctx, i18n.cancel_process); | |
| return; | |
| } | |
| if (msg.text === i18n.admin.media_done) { | |
| if (ctx.wizard.state.product.media.length === 0) return ctx.reply(i18n.admin.media_error); | |
| // Save Product | |
| try { | |
| const productData = { | |
| id: Date.now(), | |
| ...ctx.wizard.state.product | |
| }; | |
| await new Product(productData).save(); | |
| ctx.reply(`β <b>Saqlandi!</b>\n\n${productData.name} (${productData.condition === 'new' ? 'π' : 'β»οΈ'})\nπ ${productData.category}`, { parse_mode: 'HTML' }); | |
| userController.start(ctx); | |
| return ctx.scene.leave(); | |
| } catch (e) { | |
| console.error(e); | |
| ctx.reply("Error"); | |
| return ctx.scene.leave(); | |
| } | |
| } | |
| if (msg.photo) { | |
| ctx.wizard.state.product.media.push({ type: 'photo', file_id: msg.photo[msg.photo.length - 1].file_id }); | |
| ctx.reply(`Rasm (${ctx.wizard.state.product.media.length}/4)`); | |
| } else if (msg.video) { | |
| ctx.wizard.state.product.media.push({ type: 'video', file_id: msg.video.file_id }); | |
| ctx.reply(`Video (${ctx.wizard.state.product.media.length}/4)`); | |
| } | |
| } | |
| ); | |
| module.exports = addProductScene; | |