Created
February 11, 2025 20:23
-
-
Save eyJhb/204c8e1bc9da981edd9b6e2a0bfd5745 to your computer and use it in GitHub Desktop.
Elm split module
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main exposing (main) | |
import Basics | |
import Browser | |
import Browser.Events | |
import Colors | |
import Element as E exposing (Element) | |
import Element.Background as Background | |
import Element.Font as Font | |
import Html exposing (Html, button, div, text) | |
import Offers | |
import Platform.Cmd exposing (Cmd, batch) | |
main : Program Screen Model Msg | |
main = | |
Browser.element | |
{ init = init | |
, view = view | |
, update = update | |
, subscriptions = subscriptions | |
} | |
-- subscriptions | |
subscriptions : Model -> Sub Msg | |
subscriptions model = | |
Browser.Events.onResize <| | |
\width height -> | |
DeviceClassified { width = width, height = height } | |
-- MODEL | |
type alias Model = | |
{ device : E.Device | |
, screen : Screen | |
, offersModel : Offers.Model | |
} | |
type alias Screen = | |
{ width : Int | |
, height : Int | |
} | |
init : Screen -> ( Model, Cmd Msg ) | |
init screen = | |
let | |
( initialOffersModel, initialOffersCmd ) = | |
Offers.init | |
in | |
( { device = E.classifyDevice screen | |
, screen = screen | |
, offersModel = initialOffersModel | |
} | |
, Cmd.map OffersMsg initialOffersCmd | |
) | |
-- UPDATE | |
type Msg | |
= DeviceClassified Screen | |
| OffersMsg Offers.Msg | |
update : Msg -> Model -> ( Model, Cmd Msg ) | |
update msg model = | |
case msg of | |
DeviceClassified screen -> | |
( { model | |
| device = E.classifyDevice { width = screen.width, height = screen.height } | |
, screen = screen | |
} | |
, Cmd.none | |
) | |
OffersMsg t -> | |
let | |
( newOffersModel, offersCmds ) = | |
Offers.update t model.offersModel | |
in | |
( { model | offersModel = newOffersModel }, Cmd.map OffersMsg offersCmds ) | |
view : Model -> Html Msg | |
view model = | |
-- initial setup | |
E.layout | |
[ E.width (E.px model.screen.width) | |
, E.height (E.px model.screen.height) | |
, Background.color (E.rgba 0 0 0 1) | |
, Font.color Colors.white | |
, Font.size 18 | |
, Font.family | |
[ Font.external | |
{ url = "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" | |
, name = "Inter" | |
} | |
] | |
] | |
<| | |
-- actual site content | |
E.column | |
[ E.width E.fill | |
, E.height E.fill | |
, Background.gradient { angle = Basics.pi, steps = [ Colors.backgroundPrimary, Colors.backgroundSecondary ] } | |
] | |
[ E.el | |
[ E.width E.fill | |
, E.padding 10 | |
, Font.bold | |
, Font.size 50 | |
, Font.center | |
] | |
(E.text "Bilka+") | |
, E.row | |
[] | |
[ E.map OffersMsg (Offers.viewPersonalisedDiscounts model.offersModel) ] | |
-- [ E.text "lol" ] | |
-- [ viewPersonalisedDiscounts model ] | |
-- -- personalised discounts | |
-- , E.el [ E.padding 10, Font.bold, Font.size 25, Font.underline ] (E.text "Personalised Discounts") | |
-- , E.el [ E.width E.fill, E.height E.fill ] (viewPersonalisedDiscounts model) | |
-- -- member discounts | |
-- , E.el [ E.padding 10, Font.bold, Font.size 25, Font.underline ] (E.text "Membership Discounts") | |
-- , E.el [ E.width E.fill, E.height E.fill ] (viewMembershipOffers model) | |
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Offers exposing (..) | |
import Element as E exposing (Element) | |
import Http | |
import Json.Decode as D exposing (Decoder) | |
import Json.Decode.Pipeline as DP | |
import Platform.Cmd exposing (Cmd, batch) | |
import RemoteData | |
import Time | |
type alias Model = | |
{ personalDiscounts : RemoteData.WebData (List PersonalisedOffer) | |
} | |
type Msg | |
= GotPersonalisedDiscounts (RemoteData.WebData (List PersonalisedOffer)) | |
init : ( Model, Cmd Msg ) | |
init = | |
( { personalDiscounts = RemoteData.NotAsked | |
} | |
, batch | |
[ fetchPersonalisedOffers | |
] | |
) | |
update : Msg -> Model -> ( Model, Cmd Msg ) | |
update msg model = | |
case msg of | |
GotPersonalisedDiscounts o -> | |
( { model | |
| personalDiscounts = o | |
} | |
, Cmd.none | |
) | |
fetchPersonalisedOffers : Cmd Msg | |
fetchPersonalisedOffers = | |
Http.get | |
{ url = "http://192.168.1.30:1746/api_offers.json" | |
, expect = Http.expectJson (RemoteData.fromResult >> GotPersonalisedDiscounts) decoderPersonalisedOffer | |
} | |
type alias PersonalisedOffer = | |
{ id : String | |
, articleNumber : String | |
, title : String | |
, description : String | |
, imageURL : String | |
, originalPrice : Float | |
, discountedPrice : Float | |
, startDate : Time.Posix | |
, endDate : Time.Posix | |
, variants : List OfferVariant | |
} | |
type alias OfferVariant = | |
{ title : String | |
, articleNumber : String | |
, description : String | |
, imageURL : String | |
} | |
decoderPersonalisedOffer : D.Decoder (List PersonalisedOffer) | |
decoderPersonalisedOffer = | |
D.list | |
(D.succeed PersonalisedOffer | |
|> DP.required "id" D.string | |
|> DP.required "articleNumber" D.string | |
|> DP.required "title" D.string | |
|> DP.required "description" D.string | |
|> DP.required "offerImage" D.string | |
|> DP.required "originalPrice" D.float | |
|> DP.required "discountedPrice" D.float | |
|> DP.required "startDate" decoderTimestamp | |
|> DP.required "endDate" decoderTimestamp | |
|> DP.required "variants" | |
(D.list | |
(D.succeed OfferVariant | |
|> DP.required "title" D.string | |
|> DP.required "articleNumber" D.string | |
|> DP.required "description" D.string | |
|> DP.required "imageUrl" D.string | |
) | |
) | |
) | |
decoderTimestamp : Decoder Time.Posix | |
decoderTimestamp = | |
-- look at community json extra datetime for example of below | |
-- -- | |
-- could be done like the below as well for a one-off | |
-- |> DP.required "endDate" (D.andThen (\millis -> D.succeed (Time.millisToPosix millis)) D.int) | |
D.andThen | |
(\dateString -> | |
-- case Iso8601.toTime dateString of | |
D.succeed (Time.millisToPosix dateString) | |
) | |
D.int | |
viewPersonalisedDiscounts : Model -> Element Msg | |
viewPersonalisedDiscounts model = | |
case model.personalDiscounts of | |
RemoteData.NotAsked -> | |
E.text "Initialising..." | |
RemoteData.Loading -> | |
E.text "Loading..." | |
RemoteData.Failure err -> | |
E.text ("Error: " ++ Debug.toString err) | |
RemoteData.Success offers -> | |
E.row | |
[ E.width E.fill | |
, E.scrollbarY | |
, E.spacing 20 | |
] | |
[ E.text (Debug.toString offers) ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment