forked from guess-burger/elm-time
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSimpleTimeTracker.elm
160 lines (137 loc) · 3.32 KB
/
SimpleTimeTracker.elm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import Html exposing (Html, Attribute, text, toElement, div, textarea, ul, li)
import Html.Attributes exposing (..)
import Html.Events exposing (on, targetValue)
import Signal exposing (Address)
import StartApp.Simple as StartApp
import String
import Regex
import Dict
type alias Model = { text:String, times:List String }
main =
StartApp.start { model = initial_model, view = view, update = update }
initial_model =
{ text="", times=[] }
update : String -> Model -> Model
update newStr oldModel =
let
lines = String.split "\n" newStr
valid_times = List.filterMap maybe_valid_time lines
converted_times = to_thing valid_times
in
{text=newStr, times=converted_times}
maybe_valid_time line =
let
splitResult = Regex.split (Regex.AtMost 1) (Regex.regex " ") line
in
maybe_two splitResult
`Maybe.andThen` valid_time_length
`Maybe.andThen` numeric_min_hours
`Maybe.andThen` valid_time_values
maybe_two : List a -> Maybe (a, a)
maybe_two n =
case n of
[] ->
Nothing
time :: name :: [] ->
Just (time, name)
time :: other ->
Nothing
valid_time_length (time, name) =
if String.length time == 4
then Just (time, name)
else Nothing
numeric_min_hours x =
let
(time, name) = x
hours = String.left 2 time
mins = String.right 2 time
num_hours_result = String.toInt hours
num_mins_result = String.toInt mins
in
case (num_hours_result, num_mins_result) of
(Ok num_hours, Ok num_mins) ->
Just (num_hours, num_mins, name)
_ ->
Nothing
valid_time_values x =
let
(hr, min, name) = x
in
if(hr >= 0 && hr < 24 && min >= 0 && min < 60)
then Just(hr, min, name)
else Nothing
to_thing x =
x
|> zip_self
|> List.map to_minutes
|> List.foldl time_collect Dict.empty
|> Dict.toList
|> List.map format_time
zip_self list =
case list of
hl::tl ->
List.map2 (\a b -> (a, b)) list tl
[] ->
[]
to_minutes x =
let
(before, after) = x
(b_hr, b_min, b_name) = before
(a_hr, a_min, _) = after
mins = (a_hr - b_hr) * 60 + a_min - b_min
in
(b_name, mins)
time_collect x dict =
let
(name, mins) = x
in
case Dict.get name dict of
Just total ->
Dict.insert name (total+mins) dict
Nothing ->
Dict.insert name mins dict
format_time x =
let
(name, total_mins) = x
hrs = total_mins // 60
mins = total_mins % 60
string_hrs = toString hrs
string_mins = toString mins
in
string_hrs ++ "h " ++ string_mins ++ "m - " ++ name
view : Address String -> Model -> Html
view address model =
div [ container_style ]
[ div [ item_style ] [ make_input address model.text ]
, div [ item_style ] [ list model.times ]
]
list n =
ul [] (List.map (\x -> li [] [text x]) n)
make_input address text =
textarea
[ placeholder "0900 Example task"
, value text
, on "input" targetValue (Signal.message address)
, textarea_style
]
[]
container_style =
style
[ ("display", "flex")
, ("height","100vh")
]
item_style : Attribute
item_style =
style
[ ("flex-grow", "1")
, ("flex-shrink", "1")
, ("flex-basis", "150px")
, ("height","100%")
]
textarea_style : Attribute
textarea_style =
style
[ ("resize", "none")
, ("height","100%")
, ("width", "100%")
]