about summary refs log tree commit diff
path: root/users/wpcarro/assessments/tt/client/src/UI.elm
module UI exposing (..)

import Date
import DatePicker exposing (defaultSettings)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import State
import Tailwind


label_ : { for_ : String, text_ : String } -> Html msg
label_ { for_, text_ } =
    label
        [ [ "block"
          , "text-gray-700"
          , "text-sm"
          , "font-bold"
          , "mb-2"
          ]
            |> Tailwind.use
            |> class
        , for for_
        ]
        [ text text_ ]


errorBanner : { title : String, body : String } -> Html msg
errorBanner { title, body } =
    div
        [ [ "text-left"
          , "fixed"
          , "container"
          , "top-0"
          , "mt-6"
          ]
            |> Tailwind.use
            |> class
        , style "left" "50%"

        -- TODO(wpcarro): Consider supporting breakpoints, but for now
        -- don't.
        , style "width" "800px"
        , style "margin-left" "-400px"
        ]
        [ div
            [ [ "bg-red-500"
              , "text-white"
              , "font-bold"
              , "rounded-t"
              , "px-4"
              , "py-2"
              ]
                |> Tailwind.use
                |> class
            ]
            [ text title ]
        , div
            [ [ "border"
              , "border-t-0"
              , "border-red-400"
              , "rounded-b"
              , "bg-red-100"
              , "px-4"
              , "py-3"
              , "text-red-700"
              ]
                |> Tailwind.use
                |> class
            ]
            [ p [] [ text body ] ]
        ]


baseButton :
    { label : String
    , enabled : Bool
    , handleClick : msg
    , extraClasses : List String
    }
    -> Html msg
baseButton { label, enabled, handleClick, extraClasses } =
    button
        [ [ if enabled then
                "bg-blue-500"

            else
                "bg-gray-500"
          , if enabled then
                "hover:bg-blue-700"

            else
                ""
          , if enabled then
                ""

            else
                "cursor-not-allowed"
          , "text-white"
          , "font-bold"
          , "py-1"
          , "shadow-lg"
          , "px-4"
          , "rounded"
          , "focus:outline-none"
          , "focus:shadow-outline"
          ]
            ++ extraClasses
            |> Tailwind.use
            |> class
        , onClick handleClick
        , disabled (not enabled)
        ]
        [ text label ]


simpleButton :
    { label : String
    , handleClick : msg
    }
    -> Html msg
simpleButton { label, handleClick } =
    baseButton
        { label = label
        , enabled = True
        , handleClick = handleClick
        , extraClasses = []
        }


disabledButton :
    { label : String }
    -> Html State.Msg
disabledButton { label } =
    baseButton
        { label = label
        , enabled = False
        , handleClick = State.DoNothing
        , extraClasses = []
        }


textButton :
    { label : String
    , handleClick : msg
    }
    -> Html msg
textButton { label, handleClick } =
    button
        [ [ "text-blue-600"
          , "hover:text-blue-500"
          , "font-bold"
          , "hover:underline"
          , "focus:outline-none"
          ]
            |> Tailwind.use
            |> class
        , onClick handleClick
        ]
        [ text label ]


textField :
    { pholder : String
    , inputId : String
    , handleInput : String -> msg
    , inputValue : String
    }
    -> Html msg
textField { pholder, inputId, handleInput, inputValue } =
    input
        [ [ "shadow"
          , "appearance-none"
          , "border"
          , "rounded"
          , "w-full"
          , "py-2"
          , "px-3"
          , "text-gray-700"
          , "leading-tight"
          , "focus:outline-none"
          , "focus:shadow-outline"
          ]
            |> Tailwind.use
            |> class
        , id inputId
        , value inputValue
        , placeholder pholder
        , onInput handleInput
        ]
        []


toggleButton :
    { toggled : Bool
    , label : String
    , handleEnable : msg
    , handleDisable : msg
    }
    -> Html msg
toggleButton { toggled, label, handleEnable, handleDisable } =
    button
        [ [ if toggled then
                "bg-blue-700"

            else
                "bg-blue-500"
          , "hover:bg-blue-700"
          , "text-white"
          , "font-bold"
          , "py-2"
          , "px-4"
          , "rounded"
          , "focus:outline-none"
          , "focus:shadow-outline"
          ]
            |> Tailwind.use
            |> class
        , onClick
            (if toggled then
                handleDisable

             else
                handleEnable
            )
        ]
        [ text label ]


paragraph : String -> Html msg
paragraph x =
    p [ [ "text-xl" ] |> Tailwind.use |> class ] [ text x ]


header : Int -> String -> Html msg
header which x =
    let
        hStyles =
            case which of
                1 ->
                    [ "text-6xl"
                    , "py-12"
                    ]

                2 ->
                    [ "text-3xl"
                    , "py-6"
                    ]

                _ ->
                    [ "text-2xl"
                    , "py-2"
                    ]
    in
    h1
        [ hStyles
            ++ [ "font-bold"
               , "text-gray-700"
               ]
            |> Tailwind.use
            |> class
        ]
        [ text x ]


link : String -> String -> Html msg
link path label =
    a
        [ href path
        , [ "underline"
          , "text-blue-600"
          , "text-xl"
          ]
            |> Tailwind.use
            |> class
        ]
        [ text label ]


absentData : { handleFetch : msg } -> Html msg
absentData { handleFetch } =
    div []
        [ paragraph "Welp... it looks like you've caught us in a state that we considered impossible: we did not fetch the data upon which this page depends. Maybe you can help us out by clicking the super secret, highly privileged \"Fetch data\" button below (we don't normally show people this)."
        , div [ [ "py-4" ] |> Tailwind.use |> class ]
            [ simpleButton
                { label = "Fetch data"
                , handleClick = handleFetch
                }
            ]
        ]


datePicker :
    { mDate : Maybe Date.Date
    , prompt : String
    , prefix : String
    , picker : DatePicker.DatePicker
    , onUpdate : DatePicker.Msg -> State.Msg
    }
    -> Html State.Msg
datePicker { mDate, prompt, prefix, picker, onUpdate } =
    let
        settings =
            { defaultSettings
                | placeholder = prompt
                , inputClassList =
                    [ ( "text-center", True )
                    , ( "py-2", True )
                    ]
            }
    in
    div [ [ "w-1/2", "py-4", "mx-auto" ] |> Tailwind.use |> class ]
        [ DatePicker.view mDate settings picker |> Html.map onUpdate ]


wrapNoPrint : Html State.Msg -> Html State.Msg
wrapNoPrint component =
    div [ [ "no-print" ] |> Tailwind.use |> class ] [ component ]