alan2207 / bulletproof-react

🛡️ ⚛️ A simple, scalable, and powerful architecture for building production ready React applications.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question : How to make drawer globally?

galih56 opened this issue · comments

Is it possible to make drawer globally and place the content wherever it's needed? Split the form and the drawer.
For me, the drawer is not reusable enough. It will be great if I can call the drawer anywhere and place the content dynamically.
For now, i can only use the drawer and place it to every single feature i want to make.

As example :
In the code below, the FormDrawer must be used along with the form. But i want to create the form for separated from it and use it on other pages, like creatable select or some dialogs. I tried to split them, but i had a hard time syncing the mutation status because the useMutation is called inside parent component and the submit button is called inside the FormDrawer component. Any suggestions?

export const CreateTask = () => {
  const projectOptions = useProjectOptions();
  const tagOptions = useTagOptions();
  const usersOptions = useUserOptions();
  const createTaskMutation = useCreateTask();

  return (
      <FormDrawer
        isDone={createTaskMutation.isSuccess}
        triggerButton={
          <Button variant='primary' size="sm" icon={PlusIcon}>
            Create Task
          </Button>
        }
        title="Create Task"
        submitButton={
          <Button
            form="create-task"
            type="submit"
            size="sm"
            loading={createTaskMutation.isLoading}
          >
            Submit
          </Button>
        }
      >
        <Form<CreateTaskDTO['data'], typeof schema>
          id="create-task"
          onSubmit={async (values) =>  await createTaskMutation.mutateAsync({ data: values })}
          schema={schema}
        >
          {({ register, formState, control }) => (
            <>
              <SelectField
                label='Project'
                options={projectOptions}
                error={formState.errors['projectId']}
                registration={register('projectId')}
                control={control}
              />
              <InputField
                label="Title"
                error={formState.errors['title']}
                registration={register('title')}
              />
              <TextAreaField
                label="Description"
                error={formState.errors['description']}
                registration={register('description')}
              />
              
              <SelectField
                label='Tags'
                options={tagOptions}
                error={formState.errors['tags']}
                registration={register('tags')}
                control={control}
                multiple={true}
              />
              
              <SelectField
                label='Assignees'
                options={usersOptions}
                error={formState.errors['assignees']}
                registration={register('assignees')}
                control={control}
                multiple={true}
              />
            </>
          )}
        </Form>
      </FormDrawer>
  );
};

From my experience, I would place the drawer in the highest hierarchy component (App.jsx) and use a global state to decide wether I want to open it or not. If you want to customize its contents depending on where you are, you can pass additional information with that global state. For example, if it's a menu kind of drawer, maybe you can pass some information regarding available buttons like this:

[
   {
      icon: 'Home',
      text: 'Home',
      redirect: '/login',
   },
   {
      icon: 'Profile',
      text: 'Account',
      redirect: '/account',
    },
]

And so on and so forth. Then you can simply iterate over that array to build your buttons, passing the correct props to each.

It's completely possible that this can be improved. It's just the way I found.