This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.
1.0.0 1.0.1
README

Cart

A tiny library for shopping carts. It supports any Product types to add into a cart. The price function is required for cart and item subtotal calculation.

Types

type alias Item a = { product : a , qty : Int , date_added : Date }

Item record is a counter of added products into the cart.

type alias Product = { id : Int, price : Float }
item = { product = { id = 1, price = 10.0 }, qty = 1 }
type alias Cart a = List (Item a)

Cart is a list of Items.

Modifying Cart contents

add : a -> Cart a -> Time -> Cart a

Add the product to the cart. Time of adding is specified as a parameter.

type alias Product = { id : Int, price : Float }

add (Product 1 10.0) cart 12345 ==
  [{ product = { id = 1, price = 10.0 }, qty = 1, date_added = 12345 }]
inc : a -> Cart a -> Cart a

Increase quantity of the product in the cart.

type alias Product = { id : Int, price : Float }
p = Product 1 10.0

c = add p cart 12345
c == [{ product = { id = 1, price = 10.0 }, qty = 1, date_added = 12345 }]

inc p c == [{ product = { id = 1, price = 10.0 }, qty = 2, date_added = 12345 }]
dec : a -> Cart a -> Cart a

Decrease quantity of the product in the cart.

type alias Product = { id : Int, price : Float }
p = Product 1 10.0
c = inc p (add p cart 12345)

c == [{ product = { id = 1, price = 10.0 }, qty = 2, date_added = 12345 }]

dec p c == [{ product = { id = 1, price = 10.0 }, qty = 1 }]
dec p (dec p c) == []
remove : a -> Cart a -> Cart a

Remove the product from the cart.

type alias Product = { id : Int, price : Float }
p = Product 1 10.0
c = add p cart 12345
c == [{ product = { id = 1, price = 10.0 }, qty = 1, date_added = 12345 }]
remove p c == []
changeQty : a -> Int -> Cart a -> Result String (Cart a)

Change the product quantity in the cart. Returns new Cart Ok result or Err.

type alias Product = { id : Int, price : Float }
p = Product 1 10.0
c = inc p (add p cart 12345)

changeQty p 10 cart == Ok [{ product = { id = 1, price = 10.0 }, qty = 10, date_added = 12345 }]
changeQty p 0 cart == Ok []
changeQty p -1 cart == Error "Wrong negative quantuty used"

Cart operations

cart : List (Item a)

Return an empty cart.

cart == []
subtotal : (a -> Float) -> Cart a -> Float

Get subtotal of the cart with the given price function for getting price of stored products in the cart.

type alias Product = { id : Int, price : Float }
p = Product 1 10.0
subtotal .price (inc p (add p cart 12345)) == 20.0
qty : Cart a -> Int

Get a quantity of all products in the cart.

type alias Product = { id : Int, price : Float }

qty (cart add <| Product 1 10.0 ) == 1

Cart Item operations

itemSubtotal : (a -> Float) -> Item a -> Float

Get the item subtotal with the given price function required for getting price of the product.

type alias Product = { id : Int, price : Float }

itemSubtotal .price (item <| Product 1 10.0) == 10.0
module Cart exposing
  ( Item, Cart
  , qty, cart
  , add, inc, dec, remove, changeQty
  , itemSubtotal, subtotal
  )

{-| A tiny library for shopping carts. It supports any Product types to add into a cart.
The ```price``` function is required for cart and item subtotal calculation.

# Types
@docs Item, Cart

# Modifying Cart contents
@docs add, inc, dec, remove, changeQty

# Cart operations
@docs cart, subtotal, qty

# Cart Item operations
@docs itemSubtotal

-}


import List exposing (isEmpty, map, foldl, filter, append, sum)
import Time exposing (Time)
import Date exposing (Date)
import Result exposing (Result)


{-| Item record is a counter of added products into the cart.

    type alias Product = { id : Int, price : Float }
    item = { product = { id = 1, price = 10.0 }, qty = 1 }
-}
type alias Item a =
  { product : a
  , qty : Int
  , date_added : Date
  }


