Spaces:
Paused
Paused
File size: 7,054 Bytes
89ec743 aff1ffd 89ec743 9da5043 e81c9a5 9da5043 e81c9a5 9da5043 89ec743 9da5043 f9c77d2 9da5043 f9c77d2 89ec743 9da5043 e81c9a5 9da5043 aff1ffd e81c9a5 aff1ffd 89ec743 9da5043 89ec743 9da5043 e81c9a5 9da5043 aff1ffd e81c9a5 aff1ffd 89ec743 9da5043 89ec743 9da5043 89ec743 e81c9a5 9da5043 89ec743 9da5043 06e2bc3 9da5043 06e2bc3 9da5043 06e2bc3 9da5043 89ec743 9da5043 e81c9a5 9da5043 89ec743 9da5043 89ec743 9da5043 89ec743 9da5043 89ec743 e81c9a5 9da5043 89ec743 9da5043 89ec743 9da5043 89ec743 9da5043 e81c9a5 9da5043 89ec743 9da5043 89ec743 9da5043 89ec743 9da5043 89ec743 e81c9a5 89ec743 e81c9a5 aff1ffd e81c9a5 aff1ffd e81c9a5 9da5043 89ec743 9da5043 89ec743 9da5043 89ec743 9da5043 89ec743 9da5043 89ec743 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | 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;
|