diff options
Diffstat (limited to 'frontend/src/Profile.elm')
-rw-r--r-- | frontend/src/Profile.elm | 211 |
1 files changed, 211 insertions, 0 deletions
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 ] | ||