Skip to content
Snippets Groups Projects
CreateUserModal.vue 4.65 KiB
Newer Older
  • Learn to ignore specific revisions
  • <script setup lang="ts">
    import { RoleEnum, type UserIn, type UserOutExtended } from "@/client";
    import { onMounted, reactive, ref } from "vue";
    import { Modal, Toast } from "bootstrap";
    import BootstrapModal from "@/components/modals/BootstrapModal.vue";
    import { useUserStore } from "@/stores/users";
    import BootstrapToast from "@/components/BootstrapToast.vue";
    
    let modal: Modal | null = null;
    const createUserForm = ref<HTMLFormElement | undefined>(undefined);
    let successToast: Toast | undefined;
    let errorToast: Toast | undefined;
    
    const userRepository = useUserStore();
    
    const formState = reactive<{
      loading: boolean;
      user: UserIn;
      errorMessage?: string;
      registeredUserName: string;
      validated: boolean;
    }>({
      loading: false,
      errorMessage: "",
      validated: false,
      registeredUserName: "",
      user: {
        display_name: "",
        email: "",
        roles: [RoleEnum.USER],
      },
    });
    
    const props = defineProps<{
      modalId: string;
    }>();
    
    const emit = defineEmits<{
      (e: "user-created", user: UserOutExtended): void;
    }>();
    
    function createUser() {
      formState.validated = true;
      if (createUserForm.value?.checkValidity()) {
        formState.loading = true;
        formState.registeredUserName = formState.user.display_name;
        userRepository
    
          .inviteUser(formState.user)
    
          .then((user) => {
            emit("user-created", user);
            formState.validated = false;
            formState.user = {
              display_name: "",
              email: "",
              roles: [RoleEnum.USER],
            };
            successToast?.show();
            modal?.hide();
          })
          .catch((err) => {
            formState.errorMessage = err.body?.detail;
            errorToast?.show();
          })
          .finally(() => {
            formState.loading = false;
          });
      }
    }
    
    onMounted(() => {
      modal = Modal.getOrCreateInstance(`#${props.modalId}`);
      successToast = new Toast("#create-user-success-toast");
      errorToast = new Toast("#create-user-error-toast");
    });
    </script>
    
    <template>
      <bootstrap-toast toast-id="create-user-success-toast">
    
        Successfully invited user {{ formState.registeredUserName }}
    
      </bootstrap-toast>
      <bootstrap-toast toast-id="create-user-error-toast" color-class="danger">
        <template #default
    
          >Couldn't invite user
    
          {{ formState.registeredUserName }}
        </template>
        <template #body>Error: {{ formState.errorMessage }}</template>
      </bootstrap-toast>
      <bootstrap-modal
        :modalId="props.modalId"
        :static-backdrop="true"
        modal-label="Create user"
      >
    
        <template #header>Invite a user</template>
    
        <template #body>
          <form
            id="create-user-form"
            @submit.prevent="createUser()"
            :class="{ 'was-validated': formState.validated }"
            ref="createUserForm"
            novalidate
          >
            <div class="mb-3">
              <label for="create-user-name" class="form-label">Name</label>
              <input
                type="text"
                class="form-control"
                id="create-user-name"
                minlength="3"
                maxlength="256"
                required
                placeholder="John Doe"
                v-model="formState.user.display_name"
              />
              <div class="invalid-feedback">Please choose a name.</div>
            </div>
            <div class="mb-3">
              <label for="create-user-email" class="form-label"
                >Email address</label
              >
              <input
                type="email"
                class="form-control"
                id="create-user-email"
                required
                placeholder="name@example.com"
                minlength="3"
                maxlength="256"
                v-model="formState.user.email"
              />
              <div class="invalid-feedback">
                Please provide a valid email address.
              </div>
            </div>
            <div class="mb-3">
              <div class="mb-1">Roles:</div>
              <div
                class="form-check"
                v-for="role in Object.values(RoleEnum)"
                :key="role"
              >
                <input
                  class="form-check-input"
                  type="checkbox"
                  :value="role"
                  :id="`create-user-role-${role}`"
                  v-model="formState.user.roles"
                />
                <label class="form-check-label" :for="`create-user-role-${role}`">
                  {{ role.toUpperCase() }}
                </label>
              </div>
            </div>
          </form>
        </template>
        <template #footer>
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
            Close
          </button>
          <button
            type="submit"
            form="create-user-form"
            class="btn btn-primary"
            :disabled="formState.loading"
          >
            Save
          </button>
        </template>
      </bootstrap-modal>
    </template>
    
    <style scoped></style>