diff options
Diffstat (limited to 'src/client/LoggedIn/Income')
| -rw-r--r-- | src/client/LoggedIn/Income/Model.elm | 36 | ||||
| -rw-r--r-- | src/client/LoggedIn/Income/Msg.elm | 9 | ||||
| -rw-r--r-- | src/client/LoggedIn/Income/Update.elm | 24 | ||||
| -rw-r--r-- | src/client/LoggedIn/Income/View.elm | 108 | ||||
| -rw-r--r-- | src/client/LoggedIn/Income/View/Table.elm | 129 | 
5 files changed, 306 insertions, 0 deletions
diff --git a/src/client/LoggedIn/Income/Model.elm b/src/client/LoggedIn/Income/Model.elm new file mode 100644 index 0000000..7d852b9 --- /dev/null +++ b/src/client/LoggedIn/Income/Model.elm @@ -0,0 +1,36 @@ +module LoggedIn.Income.Model exposing +  ( Model +  , AddIncome +  , init +  , initForm +  , validation +  ) + +import Date exposing (Date) + +import Form exposing (Form) +import Form.Validate as Validate exposing (Validation) +import Validation + +type alias Model = +  { addIncome : Form String AddIncome +  } + +type alias AddIncome = +  { amount : Int +  , date : Date +  } + +init : Model +init = +  { addIncome = initForm +  } + +initForm : Form String AddIncome +initForm = Form.initial [] validation + +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/LoggedIn/Income/Msg.elm b/src/client/LoggedIn/Income/Msg.elm new file mode 100644 index 0000000..0a09dad --- /dev/null +++ b/src/client/LoggedIn/Income/Msg.elm @@ -0,0 +1,9 @@ +module LoggedIn.Income.Msg exposing +  ( Msg(..) +  ) + +import Form exposing (Form) + +type Msg = +  NoOp +  | AddIncomeMsg Form.Msg diff --git a/src/client/LoggedIn/Income/Update.elm b/src/client/LoggedIn/Income/Update.elm new file mode 100644 index 0000000..0023c76 --- /dev/null +++ b/src/client/LoggedIn/Income/Update.elm @@ -0,0 +1,24 @@ +module LoggedIn.Income.Update exposing +  ( update +  ) + +import Form exposing (Form) + +import LoggedData exposing (LoggedData) + +import LoggedIn.Income.Model as Income +import LoggedIn.Income.Msg as Income + +update : LoggedData -> Income.Msg -> Income.Model -> (Income.Model, Cmd Income.Msg) +update loggedData msg model = +  case msg of + +    Income.NoOp -> +      ( model +      , Cmd.none +      ) + +    Income.AddIncomeMsg formMsg -> +      ( { model | addIncome = Form.update Income.validation formMsg model.addIncome } +      , Cmd.none +      ) diff --git a/src/client/LoggedIn/Income/View.elm b/src/client/LoggedIn/Income/View.elm new file mode 100644 index 0000000..00a1646 --- /dev/null +++ b/src/client/LoggedIn/Income/View.elm @@ -0,0 +1,108 @@ +module LoggedIn.Income.View exposing +  ( view +  ) + +import Dict +import Date +import Time exposing (Time) +import Task + +import FontAwesome + +import Html exposing (..) +import Html.Events exposing (..) +import Html.Attributes exposing (..) + +import Form exposing (Form) +import View.Form as Form +import View.Events exposing (onSubmitPrevDefault) + +import Dialog +import Dialog.AddIncome.Model as AddIncome +import Dialog.AddIncome.View as AddIncome + +import Msg exposing (Msg) + +import LoggedData exposing (LoggedData) + +import Model.Income exposing (IncomeId, Income, userCumulativeIncomeSince) +import Model.Translations exposing (getMessage, getParamMessage) +import Model.Payer exposing (useIncomesFrom) +import Model.User exposing (UserId, User) +import Model.View as View +import LoggedIn.Income.Model as Income + +import LoggedIn.Msg as LoggedInMsg +import LoggedIn.Income.Msg as IncomeMsg + +import View.Date as Date +import LoggedIn.View.Format as Format +import View.Color as Color +import LoggedIn.Income.View.Table as Table + +view : LoggedData -> Income.Model -> Html Msg +view loggedData incomeModel = +  div +    [ class "income" ] +    [ 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 +    ] + +cumulativeIncomesView : LoggedData -> Time -> Html Msg +cumulativeIncomesView loggedData since = +  let longDate = Date.longView (Date.fromTime since) loggedData.translations +  in  div +        [] +        [ h1 [] [ text <| getParamMessage [longDate] loggedData.translations "CumulativeIncomesSince" ] +        , ul +            [] +            ( Dict.toList loggedData.users +                |> List.map (\(userId, user) -> +                     (user.name, userCumulativeIncomeSince loggedData.currentTime since loggedData.incomes userId) +                   ) +                |> List.sortBy Tuple.second +                |> List.map (\(userName, cumulativeIncome) -> +                     li +                       [] +                       [ text userName +                       , text " − " +                       , text <| Format.price loggedData.conf cumulativeIncome +                       ] +                   ) +            ) +        ] + +incomeView : LoggedData -> (IncomeId, Income) -> Html Msg +incomeView loggedData (incomeId, income) = +  li +    [] +    [ text <| Date.shortView (Date.fromTime income.time) loggedData.translations +    , text "    −    " +    , text <| Format.price loggedData.conf income.amount +    , let dialogConfig = +            { className = "deleteIncomeDialog" +            , title = getMessage loggedData.translations "ConfirmIncomeDelete" +            , body = always <| text "" +            , confirm = getMessage loggedData.translations "Confirm" +            , confirmMsg = always <| Msg.Dialog <| Dialog.UpdateAndClose <| Msg.DeleteIncome incomeId +            , undo = getMessage loggedData.translations "Undo" +            } +      in  button +            [ onClick (Msg.Dialog <| Dialog.Open dialogConfig) ] +            [ FontAwesome.trash Color.chestnutRose 14 ] +    ] diff --git a/src/client/LoggedIn/Income/View/Table.elm b/src/client/LoggedIn/Income/View/Table.elm new file mode 100644 index 0000000..aa5e392 --- /dev/null +++ b/src/client/LoggedIn/Income/View/Table.elm @@ -0,0 +1,129 @@ +module LoggedIn.Income.View.Table 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.AddIncome.Model as AddIncome +import Dialog.AddIncome.View as AddIncome + +import Tooltip + +import Msg exposing (Msg) + +import LoggedData exposing (LoggedData) + +import LoggedIn.Msg as LoggedInMsg + +import LoggedIn.Income.Model as Income +import View.Date as Date +import LoggedIn.View.Format as Format + +import Model.User exposing (getUserName) +import Model.Income as Income exposing (..) +import Model.Translations exposing (getMessage) + +view : LoggedData -> Income.Model -> Html Msg +view loggedData incomeModel = +  let incomes = +        loggedData.incomes +          |> Dict.toList +          |> List.sortBy (.time << Tuple.second) +          |> List.reverse +  in  div +        [ class "table" ] +        [ div +            [ class "lines" ] +            ( headerLine loggedData :: List.map (paymentLine loggedData incomeModel) incomes) +        , if List.isEmpty (Dict.toList loggedData.incomes) +            then +              div +                [ class "emptyTableMsg" ] +                [ text <| getMessage loggedData.translations "NoIncome" ] +            else +              text "" +        ] + +headerLine : LoggedData -> Html Msg +headerLine loggedData = +  div +    [ class "header" ] +    [ div [ class "cell name" ] [ text <| getMessage loggedData.translations "Name" ] +    , div [ class "cell income" ] [ text <| getMessage loggedData.translations "Income" ] +    , div [ class "cell date" ] [ text <| getMessage loggedData.translations "Date" ] +    , div [ class "cell" ] [] +    , div [ class "cell" ] [] +    , div [ class "cell" ] [] +    ] + +paymentLine : LoggedData -> Income.Model -> (IncomeId, Income) -> Html Msg +paymentLine loggedData incomeModel (incomeId, income) = +  div +    [ class "row" ] +    [ div +        [ class "cell name" ] +        [ income.userId +            |> getUserName loggedData.users +            |> Maybe.withDefault "−" +            |> text +        ] +    , div +        [ class "cell income" ] +        [ text (Format.price loggedData.conf income.amount) ] +    , div +        [ class "cell date" ] +        [ text (Date.longView (Date.fromTime income.time) loggedData.translations) ] +    , div +        [ class "cell button" ] +        [ let currentDate = Date.fromTime loggedData.currentTime +          in  AddIncome.button +                loggedData +                (AddIncome.initialClone loggedData.translations currentDate income) +                "CloneIncome" +                (FontAwesome.clone Color.chestnutRose 18) +                (Just (getMessage loggedData.translations "Clone")) +        ] +    , div +        [ class "cell button" ] +        [ if loggedData.me /= income.userId +            then +              text "" +            else +              AddIncome.button +                loggedData +                (AddIncome.initialEdit loggedData.translations incomeId income) +                "EditIncome" +                (FontAwesome.pencil Color.chestnutRose 18) +                (Just (getMessage loggedData.translations "Edit")) +        ] +    , div +        [ class "cell button" ] +        [ if loggedData.me /= income.userId +            then +              text "" +            else +              let dialogConfig = +                    { className = "deleteIncomeDialog" +                    , title = getMessage loggedData.translations "ConfirmIncomeDelete" +                    , body = always <| text "" +                    , confirm = getMessage loggedData.translations "Confirm" +                    , confirmMsg = always <| Msg.Dialog <| Dialog.UpdateAndClose <| Msg.DeleteIncome incomeId +                    , 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 ] +        ] +    ]  | 
