aboutsummaryrefslogtreecommitdiff
path: root/src/client/elm/LoggedIn
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/elm/LoggedIn')
-rw-r--r--src/client/elm/LoggedIn/Category/Model.elm36
-rw-r--r--src/client/elm/LoggedIn/Category/Msg.elm9
-rw-r--r--src/client/elm/LoggedIn/Category/Table/View.elm124
-rw-r--r--src/client/elm/LoggedIn/Category/Update.elm24
-rw-r--r--src/client/elm/LoggedIn/Category/View.elm35
-rw-r--r--src/client/elm/LoggedIn/Home/Header/View.elm7
-rw-r--r--src/client/elm/LoggedIn/Home/Model.elm15
-rw-r--r--src/client/elm/LoggedIn/Home/Update.elm4
-rw-r--r--src/client/elm/LoggedIn/Home/View.elm21
-rw-r--r--src/client/elm/LoggedIn/Home/View/Paging.elm74
-rw-r--r--src/client/elm/LoggedIn/Home/View/Table.elm42
-rw-r--r--src/client/elm/LoggedIn/Income/Model.elm15
-rw-r--r--src/client/elm/LoggedIn/Income/Update.elm12
-rw-r--r--src/client/elm/LoggedIn/Income/View.elm33
-rw-r--r--src/client/elm/LoggedIn/Income/View/Table.elm6
-rw-r--r--src/client/elm/LoggedIn/Model.elm21
-rw-r--r--src/client/elm/LoggedIn/Msg.elm18
-rw-r--r--src/client/elm/LoggedIn/Stat/View.elm4
-rw-r--r--src/client/elm/LoggedIn/Update.elm80
-rw-r--r--src/client/elm/LoggedIn/View.elm16
20 files changed, 445 insertions, 151 deletions
diff --git a/src/client/elm/LoggedIn/Category/Model.elm b/src/client/elm/LoggedIn/Category/Model.elm
new file mode 100644
index 0000000..7092fc4
--- /dev/null
+++ b/src/client/elm/LoggedIn/Category/Model.elm
@@ -0,0 +1,36 @@
+module LoggedIn.Category.Model exposing
+ ( Model
+ , AddCategory
+ , init
+ , initForm
+ , validation
+ )
+
+import Date exposing (Date)
+
+import Form exposing (Form)
+import Form.Validate as Validate exposing (Validation)
+import Validation
+
+type alias Model =
+ { addCategory : Form String AddCategory
+ }
+
+type alias AddCategory =
+ { amount : Int
+ , date : Date
+ }
+
+init : Model
+init =
+ { addCategory = initForm
+ }
+
+initForm : Form String AddCategory
+initForm = Form.initial [] validation
+
+validation : Validation String AddCategory
+validation =
+ Validate.map2 AddCategory
+ (Validate.field "amount" (Validate.int |> Validate.andThen (Validate.minInt 1)))
+ (Validate.field "date" Validation.date)
diff --git a/src/client/elm/LoggedIn/Category/Msg.elm b/src/client/elm/LoggedIn/Category/Msg.elm
new file mode 100644
index 0000000..3184297
--- /dev/null
+++ b/src/client/elm/LoggedIn/Category/Msg.elm
@@ -0,0 +1,9 @@
+module LoggedIn.Category.Msg exposing
+ ( Msg(..)
+ )
+
+import Form exposing (Form)
+
+type Msg =
+ NoOp
+ | AddCategoryMsg Form.Msg
diff --git a/src/client/elm/LoggedIn/Category/Table/View.elm b/src/client/elm/LoggedIn/Category/Table/View.elm
new file mode 100644
index 0000000..fa7a7b1
--- /dev/null
+++ b/src/client/elm/LoggedIn/Category/Table/View.elm
@@ -0,0 +1,124 @@
+module LoggedIn.Category.Table.View exposing
+ ( view
+ )
+
+import Dict exposing (..)
+import Date exposing (Date)
+import String exposing (append)
+
+import FontAwesome
+import View.Color as Color
+
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (..)
+
+import Dialog
+import Dialog.AddCategory.Model as AddCategory
+import Dialog.AddCategory.View as AddCategory
+
+import Tooltip
+
+import Msg exposing (Msg)
+
+import LoggedData exposing (LoggedData)
+
+import LoggedIn.Msg as LoggedInMsg
+
+import LoggedIn.Category.Model as Category
+import View.Date as Date
+import LoggedIn.View.Format as Format
+
+import Model.User exposing (getUserName)
+import Model.Category as Category exposing (CategoryId, Category)
+import Model.PaymentCategory as PaymentCategory
+import Model.Translations exposing (getMessage)
+
+view : LoggedData -> Category.Model -> Html Msg
+view loggedData categoryModel =
+ let categories =
+ loggedData.categories
+ |> Dict.toList
+ |> List.sortBy (.name << Tuple.second)
+ in div
+ [ class "table" ]
+ [ div
+ [ class "lines" ]
+ ( headerLine loggedData :: List.map (paymentLine loggedData categoryModel) categories)
+ , if List.isEmpty (Dict.toList loggedData.categories)
+ then
+ div
+ [ class "emptyTableMsg" ]
+ [ text <| getMessage loggedData.translations "NoCategories" ]
+ else
+ text ""
+ ]
+
+headerLine : LoggedData -> Html Msg
+headerLine loggedData =
+ div
+ [ class "header" ]
+ [ div [ class "cell name" ] [ text <| getMessage loggedData.translations "Name" ]
+ , div [ class "cell category" ] [ text <| getMessage loggedData.translations "Color" ]
+ , div [ class "cell" ] []
+ , div [ class "cell" ] []
+ , div [ class "cell" ] []
+ ]
+
+paymentLine : LoggedData -> Category.Model -> (CategoryId, Category) -> Html Msg
+paymentLine loggedData categoryModel (categoryId, category) =
+ div
+ [ class "row" ]
+ [ div
+ [ class "cell category" ]
+ [ text category.name ]
+ , div
+ [ class "cell category" ]
+ [ span
+ [ class "tag"
+ , style [("background-color", category.color)]
+ ]
+ [ text category.color ]
+ ]
+ , div
+ [ class "cell button" ]
+ [ let currentDate = Date.fromTime loggedData.currentTime
+ in AddCategory.button
+ loggedData
+ (AddCategory.initialClone loggedData.translations category)
+ "CloneCategory"
+ (FontAwesome.clone Color.chestnutRose 18)
+ (Just (getMessage loggedData.translations "Clone"))
+ ]
+ , div
+ [ class "cell button" ]
+ [ AddCategory.button
+ loggedData
+ (AddCategory.initialEdit loggedData.translations categoryId category)
+ "EditCategory"
+ (FontAwesome.pencil Color.chestnutRose 18)
+ (Just (getMessage loggedData.translations "Edit"))
+ ]
+ , div
+ [ class "cell button" ]
+ [ if PaymentCategory.isCategoryUnused categoryId loggedData.paymentCategories
+ then
+ let dialogConfig =
+ { className = "deleteCategoryDialog"
+ , title = getMessage loggedData.translations "ConfirmCategoryDelete"
+ , body = always <| text ""
+ , confirm = getMessage loggedData.translations "Confirm"
+ , confirmMsg = always <| Msg.Dialog <| Dialog.UpdateAndClose <| Msg.DeleteCategory categoryId
+ , undo = getMessage loggedData.translations "Undo"
+ }
+ in button
+ ( Tooltip.show Msg.Tooltip (getMessage loggedData.translations "Delete")
+ ++ [ onClick (Msg.Dialog <| Dialog.Open dialogConfig) ]
+ )
+ [ FontAwesome.trash Color.chestnutRose 18 ]
+ else
+ span
+ ( Tooltip.show Msg.Tooltip (getMessage loggedData.translations "UsedCategory") )
+ [ FontAwesome.trash Color.silver 18 ]
+ ]
+ ]
diff --git a/src/client/elm/LoggedIn/Category/Update.elm b/src/client/elm/LoggedIn/Category/Update.elm
new file mode 100644
index 0000000..1072ef0
--- /dev/null
+++ b/src/client/elm/LoggedIn/Category/Update.elm
@@ -0,0 +1,24 @@
+module LoggedIn.Category.Update exposing
+ ( update
+ )
+
+import Form exposing (Form)
+
+import LoggedData exposing (LoggedData)
+
+import LoggedIn.Category.Model as Category
+import LoggedIn.Category.Msg as Category
+
+update : LoggedData -> Category.Msg -> Category.Model -> (Category.Model, Cmd Category.Msg)
+update loggedData msg model =
+ case msg of
+
+ Category.NoOp ->
+ ( model
+ , Cmd.none
+ )
+
+ Category.AddCategoryMsg formMsg ->
+ ( { model | addCategory = Form.update Category.validation formMsg model.addCategory }
+ , Cmd.none
+ )
diff --git a/src/client/elm/LoggedIn/Category/View.elm b/src/client/elm/LoggedIn/Category/View.elm
new file mode 100644
index 0000000..4e04fa2
--- /dev/null
+++ b/src/client/elm/LoggedIn/Category/View.elm
@@ -0,0 +1,35 @@
+module LoggedIn.Category.View exposing
+ ( view
+ )
+
+import Html exposing (..)
+import Html.Attributes exposing (..)
+
+import LoggedData exposing (LoggedData)
+
+import Msg exposing (Msg)
+
+import Dialog.AddCategory.Model as AddCategory
+import Dialog.AddCategory.View as AddCategory
+
+import LoggedIn.Category.Model as Category
+import LoggedIn.Category.Table.View as Table
+
+import Model.Translations exposing (getMessage, getParamMessage)
+
+view : LoggedData -> Category.Model -> Html Msg
+view loggedData categoryModel =
+ div
+ [ class "categories" ]
+ [ div
+ [ class "titleButton withMargin" ]
+ [ h1 [] [ text <| getMessage loggedData.translations "Categories" ]
+ , AddCategory.button
+ loggedData
+ (AddCategory.initialAdd loggedData.translations)
+ "AddCategory"
+ (text (getMessage loggedData.translations "AddCategory"))
+ Nothing
+ ]
+ , Table.view loggedData categoryModel
+ ]
diff --git a/src/client/elm/LoggedIn/Home/Header/View.elm b/src/client/elm/LoggedIn/Home/Header/View.elm
index b67fb3b..3f8a320 100644
--- a/src/client/elm/LoggedIn/Home/Header/View.elm
+++ b/src/client/elm/LoggedIn/Home/Header/View.elm
@@ -5,7 +5,6 @@ module LoggedIn.Home.Header.View exposing
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
-import Html.App as Html
import String
import Dict
import Date
@@ -32,8 +31,6 @@ import LoggedIn.Home.View.ExceedingPayers as ExceedingPayers
import LoggedIn.View.Format as Format
import View.Plural exposing (plural)
-import Utils.Tuple as Tuple
-
view : LoggedData -> Home.Model -> Payments -> Frequency -> Html Msg
view loggedData { search } payments frequency =
let currentDate = Date.fromTime loggedData.currentTime
@@ -90,9 +87,9 @@ paymentsPartition loggedData payments =
", "
( loggedData.users
|> Dict.toList
- |> List.map (Tuple.mapFst (\userId -> Payment.totalPayments (always True) userId payments))
+ |> List.map (Tuple.mapFirst (\userId -> Payment.totalPayments (always True) userId payments))
|> List.filter (\(sum, _) -> sum > 0)
- |> List.sortBy fst
+ |> List.sortBy Tuple.first
|> List.reverse
|> List.map (\(sum, user) ->
getParamMessage [ user.name, Format.price loggedData.conf sum ] loggedData.translations "By"
diff --git a/src/client/elm/LoggedIn/Home/Model.elm b/src/client/elm/LoggedIn/Home/Model.elm
index caedc29..ace1593 100644
--- a/src/client/elm/LoggedIn/Home/Model.elm
+++ b/src/client/elm/LoggedIn/Home/Model.elm
@@ -3,6 +3,7 @@ module LoggedIn.Home.Model exposing
, Search
, init
, searchInitial
+ , validation
)
import Form exposing (Form)
@@ -26,14 +27,14 @@ type alias Search =
init : Model
init =
{ currentPage = 1
- , search = Form.initial (searchInitial Punctual) searchValidation
+ , search = Form.initial (searchInitial Punctual) validation
}
searchInitial : Frequency -> List (String, Field)
-searchInitial frequency = [ ("frequency", Field.Radio (toString frequency)) ]
+searchInitial frequency = [ ("frequency", Field.string (toString frequency)) ]
-searchValidation : Validation String Search
-searchValidation =
- Validate.form2 Search
- (Validate.get "name" (Validate.maybe Validate.string))
- (Validate.get "frequency" Payment.validateFrequency)
+validation : Validation String Search
+validation =
+ Validate.map2 Search
+ (Validate.field "name" (Validate.maybe Validate.string))
+ (Validate.field "frequency" Payment.validateFrequency)
diff --git a/src/client/elm/LoggedIn/Home/Update.elm b/src/client/elm/LoggedIn/Home/Update.elm
index d1a3239..b0ce256 100644
--- a/src/client/elm/LoggedIn/Home/Update.elm
+++ b/src/client/elm/LoggedIn/Home/Update.elm
@@ -25,10 +25,10 @@ update loggedData msg model =
Home.SearchMsg formMsg ->
( { model
- | search = Form.update formMsg model.search
+ | search = Form.update Home.validation formMsg model.search
, currentPage =
case formMsg of
- Form.Input "name" _ -> 1
+ Form.Input "name" _ _ -> 1
_ -> model.currentPage
}
, Cmd.none
diff --git a/src/client/elm/LoggedIn/Home/View.elm b/src/client/elm/LoggedIn/Home/View.elm
index 0def64e..0b90e67 100644
--- a/src/client/elm/LoggedIn/Home/View.elm
+++ b/src/client/elm/LoggedIn/Home/View.elm
@@ -2,23 +2,22 @@ module LoggedIn.Home.View exposing
( view
)
+import Date
import Html exposing (..)
import Html.Attributes exposing (..)
-import Date
import Form
import Utils.Form as Form
-import Msg exposing (Msg)
-
import LoggedData exposing (LoggedData)
-import Model.Payment as Payment exposing (Frequency(..))
-
-import LoggedIn.Home.Model as Home
import LoggedIn.Home.Header.View as Header
-
-import LoggedIn.Home.View.Table as Table
+import LoggedIn.Home.Model as Home
+import LoggedIn.Home.Msg as HomeMsg
import LoggedIn.Home.View.Paging as Paging
+import LoggedIn.Home.View.Table as Table
+import LoggedIn.Msg as LoggedInMsg
+import Model.Payment as Payment exposing (Frequency(..))
+import Msg exposing (Msg)
view : LoggedData -> Home.Model -> Html Msg
view loggedData home =
@@ -31,5 +30,9 @@ view loggedData home =
[ class "home" ]
[ Header.view loggedData home payments frequency
, Table.view loggedData home payments frequency
- , Paging.view home payments
+ , Paging.view
+ home.currentPage
+ (List.length payments)
+ Msg.NoOp
+ (Msg.UpdateLoggedIn << LoggedInMsg.HomeMsg << HomeMsg.UpdatePage)
]
diff --git a/src/client/elm/LoggedIn/Home/View/Paging.elm b/src/client/elm/LoggedIn/Home/View/Paging.elm
index 5bcb827..dffe061 100644
--- a/src/client/elm/LoggedIn/Home/View/Paging.elm
+++ b/src/client/elm/LoggedIn/Home/View/Paging.elm
@@ -10,31 +10,29 @@ import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
-import LoggedIn.Msg as LoggedInMsg
-
-import LoggedIn.Home.Msg as HomeMsg
-import LoggedIn.Home.Model as HomeModel
-
-import Msg exposing (Msg)
import LoggedData exposing (LoggedData)
import Model.Payment as Payment exposing (Payments, perPage)
showedPages : Int
showedPages = 5
-view : HomeModel.Model -> Payments -> Html Msg
-view homeModel payments =
- let maxPage = ceiling (toFloat (List.length payments) / toFloat perPage)
- pages = truncatePages homeModel.currentPage [1..maxPage]
+view : Int -> Int -> msg -> (Int -> msg) -> Html msg
+view currentPage payments noOp pageMsg =
+ let maxPage = ceiling (toFloat payments / toFloat perPage)
+ pages = truncatePages currentPage (List.range 1 maxPage)
in if maxPage <= 1
then
text ""
else
div
[ class "pages" ]
- ( [ firstPage homeModel, previousPage homeModel ]
- ++ ( List.map (paymentsPage homeModel) pages)
- ++ [ nextPage homeModel maxPage, lastPage homeModel maxPage ]
+ ( [ firstPage currentPage pageMsg
+ , previousPage currentPage noOp pageMsg
+ ]
+ ++ ( List.map (paymentsPage currentPage noOp pageMsg) pages)
+ ++ [ nextPage currentPage maxPage noOp pageMsg
+ , lastPage currentPage maxPage pageMsg
+ ]
)
truncatePages : Int -> List Int -> List Int
@@ -44,57 +42,57 @@ truncatePages currentPage pages =
showedRightPages = floor ((toFloat showedPages - 1) / 2)
truncatedPages =
if currentPage <= showedLeftPages then
- [1..showedPages]
+ (List.range 1 showedPages)
else if currentPage > totalPages - showedRightPages then
- [(totalPages - showedPages + 1)..totalPages]
+ (List.range (totalPages - showedPages + 1) totalPages)
else
- [(currentPage - showedLeftPages)..(currentPage + showedRightPages)]
+ (List.range (currentPage - showedLeftPages) (currentPage + showedRightPages))
in List.filter (flip List.member pages) truncatedPages
-firstPage : HomeModel.Model -> Html Msg
-firstPage homeModel =
+firstPage : Int -> (Int -> msg) -> Html msg
+firstPage currentPage pageMsg =
button
[ classList
[ ("page", True)
- , ("disable", homeModel.currentPage <= 1)
+ , ("disable", currentPage <= 1)
]
- , onClick (Msg.UpdateLoggedIn << LoggedInMsg.HomeMsg << HomeMsg.UpdatePage <| 1)
+ , onClick (pageMsg 1)
]
[ FontAwesome.fast_backward grey 13 ]
-previousPage : HomeModel.Model -> Html Msg
-previousPage homeModel =
+previousPage : Int -> msg -> (Int -> msg) -> Html msg
+previousPage currentPage noOp pageMsg =
button
[ class "page"
, onClick <|
- if homeModel.currentPage > 1
- then (Msg.UpdateLoggedIn << LoggedInMsg.HomeMsg << HomeMsg.UpdatePage <| homeModel.currentPage - 1)
- else Msg.NoOp
+ if currentPage > 1
+ then (pageMsg <| currentPage - 1)
+ else noOp
]
[ FontAwesome.backward grey 13 ]
-nextPage : HomeModel.Model -> Int -> Html Msg
-nextPage homeModel maxPage =
+nextPage : Int -> Int -> msg -> (Int -> msg) -> Html msg
+nextPage currentPage maxPage noOp pageMsg =
button
[ class "page"
, onClick <|
- if homeModel.currentPage < maxPage
- then (Msg.UpdateLoggedIn << LoggedInMsg.HomeMsg << HomeMsg.UpdatePage <| homeModel.currentPage + 1)
- else Msg.NoOp
+ if currentPage < maxPage
+ then (pageMsg <| currentPage + 1)
+ else noOp
]
[ FontAwesome.forward grey 13 ]
-lastPage : HomeModel.Model -> Int -> Html Msg
-lastPage homeModel maxPage =
+lastPage : Int -> Int -> (Int -> msg) -> Html msg
+lastPage currentPage maxPage pageMsg =
button
[ class "page"
- , onClick (Msg.UpdateLoggedIn << LoggedInMsg.HomeMsg << HomeMsg.UpdatePage <| maxPage)
+ , onClick (pageMsg maxPage)
]
[ FontAwesome.fast_forward grey 13 ]
-paymentsPage : HomeModel.Model -> Int -> Html Msg
-paymentsPage homeModel page =
- let onCurrentPage = page == homeModel.currentPage
+paymentsPage : Int -> msg -> (Int -> msg) -> Int -> Html msg
+paymentsPage currentPage noOp pageMsg page =
+ let onCurrentPage = page == currentPage
in button
[ classList
[ ("page", True)
@@ -102,8 +100,8 @@ paymentsPage homeModel page =
]
, onClick <|
if onCurrentPage
- then Msg.NoOp
- else Msg.UpdateLoggedIn << LoggedInMsg.HomeMsg << HomeMsg.UpdatePage <| page
+ then noOp
+ else pageMsg page
]
[ text (toString page) ]
diff --git a/src/client/elm/LoggedIn/Home/View/Table.elm b/src/client/elm/LoggedIn/Home/View/Table.elm
index 6423bf9..8828488 100644
--- a/src/client/elm/LoggedIn/Home/View/Table.elm
+++ b/src/client/elm/LoggedIn/Home/View/Table.elm
@@ -2,8 +2,8 @@ module LoggedIn.Home.View.Table exposing
( view
)
-import Dict exposing (..)
import Date exposing (Date)
+import Dict exposing (..)
import String exposing (append)
import FontAwesome
@@ -26,12 +26,13 @@ import LoggedData exposing (LoggedData)
import LoggedIn.Msg as LoggedInMsg
import LoggedIn.Home.Model as Home
-import View.Date as Date
import LoggedIn.View.Format as Format
+import View.Date as Date
-import Model.User exposing (getUserName)
import Model.Payment as Payment exposing (..)
+import Model.PaymentCategory as PaymentCategory
import Model.Translations exposing (getMessage)
+import Model.User exposing (getUserName)
view : LoggedData -> Home.Model -> Payments -> Frequency -> Html Msg
view loggedData homeModel payments frequency =
@@ -60,6 +61,7 @@ headerLine loggedData frequency =
[ div [ class "cell category" ] [ text <| getMessage loggedData.translations "Name" ]
, div [ class "cell cost" ] [ text <| getMessage loggedData.translations "Cost" ]
, div [ class "cell user" ] [ text <| getMessage loggedData.translations "Payer" ]
+ , div [ class "cell user" ] [ text <| getMessage loggedData.translations "PaymentCategory" ]
, case frequency of
Punctual -> div [ class "cell date" ] [ text <| getMessage loggedData.translations "Date" ]
Monthly -> text ""
@@ -72,7 +74,7 @@ paymentLine : LoggedData -> Home.Model -> Frequency -> Payment -> Html Msg
paymentLine loggedData homeModel frequency payment =
div
[ class "row" ]
- [ div [ class "cell category" ] [ text payment.name ]
+ [ div [ class "cell name" ] [ text payment.name ]
, div
[ classList
[ ("cell cost", True)
@@ -87,6 +89,22 @@ paymentLine loggedData homeModel frequency payment =
|> Maybe.withDefault "−"
|> text
]
+ , div
+ [ class "cell category" ]
+ ( let mbCategory =
+ PaymentCategory.search payment.name loggedData.paymentCategories
+ |> Maybe.andThen (\category -> Dict.get category loggedData.categories)
+ in case mbCategory of
+ Just category ->
+ [ span
+ [ class "tag"
+ , style [("background-color", category.color)]
+ ]
+ [ text category.name ]
+ ]
+ Nothing ->
+ []
+ )
, case frequency of
Punctual ->
div
@@ -103,9 +121,10 @@ paymentLine loggedData homeModel frequency payment =
, div
[ class "cell button" ]
[ let currentDate = Date.fromTime loggedData.currentTime
+ category = PaymentCategory.search payment.name loggedData.paymentCategories
in AddPayment.button
loggedData
- (AddPayment.initialClone loggedData.translations currentDate payment)
+ (AddPayment.initialClone loggedData.translations currentDate category payment)
"ClonePayment"
(FontAwesome.clone Color.chestnutRose 18)
(Just (getMessage loggedData.translations "Clone"))
@@ -116,12 +135,13 @@ paymentLine loggedData homeModel frequency payment =
then
text ""
else
- AddPayment.button
- loggedData
- (AddPayment.initialEdit loggedData.translations payment)
- "EditPayment"
- (FontAwesome.pencil Color.chestnutRose 18)
- (Just (getMessage loggedData.translations "Edit"))
+ let category = PaymentCategory.search payment.name loggedData.paymentCategories
+ in AddPayment.button
+ loggedData
+ (AddPayment.initialEdit loggedData.translations category payment)
+ "EditPayment"
+ (FontAwesome.pencil Color.chestnutRose 18)
+ (Just (getMessage loggedData.translations "Edit"))
]
, div
[ class "cell button" ]
diff --git a/src/client/elm/LoggedIn/Income/Model.elm b/src/client/elm/LoggedIn/Income/Model.elm
index cf1bf57..7d852b9 100644
--- a/src/client/elm/LoggedIn/Income/Model.elm
+++ b/src/client/elm/LoggedIn/Income/Model.elm
@@ -3,12 +3,13 @@ module LoggedIn.Income.Model exposing
, AddIncome
, init
, initForm
+ , validation
)
import Date exposing (Date)
import Form exposing (Form)
-import Form.Validate as Validate exposing (..)
+import Form.Validate as Validate exposing (Validation)
import Validation
type alias Model =
@@ -26,10 +27,10 @@ init =
}
initForm : Form String AddIncome
-initForm = Form.initial [] validate
+initForm = Form.initial [] validation
-validate : Validation String AddIncome
-validate =
- form2 AddIncome
- (get "amount" (int `andThen` (minInt 1)))
- (get "date" Validation.date)
+validation : Validation String AddIncome
+validation =
+ Validate.map2 AddIncome
+ (Validate.field "amount" (Validate.int |> Validate.andThen (Validate.minInt 1)))
+ (Validate.field "date" Validation.date)
diff --git a/src/client/elm/LoggedIn/Income/Update.elm b/src/client/elm/LoggedIn/Income/Update.elm
index ec6a0c1..0023c76 100644
--- a/src/client/elm/LoggedIn/Income/Update.elm
+++ b/src/client/elm/LoggedIn/Income/Update.elm
@@ -6,19 +6,19 @@ import Form exposing (Form)
import LoggedData exposing (LoggedData)
-import LoggedIn.Income.Model as IncomeModel
-import LoggedIn.Income.Msg as IncomeMsg
+import LoggedIn.Income.Model as Income
+import LoggedIn.Income.Msg as Income
-update : LoggedData -> IncomeMsg.Msg -> IncomeModel.Model -> (IncomeModel.Model, Cmd IncomeMsg.Msg)
+update : LoggedData -> Income.Msg -> Income.Model -> (Income.Model, Cmd Income.Msg)
update loggedData msg model =
case msg of
- IncomeMsg.NoOp ->
+ Income.NoOp ->
( model
, Cmd.none
)
- IncomeMsg.AddIncomeMsg formMsg ->
- ( { model | addIncome = Form.update formMsg model.addIncome }
+ Income.AddIncomeMsg formMsg ->
+ ( { model | addIncome = Form.update Income.validation formMsg model.addIncome }
, Cmd.none
)
diff --git a/src/client/elm/LoggedIn/Income/View.elm b/src/client/elm/LoggedIn/Income/View.elm
index 2c5bcaf..00a1646 100644
--- a/src/client/elm/LoggedIn/Income/View.elm
+++ b/src/client/elm/LoggedIn/Income/View.elm
@@ -12,7 +12,6 @@ import FontAwesome
import Html exposing (..)
import Html.Events exposing (..)
import Html.Attributes exposing (..)
-import Html.App as Html
import Form exposing (Form)
import View.Form as Form
@@ -45,19 +44,21 @@ view : LoggedData -> Income.Model -> Html Msg
view loggedData incomeModel =
div
[ class "income" ]
- [ case useIncomesFrom loggedData.users loggedData.incomes loggedData.payments of
- Just since -> cumulativeIncomesView loggedData since
- Nothing -> text ""
- , div
- [ class "textual monthlyNetIncomes" ]
- [ h1 [] [ text <| getMessage loggedData.translations "MonthlyNetIncomes" ]
- , AddIncome.button
- "addIncome"
- loggedData
- (AddIncome.initialAdd loggedData.translations (Date.fromTime loggedData.currentTime))
- "AddIncome"
- (text (getMessage loggedData.translations "AddIncome"))
- Nothing
+ [ div
+ [ class "withMargin" ]
+ [ case useIncomesFrom loggedData.users loggedData.incomes loggedData.payments of
+ Just since -> cumulativeIncomesView loggedData since
+ Nothing -> text ""
+ , div
+ [ class "titleButton" ]
+ [ h1 [] [ text <| getMessage loggedData.translations "MonthlyNetIncomes" ]
+ , AddIncome.button
+ loggedData
+ (AddIncome.initialAdd loggedData.translations (Date.fromTime loggedData.currentTime))
+ "AddIncome"
+ (text (getMessage loggedData.translations "AddIncome"))
+ Nothing
+ ]
]
, Table.view loggedData incomeModel
]
@@ -66,7 +67,7 @@ cumulativeIncomesView : LoggedData -> Time -> Html Msg
cumulativeIncomesView loggedData since =
let longDate = Date.longView (Date.fromTime since) loggedData.translations
in div
- [ class "textual" ]
+ []
[ h1 [] [ text <| getParamMessage [longDate] loggedData.translations "CumulativeIncomesSince" ]
, ul
[]
@@ -74,7 +75,7 @@ cumulativeIncomesView loggedData since =
|> List.map (\(userId, user) ->
(user.name, userCumulativeIncomeSince loggedData.currentTime since loggedData.incomes userId)
)
- |> List.sortBy snd
+ |> List.sortBy Tuple.second
|> List.map (\(userName, cumulativeIncome) ->
li
[]
diff --git a/src/client/elm/LoggedIn/Income/View/Table.elm b/src/client/elm/LoggedIn/Income/View/Table.elm
index dcf6d78..aa5e392 100644
--- a/src/client/elm/LoggedIn/Income/View/Table.elm
+++ b/src/client/elm/LoggedIn/Income/View/Table.elm
@@ -38,7 +38,7 @@ view loggedData incomeModel =
let incomes =
loggedData.incomes
|> Dict.toList
- |> List.sortBy (.time << snd)
+ |> List.sortBy (.time << Tuple.second)
|> List.reverse
in div
[ class "table" ]
@@ -49,7 +49,7 @@ view loggedData incomeModel =
then
div
[ class "emptyTableMsg" ]
- [ text <| getMessage loggedData.translations "NoPayment" ]
+ [ text <| getMessage loggedData.translations "NoIncome" ]
else
text ""
]
@@ -87,7 +87,6 @@ paymentLine loggedData incomeModel (incomeId, income) =
[ class "cell button" ]
[ let currentDate = Date.fromTime loggedData.currentTime
in AddIncome.button
- ""
loggedData
(AddIncome.initialClone loggedData.translations currentDate income)
"CloneIncome"
@@ -101,7 +100,6 @@ paymentLine loggedData incomeModel (incomeId, income) =
text ""
else
AddIncome.button
- ""
loggedData
(AddIncome.initialEdit loggedData.translations incomeId income)
"EditIncome"
diff --git a/src/client/elm/LoggedIn/Model.elm b/src/client/elm/LoggedIn/Model.elm
index 11386d5..6bcb0b2 100644
--- a/src/client/elm/LoggedIn/Model.elm
+++ b/src/client/elm/LoggedIn/Model.elm
@@ -9,25 +9,34 @@ import Model.Init exposing (..)
import Model.Payment exposing (Payments)
import Model.User exposing (Users, UserId)
import Model.Income exposing (Incomes)
+import Model.Category exposing (Categories)
+import Model.PaymentCategory exposing (PaymentCategories)
-import LoggedIn.Home.Model as HomeModel
-import LoggedIn.Income.Model as IncomeModel
+import LoggedIn.Home.Model as Home
+import LoggedIn.Income.Model as Income
+import LoggedIn.Category.Model as Categories
type alias Model =
- { home : HomeModel.Model
- , income : IncomeModel.Model
+ { home : Home.Model
+ , income : Income.Model
+ , category : Categories.Model
, users : Users
, me : UserId
, payments : Payments
, incomes : Incomes
+ , categories : Categories
+ , paymentCategories : PaymentCategories
}
init : Init -> Model
init initData =
- { home = HomeModel.init
- , income = IncomeModel.init
+ { home = Home.init
+ , income = Income.init
+ , category = Categories.init
, users = initData.users
, me = initData.me
, payments = initData.payments
, incomes = initData.incomes
+ , categories = initData.categories
+ , paymentCategories = initData.paymentCategories
}
diff --git a/src/client/elm/LoggedIn/Msg.elm b/src/client/elm/LoggedIn/Msg.elm
index ff275e2..a1379a6 100644
--- a/src/client/elm/LoggedIn/Msg.elm
+++ b/src/client/elm/LoggedIn/Msg.elm
@@ -6,17 +6,23 @@ import Date exposing (Date)
import Model.Payment exposing (PaymentId, Frequency)
import Model.Income exposing (IncomeId)
+import Model.Category exposing (CategoryId)
-import LoggedIn.Home.Msg as HomeMsg
-import LoggedIn.Income.Msg as IncomeMsg
+import LoggedIn.Home.Msg as Home
+import LoggedIn.Income.Msg as Income
+import LoggedIn.Category.Msg as Categories
type Msg =
NoOp
- | HomeMsg HomeMsg.Msg
- | IncomeMsg IncomeMsg.Msg
- | ValidateCreatePayment PaymentId String Int Date Frequency
- | ValidateEditPayment PaymentId String Int Date Frequency
+ | HomeMsg Home.Msg
+ | IncomeMsg Income.Msg
+ | CategoriesMsg Categories.Msg
+ | ValidateCreatePayment PaymentId String Int Date CategoryId Frequency
+ | ValidateEditPayment PaymentId String Int Date CategoryId Frequency
| ValidateDeletePayment PaymentId
| ValidateCreateIncome IncomeId Int Date
| ValidateEditIncome IncomeId Int Date
| ValidateDeleteIncome IncomeId
+ | ValidateCreateCategory CategoryId String String
+ | ValidateEditCategory CategoryId String String
+ | ValidateDeleteCategory CategoryId
diff --git a/src/client/elm/LoggedIn/Stat/View.elm b/src/client/elm/LoggedIn/Stat/View.elm
index 946005a..f57316a 100644
--- a/src/client/elm/LoggedIn/Stat/View.elm
+++ b/src/client/elm/LoggedIn/Stat/View.elm
@@ -26,7 +26,7 @@ view loggedData =
let paymentsByMonth = Payment.groupAndSortByMonth (Payment.punctual loggedData.payments)
monthPaymentMean = getMonthPaymentMean loggedData paymentsByMonth
in div
- [ class "stat textual" ]
+ [ class "stat withMargin" ]
[ h1 [] [ text (getParamMessage [ Format.price loggedData.conf monthPaymentMean ] loggedData.translations "ByMonthsAndMean") ]
, ul
[]
@@ -40,7 +40,7 @@ getMonthPaymentMean loggedData paymentsByMonth =
let currentDate = Date.fromTime loggedData.currentTime
in not (Date.month currentDate == month && Date.year currentDate == year)
)
- |> List.map (List.sum << List.map .cost << snd)
+ |> List.map (List.sum << List.map .cost << Tuple.second)
|> List.mean
monthDetail : LoggedData -> ((Month, Int), Payments) -> Html Msg
diff --git a/src/client/elm/LoggedIn/Update.elm b/src/client/elm/LoggedIn/Update.elm
index 06cd623..9e6d6ee 100644
--- a/src/client/elm/LoggedIn/Update.elm
+++ b/src/client/elm/LoggedIn/Update.elm
@@ -15,6 +15,8 @@ import Form
import Model exposing (Model)
import Model.Payment as Payment exposing (Payment, Frequency(..))
import Model.Income as Income exposing (Income)
+import Model.Category exposing (Category)
+import Model.PaymentCategory as PaymentCategory
import Server
import LoggedData
@@ -22,16 +24,16 @@ import LoggedData
import LoggedIn.Msg as LoggedInMsg
import LoggedIn.Model as LoggedInModel
-import LoggedIn.Home.Msg as HomeMsg
-import LoggedIn.Home.Update as HomeUpdate
-import LoggedIn.Home.Model as HomeModel
+import LoggedIn.Home.Msg as Home
+import LoggedIn.Home.Update as Home
+import LoggedIn.Home.Model as Home
-import LoggedIn.Income.Msg as IncomeMsg
-import LoggedIn.Income.Update as IncomeUpdate
+import LoggedIn.Income.Update as Income
+import LoggedIn.Income.Model as Income
-import LoggedIn.Income.Model as IncomeModel
+import LoggedIn.Category.Update as Categories
+import LoggedIn.Category.Model as Categories
-import Utils.Tuple as Tuple
import Utils.Cmd exposing ((:>))
update : Model -> LoggedInMsg.Msg -> LoggedInModel.Model -> (LoggedInModel.Model, Cmd LoggedInMsg.Msg)
@@ -45,32 +47,51 @@ update model msg loggedIn =
)
LoggedInMsg.HomeMsg homeMsg ->
- case HomeUpdate.update loggedData homeMsg loggedIn.home of
+ case Home.update loggedData homeMsg loggedIn.home of
(home, effects) ->
( { loggedIn | home = home }
, Cmd.map LoggedInMsg.HomeMsg effects
)
LoggedInMsg.IncomeMsg incomeMsg ->
- case IncomeUpdate.update loggedData incomeMsg loggedIn.income of
+ case Income.update loggedData incomeMsg loggedIn.income of
(income, cmd) ->
( { loggedIn | income = income }
, Cmd.map LoggedInMsg.IncomeMsg cmd
)
- LoggedInMsg.ValidateCreatePayment paymentId name cost date frequency ->
- update model (LoggedInMsg.HomeMsg <| HomeMsg.SearchMsg (Form.Reset (HomeModel.searchInitial frequency))) loggedIn
- :> update model (LoggedInMsg.HomeMsg <| HomeMsg.UpdatePage 1)
+ LoggedInMsg.CategoriesMsg categoriesMsg ->
+ case Categories.update loggedData categoriesMsg loggedIn.category of
+ (category, cmd) ->
+ ( { loggedIn | category = category }
+ , Cmd.map LoggedInMsg.CategoriesMsg cmd
+ )
+
+ LoggedInMsg.ValidateCreatePayment paymentId name cost date category frequency ->
+ update model (LoggedInMsg.HomeMsg <| Home.SearchMsg (Form.Reset (Home.searchInitial frequency))) loggedIn
+ :> update model (LoggedInMsg.HomeMsg <| Home.UpdatePage 1)
:> (\loggedIn ->
let newPayment = Payment paymentId name cost date loggedIn.me frequency
- in ( { loggedIn | payments = newPayment :: loggedIn.payments }
+ in ( { loggedIn
+ | payments = newPayment :: loggedIn.payments
+ , paymentCategories = PaymentCategory.set name category loggedIn.paymentCategories
+ }
, Cmd.none
)
)
- LoggedInMsg.ValidateEditPayment paymentId name cost date frequency ->
+ LoggedInMsg.ValidateEditPayment paymentId name cost date category frequency ->
let updatedPayment = Payment paymentId name cost date loggedIn.me frequency
- in ( { loggedIn | payments = Payment.edit updatedPayment loggedIn.payments }
+ mbOldPayment = Payment.find paymentId loggedIn.payments
+ in ( { loggedIn
+ | payments = Payment.edit updatedPayment loggedIn.payments
+ , paymentCategories =
+ case mbOldPayment of
+ Just oldPayment ->
+ PaymentCategory.update oldPayment.name name category loggedIn.paymentCategories
+ Nothing ->
+ loggedData.paymentCategories
+ }
, Cmd.none
)
@@ -86,7 +107,7 @@ update model msg loggedIn =
)
in if switchToPunctual
then
- update model (LoggedInMsg.HomeMsg <| HomeMsg.SearchMsg (Form.Reset (HomeModel.searchInitial Punctual))) loggedIn
+ update model (LoggedInMsg.HomeMsg <| Home.SearchMsg (Form.Reset (Home.searchInitial Punctual))) loggedIn
:> (\loggedIn ->
( { loggedIn | payments = payments }
, Cmd.none
@@ -99,20 +120,12 @@ update model msg loggedIn =
LoggedInMsg.ValidateCreateIncome incomeId amount date ->
let newIncome = { userId = loggedIn.me, amount = amount, time = Date.toTime date }
- loggedInIncome = loggedIn.income
- in ( { loggedIn
- | incomes = Dict.insert incomeId newIncome loggedIn.incomes
- , income = { loggedInIncome | addIncome = IncomeModel.initForm }
- }
+ in ( { loggedIn | incomes = Dict.insert incomeId newIncome loggedIn.incomes }
, Cmd.none
)
LoggedInMsg.ValidateEditIncome incomeId amount date ->
- let updatedIncome = Income loggedIn.me (Date.toTime date) amount
- updateIncome mbIncome =
- case mbIncome of
- Just _ -> Just updatedIncome
- Nothing -> Just updatedIncome
+ let updateIncome _ = Just <| Income loggedIn.me (Date.toTime date) amount
in ( { loggedIn | incomes = Dict.update incomeId updateIncome loggedIn.incomes }
, Cmd.none
)
@@ -121,3 +134,18 @@ update model msg loggedIn =
( { loggedIn | incomes = Dict.remove incomeId loggedIn.incomes }
, Cmd.none
)
+
+ LoggedInMsg.ValidateCreateCategory categoryId name color ->
+ let newCategory = { name = name, color = color }
+ in ( { loggedIn | categories = Dict.insert categoryId newCategory loggedIn.categories }
+ , Cmd.none
+ )
+
+ LoggedInMsg.ValidateEditCategory categoryId name color ->
+ let updateCategory _ = Just <| Category name color
+ in ( { loggedIn | categories = Dict.update categoryId updateCategory loggedIn.categories } , Cmd.none)
+
+ LoggedInMsg.ValidateDeleteCategory categoryId ->
+ ( { loggedIn | categories = Dict.remove categoryId loggedIn.categories }
+ , Cmd.none
+ )
diff --git a/src/client/elm/LoggedIn/View.elm b/src/client/elm/LoggedIn/View.elm
index a1fa3f0..2e42a73 100644
--- a/src/client/elm/LoggedIn/View.elm
+++ b/src/client/elm/LoggedIn/View.elm
@@ -9,13 +9,15 @@ import Page
import Msg exposing (Msg)
import Model exposing (Model)
+import Model.Translations exposing (getMessage)
import LoggedData
import LoggedIn.Model as LoggedInModel
-import LoggedIn.Home.View as HomeView
-import LoggedIn.Income.View as UserView
-import LoggedIn.Stat.View as StatView
+import LoggedIn.Home.View as Home
+import LoggedIn.Income.View as Income
+import LoggedIn.Category.View as Categories
+import LoggedIn.Stat.View as Stat
view : Model -> LoggedInModel.Model -> Html Msg
view model loggedIn =
@@ -23,7 +25,9 @@ view model loggedIn =
[ class "loggedIn" ]
[ let loggedData = LoggedData.build model loggedIn
in case model.page of
- Page.Home -> HomeView.view loggedData loggedIn.home
- Page.Income -> UserView.view loggedData loggedIn.income
- Page.Statistics -> StatView.view loggedData
+ Page.Home -> Home.view loggedData loggedIn.home
+ Page.Income -> Income.view loggedData loggedIn.income
+ Page.Categories -> Categories.view loggedData loggedIn.category
+ Page.Statistics -> Stat.view loggedData
+ Page.NotFound -> div [] [ text (getMessage model.translations "PageNotFound") ]
]