-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Task solution from happy-luna #16
Conversation
implement reusable input
🥷 Excuse me, but what is the deadline? |
1 similar comment
🥷 Excuse me, but what is the deadline? |
🥷 |
Hi, I added the deadline to the Scrive CAT - it aims to be 26.1.2025, but if you make it sooner, than let us know sooner.
It means that it should not be possible to get into this state. Pick whatever solution you see fit for this case from your experience and best judgement. |
🥷 🥷 It's ready for review, I suppose. :) |
Great. Feel free to update the Description of the PR with the description of your thinking process or challenges that you had during implementation if you feel like there is some context for us to know or take into account during reviewing. |
src/Modules/Tags.elm
Outdated
|> Dict.toList | ||
|> List.map (Tuple.second >> .name) | ||
|> List.filter ((==) model.newTagName) | ||
|> List.head | ||
|> Maybe.map (\_ -> True) | ||
|> Maybe.withDefault False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code is correct, but there are simpler ways of doing this like, for example, Dict.foldl
or maybe one of the Dict.Extra
functions if you want to use additional packages (we often do 😉 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dict.Extra.any
=|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dict.values >> List.any ((==) model.newTagName)
if you don't want to use Dict.Extra.
src/Shared/Styles.elm
Outdated
@@ -0,0 +1,16 @@ | |||
module Shared.Styles exposing (..) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mmhh, styles module on a different file... interesting... 🤔 I think one of the points of doing tailwind is precisely to allocate the styles as close to the actual code as possible... IMHO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Different approach than we are used to 🤷 Not necessarily bad part
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually think it's good they're trying to keep the style consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥷 🥷 To be honest, at the end, I came up with just splitting style classes into several attributes, so I had readable tailwind styles at place without need to go to separate module to check, what were the styles there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥷 🥷 So I would agree that extracting tailwind styles into separate module isn't good idea.
@@ -6,10 +6,12 @@ | |||
"elm-version": "0.19.1", | |||
"dependencies": { | |||
"direct": { | |||
"NoRedInk/elm-json-decode-pipeline": "1.0.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the usage of this library, I feel we should use it more often 💯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit dangerous, because it relies on the order that attributes are declared in a record.
Change the order, you get a very nasty and very silent bug.
Bit us a couple of times at a previous job of mine.
src/Modules/Tags.elm
Outdated
else if String.length model.newTagName > 32 then | ||
{ model | newTagError = Just "too long (32)" } | ||
|
||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels like we're implementing the tag validation twice (second time is https://github.com/scrive/elm-challenge/pull/16/files#diff-edc7374f17c064fedb4f48d570e9455210c16d868744151dd8cf1d725c3f011fR180 )
This is a maintenance problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥷 🥷 Oh, you're right. Sorry, haven't noticed it. Is it legal if I fix it now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure it is legal :) This task is thought as being as close to a regular day to day job in Scrive as possible and as such part of the discussion about the code in PR are some changes on stuff that we find out can be improved.
Although just do the changes in bulk and ideally once as we need to cover more candidates and it might become little bit messy and we might lost track of what has been changed and when.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh, if it's just a mistake there's no need to fix it. Happens. =)
src/Modules/Tags.elm
Outdated
{ model | newTagError = Just "empty" } | ||
|
||
else if String.length model.newTagName > 32 then | ||
{ model | newTagError = Just "too long (32)" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding errors to the model, rather than running the validation function with every view
call, requires us to remember to clear the errors every time.
It's a solution that increases maintenance overhead and exposes us to bugs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥷 🥷 I think that I didn't get your point here. I we add validation to view, so it would be called every time model changes and show us an error immediately, it could be a bit distracting for user to get errors while editing data (like when you want to add tag with name "Liked by others" it would trigger an error for a moment if there is tag with name "Like"). So I decided to validate data only on submit, when user ended up editing stuff and thinks he's ready to finish.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have something like a "showValidation" flag in the Model, that we set on input blur or (if we really want to be fancy) on a debounced delay after the user has started typing.
Still, good thinking!
emptyUserGroup : UserGroup | ||
emptyUserGroup = | ||
{ id = "" | ||
, parentId = "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the model
, newTagError
is a Maybe String
, ie, the "no error" condition is modeled by Nothing
.
Here instead, the "no parent" condition is modeled by ""
.
There isn't really a correct way to do this, but I would like to hear from the candidate about why they choose different approaches in the two instances.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥷 🥷 I've just spllitted challenge into 3 days, 1 day for each task, and decoders were written in the 1st day while tags task was completed at 3rd, so I just haven't notices that I have different approaches there, because decoders were working fine and I had no reason to look there and change them. :)
src/Modules/Tags.elm
Outdated
|> Input.withOnChange (Just NewTagNameChanged) | ||
|> Input.withErrorMessage model.newTagError | ||
|> Input.withValue model.newTagName | ||
|> Input.viewTextOrNumber |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you have an idea how to improve readability of this part (maybe how to replace builder pattern)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥷 🥷 I think so, maybe it would be better if it could take just List of arguments. Like this Input.viewTextOrNumber [Input.label "e-mail" , Input.error (Just error)]
src/Modules/Settings.elm
Outdated
(List.singleton | ||
>> List.filter ((/=) 0) | ||
>> List.head | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems a bit over engineered.
I'd go with a simple
case maybeInt of
Just 0 -> Nothing
_ -> maybeInt
adjust contact validation logic
🥷 🥷 Just fixed some comments and bugs I found during code-re-review :) |
Ready for review