okfn-brasil/serenata-de-amor

View on GitHub
jarbas/layers/elm/Reimbursement/Search/View.elm

Summary

Maintainability
Test Coverage
module Reimbursement.Search.View exposing (correctedFieldIndex, matchDate, view)

import Html exposing (Html, br, p, span, text, form, div)
import Html.Events exposing (onSubmit)
import Internationalization exposing (translate)
import Internationalization.Types exposing (Language(..), TranslationId(..))
import List.Extra
import Material.Button as Button
import Material.Grid exposing (Device(..), cell, grid, size)
import Material.Options as Options
import Material.Textfield as Textfield
import Material.Typography as Typography
import Regex
import Reimbursement.Fields as Fields exposing (Field(..), Label(..))
import Reimbursement.Model as ParentModel exposing (Model)
import Reimbursement.Search.Update exposing (Msg(..), update)
import Reimbursement.Update as ParentMsg exposing (Msg(..))


{-| Matches a date un the YYYY-MM-DD format

    matchDate "1970-01-01" --> True

    matchDate "foo-42-01" --> False

-}
matchDate : String -> Bool
matchDate value =
    if String.isEmpty value then
        True
    else
        let
            regex : Regex.Regex
            regex =
                Regex.regex "[\\d]{4}-[\\d]{2}-[\\d]{2}"
        in
            value
                |> Regex.find Regex.All regex
                |> List.isEmpty
                |> not


getField : ParentModel.Model -> Label -> Field
getField model label =
    List.Extra.find (Fields.getLabel >> (==) label) model.searchFields
        |> Maybe.withDefault (Field Empty "")


viewField : ParentModel.Model -> ( Int, ( Label, Field ) ) -> Html ParentMsg.Msg
viewField model ( index, ( label, field ) ) =
    let
        value =
            Fields.getValue field

        base =
            [ Textfield.onInput (Update label >> ParentMsg.SearchMsg)
            , Textfield.value value
            , Options.css "width" "100%"
            ]

        disabled =
            if model.loading then
                [ Textfield.disabled ]
            else
                []

        validationMsg =
            translate model.lang FieldIssueDateValidation

        dateValidation =
            if Fields.isDate label then
                [ Options.when (Textfield.error validationMsg) (not <| matchDate value) ]
            else
                []

        attrs =
            List.concat [ base, disabled, dateValidation ]
    in
        p []
            [ Options.styled span [ Typography.caption ] [ text <| Fields.getLabelTranslation model.lang field ]
            , br [] []
            , Textfield.render ParentMsg.Mdl [ index ] model.mdl attrs
            ]


viewFieldset : ParentModel.Model -> ( Int, ( TranslationId, List Label ) ) -> Material.Grid.Cell ParentMsg.Msg
viewFieldset model ( index, ( title, labels ) ) =
    let
        fields =
            List.map (getField model) labels

        namesAndFields =
            List.map2 (,) labels fields

        indexedNamesAndFields =
            List.indexedMap (,) namesAndFields
                |> List.map (\( idx, field ) -> ( correctedFieldIndex index idx, field ))

        heading =
            [ Options.styled p [ Typography.title ] [ text <| translate model.lang title ] ]

        searchFields =
            List.map (viewField model) indexedNamesAndFields
    in
        cell [ size Desktop 6, size Tablet 6, size Phone 6 ]
            (List.append heading searchFields)


{-| Creates an unique index for each field, using the hundreds for the
filedset, and the units for the field itself:

    correctedFieldIndex 0 42 --> 142

    correctedFieldIndex 100 8 --> 10108

-}
correctedFieldIndex : Int -> Int -> Int
correctedFieldIndex fieldset field =
    ((fieldset + 1) * 100) + field


view : ParentModel.Model -> Html ParentMsg.Msg
view model =
    let
        searchFields =
            grid [] <| List.map (viewFieldset model) Fields.sets

        send =
            searchButton model
                0
                [ Button.raised, Button.colored, Button.type_ "submit" ]
                Search

        showFormButton =
            searchButton model
                1
                [ Button.raised, Button.onClick ToggleForm ]
                NewSearch
    in
        if model.showForm then
            form [ onSubmit Submit ] [ searchFields, send ]
        else
            showFormButton


searchButton : ParentModel.Model -> Int -> List (Button.Property ParentMsg.Msg) -> TranslationId -> Html ParentMsg.Msg
searchButton model index defaultAttr defaultLabel =
    let
        label =
            if model.loading then
                translate model.lang Loading
            else
                translate model.lang defaultLabel

        attr =
            if model.loading then
                Button.disabled :: defaultAttr
            else
                defaultAttr
    in
        grid []
            [ cell [ size Desktop 12, size Tablet 8, size Phone 4 ]
                [ Options.styled div
                    [ Typography.center ]
                    [ Button.render Mdl
                        [ index ]
                        model.mdl
                        attr
                        [ text label ]
                    ]
                ]
            ]