summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Header.elm12
-rw-r--r--src/Main.elm47
-rw-r--r--src/Pages/Feed.elm28
-rw-r--r--src/Pages/Profile.elm25
-rw-r--r--src/Routes.elm12
-rw-r--r--src/Types.elm15
6 files changed, 111 insertions, 28 deletions
diff --git a/src/Header.elm b/src/Header.elm
index 257b308..36469aa 100644
--- a/src/Header.elm
+++ b/src/Header.elm
@@ -1,8 +1,8 @@
module Header exposing (..)
import Css exposing (..)
-import Html.Styled exposing (Html, button, div, text)
-import Html.Styled.Attributes exposing (css)
+import Html.Styled exposing (..)
+import Html.Styled.Attributes exposing (css, href)
import Html.Styled.Events exposing (onClick)
import Types exposing (Model, Msg(..))
import Utils exposing (templ)
@@ -14,6 +14,7 @@ styles =
[ displayFlex
, flexFlow2 row wrap
, justifyContent flexEnd
+ , alignItems center
, width (pct 100)
, marginBottom (px 10)
]
@@ -22,13 +23,16 @@ styles =
[ marginLeft (px 10)
, cursor pointer
]
+ , flexPad = css [ flex (int 1) ]
}
headerView : Model -> List (Html Msg)
headerView model =
- [ div [ styles.container ]
- [ div [] [ "Logged in as {0}" |> templ [ model.userData.name ] |> text ]
+ [ header [ styles.container ]
+ [ a [ href "/" ] [ h1 [] [ text "😎 SOMEBOOK" ] ]
+ , div [ styles.flexPad ] []
+ , div [] [ "Logged in as {0}" |> templ [ model.userData.name ] |> text ]
, button [ styles.logoutButton, onClick RequestLogout ] [ text "Logout" ]
]
]
diff --git a/src/Main.elm b/src/Main.elm
index 32cd992..35cf413 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -1,7 +1,7 @@
port module Main exposing (..)
import Browser exposing (Document)
-import Browser.Navigation exposing (Key)
+import Browser.Navigation as Nav
import Config exposing (makeApiUrl)
import Header exposing (headerView)
import Html.Styled exposing (..)
@@ -10,11 +10,14 @@ import Json.Decode exposing (Decoder, field, int, list, map2, map7, maybe, strin
import Json.Encode
import Json.Encode.Extra
import Pages.Feed exposing (feedView)
+import Pages.Profile exposing (profileView)
import RemoteData
+import Routes exposing (routeParser)
import Task
import Time
-import Types exposing (Author, Flags, Model, Msg(..), Post)
+import Types exposing (Author, Flags, Model, Msg(..), Post, Route(..))
import Url exposing (Url)
+import Url.Parser exposing ((</>), Parser, oneOf, s)
import Utils exposing (httpErrorToString, listFlat)
@@ -25,8 +28,8 @@ main =
, view = view
, update = update
, subscriptions = subscriptions
- , onUrlRequest = \_ -> NoOp
- , onUrlChange = \_ -> NoOp
+ , onUrlRequest = LinkClicked
+ , onUrlChange = UrlChanged
}
@@ -44,13 +47,14 @@ port requestLogout : () -> Cmd msg
-- INIT
-init : Flags -> Url -> Key -> ( Model, Cmd Msg )
-init flags _ key =
+init : Flags -> Url -> Nav.Key -> ( Model, Cmd Msg )
+init flags url key =
let
initModel : Model
initModel =
{ now = Time.millisToPosix 0
, key = key
+ , url = url
, userData = flags.userData
, apiURL = flags.apiURL
, posts = RemoteData.Loading
@@ -82,6 +86,18 @@ update msg model =
RequestLogout ->
( model, requestLogout () )
+ LinkClicked urlRequest ->
+ case urlRequest of
+ Browser.Internal url ->
+ ( model, Nav.pushUrl model.key (Url.toString url) )
+
+ Browser.External href ->
+ ( model, Nav.load href )
+
+ UrlChanged url ->
+ ( { model | url = url }, Cmd.none )
+
+ -- BUSINESS LOGIC
GetPosts ->
( model, getPosts model )
@@ -251,11 +267,28 @@ postDecoder =
-- VIEW
+urlToView : Url -> (Model -> List (Html Msg))
+urlToView url =
+ let
+ route =
+ Url.Parser.parse routeParser url
+ in
+ case route of
+ Just Index ->
+ feedView
+
+ Just (Profile id) ->
+ profileView id
+
+ Nothing ->
+ feedView
+
+
view : Model -> Document Msg
view model =
{ title = "SOMEBOOK"
, body =
- [ headerView model, feedView model ]
+ [ headerView model, urlToView model.url model ]
|> listFlat
|> List.map toUnstyled
}
diff --git a/src/Pages/Feed.elm b/src/Pages/Feed.elm
index 53f60a2..a7c2767 100644
--- a/src/Pages/Feed.elm
+++ b/src/Pages/Feed.elm
@@ -3,13 +3,14 @@ module Pages.Feed exposing (..)
import Css exposing (..)
import DateFormat.Relative exposing (relativeTime)
import Html.Styled exposing (..)
-import Html.Styled.Attributes exposing (css, placeholder, src, type_, value)
+import Html.Styled.Attributes exposing (css, href, placeholder, src, type_, value)
import Html.Styled.Events exposing (onClick, onInput, onSubmit)
import Html.Styled.Keyed as Keyed
import Html.Styled.Lazy exposing (lazy)
import RemoteData exposing (RemoteData(..))
import Time exposing (now)
import Types exposing (Model, Msg(..), Post)
+import Utils exposing (templ)
styles =
@@ -72,12 +73,14 @@ postDiv now post =
in
div
[ styles.post ]
- [ span []
- [ img [ styles.postProfilePicture, src post.userPictureUrl ] [] ]
- , span [ styles.postHeader ]
- [ h3 [ styles.postTitle ] [ text post.author.name ]
- , i []
- [ text <| relativeTime now post.createdAt
+ [ a [ href <| templ [ post.author.id ] "/profile/{0}" ]
+ [ span []
+ [ img [ styles.postProfilePicture, src post.userPictureUrl ] [] ]
+ , span [ styles.postHeader ]
+ [ h3 [ styles.postTitle ] [ text post.author.name ]
+ , i []
+ [ text <| relativeTime now post.createdAt
+ ]
]
]
, p [] [ text post.content ]
@@ -131,13 +134,6 @@ composeDiv model =
]
-headerSection : Model -> Html msg
-headerSection _ =
- header []
- [ h1 [] [ text "😎 SOMEBOOK" ]
- ]
-
-
mainSection : Model -> Html Msg
mainSection model =
main_ [] <|
@@ -149,9 +145,7 @@ mainSection model =
body : Model -> Html Msg
body model =
div [ styles.page ]
- [ headerSection model
- , mainSection model
- ]
+ [ mainSection model ]
feedView : Model -> List (Html Msg)
diff --git a/src/Pages/Profile.elm b/src/Pages/Profile.elm
new file mode 100644
index 0000000..a564b3e
--- /dev/null
+++ b/src/Pages/Profile.elm
@@ -0,0 +1,25 @@
+module Pages.Profile exposing (..)
+
+import Css exposing (marginBottom, px)
+import Html.Styled exposing (..)
+import Html.Styled.Attributes exposing (css)
+import Types exposing (Model, Msg, UrlSegmentUserId)
+
+
+styles =
+ { container =
+ css
+ [ marginBottom (px 10)
+ ]
+ }
+
+
+body : Model -> UrlSegmentUserId -> Html Msg
+body _ id =
+ div [ styles.container ]
+ [ text id ]
+
+
+profileView : UrlSegmentUserId -> Model -> List (Html Msg)
+profileView userId model =
+ [ body model userId ]
diff --git a/src/Routes.elm b/src/Routes.elm
new file mode 100644
index 0000000..04c7eb1
--- /dev/null
+++ b/src/Routes.elm
@@ -0,0 +1,12 @@
+module Routes exposing (..)
+
+import Types exposing (Route(..))
+import Url.Parser exposing ((</>), Parser, oneOf, s, string, top)
+
+
+routeParser : Parser (Route -> a) a
+routeParser =
+ oneOf
+ [ Url.Parser.map Index top
+ , Url.Parser.map Profile (s "profile" </> string)
+ ]
diff --git a/src/Types.elm b/src/Types.elm
index f10223e..aeb7d67 100644
--- a/src/Types.elm
+++ b/src/Types.elm
@@ -1,14 +1,17 @@
module Types exposing (..)
+import Browser exposing (UrlRequest)
import Browser.Navigation exposing (Key)
import Http
import RemoteData exposing (RemoteData)
import Time
+import Url exposing (Url)
type alias Model =
{ now : Time.Posix
, key : Key
+ , url : Url
, userData : UserData
, apiURL : String
, posts : RemoteData (List Post)
@@ -35,6 +38,9 @@ type Msg
| RequestLogout
-- TIME
| SetNowPosix Time.Posix
+ -- NAVIGATION
+ | UrlChanged Url
+ | LinkClicked UrlRequest
-- POSTS
| GetPosts
| GotPosts (Result Http.Error (List Post))
@@ -47,12 +53,21 @@ type Msg
| ComposedPost (Result Http.Error Post)
+type Route
+ = Index
+ | Profile UrlSegmentUserId
+
+
type alias Author =
{ id : String
, name : String
}
+type alias UrlSegmentUserId =
+ String
+
+
type alias Post =
{ id : String
, content : String