aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/Cart.elm
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/Cart.elm')
-rw-r--r--frontend/src/Cart.elm164
1 files changed, 164 insertions, 0 deletions
diff --git a/frontend/src/Cart.elm b/frontend/src/Cart.elm
new file mode 100644
index 0000000..a1750f6
--- /dev/null
+++ b/frontend/src/Cart.elm
@@ -0,0 +1,164 @@
1module Cart exposing (..)
2
3import Browser
4import Browser.Navigation as Nav
5import Html exposing (..)
6import Html.Attributes exposing (..)
7import Html.Events exposing (..)
8import Http
9import Json.Decode as D
10import Json.Encode as Encode
11import Url
12import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string)
13
14
15type alias Product =
16 { id : Int
17 , name : String
18 , kind : Maybe String
19 , price : Float
20 , description : Maybe String
21 }
22
23
24type alias Model =
25 { pageStatus : Status
26 , products : List Product
27 }
28
29
30type Status
31 = Loading
32 | Loaded
33 | NotLoaded
34
35
36type Msg
37 = CartLoaded (Result Http.Error (List Product))
38 | FetchCartItems
39 | RemoveFromCart Int
40 | CartItemRemoved (Result Http.Error ())
41
42
43init : Model
44init =
45 Model NotLoaded []
46
47
48update : Msg -> Model -> ( Model, Cmd Msg )
49update msg model =
50 case msg of
51 CartLoaded res ->
52 case res of
53 Ok s ->
54 ( { model | products = s, pageStatus = Loaded }, Cmd.none )
55
56 Err e ->
57 let
58 _ =
59 Debug.log "error" e
60 in
61 ( { model | pageStatus = NotLoaded }, Cmd.none )
62
63 RemoveFromCart id ->
64 ( model, removeProduct id )
65
66 CartItemRemoved _ ->
67 ( { model | pageStatus = Loading }, fetchCartItems )
68
69 FetchCartItems ->
70 ( { model | pageStatus = Loading }, fetchCartItems )
71
72
73decodeProduct : D.Decoder Product
74decodeProduct =
75 D.map5 Product
76 (D.field "id" D.int)
77 (D.field "name" D.string)
78 (D.field "kind" (D.nullable D.string))
79 (D.field "price" D.float)
80 (D.field "description" (D.nullable D.string))
81
82
83decodeResponse : D.Decoder (List Product)
84decodeResponse =
85 D.list decodeProduct
86
87
88removeProduct : Int -> Cmd Msg
89removeProduct id =
90 let
91 _ =
92 Debug.log "cart" "fetching cart items"
93 in
94 Http.riskyRequest
95 { method = "POST"
96 , headers = []
97 , url = "http://127.0.0.1:7878/cart/remove"
98 , body = Http.stringBody "application/json" <| String.fromInt id
99 , expect = Http.expectWhatever CartItemRemoved
100 , timeout = Nothing
101 , tracker = Nothing
102 }
103
104
105fetchCartItems : Cmd Msg
106fetchCartItems =
107 let
108 _ =
109 Debug.log "cart" "fetching cart items"
110 in
111 Http.riskyRequest
112 { method = "GET"
113 , headers = []
114 , url = "http://127.0.0.1:7878/cart/items"
115 , body = Http.emptyBody
116 , expect = Http.expectJson CartLoaded decodeResponse
117 , timeout = Nothing
118 , tracker = Nothing
119 }
120
121
122viewStatus : Status -> String
123viewStatus s =
124 case s of
125 Loading ->
126 "Loading"
127
128 Loaded ->
129 "Ready!"
130
131 NotLoaded ->
132 "Not loaded ..."
133
134
135viewProduct : Product -> Html Msg
136viewProduct p =
137 div []
138 [ text p.name
139 , div [] [ text <| Maybe.withDefault "" p.kind ]
140 , div [] [ text <| Maybe.withDefault "" p.description ]
141 , div [] [ text <| String.fromFloat p.price ]
142 , div [] [ button [ onClick (RemoveFromCart p.id) ] [ text "Remove" ] ]
143 , div [] [ a [ href ("/product/" ++ String.fromInt p.id) ] [ text "View Product" ] ]
144 ]
145
146
147view : Model -> Html Msg
148view model =
149 case model.pageStatus of
150 Loading ->
151 div [] [ text <| viewStatus Loading ]
152
153 _ ->
154 div []
155 [ let
156 cart =
157 List.map viewProduct model.products
158 in
159 if List.isEmpty cart then
160 text "No items in cart"
161
162 else
163 ul [] cart
164 ]