versao todos os cruds funcionais

This commit is contained in:
ka-lucas 2025-04-23 16:14:06 -03:00
parent 0f45adb7b6
commit 1d05933646
11 changed files with 842 additions and 361 deletions

View File

@ -1,109 +1,124 @@
<template> <template>
<v-dialog v-model="isOpen" max-width="500px" @close="closeModal"> <v-dialog v-model="isOpen" max-width="500px" @close="closeModal">
<v-form @submit="handleSave">
<v-card class="pa-6 rounded-xl elevation-2 card-modal"> <v-card class="pa-6 rounded-xl elevation-2 card-modal">
<v-card-title class="text-h5 font-weight-bold pb-0"> <v-card-title class="text-h5 font-weight-bold pb-0">
<span class="text-h5">{{ isEditMode ? 'Editar Usuário' : 'Adicionar Novo Empresa' }}</span> <span class="text-h5">{{ isEditMode ? 'Editar Empresa' : 'Adicionar Nova Empresa' }}</span>
</v-card-title> </v-card-title>
<v-card-text> <v-card-text>
<v-container> <v-container>
<v-row> <v-row>
<v-text class="text-h7">Dados básicos</v-text> <v-text class="text-h7">Dados básicos</v-text>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.name" label="Nome empresa *" clearable required /> <v-text-field v-model="localCompany.name" label="Nome da Empresa *" clearable required />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.fantasyname" label="Nome fantasia" clearable /> <v-text-field v-model="localCompany.fantasy_name" label="Nome Fantasia" clearable />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.cnpj" label="CNPJ *" type="cnpj" clearable required /> <v-text-field v-model="localCompany.cnpj" label="CNPJ *" clearable required />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.tipo" label="Tipo" clearable /> <v-text-field v-model="localCompany.type" label="Tipo" clearable />
</v-col> </v-col>
<v-text class="text-h7">Contato</v-text> <v-text class="text-h7">Contato</v-text>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.email" label="Email *" type="email" clearable <v-text-field v-model="localCompany.email" label="Email *" clearable required />
:rules="[v => !!v || 'Email é obrigatório', v => /.+@.+\..+/.test(v) || 'Email inválido']" required />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.email_sec" label="Email Secundario*" type="email_sec" clearable <v-text-field v-model="localCompany.email_sec" label="Email Secundário" clearable />
:rules="[v => !!v || 'Email é obrigatório', v => /.+@.+\..+/.test(v) || 'Email inválido']" />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.phone" label="Telefone *" type="tel" clearable <v-text-field v-model="localCompany.phone" label="Telefone *" clearable required />
:rules="[v => !!v || 'Telefone é obrigatório', v => /^[0-9]+$/.test(v) || 'Apenas números permitidos']" />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.phone_sec" label="Telefone Secundario *" type="tel_sec" clearable <v-text-field v-model="localCompany.phone_sec" label="Telefone Secundário" clearable />
:rules="[v => !!v || 'Telefone é obrigatório', v => /^[0-9]+$/.test(v) || 'Apenas números permitidos']" />
</v-col> </v-col>
<v-text class="text-h7">Endereço</v-text> <v-text class="text-h7">Endereço</v-text>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.cep" label="CEP *" type="cep" clearable /> <v-text-field v-model="localCompany.cep" label="CEP *" clearable />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.rua" label="Rua *" type="rua" clearable /> <v-text-field v-model="localCompany.rua" label="Rua *" clearable />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.numero" label="Numero *" type="numero" clearable /> <v-text-field v-model="localCompany.numero" label="Número *" clearable />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.bairro" label="Bairro *" type="bairro" clearable /> <v-text-field v-model="localCompany.bairro" label="Bairro *" clearable />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.complemento" label="Complemento" type="complemento" clearable /> <v-text-field v-model="localCompany.complemento" label="Complemento" clearable />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.estado" label="Estado" type="estado" clearable /> <v-text-field v-model="localCompany.estado" label="Estado" clearable />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localCompany.cidade" label="Cidade" type="cidade" clearable /> <v-text-field v-model="localCompany.cidade" label="Cidade" clearable />
</v-col> </v-col>
</v-row> </v-row>
</v-container> </v-container>
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions>
<v-spacer></v-spacer> <v-spacer />
<v-btn text color="blue-darken-1" @click="closeModal">Cancelar</v-btn> <v-btn text color="blue-darken-1" @click="closeModal">Cancelar</v-btn>
<v-btn text class="text-white salvar-btn" @click="handleSave" :loading="companyStore.loading"> <v-btn
type="submit"
text
class="text-white salvar-btn"
:loading="companyStore.loading"
>
Salvar Salvar
</v-btn> </v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-dialog> </v-form>
</template> </v-dialog>
<script setup> </template>
import { ref, watch, computed } from 'vue'; <script setup>
import { useCompanyStore } from '../../stores/company'; import { ref, watch } from 'vue';
import { useAuthStore } from '../../stores/auth'; import { useCompanyStore } from '../../stores/company';
import { useAuthStore } from '../../stores/auth';
const props = defineProps({ const props = defineProps({
isModalOpen: Boolean, isModalOpen: Boolean,
isEditMode: Boolean, isEditMode: Boolean,
modalCompany: Object modalCompany: Object,
}); });
const emit = defineEmits(['update:isModalOpen', 'save', 'company-updated']); const emit = defineEmits(['update:isModalOpen', 'company-updated']);
const companyStore = useCompanyStore(); const companyStore = useCompanyStore();
const authStore = useAuthStore(); const authStore = useAuthStore();
const isOpen = ref(false);
console.log('service intance id',authStore.service_instance_id); const localCompany = ref({
const isOpen = ref(false); id: null,
const localCompany = ref({ name: '',
fantasy_name: '',
type: '',
cnpj: '',
email: '',
email_sec: '',
phone: '',
phone_sec: '',
estado: '',
cidade: '',
bairro: '',
rua: '',
numero: '',
complemento: '',
cep: '',
service_instance_id: authStore.service_instance_id || 2,
parent_id: authStore.userId,
});
const resetLocalCompany = () => {
localCompany.value = {
id: null, id: null,
name: '', name: '',
fantasy_name: '', fantasy_name: '',
type: '', type: '',
cnpj: '', cnpj: '',
email: '', email: '',
email_sec: '', email_sec: '',
phone: '', phone: '',
phone_sec: '', phone_sec: '',
estado: '', estado: '',
cidade: '', cidade: '',
bairro: '', bairro: '',
@ -111,133 +126,64 @@
numero: '', numero: '',
complemento: '', complemento: '',
cep: '', cep: '',
//parent_id: authStore.companyId, service_instance_id: authStore.service_instance_id,
service_instance_id: authStore.service_instance_id || 2, parent_id: authStore.userId,
});
// Resetar dados ao abrir para novo usuário
const resetlocalCompany = () => {
localCompany.value = {
id: null,
name: '',
fantasy_name: '',
type: '',
cnpj: '',
email: '',
email_sec: '',
phone: '',
phone_sec: '',
estado: '',
cidade: '',
bairro: '',
rua: '',
numero: '',
complemento: '',
cep: '',
//parent_id: authStore.companyId,
service_instance_id: authStore.service_instance_id,
};
}; };
// Sincroniza `isOpen` com `props.isModalOpen` };
watch(() => props.isModalOpen, (newValue) => { const loadCompanyData = async () => {
isOpen.value = newValue; try {
if (newValue) { const data = await companyStore.fetchCompanyById(props.modalCompany.id);
if (props.isEditMode && props.modalCompany) { if (data) {
loadCompanyData(); Object.assign(localCompany.value, data);
} else {
resetlocalCompany(); // <- limpa os dados para novo usuário
}
} }
}); } catch (error) {
// Atualiza `props.isModalOpen` quando o modal é fechado console.error('Erro ao carregar dados:', error);
watch(isOpen, (newValue) => {
if (!newValue) {
emit('update:isModalOpen', false);
}
});
const loadCompanyData = async () => {
try {
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 companyData:', fullCompanyData);
} catch (error) {
console.error('Erro ao carregar dados do usuário:', error);
}
};
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 name &&
email &&
isEmailValid &&
birth_date &&
phone &&
isPhoneValid &&
(props.isEditMode || password);
});*/
const closeModal = () => {
isOpen.value = false;
};
const handleSave = async () => {
// if (!isFormValid.value) return;
try {
const companyData = {
...localCompany.value, // não localHoliday
service_instance_id: authStore.service_instance_id,
parent_id: authStore.userId,
};
if (!props.isEditMode) {
delete companyData.id;
}
if (props.isEditMode) {
await companyStore.updateCompany(companyData.id, companyData);
} else {
await companyStore.createCompany(companyData);
}
emit('company-updated');
closeModal();
} catch (error) {
console.error('Erro ao salvar empresa:', error);
}
};
</script>
<style scoped>
.card-modal {
background-color: #ffffff;
border-radius: 16px;
} }
};
.salvar-btn { watch(() => props.isModalOpen, (newVal) => {
background: linear-gradient(to right, #6b4eff, #2eb6ff); isOpen.value = newVal;
border-radius: 999px; if (newVal) {
text-transform: none; if (props.isEditMode) {
font-weight: 500; loadCompanyData();
} else {
resetLocalCompany();
}
} }
</style> });
watch(isOpen, (newVal) => {
if (!newVal) {
emit('update:isModalOpen', false);
}
});
const closeModal = () => {
isOpen.value = false;
};
const handleSave = async (e) => {
e.preventDefault(); // Isso é um seguro extra
try {
const companyData = { ...localCompany.value };
if (!props.isEditMode) {
delete companyData.id;
await companyStore.createCompany(companyData);
} else {
await companyStore.updateCompany(companyData.id, companyData);
}
emit('company-updated');
closeModal();
} catch (error) {
console.error('Erro ao salvar empresa:', error);
}
};
</script>
<style scoped>
.card-modal {
background-color: #FFFFFF;
border-radius: 16px;
}
.salvar-btn {
background: linear-gradient(to right, #6B4EFF, #2EB6FF);
border-radius: 999px;
text-transform: none;
font-weight: 500;
}
</style>

View File

@ -0,0 +1,167 @@
<template>
<v-dialog v-model="isOpen" max-width="500px" @close="closeModal">
<v-form>
<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">Adicionar Nova Empresa</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-text class="text-h7">Dados básicos</v-text>
<v-col cols="12">
<v-text-field v-model="localCompany.name" label="Nome da Empresa *" clearable required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.fantasy_name" label="Nome Fantasia" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.cnpj" label="CNPJ *" clearable required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.type" label="Tipo" clearable />
</v-col>
<v-text class="text-h7">Contato</v-text>
<v-col cols="12">
<v-text-field v-model="localCompany.email" label="Email *" clearable required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.email_sec" label="Email Secundário" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.phone" label="Telefone *" clearable required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.phone_sec" label="Telefone Secundário" clearable />
</v-col>
<v-text class="text-h7">Endereço</v-text>
<v-col cols="12">
<v-text-field v-model="localCompany.cep" label="CEP *" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.rua" label="Rua *" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.numero" label="Número *" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.bairro" label="Bairro *" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.complemento" label="Complemento" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.estado" label="Estado" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localCompany.cidade" label="Cidade" clearable />
</v-col>
</v-row>
<!--<FormFields :company="localCompany" />-->
</v-container>
</v-card-text>
<v-card-actions>
<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="companyStore.loading">
Salvar
</v-btn>
</v-card-actions>
</v-card>
</v-form>
</v-dialog>
</template>
<script setup>
import { ref, watch } from 'vue';
import { useCompanyStore } from '../../stores/company';
import { useAuthStore } from '../../stores/auth';
//import FormFields from './FormFields.vue'; // Campos de formulário extraídos (opcional)
const props = defineProps({
isModalOpen: Boolean
});
const emit = defineEmits(['update:isModalOpen', 'company-created']);
const isOpen = ref(false);
const companyStore = useCompanyStore();
const authStore = useAuthStore();
const localCompany = ref({
name: '',
fantasy_name: '',
type: '',
cnpj: '',
email: '',
email_sec: '',
phone: '',
phone_sec: '',
estado: '',
cidade: '',
bairro: '',
rua: '',
numero: '',
complemento: '',
cep: '',
service_instance_id: authStore.service_instance_id || 2,
parent_id: authStore.userId,
});
watch(() => props.isModalOpen, (newVal) => {
isOpen.value = newVal;
if (newVal) {
Object.assign(localCompany.value, {
name: '',
fantasy_name: '',
type: '',
cnpj: '',
email: '',
email_sec: '',
phone: '',
phone_sec: '',
estado: '',
cidade: '',
bairro: '',
rua: '',
numero: '',
complemento: '',
cep: '',
service_instance_id: authStore.service_instance_id || 2,
parent_id: authStore.userId,
});
}
});
watch(isOpen, (newVal) => {
if (!newVal){
emit('update:isModalOpen', false);
}
});
const closeModal = () => {
isOpen.value = false;
};
const handleSave = async (e) => {
e.preventDefault(); // Impede o comportamento padrão do botão
try {
await companyStore.createCompany(localCompany.value);
emit('company-created');
closeModal();
} catch (error) {
console.error('Erro ao criar empresa:', error);
}
};
</script>
<style scoped>
.card-modal {
background-color: #FFFFFF;
border-radius: 16px;
}
.salvar-btn {
background: linear-gradient(to right, #6B4EFF, #2EB6FF);
border-radius: 999px;
text-transform: none;
font-weight: 500;
}
</style>

View File

@ -1,10 +1,10 @@
<template> <template>
<v-dialog v-model="isOpen" max-width="600"> <v-dialog v-model="isOpen" max-width="600">
<v-card> <v-card class="pa-6 rounded-xl elevation-2 card-modal">
<v-card-title>Editar Escala</v-card-title> <v-card-title e class="text-h5 font-weight-bold pb-0">Editar Escala</v-card-title>
<v-card-text> <v-card-text>
<v-form @submit.prevent="submit"> <v-form @submit.prevent>
<v-text-field <v-text-field
label="Nome da escala" label="Nome da escala"
@ -44,20 +44,22 @@
label="Marcar intervalo automaticamente?" label="Marcar intervalo automaticamente?"
v-model="form.autoBreak" v-model="form.autoBreak"
/>--> />-->
<v-card-actions>
<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="companyStore.loading">
Salvar
</v-btn>
</v-card-actions>
</v-form> </v-form>
</v-card-text> </v-card-text>
<v-card-actions>
<v-btn @click="close">Cancelar</v-btn>
<v-spacer></v-spacer>
<v-btn color="primary" @click="submit">Salvar</v-btn>
</v-card-actions>
</v-card> </v-card>
</v-dialog> </v-dialog>
</template> </template>
<script setup> <script setup>
import { ref, watch } from 'vue' import { ref, watch } from 'vue'
import {useShiftStore} from '../../stores/shift';
const props = defineProps({ const props = defineProps({
modelValue: Boolean, modelValue: Boolean,
@ -86,6 +88,7 @@ watch(() => props.shiftData, (newData) => {
if (!newData) return if (!newData) return
console.log('📥 shiftData recebido no modal:', newData) console.log('📥 shiftData recebido no modal:', newData)
form.value = { form.value = {
id: newData.id || null,
name: newData.name ||'', name: newData.name ||'',
day: newData.day || '', day: newData.day || '',
start_time: newData.start_time || '', start_time: newData.start_time || '',
@ -101,9 +104,33 @@ watch(() => props.shiftData, (newData) => {
function close() { function close() {
isOpen.value = false isOpen.value = false
} }
const shiftStore = useShiftStore();
function submit() { function submit() {
shiftStore.updateShift(form.value.id,form.value);
console.log('📤 Dados enviados para o store:', form.value)
emit('save', form.value) emit('save', form.value)
close() close()
} }
const handleSave = async () => {
try {
await companyStore.createCompany(localCompany.value);
emit('company-created');
closeModal();
} catch (error) {
console.error('Erro ao criar empresa:', error);
}
};
</script> </script>
<style scoped>
.card-modal {
background-color: #FFFFFF;
border-radius: 16px;
}
.salvar-btn {
background: linear-gradient(to right, #6B4EFF, #2EB6FF);
border-radius: 999px;
text-transform: none;
font-weight: 500;
}
</style>

View File

@ -1,23 +1,21 @@
<template> <template>
<v-dialog :model-value="isOpen" max-width="500px" > <v-dialog v-model="dialogVisible" max-width="500px">
<v-card class="pa-6 rounded-xl elevation-2 card-modal"> <v-card class="pa-6 rounded-xl elevation-2 card-modal">
<v-card-title class="text-h5 font-weight-bold pb-0"> <v-card-title class="text-h5 font-weight-bold pb-0">
<span class="text-h5">{{ isEditMode ? 'Editar Feriado' : 'Adicionar Novo Feriado' }}</span> <span class="text-h5">Editar Feriado</span>
</v-card-title> </v-card-title>
<v-card-text> <v-card-text>
<v-container> <v-container>
<v-row> <v-row>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localHoliday.name" label="Feriado *" clearable <v-text-field v-model="localHoliday.name" label="Feriado *" clearable required />
required />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localHoliday.type" label="Tipo do Feriado *" clearable <v-text-field v-model="localHoliday.type" label="Tipo do Feriado *" clearable required />
required />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localHoliday.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 /> :rules="[v => !!v || 'Data é obrigatória']" required />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field v-model="localHoliday.municipio" label="Municipio" type="municipio" clearable /> <v-text-field v-model="localHoliday.municipio" label="Municipio" type="municipio" clearable />
@ -31,30 +29,33 @@
<v-card-actions> <v-card-actions>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn text color="blue-darken-1" @click="closeModal">Cancelar</v-btn> <v-btn text color="blue-darken-1" @click="closeModal">Cancelar</v-btn>
<v-btn text class="text-white salvar-btn" @click="handleSave" :loading="holidayStore.loading" > <v-btn text class="text-white salvar-btn" @click="handleSave" :loading="holidayStore.loading">
Salvar Salvar
</v-btn> </v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-dialog> </v-dialog>
</template> </template>
<script setup> <script setup>
import { ref, watch, computed } from 'vue'; import { ref, watch, onMounted } from 'vue';
import { useHolidayStore } from '../../stores/holiday'; import { useHolidayStore } from '../../stores/holiday';
import { useAuthStore } from '../../stores/auth'; import { useAuthStore } from '../../stores/auth';
const props = defineProps({ const props = defineProps({
modalValue: Boolean, modalValue: Boolean,
isEditMode: Boolean,
holiday: Object holiday: Object
}); });
const emit = defineEmits(['update:isModalOpen', 'save', 'user-updated']);
const emit = defineEmits(['update:modalValue', 'save']);
const holidayStore = useHolidayStore(); const holidayStore = useHolidayStore();
const authStore = useAuthStore(); const authStore = useAuthStore();
console.log('service intance id',authStore.service_instance_id); // Controle local da visibilidade do diálogo
const isOpen = ref(false); const dialogVisible = ref(false);
// Estado local do feriado
const localHoliday = ref({ const localHoliday = ref({
id: null, id: null,
name: '', name: '',
@ -63,137 +64,136 @@ const localHoliday = ref({
estado: '', estado: '',
municipio: '', municipio: '',
parent_id: authStore.userId, parent_id: authStore.userId,
service_instance_id: authStore.service_instance_id || 2, service_instance_id: authStore.service_instance_id || 2
}); });
// Resetar dados ao abrir para novo usuário
const resetLocalHoliday = () => {
localHoliday.value = {
id: null,
name: '',
type: '',
date: '',
estado: '',
municipio: '',
parent_id: authStore.userId,
service_instance_id: authStore.service_instance_id,
};
};
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);
// Carregar dados do feriado para edição
const loadHolidayData = async () => { const loadHolidayData = async () => {
console.log('Carregando dados do feriado ID:', props.holiday?.id);
try { try {
// Verifique se holiday foi passado corretamente
if (!props.holiday || !props.holiday.id) { if (!props.holiday || !props.holiday.id) {
console.error('Feriado não encontrado, props.holiday está vazio ou sem id'); console.error('Feriado não encontrado ou sem ID');
return; // Se não encontrar, retorna sem fazer a requisição return;
} }
const fullHolidayData = await holidayStore.fetchHolidayById(props.holiday.id); // Carregar dados completos do feriado
console.log('fullHolidayData', fullHolidayData); const holidayData = await holidayStore.fetchHolidayById(props.holiday.id);
if (fullHolidayData) {
if (holidayData) {
console.log('Dados carregados com sucesso:', holidayData);
// Preencher dados do formulário
localHoliday.value = { localHoliday.value = {
id: fullHolidayData.id || null, id: holidayData.id,
name: fullHolidayData.name || '', name: holidayData.name || '',
type: fullHolidayData.type || '', type: holidayData.type || '',
date: fullHolidayData.date date: holidayData.date
? new Date(fullHolidayData.date).toISOString().split('T')[0] ? new Date(holidayData.date).toISOString().split('T')[0]
: '', : '',
estado: fullHolidayData.estado || '', estado: holidayData.estado || '',
municipio: fullHolidayData.municipio || '' municipio: holidayData.municipio || '',
parent_id: authStore.userId,
service_instance_id: authStore.service_instance_id || 2
};
} else if (props.holiday) {
// Fallback para os dados recebidos via props
console.log('Usando dados de holiday props como fallback');
localHoliday.value = {
...props.holiday,
date: props.holiday.date
? new Date(props.holiday.date).toISOString().split('T')[0]
: ''
}; };
console.log('localHoliday.value', localHoliday.value);
} else { } else {
console.error('Dados do feriado não encontrados'); console.error('Não foi possível carregar dados do feriado');
} }
console.log('Feriado carregado:', localHoliday.value);
} catch (error) { } catch (error) {
console.error('Erro ao carregar dados do feriado:', error); console.error('Erro ao carregar dados do feriado:', error);
} // Tenta usar os dados do props como fallback
}; if (props.holiday) {
localHoliday.value = {
...props.holiday,
/* date: props.holiday.date
const loadHolidayData = () => { ? new Date(props.holiday.date).toISOString().split('T')[0]
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.modalValue, (newValue) => {
isOpen.value = newValue;
if (newValue) {
if (props.isEditMode && props.holiday) {
loadHolidayData();
} else {
resetLocalHoliday(); // <- limpa os dados para novo usuário
} }
} }
}); };
// Atualiza `props.isModalOpen` quando o modal é fechado
watch(isOpen, (newValue) => { // Observar mudanças no modalValue
if (!newValue) { watch(() => props.modalValue, async (newVal) => {
emit('update:modalValue', false); console.log('EditModal - modalValue mudou para:', newVal);
dialogVisible.value = newVal;
if (newVal) {
// Espera até o holiday ter ID antes de tentar carregar
const waitForHoliday = async () => {
const maxTries = 10;
let tries = 0;
while (!props.holiday?.id && tries < maxTries) {
await new Promise(resolve => setTimeout(resolve, 100)); // espera 100ms
tries++;
}
if (props.holiday?.id) {
console.log('Feriado encontrado após espera:', props.holiday.id);
loadHolidayData();
} else {
console.warn('Holiday não disponível após espera.');
}
};
waitForHoliday();
} }
}); });
console.log('holiday', props.holiday);
/*
const isFormValid = computed(() => { // Observar mudanças no objeto holiday
const { username, email, password, birth_date, phone } = localHoliday.value; watch(() => props.holiday, (newVal) => {
const isEmailValid = /.+@.+\..+/.test(email); console.log('Props holiday mudou:', newVal);
const isPhoneValid = /^[0-9]+$/.test(phone); if (newVal && newVal.id) {
return username && loadHolidayData();
email && }
isEmailValid && }, { deep: true });
birth_date &&
phone && // Atualizar o prop quando o diálogo local mudar
isPhoneValid && watch(dialogVisible, (newVal) => {
(props.isEditMode || password); if (props.modalValue !== newVal) {
});*/ emit('update:modalValue', newVal);
}
});
// Fechar o modal
const closeModal = () => { const closeModal = () => {
isOpen.value = false; console.log('Fechando modal de edição');
dialogVisible.value = false;
emit('update:modalValue', false);
}; };
// Salvar as alterações no feriado
const handleSave = async () => { const handleSave = async () => {
try { try {
const holidayData = { const holidayData = { ...localHoliday.value };
...localHoliday.value, // não localHoliday console.log('Atualizando feriado:', holidayData);
service_instance_id: authStore.service_instance_id,
parent_id: authStore.userId, await holidayStore.updateHoliday(holidayData.id, holidayData);
};
if (!props.isEditMode) { emit('save', holidayData);
delete holidayData.id;
}
if (props.isEditMode) {
await holidayStore.updateHoliday(holidayData.id, holidayData);
} else {
await holidayStore.createHoliday(holidayData);
}
emit('save', holidayData); // avisa o pai que salvou
closeModal(); closeModal();
} catch (error) { } catch (error) {
console.error('Erro ao salvar feriado:', error); console.error('Erro ao atualizar feriado:', error);
} }
}; };
// Inicialização do componente
onMounted(() => {
console.log('Modal de edição montado - holiday:', props.holiday);
dialogVisible.value = props.modalValue;
if (props.modalValue && props.holiday && props.holiday.id) {
loadHolidayData();
}
});
</script> </script>
<style scoped> <style scoped>

View File

@ -0,0 +1,151 @@
<template>
<v-dialog :model-value="modalValue" @update:model-value="updateModalValue" 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">Adicionar Novo Feriado</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12">
<v-text-field v-model="localHoliday.name" label="Feriado *" clearable required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localHoliday.type" label="Tipo do Feriado *" clearable required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localHoliday.date" label="Data do feriado *" type="date" clearable
:rules="[v => !!v || 'Data é obrigatória']" required />
</v-col>
<v-col cols="12">
<v-text-field v-model="localHoliday.municipio" label="Municipio" type="municipio" clearable />
</v-col>
<v-col cols="12">
<v-text-field v-model="localHoliday.estado" label="Estado" type="estado" clearable />
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text color="blue-darken-1" @click.prevent.stop="closeModal">Cancelar</v-btn>
<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, onMounted } from 'vue';
import { useHolidayStore } from '../../stores/holiday';
import { useAuthStore } from '../../stores/auth';
const props = defineProps({
modalValue: {
type: Boolean,
required: true
}
});
const emit = defineEmits(['update:modalValue', 'save']);
const holidayStore = useHolidayStore();
const authStore = useAuthStore();
// Objeto de feriado padrão
const defaultHoliday = {
name: '',
type: '',
date: '',
estado: '',
municipio: '',
parent_id: authStore.userId,
service_instance_id: authStore.service_instance_id || 2
};
// Estado local do feriado
const localHoliday = ref({...defaultHoliday});
// Função para atualizar o estado do modal
const updateModalValue = (value) => {
console.log('Dialog emitindo update:model-value:', value);
emit('update:modalValue', value);
if (!value) {
resetLocalHoliday();
}
};
// Resetar o feriado para o estado inicial
const resetLocalHoliday = () => {
console.log('Resetando formulário de criação para valores padrão');
for (const key in defaultHoliday) {
localHoliday.value[key] = defaultHoliday[key];
}
};
// Observar mudanças no modalValue
watch(() => props.modalValue, (newVal, oldVal) => {
console.log(`CreateModal - modalValue mudou de ${oldVal} para ${newVal}`);
if (newVal) {
// Modal está sendo aberto - resetar formulário
resetLocalHoliday();
}
});
// Fechar o modal e limpar os dados
const closeModal = () => {
console.log('Botão cancelar clicado - fechando modal de criação');
// Emitir evento para fechar o modal
emit('update:modalValue', false);
// Resetar dados
resetLocalHoliday();
};
// Salvar o novo feriado
const handleSave = async (event) => {
event.preventDefault(); // Impede o comportamento padrão do botão
try {
const holidayData = {
...localHoliday.value,
parent_id: authStore.userId,
service_instance_id: authStore.service_instance_id || 2
};
console.log('Criando novo feriado:', holidayData);
await holidayStore.createHoliday(holidayData);
emit('save', holidayData);
emit('update:modalValue', false);
resetLocalHoliday();
} catch (error) {
console.error('Erro ao criar feriado:', error);
}
};
// Inicialização do componente
onMounted(() => {
console.log('Modal de criação montado - modalValue:', props.modalValue);
if (props.modalValue) {
resetLocalHoliday();
}
});
</script>
<style scoped>
.card-modal {
background-color: #ffffff;
border-radius: 16px;
}
.salvar-btn {
background: linear-gradient(to right, #6b4eff, #2eb6ff);
border-radius: 999px;
text-transform: none;
font-weight: 500;
}
</style>

View File

@ -104,6 +104,7 @@ watch(isOpen, (newValue) => {
}); });
const loadUserData = async () => { const loadUserData = async () => {
try { try {
console.log('Carregando dados do usuário:', props.modalUser);
const fullUserData = await userStore.fetchUserById(props.modalUser.id); const fullUserData = await userStore.fetchUserById(props.modalUser.id);
if (fullUserData) { if (fullUserData) {
localUser.value = { localUser.value = {

View File

@ -30,18 +30,25 @@ export const useCompanyStore = defineStore('company', {
this.loading = true; this.loading = true;
const authStore = useAuthStore(); const authStore = useAuthStore();
const token = authStore.token; const token = authStore.token;
const userId = authStore.userId;
console.log('userId: ', userId); // Exibe o userId no console
const response = await api.get('/company/', { const response = await api.get('/company/', {
headers: { headers: {
'Authorization': `Bearer ${token}` 'Authorization': `Bearer ${token}`
} }
}); });
console.log('requisicao company.js: ',response.data);
// Filtra para manter apenas usuários não deletados const filteredCompanys = response.data.filter(company => {
//const filteredCompanys = response.data.filter(company => !company.deleted); console.log('Verificando company: ', company); // Exibe o objeto completo da empresa
//this.userData = filteredUsers; console.log('parent_id da empresa: ', company.parent_id); // Exibe apenas o valor do parent_id
return String(company.parent_id) === String(userId);
});
console.log('filteredCompanys', filteredCompanys);
// Retorna apenas os usuários não deletados // Retorna apenas os usuários não deletados
return response.data; this.companies = filteredCompanys;
return filteredCompanys;
} catch (error) { } catch (error) {
console.error('Erro ao buscar lista de empresas', error); console.error('Erro ao buscar lista de empresas', error);
throw error; throw error;
@ -61,7 +68,8 @@ export const useCompanyStore = defineStore('company', {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
} }
}); });
print('response.data', response.data);
print('compony', companyData);
this.companys.push(response.data); this.companys.push(response.data);
return response.data; return response.data;
} catch (error) { } catch (error) {
@ -75,8 +83,8 @@ export const useCompanyStore = defineStore('company', {
}, },
// Na função updateUser // Na função updateUser
async updateCompany(companyId, companyData) { async updateCompany(companyId, company) {
const url = `/company/${id}`; const url = `/company/${companyId}`;
this.loading = true; this.loading = true;
this.error = null; this.error = null;
@ -132,7 +140,7 @@ export const useCompanyStore = defineStore('company', {
} }
}, },
async fetchUserById(userId) { /*async fetchUserById(userId) {
try { try {
this.loading = true; this.loading = true;
const authStore = useAuthStore(); const authStore = useAuthStore();
@ -150,7 +158,7 @@ export const useCompanyStore = defineStore('company', {
} finally { } finally {
this.loading = false; this.loading = false;
} }
}, },*/
async fetchCompanyById(company_id) { async fetchCompanyById(company_id) {
const url = `/company/${company_id}`; const url = `/company/${company_id}`;

View File

@ -160,7 +160,8 @@ export const useUserStore = defineStore('users', {
? new Date(userData.birth_date).toISOString().split('T')[0] ? new Date(userData.birth_date).toISOString().split('T')[0]
: null, : null,
...(userData.password ? { password: userData.password } : {}), ...(userData.password ? { password: userData.password } : {}),
...(userData.status_at !== undefined ? { status_at: userData.status_at } : {}) ...(userData.status_at !== undefined ? { status_at: userData.status_at } : {}),
status: userData.status,
}; };
console.log("📤 Enviando dados para API:", formattedData); console.log("📤 Enviando dados para API:", formattedData);
@ -191,7 +192,7 @@ export const useUserStore = defineStore('users', {
const token = authStore.token; const token = authStore.token;
// Realiza o soft delete definindo o campo deleted como true // Realiza o soft delete definindo o campo deleted como true
const response = await api.put(`/users/${userId}`, { deleted: true }, { const response = await api.delete(`/users/${userId}`, { deleted: true }, {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': `Bearer ${token}` 'Authorization': `Bearer ${token}`

View File

@ -41,7 +41,7 @@
class="ml-2" class="ml-2"
prepend-icon="mdi-plus" prepend-icon="mdi-plus"
variant="elevated" variant="elevated"
@click="openDialog('company', 'create')" @click="openCreateModal"
> >
Adicionar Empresa Adicionar Empresa
</v-btn> </v-btn>
@ -82,6 +82,10 @@
:modalCompany="forms.company" :modalCompany="forms.company"
@save="submitForm" @save="submitForm"
/> />
<CompanyModayCreate
v-model:isModalOpen="dialogs.createCompany"
@save="SubmitFormCreate"
/>
<!-- Diálogo de Confirmação de Exclusão --> <!-- Diálogo de Confirmação de Exclusão -->
<v-dialog v-model="dialogs.delete" max-width="400px"> <v-dialog v-model="dialogs.delete" max-width="400px">
@ -139,17 +143,20 @@
import { ref, computed, onMounted } from 'vue'; import { ref, computed, onMounted } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import CompanyModal from '../components/modals/CompanyModal.vue'; import CompanyModal from '../components/modals/CompanyModal.vue';
import CompanyModayCreate from '../components/modals/CompanyModalCreate.vue';
import { useCompanyStore } from '../stores/company'; import { useCompanyStore } from '../stores/company';
export default { export default {
name: 'CompanyManagement', name: 'CompanyManagement',
components: { components: {
CompanyModal CompanyModal,
CompanyModayCreate
}, },
setup() { setup() {
const router = useRouter(); const router = useRouter();
// Estados // Estados
const isCreateModalOpen = ref(false);
const isEditing = ref(false); const isEditing = ref(false);
const itemToEdit = ref(null); const itemToEdit = ref(null);
const itemToDelete = ref(null); const itemToDelete = ref(null);
@ -168,6 +175,7 @@
// Diálogos // Diálogos
const dialogs = ref({ const dialogs = ref({
company: false, company: false,
createCompany: false,
delete: false delete: false
}); });
@ -213,8 +221,8 @@
{ title: 'ID', key: 'id' }, { title: 'ID', key: 'id' },
{ title: 'Nome empresa', key: 'name' }, { title: 'Nome empresa', key: 'name' },
{ title: 'Tipo', key: 'type' }, { title: 'Tipo', key: 'type' },
{ title: 'Endereço', key: 'endereco' }, { title: 'Bairro', key: 'bairro' },
//{ title: 'Grupo', key: 'grupo' }, { title: 'Rua', key: 'rua' },
//{ title: 'Permissão', key: 'permissao' }, //{ title: 'Permissão', key: 'permissao' },
{ title: 'Ações', key: 'actions', sortable: false, align: 'end' } { title: 'Ações', key: 'actions', sortable: false, align: 'end' }
] ]
@ -351,13 +359,17 @@
} }
dialogs.value[type] = true; dialogs.value[type] = true;
}; };
const openCreateModal = () => {
isCreateModalOpen.value = true;
dialogs.value.createCompany = true
};
const openEditPage = (type, item) => { const openEditPage = (type, item) => {
console.log('Usuário que será editado:', item); // Log para depuração console.log('Usuário que será editado:', item); // Log para depuração
// Criar uma cópia do item para evitar problemas de mutação // Criar uma cópia do item para evitar problemas de mutação
const companyData = { ...item }; const companyData = { ...item };
console.log('CompanyData que será editado:', companyData);
// Garantir que todos os campos necessários estejam presentes // Garantir que todos os campos necessários estejam presentes
forms.value[type] = { forms.value[type] = {
id: companyData.id, id: companyData.id,
@ -385,7 +397,7 @@
}; };
const handleCompanyUpdated = (updatedCompany) => { const handleCompanyUpdated = (updatedCompany) => {
const index = companys.value.findIndex(companys => company.id === updatedCompany.id); const index = companys.value.findIndex(company => company.id === updatedCompany.id);
if (index !== -1) { if (index !== -1) {
companys.value[index] = updatedCompany; companys.value[index] = updatedCompany;
} }
@ -451,7 +463,21 @@
const filterCompanys = () => { const filterCompanys = () => {
// O filtro já é realizado automaticamente por meio do computed property filteredUsers // O filtro já é realizado automaticamente por meio do computed property filteredUsers
}; };
const SubmitFormCreate = async (companyData) => {
loading.value.submit = true;
try {
//const newItem = await companyStore.createCompany(companyData);
companys.value.push(newItem);
showNotification('Empresa cadastrado com sucesso!');
} catch (error) {
console.error('Error submitting form:', error);
} finally {
loading.value.submit = false;
dialogs.value.createCompany = false;
}
};
const submitForm = async (companyData) => { const submitForm = async (companyData) => {
loading.value.submit = true; loading.value.submit = true;
try { try {
@ -462,11 +488,8 @@
if (index !== -1) { if (index !== -1) {
Companys.value[index] = companyData; Companys.value[index] = companyData;
} }
} else {
// Criar novo item
const newItem = await companyStore.createCompany(companyData);
companys.value.push(newItem);
} }
showNotification(`Empresa ${isEditing.value ? 'atualizado' : 'cadastrado'} com sucesso!`); showNotification(`Empresa ${isEditing.value ? 'atualizado' : 'cadastrado'} com sucesso!`);
dialogs.value.company = false; dialogs.value.company = false;
} catch (error) { } catch (error) {
@ -521,6 +544,8 @@
deleteItem, deleteItem,
openEditPage, openEditPage,
filterCompanys, filterCompanys,
openCreateModal,
SubmitFormCreate,
//exportToCSV, //exportToCSV,
handleCompanyUpdated handleCompanyUpdated
}; };

View File

@ -40,7 +40,7 @@
class="ml-2" class="ml-2"
prepend-icon="mdi-plus" prepend-icon="mdi-plus"
variant="elevated" variant="elevated"
@click="openDialog('holiday', 'create')" @click="openCreateModal"
> >
Adicionar Feriado Adicionar Feriado
</v-btn> </v-btn>
@ -80,7 +80,10 @@
:holiday="forms.holiday" :holiday="forms.holiday"
@save="submitForm" @save="submitForm"
/> />
<CreateHolidayModal
v-model="dialogs.createholiday"
@save="SubmitFormCreate"
/>
<!-- Diálogo de Confirmação de Exclusão --> <!-- Diálogo de Confirmação de Exclusão -->
<v-dialog v-model="dialogs.delete" max-width="400px"> <v-dialog v-model="dialogs.delete" max-width="400px">
<v-card> <v-card>
@ -138,12 +141,13 @@
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import holidayModal from '../components/modals/HolidayModal.vue'; import holidayModal from '../components/modals/HolidayModal.vue';
import {useHolidayStore} from '../stores/holiday'; import {useHolidayStore} from '../stores/holiday';
import CreateHolidayModal from '../components/modals/HolidayModalCreate.vue';
export default { export default {
name: 'holidayManagement', name: 'holidayManagement',
components: { components: {
holidayModal holidayModal,
CreateHolidayModal
}, },
setup() { setup() {
const router = useRouter(); const router = useRouter();
@ -151,6 +155,7 @@
const holidayStore = useHolidayStore(); const holidayStore = useHolidayStore();
// Estados // Estados
const isCreateModalOpen = ref(false);
const isEditing = ref(false); const isEditing = ref(false);
const itemToEdit = ref(null); const itemToEdit = ref(null);
const itemToDelete = ref(null); const itemToDelete = ref(null);
@ -169,6 +174,7 @@
// Diálogos // Diálogos
const dialogs = ref({ const dialogs = ref({
holiday: false, holiday: false,
createholiday: false,
delete: false delete: false
}); });
const editMode = ref(false) const editMode = ref(false)
@ -212,17 +218,17 @@
}); });
// Computed properties // Computed properties
const filteredholidays = computed(() => { const filteredholidays = computed(() => {
const filtered = holidays.value.filter(holiday => !holiday.deleted); const filtered = holidays.value.filter(holiday => !holiday.deleted);
console.log("Feriado após filtro 'deleted':", filtered);
return filtered.filter(holiday => { return filtered.filter(holiday => {
return holiday.name.toLowerCase().includes(filters.value.holiday.toLowerCase()) const holidayName = holiday.name || ''; // Garantir que seja uma string vazia se undefined
return holidayName.toLowerCase().includes(filters.value.holiday.toLowerCase())
}).map(holiday => ({ }).map(holiday => ({
...holiday, ...holiday,
created_at: holiday.created_at ? new Date(holiday.created_at).toLocaleString() : '-' created_at: holiday.created_at ? new Date(holiday.created_at).toLocaleString() : '-'
})); }));
}); });
/* /*
// Função para exportar para CSV // Função para exportar para CSV
const exportToCSV = () => { const exportToCSV = () => {
@ -300,14 +306,7 @@
editMode.value = action === 'edit' editMode.value = action === 'edit'
if (type === 'holiday') { if (type === 'holiday') {
if (action === 'create') { if (action === 'edit') {
forms.value.holiday = {
id: '',
name: '',
date: '',
loading: false
}
} else if (action === 'edit') {
forms.value.holiday = { forms.value.holiday = {
...item, ...item,
loading: false loading: false
@ -318,8 +317,13 @@
dialogs.value.holiday = true dialogs.value.holiday = true
} }
} }
// Abrir modal de criação
const openCreateModal = () => {
isCreateModalOpen.value = true;
dialogs.value.createholiday = true
};
const openEditPage = (type, item) => { const openEditPage = (type, item) => {
console.log('Feriado que será editado:', item); // Log para depuração console.log('Feriado que será editado:', item); // Log para depuração
@ -419,11 +423,7 @@
if (index !== -1) { if (index !== -1) {
holidays.value[index] = holidayData; holidays.value[index] = holidayData;
} }
} else { }
// Criar novo item
const newItem = await holidayStore.createHoliday(holidayData);
holidays.value.push(newItem);
}
showNotification(`Feriado ${isEditing.value ? 'atualizado' : 'cadastrado'} com sucesso!`); showNotification(`Feriado ${isEditing.value ? 'atualizado' : 'cadastrado'} com sucesso!`);
} catch (error) { } catch (error) {
@ -434,7 +434,19 @@
} }
}; };
const SubmitFormCreate = async (holidayData) => {
loading.value.submit = true;
try {
//const newItem = await holidayStore.createHoliday(holidayData);
holidays.value.push(newItem);
showNotification('Feriado cadastrado com sucesso!');
} catch (error) {
console.error('Error submitting form:', error);
} finally {
loading.value.submit = false;
dialogs.value.createholiday = false;
}
};
// Lifecycle hooks // Lifecycle hooks
onMounted(async () => { onMounted(async () => {
@ -479,8 +491,10 @@
openDialog, openDialog,
confirmDelete, confirmDelete,
submitForm, submitForm,
SubmitFormCreate,
deleteItem, deleteItem,
openEditPage, openEditPage,
openCreateModal,
// filtercameras, // filtercameras,
//exportToCSV, //exportToCSV,
handleholidayUpdated handleholidayUpdated

View File

@ -22,7 +22,19 @@
@update:model-value="filterUsers" @update:model-value="filterUsers"
clearable clearable
/> />
<!-- Filtro de Status -->
<v-select
v-model="filters.status"
:items="statusOptions"
label="Status"
density="compact"
variant="outlined"
hide-details
class="mx-2"
style="max-width: 150px;"
@update:model-value="filterUsers"
clearable
/>
<!-- Botão para exportar CSV --> <!-- Botão para exportar CSV -->
<v-btn <v-btn
color="primary" color="primary"
@ -57,6 +69,29 @@
:items-per-page="itemsPerPage" :items-per-page="itemsPerPage"
:page.sync="page" :page.sync="page"
> >
<!-- Coluna de Status -->
<template v-slot:item.status="{ item }">
<!-- Botão para alternar status -->
<v-icon
size="small"
class="mr-2"
:color="item.status ? 'error' : 'success'"
@click="toggleUserStatus(item)"
:title="item.status ? 'Desativar usuário' : 'Ativar usuário'"
>
{{ item.status ? 'mdi-account-cancel' : 'mdi-account-check' }}
</v-icon>
<!--
<v-chip
:color="item.status ? 'success' : 'error'"
text-color="white"
size="small"
>
{{ item.status ? 'Ativo' : 'Inativo' }}
</v-chip>-->
</template>
<template v-slot:item.actions="{ item }"> <template v-slot:item.actions="{ item }">
<v-icon <v-icon
size="small" size="small"
@ -115,6 +150,38 @@
</v-card> </v-card>
</v-dialog> </v-dialog>
<!-- Diálogo de Confirmação de Alteração de Status -->
<v-dialog v-model="dialogs.status" max-width="400px">
<v-card>
<v-card-title class="text-h5" :class="statusToChange ? 'bg-error' : 'bg-success'" style="color: white;">
{{ statusToChange ? 'Desativar Usuário' : 'Ativar Usuário' }}
</v-card-title>
<v-card-text class="pt-4">
<p v-if="itemToChangeStatus && itemToChangeStatus.username">
Tem certeza que deseja {{ statusToChange ? 'desativar' : 'ativar' }} o usuário
<strong>{{ itemToChangeStatus.username }}</strong>?
</p>
<p v-else>
Erro: Nenhum usuário selecionado.
</p>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="grey" @click="dialogs.status = false">Cancelar</v-btn>
<v-btn
:color="statusToChange ? 'error' : 'success'"
:loading="loading.status"
:disabled="!itemToChangeStatus || !itemToChangeStatus.id"
@click="changeUserStatus"
>
{{ statusToChange ? 'Desativar' : 'Ativar' }}
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<!-- Snackbar para Feedback --> <!-- Snackbar para Feedback -->
<v-snackbar <v-snackbar
v-model="snackbar.show" v-model="snackbar.show"
@ -156,24 +223,35 @@ export default {
const page = ref(1); const page = ref(1);
const itemsPerPage = ref(10); const itemsPerPage = ref(10);
const selectedUser = ref(null); const selectedUser = ref(null);
const itemToChangeStatus = ref(null);
const statusToChange = ref(null);
// Status options para filtro
const statusOptions = [
{ title: 'Ativo', value: true },
{ title: 'Inativo', value: false }
];
// Loading states // Loading states
const loading = ref({ const loading = ref({
users: false, users: false,
submit: false, submit: false,
delete: false, delete: false,
export: false export: false,
status: false
}); });
// Diálogos // Diálogos
const dialogs = ref({ const dialogs = ref({
user: false, user: false,
delete: false delete: false,
status: false
}); });
// Filtros // Filtros
const filters = ref({ const filters = ref({
user: '' user: '',
status: null
}); });
// Dados - array vazio que será preenchido via API ou entrada do usuário // Dados - array vazio que será preenchido via API ou entrada do usuário
@ -188,7 +266,8 @@ export default {
email: '', email: '',
birth_date: '', birth_date: '',
phone: '', phone: '',
profile_image: '' profile_image: '',
status: true,
//contrato: '', //contrato: '',
// grupo: '', // grupo: '',
//permissao: '' //permissao: ''
@ -201,6 +280,7 @@ export default {
{ title: 'ID', key: 'id' }, { title: 'ID', key: 'id' },
{ title: 'Usuário', key: 'username' }, { title: 'Usuário', key: 'username' },
{ title: 'Email', key: 'email' }, { title: 'Email', key: 'email' },
{ title: 'Status', key: 'status', align: 'center' },
//{ title: 'Contrato', key: 'contrato' }, //{ title: 'Contrato', key: 'contrato' },
//{ title: 'Grupo', key: 'grupo' }, //{ title: 'Grupo', key: 'grupo' },
//{ title: 'Permissão', key: 'permissao' }, //{ title: 'Permissão', key: 'permissao' },
@ -221,14 +301,63 @@ export default {
console.log("Usuários após filtro 'deleted':", filtered); console.log("Usuários após filtro 'deleted':", filtered);
return filtered.filter(user => { return filtered.filter(user => {
return user.username.toLowerCase().includes(filters.value.user.toLowerCase()) || // Filtro por texto (username ou email)
user.email.toLowerCase().includes(filters.value.user.toLowerCase()); const textMatch = user.username.toLowerCase().includes(filters.value.user.toLowerCase()) ||
user.email.toLowerCase().includes(filters.value.user.toLowerCase());
// Filtro por status (se selecionado)
const statusMatch = filters.value.status === null || user.status === filters.value.status;
return textMatch && statusMatch;
}).map(user => ({ }).map(user => ({
...user, ...user,
created_at: user.created_at ? new Date(user.created_at).toLocaleString() : '-' created_at: user.created_at ? new Date(user.created_at).toLocaleString() : '-'
})); }));
}); });
// Função para alternar status do usuário
const toggleUserStatus = (item) => {
itemToChangeStatus.value = {...item};
statusToChange.value = item.status; // Se true, vai desativar; se false, vai ativar
dialogs.value.status = true;
};
// Função para confirmar a alteração de status
const changeUserStatus = async () => {
if (!itemToChangeStatus.value || itemToChangeStatus.value.id === undefined) {
showNotification('Erro ao alterar status do usuário', 'error');
return;
}
console.log("Alterando status do usuário:", itemToChangeStatus.value);
loading.value.status = true;
try {
const userId = itemToChangeStatus.value.id;
const newStatusAt = statusToChange.value ? 'inativo' : 'ativo';
const updatedUser = {
...itemToChangeStatus.value,
status: newStatusAt
};
await userStore.updateUser(userId, updatedUser);
const index = users.value.findIndex(user => user.id === userId);
if (index !== -1) {
users.value[index].status = newStatusAt === 'ativo';
users.value[index].status = newStatusAt;
}
showNotification(`Usuário ${newStatusAt === 'ativo' ? 'ativado' : 'desativado'} com sucesso!`);
dialogs.value.status = false;
} catch (error) {
showNotification('Erro ao alterar status do usuário', 'error');
console.error('Error updating user status:', error);
} finally {
loading.value.status = false;
itemToChangeStatus.value = null;
}
};
// Função para exportar para CSV // Função para exportar para CSV
const exportToCSV = () => { const exportToCSV = () => {
if (filteredUsers.value.length === 0) { if (filteredUsers.value.length === 0) {
@ -298,6 +427,7 @@ export default {
birth_date: item.birth_date, birth_date: item.birth_date,
phone: item.phone, phone: item.phone,
profile_image: item.profile_image, profile_image: item.profile_image,
status: item.status,
//contrato: item.contrato, //contrato: item.contrato,
//grupo: item.grupo, //grupo: item.grupo,
//permissao: item.permissao //permissao: item.permissao
@ -311,6 +441,7 @@ export default {
birth_date: '', birth_date: '',
phone: '', phone: '',
profile_image: '', profile_image: '',
status: true,
//contrato: '', //contrato: '',
//grupo: '', //grupo: '',
//permissao: '' //permissao: ''
@ -332,7 +463,8 @@ export default {
email: userData.email || '', email: userData.email || '',
birth_date: userData.birth_date || '', birth_date: userData.birth_date || '',
phone: userData.phone || '', phone: userData.phone || '',
profile_image: userData.profile_image || '' profile_image: userData.profile_image || '',
status: userData.status || true,
}; };
// Definir modo de edição e abrir o diálogo // Definir modo de edição e abrir o diálogo
@ -444,7 +576,12 @@ export default {
console.log("Dados recebidos da API:", usersData); console.log("Dados recebidos da API:", usersData);
// Garanta que os dados já estão filtrados (usuários deletados removidos) // Garanta que os dados já estão filtrados (usuários deletados removidos)
users.value = usersData.filter(user => !user.deleted); users.value = usersData
.filter(user => !user.deleted)
.map(user => ({
...user,
status: user.status !== 'inativo'
}));
} catch (error) { } catch (error) {
showNotification('Erro ao carregar dados da API', 'error'); showNotification('Erro ao carregar dados da API', 'error');
console.error('Error fetching users:', error); console.error('Error fetching users:', error);
@ -467,7 +604,9 @@ export default {
itemsPerPage, itemsPerPage,
itemToDelete, itemToDelete,
selectedUser, selectedUser,
statusOptions,
itemToChangeStatus,
statusToChange,
// Computed // Computed
filteredUsers, filteredUsers,
@ -479,7 +618,9 @@ export default {
openEditPage, openEditPage,
filterUsers, filterUsers,
exportToCSV, exportToCSV,
handleUserUpdated handleUserUpdated,
toggleUserStatus,
changeUserStatus
}; };
} }
}; };