diff options
Diffstat (limited to 'frontend/src/Catalog.elm')
-rw-r--r-- | frontend/src/Catalog.elm | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/frontend/src/Catalog.elm b/frontend/src/Catalog.elm new file mode 100644 index 0000000..80e5e38 --- /dev/null +++ b/frontend/src/Catalog.elm | |||
@@ -0,0 +1,125 @@ | |||
1 | module Catalog exposing (..) | ||
2 | |||
3 | import Browser | ||
4 | import Browser.Navigation as Nav | ||
5 | import Html exposing (..) | ||
6 | import Html.Attributes exposing (..) | ||
7 | import Html.Events exposing (..) | ||
8 | import Http | ||
9 | import Json.Decode as D | ||
10 | import Json.Encode as Encode | ||
11 | import Url | ||
12 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) | ||
13 | |||
14 | |||
15 | type alias Product = | ||
16 | { id : Int | ||
17 | , name : String | ||
18 | , kind : Maybe String | ||
19 | , price : Float | ||
20 | , description : Maybe String | ||
21 | } | ||
22 | |||
23 | |||
24 | type alias Model = | ||
25 | { pageStatus : Status | ||
26 | , products : List Product | ||
27 | } | ||
28 | |||
29 | |||
30 | type Status | ||
31 | = Loading | ||
32 | | Loaded | ||
33 | | NotLoaded | ||
34 | |||
35 | |||
36 | type Msg | ||
37 | = ProductsLoaded (Result Http.Error (List Product)) | ||
38 | | FetchProducts | ||
39 | |||
40 | |||
41 | init : Model | ||
42 | init = | ||
43 | Model NotLoaded [] | ||
44 | |||
45 | |||
46 | update : Msg -> Model -> ( Model, Cmd Msg ) | ||
47 | update msg model = | ||
48 | case msg of | ||
49 | ProductsLoaded res -> | ||
50 | case res of | ||
51 | Ok s -> | ||
52 | ( { model | products = s, pageStatus = Loaded }, Cmd.none ) | ||
53 | |||
54 | Err e -> | ||
55 | let | ||
56 | _ = | ||
57 | Debug.log "error" e | ||
58 | in | ||
59 | ( { model | pageStatus = NotLoaded }, Cmd.none ) | ||
60 | |||
61 | FetchProducts -> | ||
62 | ( { model | pageStatus = Loading }, fetchProducts ) | ||
63 | |||
64 | |||
65 | decodeProduct : D.Decoder Product | ||
66 | decodeProduct = | ||
67 | D.map5 Product | ||
68 | (D.field "id" D.int) | ||
69 | (D.field "name" D.string) | ||
70 | (D.field "kind" (D.nullable D.string)) | ||
71 | (D.field "price" D.float) | ||
72 | (D.field "description" (D.nullable D.string)) | ||
73 | |||
74 | |||
75 | decodeResponse : D.Decoder (List Product) | ||
76 | decodeResponse = | ||
77 | D.list decodeProduct | ||
78 | |||
79 | |||
80 | fetchProducts : Cmd Msg | ||
81 | fetchProducts = | ||
82 | let | ||
83 | _ = | ||
84 | Debug.log "err" "fetching products" | ||
85 | in | ||
86 | Http.get | ||
87 | { url = "http://127.0.0.1:7878/product/catalog" | ||
88 | , expect = Http.expectJson ProductsLoaded decodeResponse | ||
89 | } | ||
90 | |||
91 | |||
92 | viewStatus : Status -> String | ||
93 | viewStatus s = | ||
94 | case s of | ||
95 | Loading -> | ||
96 | "Loading" | ||
97 | |||
98 | Loaded -> | ||
99 | "Ready!" | ||
100 | |||
101 | NotLoaded -> | ||
102 | "Not loaded ..." | ||
103 | |||
104 | |||
105 | viewProduct : Product -> Html Msg | ||
106 | viewProduct p = | ||
107 | div [] | ||
108 | [ text p.name | ||
109 | , text <| Maybe.withDefault "" p.kind | ||
110 | , text <| Maybe.withDefault "" p.description | ||
111 | , text <| String.fromFloat p.price | ||
112 | , a [ href ("/product/" ++ String.fromInt p.id) ] [ text "View Product" ] | ||
113 | ] | ||
114 | |||
115 | |||
116 | view : Model -> Html Msg | ||
117 | view model = | ||
118 | case model.pageStatus of | ||
119 | Loading -> | ||
120 | div [] [ text <| viewStatus Loading ] | ||
121 | |||
122 | _ -> | ||
123 | div [] | ||
124 | [ ul [] (List.map viewProduct model.products) | ||
125 | ] | ||