Skip to main content
The DiscountCalculatorProvider manages the state and business logic for discount calculations. It extends ChangeNotifier and persists user inputs using SharedPreferences.

Overview

This provider handles two types of discounts:
  • Percentage discounts: Apply sequential percentage-based discounts
  • Fixed amount discounts: Apply dollar-value discounts
It automatically persists all inputs and calculation results across app sessions.

Enums

DiscountType

Defines the type of discount being applied.
enum DiscountType {
  percentage,
  fixedAmount,
}
percentage
DiscountType
Apply discounts as percentages (e.g., 10% off)
fixedAmount
DiscountType
Apply discounts as fixed dollar amounts (e.g., $50 off)

Constructor

DiscountCalculatorProvider(SharedPreferences prefs)
prefs
SharedPreferences
required
The SharedPreferences instance used for persisting calculator state

Getters

Calculation Results

subtotal
double?
The price after discounts but before tax
finalPrice
double?
The final price after all discounts and tax
savedAmount
double?
The total amount saved from all discounts
taxAmount
double?
The calculated tax amount based on the subtotal
errorMessage
String?
Error message if validation fails, null otherwise

Configuration

discountType
DiscountType
The current discount type (percentage or fixedAmount)

Input State

originalPriceInput
String
The persisted original price input string
primaryDiscountInput
String
The persisted primary discount input string
additionalDiscountInput
String
The persisted additional discount input string
taxInput
String
The persisted tax percentage input string
originalPrice
double?
The parsed original price value for display

Methods

calculateDiscount

Performs the discount calculation with the provided inputs.
void calculateDiscount({
  required String originalPriceStr,
  required String primaryDiscountStr,
  String additionalDiscountStr = '',
  String taxStr = '',
})
originalPriceStr
String
required
The original price before any discounts
primaryDiscountStr
String
required
The primary discount value (percentage or fixed amount depending on discountType)
additionalDiscountStr
String
default:""
Optional additional discount applied sequentially after the primary discount
taxStr
String
default:""
Optional tax percentage to apply to the subtotal

Calculation Logic

For Percentage Discounts:
  1. Apply primary discount: saved1 = originalPrice * (primaryDiscount / 100)
  2. Apply additional discount to new price: saved2 = priceAfterFirst * (additionalDiscount / 100)
  3. Calculate subtotal: subtotal = originalPrice - saved1 - saved2
  4. Apply tax: taxAmount = subtotal * (taxPercent / 100)
  5. Calculate final price: finalPrice = subtotal + taxAmount
For Fixed Amount Discounts:
  1. Sum all discounts: totalDiscount = primaryDiscount + additionalDiscount
  2. Calculate subtotal: subtotal = originalPrice - totalDiscount
  3. Apply tax: taxAmount = subtotal * (taxPercent / 100)
  4. Calculate final price: finalPrice = subtotal + taxAmount

Validation

The method validates:
  • All numeric inputs are valid numbers
  • No negative values
  • Percentage discounts don’t exceed 100%
  • Fixed discounts don’t exceed original price
If validation fails, errorMessage is set and results are cleared.

setDiscountType

Changes the discount type and persists the selection.
void setDiscountType(DiscountType type)
type
DiscountType
required
The new discount type to apply
This method automatically persists the selection to SharedPreferences and notifies listeners.

clear

Resets all inputs and calculation results.
void clear()
This method:
  • Clears all input strings
  • Removes persisted values from SharedPreferences
  • Clears all calculation results
  • Clears any error messages
  • Notifies listeners of the state change

Usage Example

import 'package:provider/provider.dart';
import 'package:numix/features/discount_calculator/providers/discount_provider.dart';

// In your widget
final provider = context.read<DiscountCalculatorProvider>();

// Set discount type
provider.setDiscountType(DiscountType.percentage);

// Calculate discount
provider.calculateDiscount(
  originalPriceStr: '100.00',
  primaryDiscountStr: '20',      // 20% off
  additionalDiscountStr: '10',   // Additional 10% off
  taxStr: '8.5',                 // 8.5% tax
);

// Access results
if (provider.errorMessage != null) {
  print('Error: ${provider.errorMessage}');
} else {
  print('Original Price: \$${provider.originalPrice}');
  print('Amount Saved: \$${provider.savedAmount}');
  print('Subtotal: \$${provider.subtotal}');
  print('Tax: \$${provider.taxAmount}');
  print('Final Price: \$${provider.finalPrice}');
}

// Clear all
provider.clear();

UI Integration

This provider is typically used with Consumer widgets to reactively update the UI:
Consumer<DiscountCalculatorProvider>(
  builder: (context, provider, child) {
    if (provider.finalPrice != null) {
      return Text('Final Price: \$${provider.finalPrice!.toStringAsFixed(2)}');
    }
    return const SizedBox.shrink();
  },
)

Persistence

All user inputs are automatically persisted using the following SharedPreferences keys:
  • disc_orig - Original price
  • disc_pri - Primary discount
  • disc_add - Additional discount
  • disc_tax - Tax percentage
  • disc_type - Discount type (0 = percentage, 1 = fixed amount)
The provider automatically restores these values when initialized.

Build docs developers (and LLMs) love