Kaynağa Gözat

fix(user): add accessScope parameter to userTypes API call

ebagabee 2 hafta önce
ebeveyn
işleme
c5e02705f0

+ 4 - 2
src/api/user.js

@@ -38,7 +38,9 @@ export const deleteUser = async (id) => {
   return data.payload;
   return data.payload;
 };
 };
 
 
-export const userTypes = async () => {
-  const { data } = await api.get("/user/all/types");
+export const userTypes = async (accessScope = null) => {
+  const { data } = await api.get("/user/all/types", {
+    params: accessScope ? { access_scope: accessScope } : {},
+  });
   return data.payload;
   return data.payload;
 };
 };

+ 2 - 1
src/components/selects/UserTypeSelect.vue

@@ -29,6 +29,7 @@ const props = defineProps({
     type: String,
     type: String,
     default: () => useI18n().t("common.ui.misc.type"),
     default: () => useI18n().t("common.ui.misc.type"),
   },
   },
+  accessScope: { type: String, default: null },
 });
 });
 
 
 const { placeholder, label } = props;
 const { placeholder, label } = props;
@@ -63,7 +64,7 @@ const filterFn = (val, update) => {
 
 
 onMounted(async () => {
 onMounted(async () => {
   try {
   try {
-    const response = await userTypes();
+    const response = await userTypes(props.accessScope);
     userTypeOptions.value = Object.entries(response).map(([key, value]) => ({
     userTypeOptions.value = Object.entries(response).map(([key, value]) => ({
       label: value,
       label: value,
       value: key,
       value: key,

+ 7 - 1
src/pages/permissions/PermissionsPage.vue

@@ -7,7 +7,7 @@
         ref="tableRef"
         ref="tableRef"
         title="Lista de Grupos de Permissões"
         title="Lista de Grupos de Permissões"
         :columns="columns"
         :columns="columns"
-        :api-call="getUserTypes"
+        :api-call="getEditableUserTypes"
         description="grupos"
         description="grupos"
         :female="false"
         :female="false"
         add-item
         add-item
@@ -74,6 +74,12 @@ const PermissionGroupDialog = defineAsyncComponent(
 
 
 const $q = useQuasar();
 const $q = useQuasar();
 const tableRef = useTemplateRef("tableRef");
 const tableRef = useTemplateRef("tableRef");
+const getEditableUserTypes = async (...args) => {
+  const response = await getUserTypes(...args);
+  const hiddenTypes = ["ADMIN", "ADMIN_FRANCHISEE"];
+  if (Array.isArray(response)) return response.filter((row) => !hiddenTypes.includes(row.slug));
+  return response;
+};
 
 
 const columns = [
 const columns = [
   {
   {

+ 16 - 1
src/pages/permissions/components/AddEditPermissionGroupDialog.vue

@@ -14,6 +14,16 @@
             @update:model-value="onLabelChange"
             @update:model-value="onLabelChange"
           />
           />
 
 
+          <q-select
+            v-model="form.access_scope"
+            outlined
+            emit-value
+            map-options
+            label="Tipo de acesso"
+            :options="accessScopeOptions"
+            :rules="[inputRules.required]"
+          />
+
           <DefaultInput
           <DefaultInput
             v-model="form.slug"
             v-model="form.slug"
             label="Código"
             label="Código"
@@ -76,7 +86,12 @@ const dialogTitle = computed(() =>
 const form = ref({
 const form = ref({
   label: group?.label ?? "",
   label: group?.label ?? "",
   slug: group?.slug ?? "",
   slug: group?.slug ?? "",
+  access_scope: group?.access_scope ?? "unit",
 });
 });
+const accessScopeOptions = [
+  { label: "Unidade", value: "unit" },
+  { label: "Franqueadora", value: "franchisor" },
+];
 
 
 // Ao editar, o código já existe e não deve ser re-derivado do nome.
 // Ao editar, o código já existe e não deve ser re-derivado do nome.
 const slugTouched = ref(isEdit.value);
 const slugTouched = ref(isEdit.value);
@@ -110,7 +125,7 @@ const { loading, execute } = useSubmitHandler({
 });
 });
 
 
 const onSave = async () => {
 const onSave = async () => {
-  const payload = { label: form.value.label, slug: form.value.slug };
+  const payload = { label: form.value.label, slug: form.value.slug, access_scope: form.value.access_scope };
 
 
   await execute(() =>
   await execute(() =>
     isEdit.value ? updateUserType(group.id, payload) : createUserType(payload),
     isEdit.value ? updateUserType(group.id, payload) : createUserType(payload),

+ 37 - 1
src/pages/users/UserActionPage.vue

@@ -13,7 +13,20 @@
           />
           />
 
 
           <div class="row full-width q-mt-md q-col-gutter-sm">
           <div class="row full-width q-mt-md q-col-gutter-sm">
+            <div class="col-12">
+              <q-btn-toggle
+                v-model="form.access_scope"
+                spread
+                no-caps
+                toggle-color="primary"
+                :options="[
+                  { label: 'Acesso de unidade', value: 'unit' },
+                  { label: 'Acesso franqueadora', value: 'franchisor' },
+                ]"
+              />
+            </div>
             <StateSelect
             <StateSelect
+              v-if="form.access_scope === 'unit'"
               v-model="form.state"
               v-model="form.state"
               class="col-3"
               class="col-3"
               outlined
               outlined
@@ -22,6 +35,7 @@
             />
             />
 
 
             <UnitMultiSelect
             <UnitMultiSelect
+              v-if="form.access_scope === 'unit'"
               v-model="form.units"
               v-model="form.units"
               class="col-9"
               class="col-9"
               outlined
               outlined
@@ -30,7 +44,9 @@
             />
             />
 
 
             <UserTypeSelect
             <UserTypeSelect
+              :key="form.access_scope"
               v-model="form.user_type"
               v-model="form.user_type"
+              :access-scope="form.access_scope"
               class="col-6"
               class="col-6"
               outlined
               outlined
               label="Tipo de Usuário"
               label="Tipo de Usuário"
@@ -145,7 +161,7 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { ref, computed, onMounted } from "vue";
+import { ref, computed, onMounted, watch } from "vue";
 import { useRouter, useRoute } from "vue-router";
 import { useRouter, useRoute } from "vue-router";
 import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
 import DefaultHeaderPage from "src/components/layout/DefaultHeaderPage.vue";
 import DefaultInput from "src/components/defaults/DefaultInput.vue";
 import DefaultInput from "src/components/defaults/DefaultInput.vue";
@@ -170,10 +186,12 @@ const showPasswordConfirm = ref(false);
 
 
 const editStateId = ref(null);
 const editStateId = ref(null);
 const editUnitIds = ref([]);
 const editUnitIds = ref([]);
+const loadingUser = ref(false);
 
 
 const isEdit = computed(() => !!route.params.id);
 const isEdit = computed(() => !!route.params.id);
 
 
 const form = ref({
 const form = ref({
+  access_scope: "unit",
   state: null,
   state: null,
   units: [],
   units: [],
   user_type: null,
   user_type: null,
@@ -193,12 +211,14 @@ const { loading, execute } = useSubmitHandler({
 
 
 onMounted(async () => {
 onMounted(async () => {
   if (!isEdit.value) return;
   if (!isEdit.value) return;
+  loadingUser.value = true;
   try {
   try {
     const user = await getUserById(route.params.id);
     const user = await getUserById(route.params.id);
     form.value.name = user.name;
     form.value.name = user.name;
     form.value.email = user.email;
     form.value.email = user.email;
     form.value.cpf = user.cpf;
     form.value.cpf = user.cpf;
     form.value.user_type = user.user_type;
     form.value.user_type = user.user_type;
+    form.value.access_scope = user.access_scope ?? (user.units?.length ? "unit" : "franchisor");
     editStateId.value = user.state_id ?? null;
     editStateId.value = user.state_id ?? null;
     editUnitIds.value = user.units?.map((u) => u.id) ?? [];
     editUnitIds.value = user.units?.map((u) => u.id) ?? [];
     if (user.avatar_url) {
     if (user.avatar_url) {
@@ -206,6 +226,8 @@ onMounted(async () => {
     }
     }
   } catch (error) {
   } catch (error) {
     console.error("Failed to load user:", error);
     console.error("Failed to load user:", error);
+  } finally {
+    loadingUser.value = false;
   }
   }
 });
 });
 
 
@@ -213,6 +235,7 @@ function buildFormData() {
   const fd = new FormData();
   const fd = new FormData();
 
 
   if (avatarFile.value) fd.append("avatar", avatarFile.value);
   if (avatarFile.value) fd.append("avatar", avatarFile.value);
+  fd.append("access_scope", form.value.access_scope);
   if (form.value.state?.value) fd.append("state_id", form.value.state.value);
   if (form.value.state?.value) fd.append("state_id", form.value.state.value);
   form.value.units?.forEach((u) => fd.append("unit_ids[]", u.value));
   form.value.units?.forEach((u) => fd.append("unit_ids[]", u.value));
   if (form.value.user_type) fd.append("user_type", form.value.user_type);
   if (form.value.user_type) fd.append("user_type", form.value.user_type);
@@ -230,6 +253,7 @@ function buildUpdateData() {
   fd.append("_method", "PUT");
   fd.append("_method", "PUT");
 
 
   if (avatarFile.value) fd.append("avatar", avatarFile.value);
   if (avatarFile.value) fd.append("avatar", avatarFile.value);
+  fd.append("access_scope", form.value.access_scope);
   if (form.value.state?.value) fd.append("state_id", form.value.state.value);
   if (form.value.state?.value) fd.append("state_id", form.value.state.value);
   // Sempre envia unit_ids[] para sincronizar (array vazio limpa todas as unidades)
   // Sempre envia unit_ids[] para sincronizar (array vazio limpa todas as unidades)
   (form.value.units ?? []).forEach((u) => fd.append("unit_ids[]", u.value));
   (form.value.units ?? []).forEach((u) => fd.append("unit_ids[]", u.value));
@@ -259,4 +283,16 @@ function generatePassword() {
   form.value.password = password;
   form.value.password = password;
   form.value.password_confirmation = password;
   form.value.password_confirmation = password;
 }
 }
+
+watch(
+  () => form.value.access_scope,
+  (scope, previousScope) => {
+    if (previousScope && !loadingUser.value) form.value.user_type = null;
+    if (scope === "franchisor") {
+      form.value.state = null;
+      form.value.units = [];
+    }
+  },
+  { flush: "sync" },
+);
 </script>
 </script>