Plans for logins

When I originally started working on the Deep Sky, I had envisioned the user interface being just a plain HTML website. Pretty soon I started experimenting with Elm and switched over to it, mostly. Everything else is written in Elm on the client-side, except user account creation and login. Plan is to rewrite that portion on Elm too and hopefully clean up the code somewhat in the process.

Model is data structure that holds everything the client needs to operate. It currently looks as following:

type alias Model =
    { key : Key
    , url : Url
    , user : SaveData User
    , avatar : SaveData (Maybe Person)
    , currentTime : WebData StarDate
    , resources : WebData Resources
    , starSystemR : StarSystemViewModel
    , starSystemsR : StarSystemsViewModel
    , planetR : PlanetViewModel
    , messagesR : MessagesViewModel
    , errors : List ErrorMessage
    , researchR : ResearchViewModel
    , designerR : DesignerViewModel
    , personR : PersonViewModel
    , homeR : HomeViewModel
    , adminR : AdminViewModel
    , unitR : UnitViewModel
    }

user is currently logged in user and avatar is their in-game character, while resources represents natural resources in their disposal. SaveData is slightly extended version of RemoteData library that makes handling retrieving data from the server and representing status of the fetch really simple. For example, avatar can be NotAsked (nobody has requested it from server), Loading (it has been requested), Success (Maybe Person) (it was successfully loaded), Failure Error (there was an error while fetching the data) or Saving (Maybe Person) it is currently being saved.

Since the player might not have selected their avatar yet, we are using Maybe Person instead of Person. When I want to display any information about the avatar, I have to pattern match these cases. When in reality, player should never even end up in a page that shows info of their avatar, if they haven’t chosen one.

I want to break this down a bit and represent on the type level what is the current status of the program:

type Model
    = NotLoggedIn LoginModel
    | UserWithoutAvatar AvatarSelectionModel
    | UserWithAvatar GameModel

type alias LoginModel =
    { key : Key
    , url : Url
    , currentTime : WebData StarDate
    , loginR : LoginViewModel
    }

type alias AvatarSelectionModel =
    { key : Key
    , url : Url
    , user : SaveData User
    , currentTime : WebData StarDate
    , avatarSelectionR : AvatarSelectionViewModel
    }

type alias GameModel =
    { key : Key
    , url : Url
    , user : SaveData User
    , avatar : SaveData Person
    , currentTime : WebData StarDate
    , resources : WebData Resources
    , starSystemR : StarSystemViewModel
    , starSystemsR : StarSystemsViewModel
    , planetR : PlanetViewModel
    , messagesR : MessagesViewModel
    , errors : List ErrorMessage
    , researchR : ResearchViewModel
    , designerR : DesignerViewModel
    , personR : PersonViewModel
    , homeR : HomeViewModel
    , adminR : AdminViewModel
    , unitR : UnitViewModel
    }

This hopefully makes it easier to decide what to show to user and when, depending on their status (not logged in, no avatar selected, avatar selected). And later on I can move AdminViewModel to separate case, which is only used when the user actually has administrator rights.