creat,get e delete rota empresas funcionais

This commit is contained in:
ka-lucas 2025-04-18 17:46:15 -03:00
parent a014cedfbd
commit 0f45adb7b6
6 changed files with 437 additions and 420 deletions

View File

@ -9,59 +9,59 @@
<v-row>
<v-text class="text-h7">Dados básicos</v-text>
<v-col cols="12">
<v-text-field v-model="localUser.username" label="Nome empresa *" clearable required />
<v-text-field v-model="localCompany.name" label="Nome empresa *" clearable required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.fantasyname" label="Nome fantasia" clearable />
<v-text-field v-model="localCompany.fantasyname" label="Nome fantasia" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.cnpj" label="CNPJ *" type="cnpj" clearable required />
<v-text-field v-model="localCompany.cnpj" label="CNPJ *" type="cnpj" clearable required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.tipo" label="Tipo" clearable />
<v-text-field v-model="localCompany.tipo" label="Tipo" clearable />
</v-col>
<v-text class="text-h7">Contato</v-text>
<v-col cols="12">
<v-text-field v-model="localUser.email" label="Email *" type="email" clearable
<v-text-field v-model="localCompany.email" label="Email *" type="email" clearable
:rules="[v => !!v || 'Email é obrigatório', v => /.+@.+\..+/.test(v) || 'Email inválido']" required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.email_sec" label="Email Secundario*" type="email_sec" clearable
<v-text-field v-model="localCompany.email_sec" label="Email Secundario*" type="email_sec" clearable
:rules="[v => !!v || 'Email é obrigatório', v => /.+@.+\..+/.test(v) || 'Email inválido']" />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.phone" label="Telefone *" type="tel" clearable
<v-text-field v-model="localCompany.phone" label="Telefone *" type="tel" clearable
:rules="[v => !!v || 'Telefone é obrigatório', v => /^[0-9]+$/.test(v) || 'Apenas números permitidos']" />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.phone_sec" label="Telefone Secundario *" type="tel_sec" clearable
<v-text-field v-model="localCompany.phone_sec" label="Telefone Secundario *" type="tel_sec" clearable
:rules="[v => !!v || 'Telefone é obrigatório', v => /^[0-9]+$/.test(v) || 'Apenas números permitidos']" />
</v-col>
<v-text class="text-h7">Endereço</v-text>
<v-col cols="12">
<v-text-field v-model="localUser.cep" label="CEP *" type="cep" clearable />
<v-text-field v-model="localCompany.cep" label="CEP *" type="cep" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.rua" label="Rua *" type="rua" clearable />
<v-text-field v-model="localCompany.rua" label="Rua *" type="rua" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.numero" label="Numero *" type="numero" clearable />
<v-text-field v-model="localCompany.numero" label="Numero *" type="numero" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.bairro" label="Bairro *" type="bairro" clearable />
<v-text-field v-model="localCompany.bairro" label="Bairro *" type="bairro" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.complemento" label="Complemento" type="complemento" clearable />
<v-text-field v-model="localCompany.complemento" label="Complemento" type="complemento" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.estado" label="Estado" type="estado" clearable />
<v-text-field v-model="localCompany.estado" label="Estado" type="estado" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.cidade" label="Cidade" type="cidade" clearable />
<v-text-field v-model="localCompany.cidade" label="Cidade" type="cidade" clearable />
</v-col>
</v-row>
</v-container>
@ -69,7 +69,7 @@
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text color="blue-darken-1" @click="closeModal">Cancelar</v-btn>
<v-btn text class="text-white salvar-btn" @click="handleSave" :loading="userStore.loading" :disabled="!isFormValid">
<v-btn text class="text-white salvar-btn" @click="handleSave" :loading="companyStore.loading">
Salvar
</v-btn>
</v-card-actions>
@ -78,43 +78,65 @@
</template>
<script setup>
import { ref, watch, computed } from 'vue';
import { useUserStore } from '../../stores/users';
import { useCompanyStore } from '../../stores/company';
import { useAuthStore } from '../../stores/auth';
const props = defineProps({
isModalOpen: Boolean,
isEditMode: Boolean,
modalUser: Object
modalCompany: Object
});
const emit = defineEmits(['update:isModalOpen', 'save', 'user-updated']);
const userStore = useUserStore();
const emit = defineEmits(['update:isModalOpen', 'save', 'company-updated']);
const companyStore = useCompanyStore();
const authStore = useAuthStore();
console.log('service intance id',authStore.service_instance_id);
const isOpen = ref(false);
const localUser = ref({
const localCompany = ref({
id: null,
username: '',
name: '',
fantasy_name: '',
type: '',
cnpj: '',
email: '',
password: '',
birth_date: '',
email_sec: '',
phone: '',
profile_image: '',
parent_id: authStore.userId,
phone_sec: '',
estado: '',
cidade: '',
bairro: '',
rua: '',
numero: '',
complemento: '',
cep: '',
//parent_id: authStore.companyId,
service_instance_id: authStore.service_instance_id || 2,
});
// Resetar dados ao abrir para novo usuário
const resetLocalUser = () => {
localUser.value = {
const resetlocalCompany = () => {
localCompany.value = {
id: null,
username: '',
name: '',
fantasy_name: '',
type: '',
cnpj: '',
email: '',
password: '',
birth_date: '',
email_sec: '',
phone: '',
profile_image: '',
parent_id: authStore.userId,
service_instance_id: authStore.service_instance_id,
phone_sec: '',
estado: '',
cidade: '',
bairro: '',
rua: '',
numero: '',
complemento: '',
cep: '',
//parent_id: authStore.companyId,
service_instance_id: authStore.service_instance_id,
};
};
@ -122,10 +144,10 @@
watch(() => props.isModalOpen, (newValue) => {
isOpen.value = newValue;
if (newValue) {
if (props.isEditMode && props.modalUser) {
loadUserData();
if (props.isEditMode && props.modalCompany) {
loadCompanyData();
} else {
resetLocalUser(); // <- limpa os dados para novo usuário
resetlocalCompany(); // <- limpa os dados para novo usuário
}
}
});
@ -133,69 +155,75 @@
watch(isOpen, (newValue) => {
if (!newValue) {
emit('update:isModalOpen', false);
}
});
const loadUserData = async () => {
const loadCompanyData = async () => {
try {
const fullUserData = await userStore.fetchUserById(props.modalUser.id);
if (fullUserData) {
localUser.value = {
id: fullUserData.user.id || null,
username: fullUserData.user.username || '',
email: fullUserData.user.email || '',
password: '',
birth_date: fullUserData.user.birth_date
? new Date(fullUserData.user.birth_date).toISOString().split('T')[0]
: '',
phone: fullUserData.user.phone || '',
profile_image: fullUserData.user.profile_image || '',
parent_id: authStore.userId,
const fullCompanyData = await companyStore.fetchCompanyById(props.modalCompany.id);
if (fullCompanyData) {
localCompany.value = {
id: fullCompanyData.company.id || null,
name: fullCompanyData.company.name || '',
fantasy_name: fullCompanyData.company.fantasy_name || '',
type: fullCompanyData.company.type || '',
cnpj: fullCompanyData.company.cnpj || '',
email: fullCompanyData.company.email || '',
email_sec: fullCompanyData.company.email_sec || '',
phone: fullCompanyData.company.phone || '',
phone_sec: fullCompanyData.company.phone_sec || '',
estado: fullCompanyData.company.estado || '',
cidade: fullCompanyData.company.cidade || '',
bairro: fullCompanyData.company.bairro || '',
rua: fullCompanyData.company.rua || '',
numero: fullCompanyData.company.numero || '',
complemento: fullCompanyData.company.complemento || '',
cep: fullCompanyData.company.cep || '',
service_instance_id: authStore.service_instance_id,
};
}
console.log('Enviando userData:', fullUserData);
console.log('Enviando companyData:', fullCompanyData);
} catch (error) {
console.error('Erro ao carregar dados do usuário:', error);
}
};
const isFormValid = computed(() => {
const { username, email, password, birth_date, phone } = localUser.value;
console.log('company', props.modalCompany);
/*const isFormValid = computed(() => {
const { name, email, password, birth_date, phone } = localCompany.value;
const isEmailValid = /.+@.+\..+/.test(email);
const isPhoneValid = /^[0-9]+$/.test(phone);
return username &&
return name &&
email &&
isEmailValid &&
birth_date &&
phone &&
isPhoneValid &&
(props.isEditMode || password);
});
});*/
const closeModal = () => {
isOpen.value = false;
};
const handleSave = async () => {
if (!isFormValid.value) return;
// if (!isFormValid.value) return;
try {
const userData = {
phone: String(localUser.value.phone || '').replace(/\D/g, ''),
birth_date: new Date(localUser.value.birth_date).toISOString(),
service_instance_id: authStore.service_instance_id,
parent_id: authStore.userId,
...localUser.value,
};
const companyData = {
...localCompany.value, // não localHoliday
service_instance_id: authStore.service_instance_id,
parent_id: authStore.userId,
};
if (!props.isEditMode) {
delete userData.id;
delete companyData.id;
}
if (props.isEditMode) {
await userStore.updateUser(userData.id, userData);
await companyStore.updateCompany(companyData.id, companyData);
} else {
await userStore.createUser(userData);
await companyStore.createCompany(companyData);
}
emit('user-updated');
emit('company-updated');
closeModal();
} catch (error) {
console.error('Erro ao salvar usuário:', error);
console.error('Erro ao salvar empresa:', error);
}
};
</script>

View File

@ -1,5 +1,5 @@
<template>
<v-dialog v-model="isOpen" max-width="500px" @close="closeModal">
<v-dialog :model-value="isOpen" max-width="500px" >
<v-card class="pa-6 rounded-xl elevation-2 card-modal">
<v-card-title class="text-h5 font-weight-bold pb-0">
<span class="text-h5">{{ isEditMode ? 'Editar Feriado' : 'Adicionar Novo Feriado' }}</span>
@ -8,22 +8,22 @@
<v-container>
<v-row>
<v-col cols="12">
<v-text-field v-model="localUser.name" label="Feriado *" clearable
<v-text-field v-model="localHoliday.name" label="Feriado *" clearable
required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.type" label="Tipo do Feriado *" clearable
<v-text-field v-model="localHoliday.type" label="Tipo do Feriado *" clearable
required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.date" label="Data do feriado *" type="date" clearable
<v-text-field v-model="localHoliday.date" label="Data do feriado *" type="date" clearable
:rules="[v => !!v || 'Data de nascimento é obrigatória']" required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.municipio" label="Municipio" type="municipio" clearable />
<v-text-field v-model="localHoliday.municipio" label="Municipio" type="municipio" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localUser.estado" label="Estado" type="estado" clearable />
<v-text-field v-model="localHoliday.estado" label="Estado" type="estado" clearable />
</v-col>
</v-row>
</v-container>
@ -31,12 +31,13 @@
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text color="blue-darken-1" @click="closeModal">Cancelar</v-btn>
<v-btn text class="text-white salvar-btn" @click="handleSave" :loading="userStore.loading" :disabled="!isFormValid">
<v-btn text class="text-white salvar-btn" @click="handleSave" :loading="holidayStore.loading" >
Salvar
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script setup>
import { ref, watch, computed } from 'vue';
@ -44,9 +45,9 @@ import { useHolidayStore } from '../../stores/holiday';
import { useAuthStore } from '../../stores/auth';
const props = defineProps({
isModalOpen: Boolean,
modalValue: Boolean,
isEditMode: Boolean,
modalUser: Object
holiday: Object
});
const emit = defineEmits(['update:isModalOpen', 'save', 'user-updated']);
const holidayStore = useHolidayStore();
@ -54,7 +55,7 @@ const authStore = useAuthStore();
console.log('service intance id',authStore.service_instance_id);
const isOpen = ref(false);
const localUser = ref({
const localHoliday = ref({
id: null,
name: '',
type: '',
@ -65,8 +66,8 @@ const localUser = ref({
service_instance_id: authStore.service_instance_id || 2,
});
// Resetar dados ao abrir para novo usuário
const resetLocalUser = () => {
localUser.value = {
const resetLocalHoliday = () => {
localHoliday.value = {
id: null,
name: '',
type: '',
@ -78,11 +79,70 @@ const resetLocalUser = () => {
};
};
watch(
() => props.holiday,
async (newVal) => {
if (props.isEditMode && newVal && newVal.id) {
await loadHolidayData(); // busca os dados completos pela API
}
},
{ immediate: true }
);
console.log('holiday no modal', props.holiday);
const loadHolidayData = async () => {
try {
// Verifique se holiday foi passado corretamente
if (!props.holiday || !props.holiday.id) {
console.error('Feriado não encontrado, props.holiday está vazio ou sem id');
return; // Se não encontrar, retorna sem fazer a requisição
}
const fullHolidayData = await holidayStore.fetchHolidayById(props.holiday.id);
console.log('fullHolidayData', fullHolidayData);
if (fullHolidayData) {
localHoliday.value = {
id: fullHolidayData.id || null,
name: fullHolidayData.name || '',
type: fullHolidayData.type || '',
date: fullHolidayData.date
? new Date(fullHolidayData.date).toISOString().split('T')[0]
: '',
estado: fullHolidayData.estado || '',
municipio: fullHolidayData.municipio || ''
};
console.log('localHoliday.value', localHoliday.value);
} else {
console.error('Dados do feriado não encontrados');
}
console.log('Feriado carregado:', localHoliday.value);
} catch (error) {
console.error('Erro ao carregar dados do feriado:', error);
}
};
/*
const loadHolidayData = () => {
localHoliday.value = {
id: props.holiday.id || null,
name: props.holiday.name || '',
type: props.holiday.type || '',
date: props.holiday.date || '',
estado: props.holiday.estado || '',
municipio: props.holiday.municipio || '',
parent_id: authStore.userId,
service_instance_id: authStore.service_instance_id,
};
};*/
// Sincroniza `isOpen` com `props.isModalOpen`
watch(() => props.isModalOpen, (newValue) => {
watch(() => props.modalValue, (newValue) => {
isOpen.value = newValue;
if (newValue) {
if (props.isEditMode && props.modalUser) {
if (props.isEditMode && props.holiday) {
loadHolidayData();
} else {
resetLocalHoliday(); // <- limpa os dados para novo usuário
@ -92,33 +152,14 @@ watch(() => props.isModalOpen, (newValue) => {
// Atualiza `props.isModalOpen` quando o modal é fechado
watch(isOpen, (newValue) => {
if (!newValue) {
emit('update:isModalOpen', false);
emit('update:modalValue', false);
}
});
const loadHolidayData = async () => {
try {
const fullUserData = await userStore.fetchUserById(props.modalUser.id);
if (fullUserData) {
localUser.value = {
id: fullUserData.holiday.id || null,
name: fullUserData.holiday.name || '',
type: fullUserData.holiday.type || '',
date: fullUserData.holiday.date
? new Date(fullUserData.holiday.date).toISOString().split('T')[0]
: '',
estado: fullUserData.holiday.estado || '',
estado: fullUserData.holiday.municipio || '',
parent_id: authStore.userId,
service_instance_id: authStore.service_instance_id,
};
}
console.log('Enviando userData:', fullUserData);
} catch (error) {
console.error('Erro ao carregar dados do usuário:', error);
}
};
console.log('holiday', props.holiday);
/*
const isFormValid = computed(() => {
const { username, email, password, birth_date, phone } = localUser.value;
const { username, email, password, birth_date, phone } = localHoliday.value;
const isEmailValid = /.+@.+\..+/.test(email);
const isPhoneValid = /^[0-9]+$/.test(phone);
return username &&
@ -128,29 +169,26 @@ const isFormValid = computed(() => {
phone &&
isPhoneValid &&
(props.isEditMode || password);
});
});*/
const closeModal = () => {
isOpen.value = false;
};
const handleSave = async () => {
if (!isFormValid.value) return;
try {
const userData = {
date: new Date(localUser.value.date).toISOString(),
const holidayData = {
...localHoliday.value, // não localHoliday
service_instance_id: authStore.service_instance_id,
parent_id: authStore.userId,
...localUser.value,
};
if (!props.isEditMode) {
delete userData.id;
delete holidayData.id;
}
if (props.isEditMode) {
await holidayStore.updateUser(userData.id, userData);
await holidayStore.updateHoliday(holidayData.id, holidayData);
} else {
await holidayStore.createUser(userData);
await holidayStore.createHoliday(holidayData);
}
emit('user-updated');
emit('save', holidayData); // avisa o pai que salvou
closeModal();
} catch (error) {
console.error('Erro ao salvar feriado:', error);

View File

@ -3,207 +3,129 @@ import api from '../services/api'; // Importa a instância do axios
import router from '../routes/router';
import { useAuthStore } from './auth'; // Importa o AuthStore
export const useUserStore = defineStore('users', {
state: () => ({
usersHierarchy: null,
user: null,
error: null,
loading: false,
pagination: {},
}),
getters: {
allUsers() {
const flattenUsers = (users) => {
return users.reduce((acc, user) => {
if (!user.deleted) { // Ignora usuários deletados
acc.push(user);
if (user.subordinates?.length > 0) {
acc.push(...flattenUsers(user.subordinates));
}
}
return acc;
}, []);
};
return this.usersHierarchy ? flattenUsers(this.usersHierarchy) : [];
export const useCompanyStore = defineStore('company', {
state: () => ({
companys: [],
total: 0,
page: 1,
perPage: 10,
error: null,
loading: false,
}),
getters: {
currentPage(state) {
return state.page;
},
totalPages(state) {
return Math.ceil(state.total / state.perPage);
},
},
},
actions: {
async fetchUsersHierarchy() {
try {
this.loading = true;
const authStore = useAuthStore();
const token = authStore.token; // Obtém o token de autenticação
const response = await api.get('/users/hierarchy_by_user_id?responsible_id=1', {
headers: {
'Authorization': `Bearer ${token}`
}
});
this.usersHierarchy = response.data.filter(user => !user.deleted); // Filtra usuários deletados
return response.data.subordinates;
} catch (error) {
console.error('Erro ao buscar hierarquia de usuários', error);
throw error; // Lança o erro para tratar em outro lugar
} finally {
this.loading = false;
}
},
async fetchUsersHierarchy() {
try {
this.loading = true;
const authStore = useAuthStore();
const token = authStore.token; // Obtém o token de autenticação
const response = await api.get('/users/', {
headers: {
'Authorization': `Bearer ${token}`
}
});
this.usersHierarchy = response.data.filter(user => !user.deleted); // Filtra usuários deletados
return response.data;
} catch (error) {
console.error('Erro ao buscar hierarquia de usuários', error);
throw error; // Lança o erro para tratar em outro lugar
} finally {
this.loading = false;
}
},
async catchUsers() {
async catchCompanys() {
try {
this.loading = true;
const authStore = useAuthStore();
const token = authStore.token;
const response = await api.get('/users/', {
const response = await api.get('/company/', {
headers: {
'Authorization': `Bearer ${token}`
}
});
// Filtra para manter apenas usuários não deletados
const filteredUsers = response.data.filter(user => !user.deleted);
this.userData = filteredUsers;
//const filteredCompanys = response.data.filter(company => !company.deleted);
//this.userData = filteredUsers;
// Retorna apenas os usuários não deletados
return filteredUsers;
return response.data;
} catch (error) {
console.error('Erro ao buscar lista de usuários', error);
console.error('Erro ao buscar lista de empresas', error);
throw error;
} finally {
this.loading = false;
}
},
async createUser(userData) {
async createCompany(companyData) {
const url = '/company/';
this.loading = true;
this.error = null;
try {
this.loading = true;
const authStore = useAuthStore();
const token = authStore.token;
// Função para formatar a data no formato YYYY-MM-DD
const formatDateForMySQL = (dateString) => {
if (!dateString) return null;
const date = new Date(dateString);
return date.toISOString().split('T')[0]; // Retorna apenas a parte da data
};
const formattedData = {
birth_date: formatDateForMySQL(userData.birth_date),
email: userData.email,
parent_id: userData.parent_id,
password: userData.password,
phone: userData.phone,
profile_image: userData.profile_image,
username: userData.username,
service_instance_id: userData.service_instance_id,
deleted: false
};
console.log("📤 Enviando dados para API:", formattedData);
const response = await api.post('/users/', formattedData, {
const response = await api.post(url, companyData, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
'Content-Type': 'application/json'
}
});
console.log("✅ Resposta da API:", response.data);
await this.fetchUsersHierarchy();
this.companys.push(response.data);
return response.data;
} catch (error) {
console.error('❌ Erro ao criar usuário', error);
this.error = error?.response?.data?.message || error.message || 'Erro ao criar empresa';
console.error('Erro ao criar turno', error);
throw error;
} finally {
this.loading = false;
}
},
// Na função updateUser
async updateUser(userId, userData) {
async updateCompany(companyId, companyData) {
const url = `/company/${id}`;
this.loading = true;
this.error = null;
try {
this.loading = true;
const authStore = useAuthStore();
const token = authStore.token;
// Formata os dados conforme o esperado pela API
const formattedData = {
username: userData.username,
email: userData.email,
phone: String(userData.phone || '').replace(/\D/g, ''),
profile_image: userData.profile_image,
parent_id: userData.parent_id,
service_instance_id: userData.service_instance_id,
birth_date: userData.birth_date
? new Date(userData.birth_date).toISOString().split('T')[0]
: null,
...(userData.password ? { password: userData.password } : {}),
...(userData.status_at !== undefined ? { status_at: userData.status_at } : {})
};
console.log("📤 Enviando dados para API:", formattedData);
const response = await api.put(`/users/${userId}`, formattedData, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
const response = await api.put(url, {
name: company.name,
fantasy_name: company.fantasy_name,
type: company.type,
cnpj: company.cnpj,
email: company.email,
email: company.email,
email_sec: company.email_sec,
phone: company.phone,
phone_sec: company.phone_sec,
estado: company.estado,
cidade: company.cidade,
bairro: company.bairro,
rua: company.rua,
numero: company.numero,
complemento: company.complemento,
cep: company.cep,
});
console.log("✅ Resposta da API:", response.data);
const index = this.companys.findIndex((s) => s.id === id);
if (index !== -1) {
this.companys[index] = response.data;
}
await this.fetchUsersHierarchy();
return response.data;
} catch (error) {
console.error('❌ Erro ao atualizar usuário', error);
this.error = error?.response?.data?.message || error.message || 'Erro ao atualizar empresa';
console.error('Erro ao atualizar turno', error);
throw error;
} finally {
this.loading = false;
}
},
async deleteCompany(id) {
const url = `/company/${id}`;
this.loading = true;
this.error = null;
async deleteUser(userId) {
try {
this.loading = true;
const authStore = useAuthStore();
const token = authStore.token;
// Realiza o soft delete definindo o campo deleted como true
const response = await api.put(`/users/${userId}`, { deleted: true }, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
}
});
console.log("✅ Usuário deletado (soft delete):", response.data);
// Retorna os dados atualizados
return response.data;
await api.delete(url);
this.companys = this.companys.filter((company) => company.id !== id);
} catch (error) {
console.error('Erro ao excluir usuário', error);
this.error = error?.response?.data?.message || error.message || 'Erro ao excluir empresa';
console.error('Erro ao excluir empresa', error);
throw error;
} finally {
this.loading = false;
@ -230,48 +152,18 @@ export const useUserStore = defineStore('users', {
}
},
async fetchFilteredUsers(filters = {}) {
const {
page = 1,
per_page = 10,
group_id,
group_name,
group_type,
instance_id,
space_id,
} = filters;
const queryParams = new URLSearchParams({
page,
per_page,
});
// Adiciona os filtros dinâmicos
if (group_id) queryParams.append('group_id', group_id);
if (group_name) queryParams.append('group_name', group_name);
if (group_type) queryParams.append('group_type', group_type);
if (instance_id) queryParams.append('instance_id', instance_id);
if (space_id) queryParams.append('space_id', space_id);
async fetchCompanyById(company_id) {
const url = `/company/${company_id}`;
this.loading = true;
this.error = null;
try {
this.loading = true;
const authStore = useAuthStore();
const token = authStore.token; // Obtém o token de autenticação
const response = await api.get(`/users/filter?${queryParams.toString()}`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
this.users = response.data.users.filter(user => !user.deleted); // Filtra usuários deletados
this.pagination = {
total: response.data.total,
pages: response.data.pages,
current_page: response.data.current_page,
per_page: response.data.per_page,
};
const response = await api.get(url);
console.log('requisicao: ',response.data);
return response.data;
} catch (error) {
console.error('Erro ao buscar usuários filtrados', error);
this.error = error?.response?.data?.message || error.message || 'Erro ao buscar empresa';
console.error('Erro ao buscar turno', error);
throw error;
} finally {
this.loading = false;

View File

@ -105,7 +105,7 @@ export const useHolidayStore = defineStore('holidays', {
this.holidays.push(response.data);
return response.data;
} catch (error) {
this.error = error?.response?.data?.message || error.message || 'Erro ao criar turno';
this.error = error?.response?.data?.message || error.message || 'Erro ao criar feriado';
console.error('Erro ao criar turno', error);
throw error;
} finally {

View File

@ -10,8 +10,8 @@
<!-- Barra de Pesquisa com Ícone -->
<v-text-field
v-model="filters.user"
:loading="loading.users"
v-model="filters.company"
:loading="loading.companys"
prepend-inner-icon="mdi-magnify"
density="compact"
variant="outlined"
@ -19,7 +19,7 @@
hide-details
class="mx-2"
style="max-width: 250px;"
@update:model-value="filterUsers"
@update:model-value="filterCompanys"
clearable
/>
@ -41,7 +41,7 @@
class="ml-2"
prepend-icon="mdi-plus"
variant="elevated"
@click="openDialog('user', 'create')"
@click="openDialog('company', 'create')"
>
Adicionar Empresa
</v-btn>
@ -50,10 +50,10 @@
<!-- Tabela de Dados -->
<v-data-table
class="dados"
:headers="headers.users"
:items="filteredUsers"
:search="filters.user"
:loading="loading.users"
:headers="headers.companys"
:items="filteredCompanys"
:search="filters.company"
:loading="loading.companys"
:items-per-page="itemsPerPage"
:page.sync="page"
>
@ -61,13 +61,13 @@
<v-icon
size="small"
class="mr-2"
@click="openEditPage('user', item)"
@click="openEditPage('company', item)"
>
mdi-pencil
</v-icon>
<v-icon
size="small"
@click="confirmDelete('user', item)"
@click="confirmDelete('company', item)"
>
mdi-delete
</v-icon>
@ -77,9 +77,9 @@
<!-- Diálogo de Usuário (Novo/Edição) -->
<CompanyModal
v-model:isModalOpen="dialogs.user"
v-model:isModalOpen="dialogs.company"
:isEditMode="isEditing"
:modalUser="forms.user"
:modalCompany="forms.company"
@save="submitForm"
/>
@ -91,8 +91,8 @@
</v-card-title>
<v-card-text class="pt-4">
<p v-if="itemToDelete && itemToDelete.username">
Tem certeza que deseja excluir <strong>{{ itemToDelete.username }}</strong>?
<p v-if="itemToDelete && itemToDelete.name">
Tem certeza que deseja excluir <strong>{{ itemToDelete.name }}</strong>?
Esta ação não pode ser desfeita.
</p>
<p v-else>
@ -139,10 +139,10 @@
import { ref, computed, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import CompanyModal from '../components/modals/CompanyModal.vue';
import { useUserStore } from '../stores/users';
import { useCompanyStore } from '../stores/company';
export default {
name: 'UserManagement',
name: 'CompanyManagement',
components: {
CompanyModal
},
@ -155,11 +155,11 @@
const itemToDelete = ref(null);
const page = ref(1);
const itemsPerPage = ref(10);
const selectedUser = ref(null);
const selectedCompany = ref(null);
// Loading states
const loading = ref({
users: false,
companys: false,
submit: false,
delete: false,
export: false
@ -167,28 +167,40 @@
// Diálogos
const dialogs = ref({
user: false,
company: false,
delete: false
});
// Filtros
const filters = ref({
user: ''
company: ''
});
// Dados - array vazio que será preenchido via API ou entrada do usuário
const users = ref([]);
const companys = ref([]);
// Formulários
const forms = ref({
userValid: false,
user: {
companyValid: false,
company: {
id: null,
username: '',
name: '',
fantasy_name: '',
type: '',
cnpj: '',
email: '',
birth_date: '',
email_sec: '',
phone: '',
profile_image: ''
phone_sec: '',
estado: '',
cidade: '',
bairro: '',
rua: '',
numero: '',
complemento: '',
cep: ''
//contrato: '',
// grupo: '',
//permissao: ''
@ -197,11 +209,11 @@
// Headers para as tabelas
const headers = ref({
users: [
companys: [
{ title: 'ID', key: 'id' },
{ title: 'Usuário', key: 'username' },
{ title: 'Email', key: 'email' },
//{ title: 'Contrato', key: 'contrato' },
{ title: 'Nome empresa', key: 'name' },
{ title: 'Tipo', key: 'type' },
{ title: 'Endereço', key: 'endereco' },
//{ title: 'Grupo', key: 'grupo' },
//{ title: 'Permissão', key: 'permissao' },
{ title: 'Ações', key: 'actions', sortable: false, align: 'end' }
@ -216,19 +228,18 @@
});
// Computed properties
const filteredUsers = computed(() => {
const filtered = users.value.filter(user => !user.deleted);
console.log("Usuários após filtro 'deleted':", filtered);
const filteredCompanys = computed(() => {
const filtered = companys.value.filter(company => !company.deleted);
console.log("Empresa após filtro 'deleted':", filtered);
return filtered.filter(user => {
return user.username.toLowerCase().includes(filters.value.user.toLowerCase()) ||
user.email.toLowerCase().includes(filters.value.user.toLowerCase());
}).map(user => ({
...user,
created_at: user.created_at ? new Date(user.created_at).toLocaleString() : '-'
return filtered.filter(company => {
return company.name.toLowerCase().includes(filters.value.company.toLowerCase());
}).map(company => ({
...company,
created_at: company.created_at ? new Date(company.created_at).toLocaleString() : '-'
}));
});
/*
// Função para exportar para CSV
const exportToCSV = () => {
if (filteredUsers.value.length === 0) {
@ -284,7 +295,7 @@
} finally {
loading.value.export = false;
}
};
};*/
// Métodos
const openDialog = (type, action, item = null) => {
@ -293,11 +304,24 @@
// Ajustando para o formato esperado pelo UserModal
forms.value[type] = {
id: item.id,
username: item.username,
name: item.name,
fantasy_name: item.fantasy_name,
type: item.type,
cnpj: item.cnpj,
email: item.email,
birth_date: item.birth_date,
email_sec: item.email_sec,
phone: item.phone,
profile_image: item.profile_image,
phone_sec: item.phone_sec,
estado: item.estado,
cidade: item.cidade,
bairro: item.bairro,
rua: item.rua,
numero: item.numero,
complemento: item.complemento,
cep: item.cep,
id: null,
//contrato: item.contrato,
//grupo: item.grupo,
//permissao: item.permissao
@ -306,14 +330,23 @@
// Reset form
forms.value[type] = {
id: null,
username: '',
name: '',
fantasy_name: '',
type: '',
cnpj: '',
email: '',
birth_date: '',
email_sec: '',
phone: '',
profile_image: '',
//contrato: '',
//grupo: '',
//permissao: ''
phone_sec: '',
estado: '',
cidade: '',
bairro: '',
rua: '',
numero: '',
complemento: '',
cep: ''
};
}
dialogs.value[type] = true;
@ -323,30 +356,40 @@
console.log('Usuário que será editado:', item); // Log para depuração
// Criar uma cópia do item para evitar problemas de mutação
const userData = { ...item };
const companyData = { ...item };
// Garantir que todos os campos necessários estejam presentes
forms.value[type] = {
id: userData.id,
username: userData.username || '',
email: userData.email || '',
birth_date: userData.birth_date || '',
phone: userData.phone || '',
profile_image: userData.profile_image || ''
id: companyData.id,
name: companyData.name || '',
fantasy_name: companyData.fantasy_name || '',
type: companyData.type || '',
cnpj: companyData.cnpj || '',
email: companyData.email || '',
email_sec: companyData.email_sec || '',
phone: companyData.phone || '',
phone_sec: companyData.phone_sec || '',
estado: companyData.estado || '',
cidade: companyData.cidade || '',
bairro: companyData.bairro || '',
rua: companyData.rua || '',
numero: companyData.numero || '',
complemento: companyData.complemento || '',
cep: companyData.cep || ''
};
// Definir modo de edição e abrir o diálogo
isEditing.value = true;
dialogs.value[type] = true;
selectedUser.value = null; // Remover a seleção do usuário
selectedCompany.value = null; // Remover a seleção do usuário
};
const handleUserUpdated = (updatedUser) => {
const index = users.value.findIndex(user => user.id === updatedUser.id);
const handleCompanyUpdated = (updatedCompany) => {
const index = companys.value.findIndex(companys => company.id === updatedCompany.id);
if (index !== -1) {
users.value[index] = updatedUser;
companys.value[index] = updatedCompany;
}
showNotification('Usuário atualizado com sucesso!');
showNotification('Empresa atualizado com sucesso!');
};
const confirmDelete = (type, item) => {
@ -375,18 +418,18 @@
loading.value.delete = true;
try {
const userId = itemToDelete.value.id;
console.log(`Excluindo usuário com ID: ${userId}`);
const companyId = itemToDelete.value.id;
console.log(`Excluindo empresa com ID: ${companyId}`);
// Faz a requisição para deletar
await userStore.deleteUser(userId);
await companyStore.deleteCompany(companyId);
// Remover o item diretamente da lista local
// Esta é uma abordagem mais direta e imediata
users.value = users.value.filter(user => user.id !== userId);
console.log("Lista atualizada após exclusão:", users.value);
companys.value = companys.value.filter(company => company.id !== companyId);
console.log("Lista atualizada após exclusão:", companys.value);
showNotification(`Usuário excluído com sucesso!`);
showNotification(`Empresa excluído com sucesso!`);
dialogs.value.delete = false;
} catch (error) {
showNotification('Erro ao excluir o item', 'error');
@ -405,27 +448,27 @@
};
};
const filterUsers = () => {
const filterCompanys = () => {
// O filtro já é realizado automaticamente por meio do computed property filteredUsers
};
const submitForm = async (userData) => {
const submitForm = async (companyData) => {
loading.value.submit = true;
try {
if (isEditing.value) {
// Atualizar item existente
await userStore.updateUser(userData.id, userData);
const index = users.value.findIndex(user => user.id === userData.id);
await companyStore.updateCompany(companyData.id, companyData);
const index = companys.value.findIndex(company => company.id === companyData.id);
if (index !== -1) {
users.value[index] = userData;
Companys.value[index] = companyData;
}
} else {
// Criar novo item
const newItem = await userStore.createUser(userData);
users.value.push(newItem);
const newItem = await companyStore.createCompany(companyData);
companys.value.push(newItem);
}
showNotification(`Usuário ${isEditing.value ? 'atualizado' : 'cadastrado'} com sucesso!`);
dialogs.value.user = false;
showNotification(`Empresa ${isEditing.value ? 'atualizado' : 'cadastrado'} com sucesso!`);
dialogs.value.company = false;
} catch (error) {
showNotification('Erro ao salvar os dados', 'error');
console.error('Error submitting form:', error);
@ -434,22 +477,22 @@
}
};
const userStore = useUserStore();
const companyStore = useCompanyStore();
// Lifecycle hooks
onMounted(async () => {
try {
loading.value.users = true;
const usersData = await userStore.catchUsers();
console.log("Dados recebidos da API:", usersData);
loading.value.companys = true;
const companysData = await companyStore.catchCompanys();
console.log("Dados recebidos da API:", companysData);
// Garanta que os dados já estão filtrados (usuários deletados removidos)
users.value = usersData.filter(user => !user.deleted);
companys.value = companysData.filter(company => !company.deleted);
} catch (error) {
showNotification('Erro ao carregar dados da API', 'error');
console.error('Error fetching users:', error);
console.error('Error fetching companys:', error);
} finally {
loading.value.users = false;
loading.value.companys = false;
}
});
@ -459,17 +502,17 @@
loading,
dialogs,
filters,
users,
companys,
forms,
headers,
snackbar,
page,
itemsPerPage,
itemToDelete,
selectedUser,
selectedCompany,
// Computed
filteredUsers,
filteredCompanys,
// Methods
openDialog,
@ -477,9 +520,9 @@
submitForm,
deleteItem,
openEditPage,
filterUsers,
exportToCSV,
handleUserUpdated
filterCompanys,
//exportToCSV,
handleCompanyUpdated
};
}
};

View File

@ -40,7 +40,7 @@
class="ml-2"
prepend-icon="mdi-plus"
variant="elevated"
@click="openDialog('ambiente', 'create')"
@click="openDialog('holiday', 'create')"
>
Adicionar Feriado
</v-btn>
@ -171,7 +171,8 @@
holiday: false,
delete: false
});
const editMode = ref(false)
// Filtros
const filters = ref({
holiday: ''
@ -182,13 +183,13 @@
// Formulários
const forms = ref({
holidayValid: false,
holiday: {
id: null,
name: '',
date:'',
estado: '',
municipio: '',
loading:false
}
});
@ -283,28 +284,41 @@
*/
// Métodos
const openDialog = (type, action, item = null) => {
isEditing.value = action === 'edit';
if (item) {
// Ajustando para o formato esperado pelo cameraModal
forms.value[type] = {
id: item.id,
name: item.name,
date: item.date,
estado: item.estado,
municipio: item.municipio
};
} else {
// Reset form
if (!dialogs.value[type]) {
dialogs.value[type] = false
}
if (!forms.value[type]) {
forms.value[type] = {
id: null,
id: '',
name: '',
date: '',
estado: '',
municipio: '',
};
loading: false
}
}
dialogs.value[type] = true;
};
editMode.value = action === 'edit'
if (type === 'holiday') {
if (action === 'create') {
forms.value.holiday = {
id: '',
name: '',
date: '',
loading: false
}
} else if (action === 'edit') {
forms.value.holiday = {
...item,
loading: false
}
}
// Agora sim abre o modal depois que tudo tá definido
dialogs.value.holiday = true
}
}
const openEditPage = (type, item) => {
console.log('Feriado que será editado:', item); // Log para depuração
@ -365,7 +379,7 @@
console.log(`Excluindo Feriado com ID: ${holidayId}`);
// Faz a requisição para deletar
await holidayStore.deleteCamera(holidayId);
await holidayStore.deleteHoliday(holidayId);
// Remover o item diretamente da lista local
// Esta é uma abordagem mais direta e imediata
@ -416,7 +430,9 @@
console.error('Error submitting form:', error);
} finally {
loading.value.submit = false;
dialogs.value.holiday = false;
}
};