All files / src/components/features/promotions/AppliedPromotions index.tsx

14.54% Statements 16/110
100% Branches 0/0
0% Functions 0/1
14.54% Lines 16/110

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 1111x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                                                                                                                                             1x 1x  
"use client";
 
import { Icon } from "@/components/ui/icons";
import { cn } from "@/lib/core";
import type { SavingsBreakdownItem } from "@/lib/promotions/types";
 
interface AppliedPromotionsProps {
  promotions: SavingsBreakdownItem[];
  totalSavings: number;
  onRemove?: (promotionId: number) => void;
  removablePromotionIds?: number[];
  className?: string;
}
 
export function AppliedPromotions({
  promotions,
  totalSavings,
  onRemove,
  removablePromotionIds = [],
  className}: AppliedPromotionsProps) {
  if (promotions.length === 0) {
    return null;
  }

  const formatCurrency = (amount: number) => {
    return new Intl.NumberFormat("en-US", {
      style: "currency",
      currency: "USD"}).format(amount);
  };

  const getPromotionIcon = (type: string): "tag" | "package" | "star" | "shopping-bag" => {
    switch (type) {
      case "PERCENTAGE_OFF":
      case "FIXED_AMOUNT_OFF":
        return "tag";
      case "FREE_SHIPPING":
        return "package";
      case "BOGO":
        return "shopping-bag";
      case "BUNDLE":
        return "package";
      case "FLASH_SALE":
        return "tag";
      case "LOYALTY_REDEMPTION":
        return "star";
      default:
        return "tag";
    }
  };

  return (
    <div className={cn("space-y-3", className)}>
      <h4 className="text-sm font-semibold text-gray-700 flex items-center gap-2">
        <Icon name="check-circle" size={16} className="text-green-500" />
        Applied Discounts
      </h4>

      <div className="space-y-2">
        {promotions.map((promo) => {
          const isRemovable = removablePromotionIds.includes(promo.promotionId);

          return (
            <div
              key={promo.promotionId}
              className="flex items-center justify-between p-2 bg-green-50 border border-green-100 rounded-lg"
            >
              <div className="flex items-center gap-2">
                <Icon
                  name={getPromotionIcon(promo.type)}
                  size={16}
                  className="text-green-600"
                />
                <span className="text-sm text-green-800">
                  {promo.displayName || promo.promotionName}
                </span>
              </div>
              <div className="flex items-center gap-2">
                <span className="text-sm font-semibold text-green-700">
                  -{formatCurrency(promo.discountAmount)}
                </span>
                {isRemovable && onRemove && (
                  <button
                    onClick={() => onRemove(promo.promotionId)}
                    className="text-green-500 hover:text-green-700 transition-colors"
                    aria-label={`Remove ${promo.promotionName}`}
                  >
                    <Icon name="close" size={14} />
                  </button>
                )}
              </div>
            </div>
          );
        })}
      </div>

      {promotions.length > 1 && (
        <div className="flex justify-between items-center pt-2 border-t border-green-200">
          <span className="text-sm font-semibold text-green-800">
            Total Savings
          </span>
          <span className="text-base font-bold text-green-700">
            -{formatCurrency(totalSavings)}
          </span>
        </div>
      )}
    </div>
  );
}
 
export default AppliedPromotions;