{-| Cart is a list of Items.
-}
type alias Cart a =
  List (Item a)


{-| Return an empty cart.

    cart == []
-}
cart : List (Item a)
cart =
  []


{-| Get a quantity of all products in the cart.

    type alias Product = { id : Int, price : Float }

    qty (cart add <| Product 1 10.0 ) == 1
-}
qty : Cart a -> Int
qty cart =
  foldl (+) 0 (map .qty cart)


{-| Get the item subtotal with the given price function required for getting price of the product.

    type alias Product = { id : Int, price : Float }

    itemSubtotal .price (item <| Product 1 10.0) == 10.0
-}
itemSubtotal : (a -> Float) -> Item a -> Float
itemSubtotal price_f item =
  price_f item.product * toFloat item.qty


{-| Add the product to the cart. Time of adding is specified as a parameter.

    type alias Product = { id : Int, price : Float }

    add (Product 1 10.0) cart 12345 ==
      [{ product = { id = 1, price = 10.0 }, qty = 1, date_added = 12345 }]
-}
add : a -> Cart a -> Time -> Cart a
add product cart time =
    if (isEmpty cart) || isEmpty (filter (\i -> i.product == product) cart)
      then append cart [Item product 1 (Date.fromTime time) ]
      else inc product cart


{-| Increase quantity of the product in the cart.

    type alias Product = { id : Int, price : Float }
    p = Product 1 10.0

    c = add p cart 12345
    c == [{ product = { id = 1, price = 10.0 }, qty = 1, date_added = 12345 }]

    inc p c == [{ product = { id = 1, price = 10.0 }, qty = 2, date_added = 12345 }]
-}
inc : a -> Cart a -> Cart a
inc product cart =
  let
    updateQty i =
      if i.product == product then { i | qty = i.qty + 1 } else i
  in
    map updateQty cart


{-| Decrease quantity of the product in the cart.

    type alias Product = { id : Int, price : Float }
    p = Product 1 10.0
    c = inc p (add p cart 12345)

    c == [{ product = { id = 1, price = 10.0 }, qty = 2, date_added = 12345 }]

    dec p c == [{ product = { id = 1, price = 10.0 }, qty = 1 }]
    dec p (dec p c) == []
-}
dec : a -> Cart a -> Cart a
dec product cart =
  let
    isLastItem i =
      if i.qty == 1 && i.product == product then False else True

    decItem i =
      if i.product == product then { i | qty = i.qty - 1 } else i

  in
    map decItem <| filter isLastItem cart

{-| Change the product quantity in the cart. Returns new Cart Ok result or Err.

    type alias Product = { id : Int, price : Float }
    p = Product 1 10.0
    c = inc p (add p cart 12345)

    changeQty p 10 cart == Ok [{ product = { id = 1, price = 10.0 }, qty = 10, date_added = 12345 }]
    changeQty p 0 cart == Ok []
    changeQty p -1 cart == Error "Wrong negative quantuty used"
-}
changeQty : a -> Int -> Cart a -> Result String (Cart a)
changeQty product qty cart =
  if qty == 0 then
    Ok (remove product cart)
  else if qty > 0 then
    let
      updateQty i =
        if i.product == product then { i | qty = qty } else i
    in
      Result.Ok (map updateQty cart)
  else
    Result.Err "Wrong negative quantuty used"


{-| Remove the product from the cart.

    type alias Product = { id : Int, price : Float }
    p = Product 1 10.0
    c = add p cart 12345
    c == [{ product = { id = 1, price = 10.0 }, qty = 1, date_added = 12345 }]
    remove p c == []
-}
remove : a -> Cart a -> Cart a
remove product cart =
  filter (\i -> i.product /= product) cart


{-| Get subtotal of the cart with the given price function for getting price of stored products in the cart.

    type alias Product = { id : Int, price : Float }
    p = Product 1 10.0
    subtotal .price (inc p (add p cart 12345)) == 20.0

-}
subtotal : (a -> Float) -> Cart a -> Float
subtotal price_f cart =
  sum <| map (itemSubtotal price_f) cart