module CreatePage exposing (Model, Msg, init, update, view) import Browser.Navigation as Nav import Css import Css.Media as Media import Html.Styled exposing (..) import Html.Styled.Attributes as Attr import Html.Styled.Events as Events import Http import Input import Json.Decode as Decode exposing (Decoder) import Json.Decode.Pipeline exposing (required) import Json.Encode as Encode type alias Model = { link : String , error : Maybe String } init : Model init = { link = "" , error = Nothing } descriptionStyles : Css.Style descriptionStyles = Css.marginTop (Css.px 0) inputLineStyles : Css.Style inputLineStyles = Css.batch [ Css.displayFlex , Media.withMedia [ Media.only Media.screen [ Media.maxWidth (Css.px 500) ] ] [ Css.display Css.block ] ] view : Model -> Html Msg view model = div [] [ form [ Events.onSubmit (ClickedCreate model.link) ] [ p [ Attr.css [ descriptionStyles ] ] [ text "A Doglink is just an alias, or a redirect for an existing link. Paste a link you want to redirect to into the field below!" ] , div [ Attr.css [ inputLineStyles ] ] [ Input.text [ Attr.placeholder "https://example.com" , Events.onInput LinkUpdated ] [] , Input.submitButton [] [ text "Create doglink" ] ] ] , case model.error of Just error -> viewError error Nothing -> text "" ] viewError : String -> Html msg viewError error = div [] [ h3 [] [ text "Couldn't create doglink" ] , p [] [ text error ] ] type Msg = ClickedCreate String | LinkUpdated String | GotUuid (Result Http.Error String) update : String -> Nav.Key -> Msg -> Model -> ( Model, Cmd Msg ) update origin key msg model = case msg of ClickedCreate _ -> ( model, createLink origin model ) LinkUpdated link -> ( { model | link = link }, Cmd.none ) GotUuid (Ok uuid) -> ( model, Nav.pushUrl key ("/" ++ uuid) ) GotUuid (Err error) -> case error of Http.BadUrl url -> ( { model | error = Just ("Bad url: " ++ url) }, Cmd.none ) Http.Timeout -> ( { model | error = Just "Request timed out" }, Cmd.none ) Http.NetworkError -> ( { model | error = Just "Couldn't talk to server" }, Cmd.none ) Http.BadStatus int -> ( { model | error = Just ("Server responded with invalid status: " ++ String.fromInt int) }, Cmd.none ) Http.BadBody body -> ( { model | error = Just ("Server responed with unexpected data: " ++ body) }, Cmd.none ) createLink : String -> Model -> Cmd Msg createLink origin model = Http.post { url = origin ++ "/link" , body = Http.jsonBody (encodeLink model.link) , expect = Http.expectJson GotUuid uuidDecoder } uuidDecoder : Decoder String uuidDecoder = Decode.succeed identity |> required "uuid" Decode.string encodeLink : String -> Encode.Value encodeLink link = Encode.object [ ( "url", Encode.string link ) ]