aboutsummaryrefslogtreecommitdiff
path: root/front/src
diff options
context:
space:
mode:
authorGuillermo Ramos2025-02-21 23:00:07 +0100
committerGuillermo Ramos2025-03-06 23:26:15 +0100
commit1f04e6ed44e789908138f2acb448789c3da568b4 (patch)
tree4a46ea3db013c85b77911599ec2867b491b3ab8b /front/src
parent21352bf0dd245c747fe265abbd9b6283d7a088bd (diff)
downloadhiccup-1f04e6ed44e789908138f2acb448789c3da568b4.tar.gz
URLs
Diffstat (limited to 'front/src')
-rw-r--r--front/src/Main.elm186
1 files changed, 151 insertions, 35 deletions
diff --git a/front/src/Main.elm b/front/src/Main.elm
index 4ead1d6..35ec06d 100644
--- a/front/src/Main.elm
+++ b/front/src/Main.elm
@@ -1,11 +1,30 @@
module Main exposing (main)
-import Browser
-import Html exposing (Attribute, Html, button, div, hr, input, span, table, tbody, td, text, th, thead, tr)
+import Browser exposing (Document, UrlRequest(..))
+import Browser.Navigation as Nav
+import Html
+ exposing
+ ( Attribute
+ , Html
+ , a
+ , button
+ , div
+ , hr
+ , input
+ , span
+ , table
+ , tbody
+ , td
+ , text
+ , th
+ , thead
+ , tr
+ )
import Html.Attributes
exposing
( class
, disabled
+ , href
, max
, min
, placeholder
@@ -17,10 +36,15 @@ import Html.Attributes
)
import Html.Events exposing (onClick, onInput)
import Http
-import Json.Decode exposing (Decoder, field, float, int, list, map, map2, map3, map4)
+import Json.Decode exposing (Decoder, field, float, int, list, map2, map3, map4)
import Json.Encode as Encode exposing (Value, object)
+import Platform.Cmd exposing (batch)
import Round
import Set exposing (Set)
+import Url exposing (Url)
+import Url.Builder as UB
+import Url.Parser as U exposing ((<?>))
+import Url.Parser.Query as UQ
@@ -28,7 +52,14 @@ import Set exposing (Set)
main =
- Browser.element { init = init, update = update, view = view, subscriptions = \_ -> Sub.none }
+ Browser.application
+ { init = init
+ , update = update
+ , view = view
+ , subscriptions = \_ -> Sub.none
+ , onUrlRequest = SetUrl
+ , onUrlChange = ChangedUrl
+ }
@@ -96,6 +127,47 @@ type alias SimSpecsRaw =
}
+defaultSimSpecsRaw : SimSpecsRaw
+defaultSimSpecsRaw =
+ { title = ""
+ , totalValue = "200000"
+ , initial = "40000"
+ , financedRate = "80"
+ , i1 = "1.621"
+ , years = "30"
+ }
+
+
+simSpecsRawParser : UQ.Parser SimSpecsRaw
+simSpecsRawParser =
+ UQ.map6 SimSpecsRaw
+ (UQ.map (Maybe.withDefault defaultSimSpecsRaw.title) <| UQ.string "title")
+ (UQ.map (Maybe.withDefault defaultSimSpecsRaw.totalValue) <| UQ.string "totalValue")
+ (UQ.map (Maybe.withDefault defaultSimSpecsRaw.initial) <| UQ.string "initial")
+ (UQ.map (Maybe.withDefault defaultSimSpecsRaw.financedRate) <| UQ.string "financedRate")
+ (UQ.map (Maybe.withDefault defaultSimSpecsRaw.i1) <| UQ.string "i1")
+ (UQ.map (Maybe.withDefault defaultSimSpecsRaw.years) <| UQ.string "years")
+
+
+simSpecsRawToQS : SimSpecsRaw -> String
+simSpecsRawToQS { title, totalValue, initial, financedRate, i1, years } =
+ UB.toQuery <|
+ [ UB.string "title" title
+ , UB.string "totalValue" totalValue
+ , UB.string "initial" initial
+ , UB.string "financedRate" financedRate
+ , UB.string "i1" i1
+ , UB.string "years" years
+ ]
+
+
+type alias SimSpecs =
+ { principal : Float
+ , i1 : Float
+ , years : Int
+ }
+
+
simSpecsParse : SimSpecsRaw -> Maybe SimSpecs
simSpecsParse { totalValue, financedRate, i1, years } =
case
@@ -110,15 +182,9 @@ simSpecsParse { totalValue, financedRate, i1, years } =
Nothing
-type alias SimSpecs =
- { principal : Float
- , i1 : Float
- , years : Int
- }
-
-
type alias Model =
{ error : String
+ , navKey : Nav.Key
, simSpecsRaw : SimSpecsRaw
, expandedYears : Set Int
, simulation : Maybe Simulation
@@ -157,19 +223,47 @@ runSimulation m simSpecs =
}
-init : () -> ( Model, Cmd Msg )
-init () =
+type Route
+ = NotFound
+ | Root SimSpecsRaw
+
+
+routeQuery : Route -> SimSpecsRaw
+routeQuery route =
+ case route of
+ NotFound ->
+ defaultSimSpecsRaw
+
+ Root query ->
+ query
+
+
+routeParser : U.Parser (Route -> a) a
+routeParser =
+ U.oneOf
+ [ U.map Root (U.top <?> simSpecsRawParser)
+ ]
+
+
+toRoute : Url -> Route
+toRoute url =
+ Maybe.withDefault NotFound (U.parse routeParser url)
+
+
+init : () -> Url -> Nav.Key -> ( Model, Cmd Msg )
+init () url navKey =
let
simSpecsRaw =
- { title = ""
- , totalValue = "200000"
- , financedRate = "80"
- , initial = "40000"
- , i1 = "1.621"
- , years = "30"
- }
+ routeQuery (toRoute url)
in
- ( { error = "", simSpecsRaw = simSpecsRaw, expandedYears = Set.empty, simulation = Nothing }, Cmd.none )
+ ( { navKey = navKey
+ , error = ""
+ , simSpecsRaw = simSpecsRaw
+ , expandedYears = Set.empty
+ , simulation = Nothing
+ }
+ , Cmd.none
+ )
@@ -210,6 +304,8 @@ type Msg
| UpdateSimSpecs SimSpecUpdate String
| RunSimulation SimSpecs
| SetExpandedYears (Set Int)
+ | SetUrl UrlRequest
+ | ChangedUrl Url
update : Msg -> Model -> ( Model, Cmd Msg )
@@ -234,14 +330,30 @@ update msg model =
( { model | error = errorToString err }, Cmd.none )
RunSimulation specs ->
- ( model, runSimulation model specs )
+ ( model
+ , batch
+ [ runSimulation model specs
+ , Nav.pushUrl model.navKey (simSpecsRawToQS model.simSpecsRaw)
+ ]
+ )
+
+ SetUrl (Internal url) ->
+ -- TODO
+ ( model, Nav.pushUrl model.navKey (Url.toString url) )
+
+ SetUrl (External url) ->
+ -- TODO
+ ( model, Nav.load url )
+
+ ChangedUrl url ->
+ ( model, Cmd.none )
UpdateSimSpecs u val ->
let
simSpecsRaw =
model.simSpecsRaw
- newSimSpecsTxt =
+ newSimSpecsRaw =
case u of
Title ->
{ simSpecsRaw | title = val }
@@ -276,7 +388,7 @@ update msg model =
Years ->
{ simSpecsRaw | years = val }
in
- ( { model | simSpecsRaw = newSimSpecsTxt }, Cmd.none )
+ ( { model | simSpecsRaw = newSimSpecsRaw }, Cmd.none )
SetExpandedYears eyears ->
( { model | expandedYears = eyears }, Cmd.none )
@@ -548,17 +660,21 @@ simView m { initial, financed } =
]
-view : Model -> Html Msg
+view : Model -> Document Msg
view m =
- div [ class "flex flex-col max-w-lg mx-auto items-center mt-2 p-3 border-2 rounded-md border-gray-500 bg-gray-100" ]
- [ div [ class "min-w-full" ]
- [ specsView m.simSpecsRaw
- , case m.simulation of
- Nothing ->
- text ""
-
- Just sim ->
- simView m sim
- , text m.error
+ { title = "Hiccup"
+ , body =
+ [ div [ class "flex flex-col max-w-lg mx-auto items-center mt-2 p-3 border-2 rounded-md border-gray-500 bg-gray-100" ]
+ [ div [ class "min-w-full" ]
+ [ specsView m.simSpecsRaw
+ , case m.simulation of
+ Nothing ->
+ text ""
+
+ Just sim ->
+ simView m sim
+ , text m.error
+ ]
]
]
+ }