Module

FPO.Components.UI.UserList

Card containing a list of users. The users list is paginated and can be filtered by username and email. Furthermore, it allows the refetching of users (e.g., after a user has been created or deleted).

Refer to the Input, Query and Output types for interface documentation.

#_pagination

_pagination :: Proxy @Symbol "pagination"

#State

type State ba = FPOState (buttonStyles :: Input ba, filteredUsers :: Array UserOverviewDto, loading :: Boolean, page :: Int, users :: Array UserOverviewDto)

#ButtonStyle

type ButtonStyle ba = { classes :: Array ClassName, disabled :: Boolean, effect :: ba, icon :: String, popover :: String }

#Input

type Input ba = UserOverviewDto -> Array (ButtonStyle ba)

For the input, the parent component can pass an array of ButtonStyle to set the button of the user list. This way, for each user in the list, buttons with specific styles and effects can be rendered. The effect is then, if the button is pressed, passed to the parent component (together with the associated user dto) via the Output type, and the parent component can handle the specific button effect (e.g., deleting the user, navigating to the profile page, etc.).

The effect is polymorphic, i.e., it's best practice to use some kind of algebraic data type (enum) to represent the possible effects in the parent component, then do exhaustive pattern matching on the effect and define the business logic accordingly.

Furthermore, the button style is parametrized over the user dto (i.e., parametrized over each user in the list), so that the parent component can define the button styles based on the user dto. This allows the parent to, for example, disable buttons for certain users, or change the button style based on the user dto.

TODO: It would be nice to not only be able to pass an array of ButtonStyle, but simply pass a function that takes a UserOverviewDto and returns a div or similar, i.e., a function that can be used to generate whatever HTML is needed for the user list. Then, it would also be nice to parametrize this component over the Action type of the parent component, so that the parent component can define the action type that is returned when a button is pressed and handle it directly. This would've been a much nicer approach because the parent component could then define all possible actions and simply use handleAction to handle the button presses, with no need to define a specific data type to represent the button effects.

#Slots

type Slots :: Row Typetype Slots = (pagination :: Slot Query Output Unit)

#Query

data Query a

Constructors

  • ReloadUsersQ a

    Query to reload the users list, for example, after the parent component has changed the user list using backend requests.

  • HandleFilterQ (Output) a

    Query to handle filter changes. The filter is passed as an argument, usually by

    1. The parent component that received the filter change from the UserFilter child.
    2. The parent component that synthesizes the filter itself.

#Output

data Output ba

Constructors

  • Loading Boolean

    Output to indicate to the parent whether or not the user list is ready/loaded. This can be used to disable UI elements that depend on the user list, e.g., the "Create User" button, if wished.

  • Error String

    Output to indicate an error, e.g., when the user list could not be loaded.

  • ButtonPressed UserOverviewDto ba

#component

component :: forall m ba. MonadAff m => MonadStore Action Store m => Navigate m => Component Query (Input ba) (Output ba) m

Modules