module Route exposing (Route(..), fromUrl, href, replaceUrl) import Browser.Navigation as Nav import Html exposing (Attribute) import Html.Attributes as Attr import Todo.UUID as UUID import Url exposing (Url) import Url.Parser as Parser exposing ((), Parser, oneOf, s, string) import Username exposing (Username) -- ROUTING type Route = Home | Login | Logout | Signup | Account | Todo UUID.UUID | NewTodo | EditTodo UUID.UUID parser : Parser (Route -> a) a parser = oneOf [ Parser.map Home Parser.top , Parser.map Login (s "login") , Parser.map Logout (s "logout") , Parser.map Account (s "account") , Parser.map Signup (s "signup") , Parser.map Todo (s "article" UUID.urlParser) , Parser.map NewTodo (s "editor") , Parser.map EditTodo (s "editor" UUID.urlParser) ] -- PUBLIC HELPERS href : Route -> Attribute msg href targetRoute = Attr.href (routeToString targetRoute) replaceUrl : Nav.Key -> Route -> Cmd msg replaceUrl key route = Nav.replaceUrl key (routeToString route) fromUrl : Url -> Maybe Route fromUrl url = -- The RealWorld spec treats the fragment like a path. -- This makes it *literally* the path, so we can proceed -- with parsing as if it had been a normal path all along. { url | path = Maybe.withDefault "" url.fragment, fragment = Nothing } |> Parser.parse parser -- INTERNAL routeToString : Route -> String routeToString page = "#/" ++ String.join "/" (routeToPieces page) routeToPieces : Route -> List String routeToPieces page = case page of Home -> [] Login -> [ "login" ] Logout -> [ "logout" ] Signup -> [ "Signup" ] Account -> [ "account" ] Todo uuid -> [ "article", UUID.toString uuid ] NewTodo -> [ "editor" ] EditTodo uuid -> [ "editor", UUID.toString uuid ]