Implement product variant selection in TeleBot

FEATURES IMPLEMENTED:

1. Enhanced Product Display:
   - Shows multi-buy deals with pricing (e.g., "3 for £25")
   - Displays available variants grouped by type (Color, Flavor, etc.)
   - Clear visual separation between multi-buys and variants

2. Variant Selection Flow:
   - Single item: Select one variant from available options
   - Multi-buy bundles: Select individual variants for each item
   - Example: 3-pack allows choosing Red, Blue, Green individually
   - Visual feedback with checkmarks and counters

3. Smart Cart Management:
   - Tracks selected variants for each cart item
   - Supports both single variant (regular items) and multiple variants (multi-buys)
   - Unique cart entries based on product + variant combination
   - Prevents duplicate multi-buy bundles

4. User Experience Improvements:
   - Clear "Select Color/Flavor" prompts
   - Progress indicator for multi-item selection
   - Confirm button appears when selection complete
   - Clear selection option for multi-buys
   - Back navigation preserves context

TECHNICAL CHANGES:
- ProductCarouselService: Enhanced caption formatting with variants/multi-buys
- MenuBuilder: New VariantSelectionMenu with dynamic button generation
- CallbackHandler: Added handlers for selectvar, setvariant, addvariant, confirmvar
- ShoppingCart: New AddItem overload accepting Product and variant list
- CartItem: Added SelectedVariants list for multi-buy support
- UserSession: Added SelectingVariants state

This update enables customers to:
- See all available product options at a glance
- Choose specific variants when ordering
- Mix and match variants in multi-buy deals
- Get exactly what they want with clear visual feedback

Next steps: Add bot activity tracking for live dashboard

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-24 23:09:33 +01:00
parent 5530f9e4f5
commit f12f35cc48
5 changed files with 383 additions and 17 deletions

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using LittleShop.Client.Models;
namespace TeleBot.Models
{
@@ -11,6 +12,64 @@ namespace TeleBot.Models
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
// New method that accepts Product and variants list
public CartItem AddItem(Product product, int quantity = 1, Guid? multiBuyId = null, List<string>? selectedVariants = null)
{
decimal price = product.Price;
// If multi-buy selected, get the multi-buy price
if (multiBuyId.HasValue && product.MultiBuys != null)
{
var multiBuy = product.MultiBuys.FirstOrDefault(mb => mb.Id == multiBuyId.Value);
if (multiBuy != null)
{
price = multiBuy.Price;
quantity = multiBuy.Quantity; // Use the multi-buy quantity
}
}
// Create unique key for comparison
var variantKey = selectedVariants != null && selectedVariants.Any()
? string.Join(",", selectedVariants.OrderBy(v => v))
: null;
// Check if item already exists
var existingItem = Items.FirstOrDefault(i =>
i.ProductId == product.Id &&
i.MultiBuyId == multiBuyId &&
(i.SelectedVariant == variantKey ||
(i.SelectedVariants != null && string.Join(",", i.SelectedVariants.OrderBy(v => v)) == variantKey)));
if (existingItem != null)
{
// For multi-buys, we don't add quantities - each multi-buy is a separate bundle
if (!multiBuyId.HasValue)
{
existingItem.Quantity += quantity;
existingItem.UpdateTotalPrice();
}
return existingItem;
}
else
{
var newItem = new CartItem
{
ProductId = product.Id,
MultiBuyId = multiBuyId,
SelectedVariant = selectedVariants?.Count == 1 ? selectedVariants[0] : null,
SelectedVariants = selectedVariants ?? new List<string>(),
ProductName = product.Name,
UnitPrice = price,
Quantity = quantity
};
newItem.UpdateTotalPrice();
Items.Add(newItem);
UpdatedAt = DateTime.UtcNow;
return newItem;
}
}
// Keep the old method for backward compatibility
public void AddItem(Guid productId, string productName, decimal price, int quantity = 1, Guid? multiBuyId = null, string? selectedVariant = null)
{
var existingItem = Items.FirstOrDefault(i =>
@@ -96,7 +155,8 @@ namespace TeleBot.Models
{
public Guid ProductId { get; set; }
public Guid? MultiBuyId { get; set; } // For quantity pricing (e.g., 3 for £25)
public string? SelectedVariant { get; set; } // For color/flavor selection
public string? SelectedVariant { get; set; } // For single items - one variant
public List<string> SelectedVariants { get; set; } = new(); // For multi-buys - multiple variants
public string ProductName { get; set; } = string.Empty;
public int Quantity { get; set; }
public decimal UnitPrice { get; set; } // For multi-buys, this is the bundle price; for regular items, it's per-unit

View File

@@ -92,6 +92,7 @@ namespace TeleBot.Models
BrowsingCategories,
ViewingProducts,
ViewingProduct,
SelectingVariants,
ViewingCart,
CheckoutFlow,
ViewingOrders,