elm-pages-v3-beta/examples/trails/app/Route/Search.elm

247 lines
6.7 KiB
Elm
Raw Normal View History

2022-05-18 02:07:07 +03:00
module Route.Search exposing (ActionData, Data, Model, Msg, route)
2022-05-18 18:43:50 +03:00
import Api.InputObject
import Api.Object
import Api.Object.Trails
import Api.Query
2022-05-18 02:07:07 +03:00
import DataSource exposing (DataSource)
import Effect exposing (Effect)
import ErrorPage exposing (ErrorPage)
2022-05-18 18:43:50 +03:00
import Graphql.Operation exposing (RootQuery)
import Graphql.OptionalArgument exposing (OptionalArgument(..))
import Graphql.SelectionSet as SelectionSet exposing (SelectionSet)
2022-05-18 02:07:07 +03:00
import Head
import Head.Seo as Seo
import Html exposing (Html)
import Html.Attributes as Attr
import Pages.Msg
import Pages.PageUrl exposing (PageUrl)
import Pages.Url
import Path exposing (Path)
2022-05-18 18:43:50 +03:00
import Request.Hasura
2022-05-18 02:07:07 +03:00
import RouteBuilder exposing (StatefulRoute, StatelessRoute, StaticPayload)
import Server.Request as Request
import Server.Response as Response exposing (Response)
import Shared
import View exposing (View)
type alias Model =
{}
type Msg
= NoOp
type alias RouteParams =
{}
route : StatefulRoute RouteParams Data ActionData Model Msg
route =
RouteBuilder.serverRender
{ head = head
, data = data
, action = action
}
|> RouteBuilder.buildWithLocalState
{ view = view
, update = update
, subscriptions = subscriptions
, init = init
}
init :
Maybe PageUrl
-> Shared.Model
-> StaticPayload Data ActionData RouteParams
-> ( Model, Effect Msg )
init maybePageUrl sharedModel static =
( {}, Effect.none )
update :
PageUrl
-> Shared.Model
-> StaticPayload Data ActionData RouteParams
-> Msg
-> Model
-> ( Model, Effect Msg )
update pageUrl sharedModel static msg model =
case msg of
NoOp ->
( model, Effect.none )
subscriptions : Maybe PageUrl -> RouteParams -> Path -> Shared.Model -> Model -> Sub Msg
subscriptions maybePageUrl routeParams path sharedModel model =
Sub.none
type alias SearchResults =
{ query : String
, results : List SearchResult
}
type alias SearchResult =
{ name : String
, coverImage : String
2022-05-18 02:07:07 +03:00
}
type alias Data =
{ results : Maybe SearchResults
}
type alias ActionData =
{}
data : RouteParams -> Request.Parser (DataSource (Response Data ErrorPage))
data routeParams =
Request.oneOf
[ Request.expectForm
(\{ field, optionalField } ->
field "q"
|> Request.map
(\query ->
2022-05-18 18:43:50 +03:00
Request.Hasura.dataSource ""
(search query)
|> DataSource.map
(\results ->
Response.render
{ results =
Just
{ query = query
, results = results
}
2022-05-18 02:07:07 +03:00
}
2022-05-18 18:43:50 +03:00
)
2022-05-18 02:07:07 +03:00
)
)
, Request.succeed (DataSource.succeed (Response.render { results = Nothing }))
]
action : RouteParams -> Request.Parser (DataSource (Response ActionData ErrorPage))
action routeParams =
Request.skip "No action."
head :
StaticPayload Data ActionData RouteParams
-> List Head.Tag
head static =
Seo.summary
{ canonicalUrlOverride = Nothing
2022-05-18 18:43:50 +03:00
, siteName = "Trail Blazer"
2022-05-18 02:07:07 +03:00
, image =
{ url = Pages.Url.external "TODO"
, alt = "elm-pages logo"
, dimensions = Nothing
, mimeType = Nothing
}
, description = "TODO"
, locale = Nothing
2022-05-18 18:43:50 +03:00
, title =
case static.data.results of
Nothing ->
"Find your next trail"
Just { results, query } ->
query
++ " at TrailBlazer ("
++ String.fromInt (List.length results)
++ " results)"
2022-05-18 02:07:07 +03:00
}
|> Seo.website
view :
Maybe PageUrl
-> Shared.Model
-> Model
-> StaticPayload Data ActionData RouteParams
-> View (Pages.Msg.Msg Msg)
view maybeUrl sharedModel model static =
{ title = "Search"
, body =
[ Html.h2 [] [ Html.text "Search" ]
, Html.form
[ Pages.Msg.onSubmit
]
2022-05-18 02:07:07 +03:00
[ Html.label []
[ Html.text "Query "
, Html.input [ Attr.name "q" ] []
]
, case static.transition of
Just _ ->
Html.button
[ Attr.disabled True
]
[ Html.text "Searching..."
]
Nothing ->
Html.button []
[ Html.text "Search"
]
2022-05-18 02:07:07 +03:00
]
, static.data.results
|> Maybe.map resultsView
|> Maybe.withDefault (Html.div [] [])
]
}
resultsView : SearchResults -> Html msg
resultsView results =
Html.div []
[ Html.h2 [] [ Html.text <| "Results matching " ++ results.query ]
2022-05-18 18:43:50 +03:00
, results.results
|> List.map
(\result ->
Html.li []
[ Html.img
[ Attr.src result.coverImage
, Attr.style "width" "200px"
, Attr.style "border-radius" "10px"
]
[]
, Html.text result.name
2022-05-18 18:43:50 +03:00
]
)
|> Html.ul []
2022-05-18 02:07:07 +03:00
]
2022-05-18 18:43:50 +03:00
search : String -> SelectionSet (List SearchResult) RootQuery
2022-05-18 18:43:50 +03:00
search query =
Api.Query.trails
(\optionals ->
{ optionals
| where_ =
Present
(Api.InputObject.buildTrails_bool_exp
(\whereOptionals ->
{ whereOptionals
| name =
Api.InputObject.buildString_comparison_exp
(\stringOptionals ->
{ stringOptionals | ilike_ = Present <| "%" ++ query ++ "%" }
)
|> Present
}
)
)
}
)
(SelectionSet.map2 SearchResult
Api.Object.Trails.name
Api.Object.Trails.coverImage
)