diff options
Diffstat (limited to 'frontend/src')
-rw-r--r-- | frontend/src/Cart.elm | 83 | ||||
-rw-r--r-- | frontend/src/Catalog.elm | 2 | ||||
-rw-r--r-- | frontend/src/Checkout.elm | 31 | ||||
-rw-r--r-- | frontend/src/Main.elm | 62 | ||||
-rw-r--r-- | frontend/src/Product.elm | 2 | ||||
-rw-r--r-- | frontend/src/Profile.elm | 211 | ||||
-rw-r--r-- | frontend/src/Styles.elm | 14 |
7 files changed, 361 insertions, 44 deletions
diff --git a/frontend/src/Cart.elm b/frontend/src/Cart.elm index 44d5a0d..008d0bc 100644 --- a/frontend/src/Cart.elm +++ b/frontend/src/Cart.elm | |||
@@ -2,6 +2,7 @@ module Cart exposing (..) | |||
2 | 2 | ||
3 | import Browser | 3 | import Browser |
4 | import Browser.Navigation as Nav | 4 | import Browser.Navigation as Nav |
5 | import Css exposing (..) | ||
5 | import Html | 6 | import Html |
6 | import Html.Styled exposing (..) | 7 | import Html.Styled exposing (..) |
7 | import Html.Styled.Attributes exposing (..) | 8 | import Html.Styled.Attributes exposing (..) |
@@ -9,8 +10,8 @@ import Html.Styled.Events exposing (..) | |||
9 | import Http | 10 | import Http |
10 | import Json.Decode as D | 11 | import Json.Decode as D |
11 | import Json.Encode as Encode | 12 | import Json.Encode as Encode |
12 | import Url | 13 | import Styles exposing (..) |
13 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) | 14 | import Utils exposing (..) |
14 | 15 | ||
15 | 16 | ||
16 | type alias Product = | 17 | type alias Product = |
@@ -181,15 +182,24 @@ calculateTotal model = | |||
181 | 182 | ||
182 | viewCartItemListing : CartListing -> Html Msg | 183 | viewCartItemListing : CartListing -> Html Msg |
183 | viewCartItemListing listing = | 184 | viewCartItemListing listing = |
184 | div [] | 185 | -- div [] |
185 | [ text listing.productItem.name | 186 | -- [ text listing.productItem.name |
186 | , div [] [ text <| Maybe.withDefault "" listing.productItem.kind ] | 187 | -- , div [] [ text <| Maybe.withDefault "" listing.productItem.kind ] |
187 | , div [] [ text <| Maybe.withDefault "" listing.productItem.description ] | 188 | -- , div [] [ text <| Maybe.withDefault "" listing.productItem.description ] |
188 | , div [] [ text <| String.fromFloat listing.productItem.price ] | 189 | -- , div [] [ text <| String.fromFloat listing.productItem.price ] |
189 | , div [] [ text <| String.fromInt listing.quantity ] | 190 | -- , div [] [ text <| String.fromInt listing.quantity ] |
190 | , div [] [ button [ onClick (AddToCartPressed listing.productItem.id) ] [ text "Add" ] ] | 191 | -- , div [] [ button [ onClick (AddToCartPressed listing.productItem.id) ] [ text "Add" ] ] |
191 | , div [] [ button [ onClick (RemoveFromCart listing.productItem.id) ] [ text "Remove" ] ] | 192 | -- , div [] [ button [ onClick (RemoveFromCart listing.productItem.id) ] [ text "Remove" ] ] |
192 | , div [] [ a [ href ("/product/" ++ String.fromInt listing.productItem.id) ] [ text "View Product" ] ] | 193 | -- , div [] [ a [ href ("/product/" ++ String.fromInt listing.productItem.id) ] [ text "View Product" ] ] |
194 | -- ] | ||
195 | tr [] | ||
196 | [ td [] [ a [ href ("/product/" ++ String.fromInt listing.productItem.id) ] [ text listing.productItem.name ] ] | ||
197 | , td [] [ text <| String.fromFloat listing.productItem.price ] | ||
198 | , td [] | ||
199 | [ furbyButton [ onClick (RemoveFromCart listing.productItem.id) ] [ div [ style "font-family" "monospace" ] [ text "-" ] ] | ||
200 | , text <| String.fromInt listing.quantity | ||
201 | , furbyButton [ onClick (AddToCartPressed listing.productItem.id) ] [ div [ style "font-family" "monospace" ] [ text "+" ] ] | ||
202 | ] | ||
193 | ] | 203 | ] |
194 | 204 | ||
195 | 205 | ||
@@ -200,16 +210,41 @@ view model = | |||
200 | div [] [ text <| viewStatus Loading ] | 210 | div [] [ text <| viewStatus Loading ] |
201 | 211 | ||
202 | _ -> | 212 | _ -> |
203 | div [] | 213 | let |
204 | [ let | 214 | cart = |
205 | cart = | 215 | List.map viewCartItemListing model.products |
206 | List.map viewCartItemListing model.products | 216 | |
207 | in | 217 | headings = |
208 | if List.isEmpty cart then | 218 | [ "Product Name", "Price (₹)", "Quantity" ] |
209 | text "No items in cart" | 219 | |> List.map (th [] << List.singleton << text) |
210 | 220 | in | |
211 | else | 221 | if List.isEmpty cart then |
212 | ul [] cart | 222 | text "No items in cart" |
213 | , calculateTotal model |> String.fromFloat |> text | 223 | |
214 | , a [ href "/checkout" ] [ text "Checkout" ] | 224 | else |
215 | ] | 225 | div |
226 | [ css | ||
227 | [ margin auto | ||
228 | , marginTop (pct 5) | ||
229 | , Css.width (pct 40) | ||
230 | ] | ||
231 | ] | ||
232 | [ div [ css [ bigHeading, marginBottom (px 20) ] ] [ text "Cart" ] | ||
233 | , Html.Styled.table | ||
234 | [ css | ||
235 | [ Css.width (pct 100) | ||
236 | , maxWidth (px 650) | ||
237 | , textAlign right | ||
238 | ] | ||
239 | ] | ||
240 | (tr [] headings | ||
241 | :: cart | ||
242 | ++ [ tr [ style "padding-top" "20px" ] | ||
243 | [ td [ style "border-top" "1px solid black" ] [] | ||
244 | , td [ style "border-top" "1px solid black" ] [ div [] [ text "Cart total: " ] ] | ||
245 | , td [ style "border-top" "1px solid black" ] [ calculateTotal model |> String.fromFloat |> text ] | ||
246 | ] | ||
247 | ] | ||
248 | ) | ||
249 | , a [ href "/checkout" ] [ text "Checkout" ] | ||
250 | ] | ||
diff --git a/frontend/src/Catalog.elm b/frontend/src/Catalog.elm index 7e9bde7..d4cbf96 100644 --- a/frontend/src/Catalog.elm +++ b/frontend/src/Catalog.elm | |||
@@ -210,7 +210,7 @@ viewProduct p = | |||
210 | [ css | 210 | [ css |
211 | [ cardSecondaryText | 211 | [ cardSecondaryText |
212 | , paddingBottom (px 3) | 212 | , paddingBottom (px 3) |
213 | , fontVariant smallCaps | 213 | , textTransform uppercase |
214 | ] | 214 | ] |
215 | ] | 215 | ] |
216 | [ text <| Maybe.withDefault "" p.kind ] | 216 | [ text <| Maybe.withDefault "" p.kind ] |
diff --git a/frontend/src/Checkout.elm b/frontend/src/Checkout.elm index 4df20d8..216b90d 100644 --- a/frontend/src/Checkout.elm +++ b/frontend/src/Checkout.elm | |||
@@ -2,6 +2,7 @@ module Checkout exposing (..) | |||
2 | 2 | ||
3 | import Browser | 3 | import Browser |
4 | import Browser.Navigation as Nav | 4 | import Browser.Navigation as Nav |
5 | import Css exposing (..) | ||
5 | import Html | 6 | import Html |
6 | import Html.Styled exposing (..) | 7 | import Html.Styled exposing (..) |
7 | import Html.Styled.Attributes exposing (..) | 8 | import Html.Styled.Attributes exposing (..) |
@@ -9,9 +10,8 @@ import Html.Styled.Events exposing (..) | |||
9 | import Http | 10 | import Http |
10 | import Json.Decode as D | 11 | import Json.Decode as D |
11 | import Json.Encode as Encode | 12 | import Json.Encode as Encode |
13 | import Styles exposing (..) | ||
12 | import Tuple exposing (..) | 14 | import Tuple exposing (..) |
13 | import Url | ||
14 | import Url.Parser as P exposing ((</>), Parser, int, oneOf, s, string) | ||
15 | import Utils exposing (..) | 15 | import Utils exposing (..) |
16 | 16 | ||
17 | 17 | ||
@@ -26,6 +26,7 @@ type Status | |||
26 | = Loading | 26 | = Loading |
27 | | Loaded | 27 | | Loaded |
28 | | NotLoaded | 28 | | NotLoaded |
29 | | CheckedOut | ||
29 | 30 | ||
30 | 31 | ||
31 | type Msg | 32 | type Msg |
@@ -48,7 +49,7 @@ update msg model = | |||
48 | ( model, tryCheckout model.paymentMode ) | 49 | ( model, tryCheckout model.paymentMode ) |
49 | 50 | ||
50 | CheckoutSuccessful _ -> | 51 | CheckoutSuccessful _ -> |
51 | ( model, Cmd.none ) | 52 | ( { model | pageStatus = CheckedOut }, Cmd.none ) |
52 | 53 | ||
53 | AmountLoaded res -> | 54 | AmountLoaded res -> |
54 | case res of | 55 | case res of |
@@ -107,6 +108,9 @@ viewStatus s = | |||
107 | NotLoaded -> | 108 | NotLoaded -> |
108 | "Not loaded ..." | 109 | "Not loaded ..." |
109 | 110 | ||
111 | CheckedOut -> | ||
112 | "Checked out!" | ||
113 | |||
110 | 114 | ||
111 | view : Model -> Html Msg | 115 | view : Model -> Html Msg |
112 | view model = | 116 | view model = |
@@ -115,13 +119,22 @@ view model = | |||
115 | div [] [ text <| viewStatus Loading ] | 119 | div [] [ text <| viewStatus Loading ] |
116 | 120 | ||
117 | _ -> | 121 | _ -> |
118 | div [] | 122 | div |
119 | [ div [] [ text <| String.fromFloat <| model.cartTotal ] | 123 | [ css |
120 | , select [] | 124 | [ margin auto |
121 | [ option [ onInput PaymentModeSelected ] [ text "Cash" ] | 125 | , marginTop (pct 5) |
122 | , option [ onInput PaymentModeSelected ] [ text "Debit Card" ] | 126 | , Css.width (pct 40) |
123 | , option [ onInput PaymentModeSelected ] [ text "Credit Card" ] | ||
124 | ] | 127 | ] |
128 | ] | ||
129 | [ div [ css [ bigHeading, marginBottom (px 20) ] ] [ text "Checkout" ] | ||
130 | , div [ css [ cardSupportingText ] ] [ text "Your total is" ] | ||
131 | , div | ||
132 | [ css [ bigHeading, fontWeight bold, marginBottom (px 20) ] ] | ||
133 | [ text <| (++) "₹ " <| String.fromFloat <| model.cartTotal ] | ||
134 | , div [ css [ cardSupportingText ] ] [ text "Select a payment mode" ] | ||
135 | , div [] [ furbyRadio "Cash" (PaymentModeSelected "Cash") ] | ||
136 | , div [] [ furbyRadio "Debit Card" (PaymentModeSelected "Debit Card") ] | ||
137 | , div [] [ furbyRadio "Credit Card" (PaymentModeSelected "Credit Card") ] | ||
125 | , div [] [ a [ href "/cart" ] [ text "Cancel" ] ] | 138 | , div [] [ a [ href "/cart" ] [ text "Cancel" ] ] |
126 | , div [] [ button [ onClick CheckoutPressed ] [ text "Confirm and Pay" ] ] | 139 | , div [] [ button [ onClick CheckoutPressed ] [ text "Confirm and Pay" ] ] |
127 | ] | 140 | ] |
diff --git a/frontend/src/Main.elm b/frontend/src/Main.elm index c1489bf..09a851d 100644 --- a/frontend/src/Main.elm +++ b/frontend/src/Main.elm | |||
@@ -14,6 +14,7 @@ import Http | |||
14 | import Json.Encode as Encode | 14 | import Json.Encode as Encode |
15 | import Login | 15 | import Login |
16 | import Product | 16 | import Product |
17 | import Profile | ||
17 | import Signup | 18 | import Signup |
18 | import Styles exposing (..) | 19 | import Styles exposing (..) |
19 | import Url | 20 | import Url |
@@ -48,6 +49,7 @@ type Route | |||
48 | | CartPage | 49 | | CartPage |
49 | | ProductPage Int | 50 | | ProductPage Int |
50 | | CheckoutPage | 51 | | CheckoutPage |
52 | | ProfilePage | ||
51 | | NotFoundPage | 53 | | NotFoundPage |
52 | 54 | ||
53 | 55 | ||
@@ -61,6 +63,7 @@ parseRoute = | |||
61 | , P.map SignupPage (P.s "signup") | 63 | , P.map SignupPage (P.s "signup") |
62 | , P.map CheckoutPage (P.s "checkout") | 64 | , P.map CheckoutPage (P.s "checkout") |
63 | , P.map ProductPage (P.s "product" </> P.int) | 65 | , P.map ProductPage (P.s "product" </> P.int) |
66 | , P.map ProfilePage (P.s "profile") | ||
64 | ] | 67 | ] |
65 | 68 | ||
66 | 69 | ||
@@ -74,6 +77,7 @@ type alias Model = | |||
74 | , signupModel : Signup.Model | 77 | , signupModel : Signup.Model |
75 | , cartModel : Cart.Model | 78 | , cartModel : Cart.Model |
76 | , checkoutModel : Checkout.Model | 79 | , checkoutModel : Checkout.Model |
80 | , profileModel : Profile.Model | ||
77 | } | 81 | } |
78 | 82 | ||
79 | 83 | ||
@@ -100,8 +104,11 @@ init flags url key = | |||
100 | 104 | ||
101 | checkout = | 105 | checkout = |
102 | Checkout.init | 106 | Checkout.init |
107 | |||
108 | profile = | ||
109 | Profile.init | ||
103 | in | 110 | in |
104 | ( Model key url start login catalog product signup cart checkout, Cmd.none ) | 111 | ( Model key url start login catalog product signup cart checkout profile, Cmd.none ) |
105 | 112 | ||
106 | 113 | ||
107 | 114 | ||
@@ -117,6 +124,7 @@ type Msg | |||
117 | | SignupMessage Signup.Msg | 124 | | SignupMessage Signup.Msg |
118 | | CartMessage Cart.Msg | 125 | | CartMessage Cart.Msg |
119 | | CheckoutMessage Checkout.Msg | 126 | | CheckoutMessage Checkout.Msg |
127 | | ProfileMessage Profile.Msg | ||
120 | | LogoutPressed | 128 | | LogoutPressed |
121 | | LogoutSuccess (Result Http.Error ()) | 129 | | LogoutSuccess (Result Http.Error ()) |
122 | 130 | ||
@@ -174,6 +182,13 @@ update msg model = | |||
174 | in | 182 | in |
175 | ( { model | location = CheckoutPage }, cmd ) | 183 | ( { model | location = CheckoutPage }, cmd ) |
176 | 184 | ||
185 | Just ProfilePage -> | ||
186 | let | ||
187 | cmd = | ||
188 | Cmd.map ProfileMessage Profile.tryFetchProfile | ||
189 | in | ||
190 | ( { model | location = ProfilePage }, cmd ) | ||
191 | |||
177 | Just p -> | 192 | Just p -> |
178 | ( { model | location = p }, Cmd.none ) | 193 | ( { model | location = p }, Cmd.none ) |
179 | 194 | ||
@@ -229,10 +244,28 @@ update msg model = | |||
229 | ( cmn, cmd ) = | 244 | ( cmn, cmd ) = |
230 | Checkout.update cm model.checkoutModel | 245 | Checkout.update cm model.checkoutModel |
231 | 246 | ||
247 | redir = | ||
248 | case cmn.pageStatus of | ||
249 | Checkout.CheckedOut -> | ||
250 | Nav.replaceUrl model.key "/profile" | ||
251 | |||
252 | _ -> | ||
253 | Cmd.none | ||
254 | |||
232 | _ = | 255 | _ = |
233 | Debug.log "err" "received checkout message ..." | 256 | Debug.log "err" "received checkout message ..." |
234 | in | 257 | in |
235 | ( { model | checkoutModel = cmn }, Cmd.map CheckoutMessage cmd ) | 258 | ( { model | checkoutModel = cmn }, Cmd.batch [ Cmd.map CheckoutMessage cmd, redir ] ) |
259 | |||
260 | ProfileMessage pm -> | ||
261 | let | ||
262 | ( pmn, cmd ) = | ||
263 | Profile.update pm model.profileModel | ||
264 | |||
265 | _ = | ||
266 | Debug.log "err" "recieved profile message" | ||
267 | in | ||
268 | ( { model | profileModel = pmn }, Cmd.map ProfileMessage cmd ) | ||
236 | 269 | ||
237 | ProductMessage pm -> | 270 | ProductMessage pm -> |
238 | let | 271 | let |
@@ -359,6 +392,15 @@ view model = | |||
359 | |> pageWrap model | 392 | |> pageWrap model |
360 | } | 393 | } |
361 | 394 | ||
395 | ProfilePage -> | ||
396 | { title = "Profile" | ||
397 | , body = | ||
398 | model.profileModel | ||
399 | |> Profile.view | ||
400 | |> Html.Styled.map ProfileMessage | ||
401 | |> pageWrap model | ||
402 | } | ||
403 | |||
362 | ProductPage item -> | 404 | ProductPage item -> |
363 | { title = "Product " ++ String.fromInt item | 405 | { title = "Product " ++ String.fromInt item |
364 | , body = | 406 | , body = |
@@ -379,7 +421,7 @@ viewHeader model = | |||
379 | in | 421 | in |
380 | div | 422 | div |
381 | [ css | 423 | [ css |
382 | [ padding (px 40) | 424 | [ padding (px 30) |
383 | , paddingTop (px 3) | 425 | , paddingTop (px 3) |
384 | , paddingBottom (px 3) | 426 | , paddingBottom (px 3) |
385 | , textAlign left | 427 | , textAlign left |
@@ -393,17 +435,19 @@ viewHeader model = | |||
393 | ] | 435 | ] |
394 | ) | 436 | ) |
395 | links | 437 | links |
396 | ++ [ if model.loginModel.loginStatus /= Login.LoggedIn then | 438 | ++ (if model.loginModel.loginStatus /= Login.LoggedIn then |
397 | li [ css [ display inline ] ] [ headerLink [ href "/login" ] [ text "Login" ] ] | 439 | [ furbyButton [] [ headerLink [ href "/login" ] [ text "Login" ] ] ] |
398 | 440 | ||
399 | else | 441 | else |
400 | furbyButton [ onClick LogoutPressed ] [ text "Logout" ] | 442 | [ headerLink [ href "/profile" ] [ text "Profile" ] |
401 | ] | 443 | , furbyButton [ onClick LogoutPressed ] [ text "Logout" ] |
444 | ] | ||
445 | ) | ||
402 | |> ul | 446 | |> ul |
403 | [ css | 447 | [ css |
404 | [ listStyle Css.none | 448 | [ listStyle Css.none |
405 | , padding (px 0) | 449 | , padding (px 0) |
406 | , margin (px 24) | 450 | , margin (px 12) |
407 | ] | 451 | ] |
408 | ] | 452 | ] |
409 | ] | 453 | ] |
diff --git a/frontend/src/Product.elm b/frontend/src/Product.elm index 79256cc..0975c8d 100644 --- a/frontend/src/Product.elm +++ b/frontend/src/Product.elm | |||
@@ -287,7 +287,7 @@ viewProduct p = | |||
287 | [ css | 287 | [ css |
288 | [ cardSecondaryText | 288 | [ cardSecondaryText |
289 | , paddingBottom (px 3) | 289 | , paddingBottom (px 3) |
290 | , fontVariant smallCaps | 290 | , textTransform uppercase |
291 | ] | 291 | ] |
292 | ] | 292 | ] |
293 | [ text <| Maybe.withDefault "" p.kind ] | 293 | [ text <| Maybe.withDefault "" p.kind ] |
diff --git a/frontend/src/Profile.elm b/frontend/src/Profile.elm new file mode 100644 index 0000000..6575d41 --- /dev/null +++ b/frontend/src/Profile.elm | |||
@@ -0,0 +1,211 @@ | |||
1 | module Profile exposing (..) | ||
2 | |||
3 | import Browser | ||
4 | import Browser.Navigation as Nav | ||
5 | import Css exposing (..) | ||
6 | import Html | ||
7 | import Html.Styled exposing (..) | ||
8 | import Html.Styled.Attributes exposing (..) | ||
9 | import Html.Styled.Events exposing (..) | ||
10 | import Http | ||
11 | import Icons exposing (..) | ||
12 | import Json.Decode as D | ||
13 | import Json.Encode as Encode | ||
14 | import Styles exposing (..) | ||
15 | import Utils exposing (..) | ||
16 | |||
17 | |||
18 | emptyProfile = | ||
19 | UserProfile "" "" "" Nothing 0 [] | ||
20 | |||
21 | |||
22 | type alias Transaction = | ||
23 | { amount : Float | ||
24 | , transactionId : Int | ||
25 | , orderDate : String | ||
26 | , paymentMode : String | ||
27 | } | ||
28 | |||
29 | |||
30 | type alias UserProfile = | ||
31 | { username : String | ||
32 | , phoneNumber : String | ||
33 | , emailId : String | ||
34 | , address : Maybe String | ||
35 | , ratingsGiven : Int | ||
36 | , transactions : List Transaction | ||
37 | } | ||
38 | |||
39 | |||
40 | type alias Model = | ||
41 | { profile : UserProfile | ||
42 | , status : Status | ||
43 | } | ||
44 | |||
45 | |||
46 | type Status | ||
47 | = Loading | ||
48 | | Loaded | ||
49 | | NotLoaded | ||
50 | |||
51 | |||
52 | type Msg | ||
53 | = ProfileLoaded (Result Http.Error UserProfile) | ||
54 | | FetchProfile | ||
55 | |||
56 | |||
57 | init : Model | ||
58 | init = | ||
59 | Model emptyProfile NotLoaded | ||
60 | |||
61 | |||
62 | update : Msg -> Model -> ( Model, Cmd Msg ) | ||
63 | update msg model = | ||
64 | case msg of | ||
65 | ProfileLoaded res -> | ||
66 | case res of | ||
67 | Ok p -> | ||
68 | ( { model | profile = p }, Cmd.none ) | ||
69 | |||
70 | Err _ -> | ||
71 | ( { model | status = NotLoaded }, Cmd.none ) | ||
72 | |||
73 | FetchProfile -> | ||
74 | ( { model | status = Loading }, tryFetchProfile ) | ||
75 | |||
76 | |||
77 | decodeProfile : D.Decoder UserProfile | ||
78 | decodeProfile = | ||
79 | D.map6 UserProfile | ||
80 | (D.field "username" D.string) | ||
81 | (D.field "phone_number" D.string) | ||
82 | (D.field "email_id" D.string) | ||
83 | (D.field "address" (D.nullable D.string)) | ||
84 | (D.field "ratings_given" D.int) | ||
85 | (D.field "transactions" (D.list decodeTransaction)) | ||
86 | |||
87 | |||
88 | decodeTransaction : D.Decoder Transaction | ||
89 | decodeTransaction = | ||
90 | D.map4 Transaction | ||
91 | (D.field "amount" D.float) | ||
92 | (D.field "id" D.int) | ||
93 | (D.field "order_date" D.string) | ||
94 | (D.field "payment_type" D.string) | ||
95 | |||
96 | |||
97 | tryFetchProfile : Cmd Msg | ||
98 | tryFetchProfile = | ||
99 | let | ||
100 | _ = | ||
101 | Debug.log "err" <| "fetching user profile" | ||
102 | in | ||
103 | Http.riskyRequest | ||
104 | { method = "GET" | ||
105 | , headers = [] | ||
106 | , url = "http://127.0.0.1:7878/user/profile" | ||
107 | , body = Http.emptyBody | ||
108 | , expect = Http.expectJson ProfileLoaded decodeProfile | ||
109 | , timeout = Nothing | ||
110 | , tracker = Nothing | ||
111 | } | ||
112 | |||
113 | |||
114 | viewStatus : Status -> String | ||
115 | viewStatus s = | ||
116 | case s of | ||
117 | Loading -> | ||
118 | "Loading" | ||
119 | |||
120 | Loaded -> | ||
121 | "Ready!" | ||
122 | |||
123 | NotLoaded -> | ||
124 | "Not loaded ..." | ||
125 | |||
126 | |||
127 | viewTransactions : List Transaction -> Html Msg | ||
128 | viewTransactions ts = | ||
129 | let | ||
130 | headings = | ||
131 | [ "Order ID", "Date", "Amount (₹)", "Payment Mode" ] | ||
132 | |> List.map (th [] << List.singleton << text) | ||
133 | |||
134 | transactionRow t = | ||
135 | List.map (td [] << List.singleton) | ||
136 | [ text <| String.fromInt t.transactionId | ||
137 | , text t.orderDate | ||
138 | , text <| String.fromFloat t.amount | ||
139 | , text t.paymentMode | ||
140 | ] | ||
141 | in | ||
142 | div [] | ||
143 | [ div | ||
144 | [ css [ bigHeading, marginTop (px 20), marginBottom (px 12) ] ] | ||
145 | [ text "Transactions" ] | ||
146 | , Html.Styled.table | ||
147 | [ css | ||
148 | [ Css.width (pct 100) | ||
149 | , maxWidth (px 650) | ||
150 | ] | ||
151 | ] | ||
152 | ([ tr [ style "text-align" "right" ] headings | ||
153 | ] | ||
154 | ++ List.map (tr [ style "text-align" "right" ] << transactionRow) ts | ||
155 | ) | ||
156 | ] | ||
157 | |||
158 | |||
159 | profileField : String -> String -> Html Msg | ||
160 | profileField fieldName entry = | ||
161 | div [] | ||
162 | [ div | ||
163 | [ css | ||
164 | [ cardSecondaryText | ||
165 | , textTransform uppercase | ||
166 | , paddingBottom (px 3) | ||
167 | ] | ||
168 | ] | ||
169 | [ text fieldName ] | ||
170 | , div | ||
171 | [ css | ||
172 | [ cardPrimaryText | ||
173 | , paddingBottom (px 12) | ||
174 | ] | ||
175 | ] | ||
176 | [ text entry ] | ||
177 | ] | ||
178 | |||
179 | |||
180 | viewProfile : UserProfile -> Html Msg | ||
181 | viewProfile u = | ||
182 | div | ||
183 | [] | ||
184 | [ div | ||
185 | [ css [ bigHeading, marginTop (px 20), marginBottom (px 12) ] ] | ||
186 | [ text "Profile" ] | ||
187 | , profileField "name" u.username | ||
188 | , profileField "email" u.emailId | ||
189 | , profileField "contact number" u.phoneNumber | ||
190 | , profileField "address" <| Maybe.withDefault "No address provided" u.address | ||
191 | , profileField "Total Reviews" <| String.fromInt u.ratingsGiven | ||
192 | , hr [] [] | ||
193 | , viewTransactions u.transactions | ||
194 | ] | ||
195 | |||
196 | |||
197 | view : Model -> Html Msg | ||
198 | view model = | ||
199 | case model.status of | ||
200 | Loading -> | ||
201 | div [] [ text <| viewStatus Loading ] | ||
202 | |||
203 | _ -> | ||
204 | div | ||
205 | [ css | ||
206 | [ margin auto | ||
207 | , marginTop (pct 5) | ||
208 | , Css.width (pct 40) | ||
209 | ] | ||
210 | ] | ||
211 | [ viewProfile model.profile ] | ||
diff --git a/frontend/src/Styles.elm b/frontend/src/Styles.elm index fbef6e1..4222024 100644 --- a/frontend/src/Styles.elm +++ b/frontend/src/Styles.elm | |||
@@ -71,6 +71,20 @@ furbyButton = | |||
71 | ] | 71 | ] |
72 | 72 | ||
73 | 73 | ||
74 | furbyRadio : String -> msg -> Html msg | ||
75 | furbyRadio value msg = | ||
76 | label | ||
77 | [] | ||
78 | [ input | ||
79 | [ type_ "radio" | ||
80 | , onClick msg | ||
81 | , name "radio" | ||
82 | ] | ||
83 | [] | ||
84 | , text value | ||
85 | ] | ||
86 | |||
87 | |||
74 | furbySelect : List (Attribute msg) -> List (Html msg) -> Html msg | 88 | furbySelect : List (Attribute msg) -> List (Html msg) -> Html msg |
75 | furbySelect = | 89 | furbySelect = |
76 | styled select | 90 | styled select |