Skip to content

Instantly share code, notes, and snippets.

@szabba
Created May 19, 2016 15:13
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save szabba/ebc4fb00edbb8db365221762237a1d82 to your computer and use it in GitHub Desktop.
Save szabba/ebc4fb00edbb8db365221762237a1d82 to your computer and use it in GitHub Desktop.
import Html
import Html.App as App
import Html.Attributes as Attributes
import Html.Events as Events
import Json.Decode as Json
import String
main =
App.beginnerProgram
{ model =
{ people =
[ ( 1
, { name = "Sanjit"
, avatar = Nothing
, hearts = 12
}
)
, ( 2
,{ name = "Anna"
, avatar = Nothing
, hearts = 9
}
)
]
, form = Nothing
}
, update = updateList
, view = viewList
}
-- PARENT
type alias HeartList =
{ people : List (Int, Person)
, form : Maybe (Int, Form)
}
type ListMsg
= Delete Int
| Forward Int PersonMsg
| FormForward FormMsg
| Edit Int
| Save
updateList msg list =
let
dropIfID idToDrop (id, person) =
if idToDrop == id then
Nothing
else
Just (id, person)
applyMsgToID target msg (id, person) =
if target == id then
(id, updatePerson msg person)
else
(id, person)
personToForm (id, { name, avatar }) =
( id
, { name = name
, avatarURL = avatar |> Maybe.withDefault ""
}
)
saveFormTo idFormOpt (id, person) =
case idFormOpt of
Nothing ->
(id, person)
Just (target, { name, avatarURL }) ->
if target == id then
( id
, { person
| name = name
, avatar =
if avatarURL /= "" then
Just avatarURL
else
Nothing
}
)
else
(id, person)
in
case msg of
Delete idToDrop ->
{ list
| people =
list.people |> List.filterMap (dropIfID idToDrop)
}
Forward target msg ->
{ list
| people =
list.people |> List.map (applyMsgToID target msg)
}
FormForward msg ->
{ list
| form =
list.form
|> Maybe.map (\(id, form) -> (id, updateForm msg form))
}
Edit target ->
{ list
| form =
list.people
|> List.filter (fst >> (==) target)
|> List.map personToForm
|> List.head
}
Save ->
{ list
| form = Nothing
, people =
list.people
|> List.map (saveFormTo list.form)
}
viewList { form, people } =
let
wrapPerson (id, person) =
Html.div
[]
[ App.map (Forward id) (viewPerson person)
, Html.button [ Events.onClick (Delete id) ] [ Html.text "X" ]
, Html.button [ Events.onClick (Edit id) ] [ Html.text "E" ]
]
in
Html.div [] <|
[ form
|> Maybe.map (snd >> viewForm Save FormForward)
|> Maybe.withDefault (Html.text "")
]
++
(List.map wrapPerson people)
-- PERSON
type alias Person =
{ name : String
, avatar : Maybe String
, hearts : Int
}
type PersonMsg
= SetAvatarAndName { name : String, avatar : Maybe String }
| IncrHearts
| DecrHearts
updatePerson msg person =
case msg of
SetAvatarAndName { name, avatar } ->
{ person | name = name, avatar = avatar }
IncrHearts ->
{ person | hearts = person.hearts + 1 }
DecrHearts ->
{ person | hearts = person.hearts - 1 }
viewPerson person =
Html.div
[]
[ viewName person
, viewAvatar person
, viewHearts person
]
viewAvatar { avatar } =
avatar
|> Maybe.map (\url -> Html.img [ Attributes.src url ] [])
|> Maybe.withDefault (Html.text "")
viewName { name } =
Html.p [] [ Html.text name ]
viewHearts { hearts } =
Html.p
[]
[ Html.button [ Events.onClick DecrHearts ] [ Html.text "-" ]
, Html.button [ Events.onClick IncrHearts ] [ Html.text "+" ]
, Html.text <| String.repeat hearts " <3 "
]
-- EDIT FORM
type alias Form =
{ name : String
, avatarURL : String
}
type FormMsg
= FormSetName String
| FormSetAvatarURL String
updateForm msg form =
case msg of
FormSetName name ->
{ form | name = name }
FormSetAvatarURL url ->
{ form | avatarURL = url }
viewForm onSave wrap { name, avatarURL } =
Html.div
[]
[ Html.p
[]
[ Html.text "Name:"
, Html.input
[ Events.onInput (wrap << FormSetName)
, Attributes.value name
]
[]
]
, Html.p
[]
[ Html.text "Avatar URL:"
, Html.input
[ Events.onInput (wrap << FormSetAvatarURL)
, Attributes.value avatarURL
]
[]
]
, Html.p
[]
[ Html.button [ Events.onClick onSave ] [ Html.text "Save" ]
]
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment