-
I dont know the storybook, heard of it, I tried to do something with it, but it seemed like a totally different thing
-
I think I have used the styled components, but never reflected an extent to which they can be used. Took me a while to figure out that their default export is not here to stay (or is it?)
-
When asking questions, I am perfectly fine to look stupid, but it is not easy to come with the question in the first place (I admit, I don't want to risk asking something hillariously elementary, just for the sake of wasting the other person's time. I also find it silly to But I digress.)
-
...
At the beginning I have decided not to use some app-wide state management, for it seems that app will be to small for it to make sense.
At about halfway through I have found out that I want to keep the structure of the application (I'm not sure I would come out with the better way without duplicationg code), I have decided it would be less of a mess if I add Redux (and maybe Axios for fetching, to be sure it is done better).
I had a a problem with passing the newTodo state to the list; I see that it is not a good way to use it to trigger the useEffect to update the array of Todos.
I figured out that in order to update the array consistently and less messy, Redux could be the way. Because: I need to update the array in a different components and right now there is starting to be too much of props being passed between the components.
-
I find adding it challenging to add Redux by smaller pieces, since it only works... when it works. You can bargain with first adding a static selector and then some reducers.
-
I do not know if atomic comits mean that the thing needs to be functioning in each and every commit (that would make sense)
-
Adding redux (redux toolkit) according to the official documentation.
I have a added a Provider to the Main.tsx. The Provider wraps the component. I pass the "store" store to the Provider.
I have created a "redux" folder, for the clarity (the official docs would recomend the /app folder and then also creating separate folders for other parts; this could be wise, especially with new functionalities).
In the store, the configureStore function is used to setup the redux store. The store has reducers defined - the functions that will be the only functions that can mutate the store. The whole store has a collection of reducers, but we can break them down into slices for better management.
TodosSlice is a part of the store that will contain the array of Todos. In its first iteration it will only return the array.
TodoSlice itself would have the addTodo reducer
Following the documentation, I use hooks for selecting (later dispatching). Selecting means the returning the value of particular piece of redux store.
I have added useAppSelector to the List component; where the todos state will be mapped. I have also added this selector to the Footer, where (for the moment) I will return the length of todos. This may change a bit; maybe I should filter NOT DONE todos and done todos and save the count into the store; but it is also possible to filter them in footer and show the count for both.
While there are definitely different ways, or different components that could do a fetch, for now I will use Lists.tsx for fetching; because we already have the infrastructure for that. So on the first render we would use useEffect for fetching and updating We import reducer "setTodos" from todosSlice.
I have corrected useAppSelector, calling selectTodos directly. The first way const todos = useAppSelector((state) => state.todos); if used in different places, would lead to duplicit code and no cetralized way for changing the selector. With the help of ChatGPT I have found out, that the former approach would not memoize the value, it seems.
New single todo will be posted and the response (with timestamp) will be added to the beginning of the redux state (the newest one). This way we will update the DB state and the UI state, without the need of fetching the WHOLE array of todos. AND, since the redux state will be updated (copy of a new state is created), this causes the List to rerender and show the new item, without a need of special treatment. Having the fetching don in the header is not the ideal from the structural/logical perspective, but I will leave it there for now.
In the ListItem I have added a conditional rendering of a label or Form. On submit, the ListItem uses PATCH to change label in the API and editTodo in Redux. I have added a cancel function. I have added Axios to take care of the fetching. I have added also the "dynamicLabel" in a hope that it will fix the brief moment after submitting the label change, where you still can see the old label. This didn't work yet, but I will keep it here for a moment.
I have added todo complition functionality. By now I am almost sure that the fetching / status changing logic was meant to be all in the List component (or maybe some separate component?). In some sense I agree, the logic should be in one place. On the other hand, editing / completing / deleting(!) somehow fits in the ListItem scope.
I have just realized the restriction "Do not modify the API (props) of the provided components." TODO: For the moment it would be impractical not to pass "id" prop to the ListItem. But if all the filtering is done on the List level, then ID may not be needed in the ListItem.
Until a bug is found, I consieder it done.
I wasn't sure about the intended desing of all buttons. I guess the exercise was about passing states / maniging the wrapping. Searching for some additional button in redix seems like a waste of time for now, but could be nice.
List items, align in static and edit mode. Just realized, that multiple items can be in "edit", which is bad UX.
Action buttons visibility was done via css and styled components.
Adding flex: 1
to the List, meaning it will stretch to the empty place.
Refactoring: Deleting todo now with Redux, Axios and in List (which, I believe, is more in line with the no-props-changing-policy).
I couldn't figure out, what means "B1: List
content - Fix the content alignment of the non-empty List
component."
I have implemented a custom endpoint. I had to consult ChatGPT; I couldn't find relevant information in a documentation in a reasonable time. It was clear to me, that I should create a separate endpoint under server.[verb], but it was not clear, how to access another array without creating a new "done" array. I am not sure about the .assign and .write. I prefer to understand the code I am using... Moreover, the task only mentioned isdone - true. I used this endopoint only to mark a task as done. For marking it back, I have kept the previous endpoint.
Another thing: I presume that onItemDoneToggle
was suppose to work in List. It is not clear to me how the proper ListItem (id) would be identified, if onItemDoneToggle
is to pass only the boolean value. I guess there is some trivial way to do this.
I was unable to finish the project within the given limits (temporal or restriction-wise). I consider would consider it mostly done
for my personal purposes and personal growth. After 5 hours I have stopped tracking my time spent and then it took me several more hours (multiple pauses between the runs). Even without the other responsibilities I had, the task would have taken me longer than 6 hours.
More improvements definitely could be made, at least with the visual style. The usage of redux is highly questionable. The restrictions were not respected.