module Main exposing (main) import Browser exposing(..) import Page.ListPosts exposing (..) import Route exposing (Route) import Browser.Navigation as Nav import Url exposing (Url) import Html exposing (..) import Page.EditPost as EditPost import Page.NewPost as NewPost main : Program () Model Msg main = Browser.application { init = init , view = view , update = update , subscriptions = \_ -> Sub.none , onUrlRequest = LinkClicked , onUrlChange = UrlChanged } type Page = NotFoundPage | ListPage Page.ListPosts.Model | EditPage EditPost.Model | NewPage NewPost.Model type Msg = ListPageMsg Page.ListPosts.Msg | LinkClicked UrlRequest | UrlChanged Url | EditPageMsg EditPost.Msg | NewPageMsg NewPost.Msg type alias Model = { route : Route , page : Page , navKey : Nav.Key } init : () -> Url -> Nav.Key -> ( Model, Cmd Msg ) init flags url navKey = let model = { navKey = navKey , route = Route.parseUrl url , page = NotFoundPage } in initCurrentPage ( model, Cmd.none ) initCurrentPage : ( Model, Cmd Msg ) -> ( Model, Cmd Msg ) initCurrentPage ( model, existingCmds ) = let ( currentPage, mappedPageCmds ) = case model.route of Route.NotFound -> ( NotFoundPage, Cmd.none ) Route.Posts -> let ( pageModel, pageCmds ) = Page.ListPosts.init in ( ListPage pageModel, Cmd.map ListPageMsg pageCmds ) Route.Post postId -> let ( pageModel, pageCmd ) = EditPost.init postId model.navKey in ( EditPage pageModel, Cmd.map EditPageMsg pageCmd ) Route.NewPost -> let ( pageModel, pageCmd ) = NewPost.init model.navKey in ( NewPage pageModel, Cmd.map NewPageMsg pageCmd ) in ( { model | page = currentPage } , Cmd.batch [ existingCmds, mappedPageCmds ] ) view : Model -> Document Msg view model = { title = "Post App" , body = [ currentView model ] } currentView : Model -> Html Msg currentView model = case model.page of NotFoundPage -> notFoundView ListPage pageModel -> Page.ListPosts.view pageModel |> Html.map ListPageMsg EditPage pageModel -> EditPost.view pageModel |> Html.map EditPageMsg NewPage pageModel -> NewPost.view pageModel |> Html.map NewPageMsg notFoundView : Html msg notFoundView = h3 [] [ text "Oops! The page you requested was not found!" ] update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case ( msg, model.page ) of ( ListPageMsg subMsg, ListPage pageModel ) -> let ( updatedPageModel, updatedCmd ) = Page.ListPosts.update subMsg pageModel in ( { model | page = ListPage updatedPageModel } , Cmd.map ListPageMsg updatedCmd ) ( LinkClicked urlRequest, _ ) -> case urlRequest of Browser.Internal url -> ( model , Nav.pushUrl model.navKey (Url.toString url) ) Browser.External url -> ( model , Nav.load url ) ( UrlChanged url, _ ) -> let newRoute = Route.parseUrl url in ( { model | route = newRoute }, Cmd.none ) |> initCurrentPage ( EditPageMsg subMsg, EditPage pageModel ) -> let ( updatedPageModel, updatedCmd ) = EditPost.update subMsg pageModel in ( { model | page = EditPage updatedPageModel } , Cmd.map EditPageMsg updatedCmd ) ( NewPageMsg subMsg, NewPage pageModel ) -> let ( updatedPageModel, updatedCmd ) = NewPost.update subMsg pageModel in ( { model | page = NewPage updatedPageModel } , Cmd.map NewPageMsg updatedCmd ) ( _, _ ) -> ( model, Cmd.none )