diff --git a/TeleBot/TeleBot/Handlers/CallbackHandler.cs b/TeleBot/TeleBot/Handlers/CallbackHandler.cs index b3be7ab..94a9e7b 100644 --- a/TeleBot/TeleBot/Handlers/CallbackHandler.cs +++ b/TeleBot/TeleBot/Handlers/CallbackHandler.cs @@ -494,14 +494,12 @@ namespace TeleBot.Handlers finalQuantity ); - await bot.AnswerCallbackQueryAsync( - callbackQuery.Id, - $"āœ… Added {finalQuantity}x {itemName} to cart", - showAlert: false + // Send new message with post-add prompt + await bot.SendTextMessageAsync( + callbackQuery.Message!.Chat.Id, + $"āœ… Added {product.Name} to basket!\n\nWhat would you like to do next?", + replyMarkup: _menuBuilder.PostAddToCartMenu(productId.Value) ); - - // Send new cart message instead of editing - await SendNewCartMessage(bot, callbackQuery.Message!.Chat.Id, session); } private async Task HandleViewCart(ITelegramBotClient bot, Message message, UserSession session) @@ -1453,18 +1451,11 @@ namespace TeleBot.Handlers session.TempData["selected_variants"] = selectedVariants; - var quantity = session.TempData.ContainsKey("current_quantity") - ? (int)session.TempData["current_quantity"] - : 1; - - var multiBuyId = session.TempData.ContainsKey("current_multibuy") - ? session.TempData["current_multibuy"] as string - : null; - + // Update the product detail menu with the selected variants await bot.EditMessageReplyMarkupAsync( message.Chat.Id, message.MessageId, - replyMarkup: _menuBuilder.VariantSelectionMenu(product, quantity, multiBuyId, selectedVariants) + replyMarkup: _menuBuilder.ProductDetailMenu(product, 1, selectedVariants) ); } @@ -1523,16 +1514,13 @@ namespace TeleBot.Handlers // Add to cart with selected variants var cartItem = session.Cart.AddItem(product, quantity.Value, multiBuyId, variantId: null, selectedVariants); - // Show success message - await bot.AnswerCallbackQueryAsync( - callbackQuery.Id, - $"āœ… Added {quantity.Value}x {product.Name} with {string.Join(", ", selectedVariants)} to cart!", - showAlert: true + // Send new message with post-add prompt + await bot.SendTextMessageAsync( + callbackQuery.Message!.Chat.Id, + $"āœ… Added {product.Name} ({string.Join(", ", selectedVariants)}) to basket!\n\nWhat would you like to do next?", + replyMarkup: _menuBuilder.PostAddToCartMenu(productId.Value) ); - // Return to product view - await HandleProductDetail(bot, callbackQuery.Message!, session, productId.Value); - // Clear temp data session.TempData.Remove("selected_variants"); session.TempData.Remove("current_multibuy"); diff --git a/TeleBot/TeleBot/UI/MenuBuilder.cs b/TeleBot/TeleBot/UI/MenuBuilder.cs index 090f003..6b2a768 100644 --- a/TeleBot/TeleBot/UI/MenuBuilder.cs +++ b/TeleBot/TeleBot/UI/MenuBuilder.cs @@ -21,7 +21,7 @@ namespace TeleBot.UI return new InlineKeyboardMarkup(new[] { new[] { InlineKeyboardButton.WithCallbackData("šŸ›ļø Browse Products", "browse") }, - new[] { InlineKeyboardButton.WithCallbackData("šŸ›’ View Cart", "cart") }, + new[] { InlineKeyboardButton.WithCallbackData("šŸ›’ View Basket", "cart") }, new[] { InlineKeyboardButton.WithCallbackData("šŸ“¦ My Orders", "orders") }, new[] { InlineKeyboardButton.WithCallbackData("⭐ Reviews", "reviews") }, new[] { InlineKeyboardButton.WithCallbackData("šŸ’¬ Support", "support") }, @@ -91,75 +91,92 @@ namespace TeleBot.UI } // Navigation - buttons.Add(new[] { InlineKeyboardButton.WithCallbackData("šŸ›’ View Cart", "cart") }); + buttons.Add(new[] { InlineKeyboardButton.WithCallbackData("šŸ›’ View Basket", "cart") }); buttons.Add(new[] { InlineKeyboardButton.WithCallbackData("ā¬…ļø Back", "browse") }); return new InlineKeyboardMarkup(buttons); } - public InlineKeyboardMarkup ProductDetailMenu(Product product, int quantity = 1) + public InlineKeyboardMarkup ProductDetailMenu(Product product, int quantity = 1, List? selectedVariants = null) { var buttons = new List(); + selectedVariants ??= new List(); // Check if product has variants bool hasVariants = product.Variants?.Any(v => v.IsActive) == true; - // Show multi-buy options if available - if (product.MultiBuys?.Any(mb => mb.IsActive) == true) + // If product has variants, show variant selection directly (no intermediate button) + if (hasVariants) { - buttons.Add(new[] { - InlineKeyboardButton.WithCallbackData("šŸ’° Multi-Buy Deals:", "noop") - }); + // Group variants by type + var variantGroups = product.Variants! + .Where(v => v.IsActive) + .GroupBy(v => v.VariantType) + .ToList(); - foreach (var multiBuy in product.MultiBuys.Where(mb => mb.IsActive).OrderBy(mb => mb.Quantity)) + // For each variant type, show options + foreach (var group in variantGroups) { - var label = $"{multiBuy.Name} - Ā£{multiBuy.Price:F2}"; - if (multiBuy.Quantity > 1) - label += $" (Ā£{multiBuy.PricePerUnit:F2}/each)"; - - // Use short callback data - var callbackData = hasVariants - ? _mapper.BuildCallback("selectvar", product.Id, multiBuy.Quantity, multiBuy.Id) - : _mapper.BuildCallback("add", product.Id, multiBuy.Quantity, multiBuy.Id); - - buttons.Add(new[] - { - InlineKeyboardButton.WithCallbackData(label, callbackData) + buttons.Add(new[] { + InlineKeyboardButton.WithCallbackData($"Select {group.Key}:", "noop") }); + + var variantButtons = new List(); + foreach (var variant in group.OrderBy(v => v.SortOrder)) + { + string variantInfo = ""; + + // Show price if different from base product price + if (variant.Price.HasValue && variant.Price.Value != product.Price) + { + variantInfo = $" - Ā£{variant.Price.Value:F2}"; + } + + var isSelected = selectedVariants.Contains(variant.Name); + var buttonText = isSelected + ? $"āœ… {variant.Name}{variantInfo}" + : $"{variant.Name}{variantInfo}"; + + var callbackData = $"setvariant:{_mapper.GetShortId(product.Id, "p")}:{variant.Name}"; + + variantButtons.Add(InlineKeyboardButton.WithCallbackData( + buttonText, + callbackData + )); + } + + // Add variant buttons in rows of 3 + for (int i = 0; i < variantButtons.Count; i += 3) + { + buttons.Add(variantButtons.Skip(i).Take(3).ToArray()); + } } - // Add regular single item option - var singleCallbackData = hasVariants - ? _mapper.BuildCallback("selectvar", product.Id, 1) - : _mapper.BuildCallback("add", product.Id, 1); + // Check if all variant types have been selected + bool canConfirm = variantGroups.All(g => g.Any(v => selectedVariants.Contains(v.Name))); - buttons.Add(new[] { - InlineKeyboardButton.WithCallbackData( - $"šŸ›’ BUY {product.Name} - Ā£{product.Price:F2}", - singleCallbackData - ) - }); + if (canConfirm) + { + var variantString = string.Join(",", selectedVariants); + var shortProductId = _mapper.GetShortId(product.Id, "p"); + var callbackData = $"confirmvar:{shortProductId}:1:null:{variantString}"; + + buttons.Add(new[] { + InlineKeyboardButton.WithCallbackData( + $"āœ… Add to Basket", + callbackData + ) + }); + } } else { - // No multi-buys, show quantity selector - var quantityButtons = new List(); - if (quantity > 1) - quantityButtons.Add(InlineKeyboardButton.WithCallbackData("āž–", _mapper.BuildCallback("qty", product.Id, quantity - 1))); - quantityButtons.Add(InlineKeyboardButton.WithCallbackData($"Qty: {quantity}", "noop")); - if (quantity < 10) - quantityButtons.Add(InlineKeyboardButton.WithCallbackData("āž•", _mapper.BuildCallback("qty", product.Id, quantity + 1))); - - buttons.Add(quantityButtons.ToArray()); - - // Buy button - var addCallbackData = hasVariants - ? _mapper.BuildCallback("selectvar", product.Id, quantity) - : _mapper.BuildCallback("add", product.Id, quantity); + // No variants, simple add to basket button + var addCallbackData = _mapper.BuildCallback("add", product.Id, 1); buttons.Add(new[] { InlineKeyboardButton.WithCallbackData( - $"šŸ›’ BUY {product.Name} - Ā£{product.Price * quantity:F2}", + $"šŸ›’ Add to Basket - Ā£{product.Price:F2}", addCallbackData ) }); @@ -170,7 +187,25 @@ namespace TeleBot.UI return new InlineKeyboardMarkup(buttons); } - + + public InlineKeyboardMarkup PostAddToCartMenu(Guid productId) + { + var buttons = new List + { + new[] + { + InlineKeyboardButton.WithCallbackData("šŸ›’ View Basket", "cart"), + InlineKeyboardButton.WithCallbackData("šŸ’³ Checkout", "checkout") + }, + new[] + { + InlineKeyboardButton.WithCallbackData("ā—€ļø Continue Shopping", _mapper.BuildCallback("product", productId)) + } + }; + + return new InlineKeyboardMarkup(buttons); + } + public InlineKeyboardMarkup CartMenu(ShoppingCart cart) { var buttons = new List(); @@ -193,9 +228,9 @@ namespace TeleBot.UI InlineKeyboardButton.WithCallbackData("āœ… Proceed to Checkout", "checkout") }); - // Clear cart button - buttons.Add(new[] { - InlineKeyboardButton.WithCallbackData("šŸ—‘ļø Clear Cart", "clear_cart") + // Clear basket button + buttons.Add(new[] { + InlineKeyboardButton.WithCallbackData("šŸ—‘ļø Clear Basket", "clear_cart") }); } @@ -379,7 +414,7 @@ namespace TeleBot.UI : _mapper.BuildCallback("add", product.Id, quantity); buttons.Add(new[] { - InlineKeyboardButton.WithCallbackData($"šŸ›’ Add to Cart", callbackData) + InlineKeyboardButton.WithCallbackData($"šŸ›’ Add to Basket", callbackData) }); buttons.Add(new[] { InlineKeyboardButton.WithCallbackData("ā¬…ļø Back", _mapper.BuildCallback("product", product.Id)) }); return new InlineKeyboardMarkup(buttons); @@ -522,7 +557,7 @@ namespace TeleBot.UI buttons.Add(new[] { InlineKeyboardButton.WithCallbackData( - $"āœ… Confirm & Add to Cart", + $"āœ… Confirm & Add to Basket", callbackData ) }); @@ -626,10 +661,10 @@ namespace TeleBot.UI } else { - // No multi-buys, just show regular add to cart + // No multi-buys, just show regular add to basket buttons.Add(new[] { - InlineKeyboardButton.WithCallbackData($"Add to Cart - Ā£{product.Price:F2}", $"add:{product.Id}:{defaultQuantity}") + InlineKeyboardButton.WithCallbackData($"Add to Basket - Ā£{product.Price:F2}", $"add:{product.Id}:{defaultQuantity}") }); } @@ -669,7 +704,7 @@ namespace TeleBot.UI { new[] { InlineKeyboardButton.WithCallbackData("ā¬…ļø Back to Categories", "browse"), - InlineKeyboardButton.WithCallbackData("šŸ›’ View Cart", "cart") + InlineKeyboardButton.WithCallbackData("šŸ›’ View Basket", "cart") }, new[] { InlineKeyboardButton.WithCallbackData("šŸ  Main Menu", "menu") diff --git a/TeleBot/TeleBot/UI/MessageFormatter.cs b/TeleBot/TeleBot/UI/MessageFormatter.cs index 6b510b0..ed03896 100644 --- a/TeleBot/TeleBot/UI/MessageFormatter.cs +++ b/TeleBot/TeleBot/UI/MessageFormatter.cs @@ -136,7 +136,7 @@ namespace TeleBot.UI sb.AppendLine($"\nšŸ–¼ļø _{product.Photos.Count} photo(s) available_"); } - sb.AppendLine("\nSelect quantity and add to cart:"); + sb.AppendLine("\nSelect quantity and add to basket:"); return sb.ToString(); } @@ -183,7 +183,7 @@ namespace TeleBot.UI sb.AppendLine($"\nšŸ“ *Description:*\n{product.Description}"); } - sb.AppendLine("\n*Select an option to add to cart:*"); + sb.AppendLine("\n*Select an option to add to basket:*"); return sb.ToString(); } @@ -191,12 +191,12 @@ namespace TeleBot.UI public static string FormatCart(ShoppingCart cart) { var sb = new StringBuilder(); - sb.AppendLine("šŸ›’ *Shopping Cart*\n"); + sb.AppendLine("šŸ›’ *Shopping Basket*\n"); if (cart.IsEmpty()) { - sb.AppendLine("Your cart is empty.\n"); - sb.AppendLine("Browse products to add items to your cart."); + sb.AppendLine("Your basket is empty.\n"); + sb.AppendLine("Browse products to add items to your basket."); return sb.ToString(); } @@ -363,13 +363,13 @@ namespace TeleBot.UI "/start - Start shopping\n" + "/browse - Browse categories\n" + "/products - View all products\n" + - "/cart - View shopping cart\n" + + "/cart - View shopping basket\n" + "/orders - View your orders\n" + "/review - Review delivered products\n" + "/reviews - View all product reviews\n" + "/support - Chat with support\n" + "/privacy - Privacy policy\n" + - "/clear - Clear shopping cart\n" + + "/clear - Clear shopping basket\n" + "/cancel - Cancel current operation\n" + "/delete - Delete all your data\n" + "/help - Show this help message\n\n";