This commit is contained in:
LeoMortari
2025-11-04 00:07:56 -03:00
parent 6e9327fee4
commit d7fe497df6

View File

@@ -107,6 +107,113 @@
</q-tr>
</template>
</Table>
<!-- Dialog para adicionar novo usuário -->
<q-dialog v-model="showNewUserDialog" persistent>
<q-card class="new-user-dialog">
<q-card-section class="new-user-dialog__header">
<div>
<h3 class="new-user-dialog__title">Adicionar Novo Usuário</h3>
<p class="new-user-dialog__subtitle">
Preencha os dados para criar um novo usuário no sistema
</p>
</div>
<q-btn
icon="sym_o_close"
flat
round
dense
v-close-popup
color="grey-7"
/>
</q-card-section>
<q-separator />
<q-card-section class="new-user-dialog__form">
<TextField
v-model="newUser.nome"
label="Nome"
placeholder="Ex.: Ana"
:error="!!formErrors.nome"
:error-message="formErrors.nome"
>
<template #prepend>
<q-icon name="sym_o_person" color="primary" />
</template>
</TextField>
<TextField
v-model="newUser.sobrenome"
label="Sobrenome"
placeholder="Ex.: Silva"
:error="!!formErrors.sobrenome"
:error-message="formErrors.sobrenome"
>
<template #prepend>
<q-icon name="sym_o_person" color="primary" />
</template>
</TextField>
<TextField
v-model="newUser.email"
label="E-mail"
type="email"
placeholder="Ex.: ana.silva@clipperia.com"
:error="!!formErrors.email"
:error-message="formErrors.email"
>
<template #prepend>
<q-icon name="sym_o_alternate_email" color="primary" />
</template>
</TextField>
<TextField
v-model="newUser.password"
label="Senha"
:type="showPassword ? 'text' : 'password'"
placeholder="Digite uma senha segura"
:error="!!formErrors.password"
:error-message="formErrors.password"
>
<template #prepend>
<q-icon name="sym_o_lock" color="primary" />
</template>
<template #append>
<q-btn
:icon="
showPassword ? 'sym_o_visibility_off' : 'sym_o_visibility'
"
flat
round
dense
@click="showPassword = !showPassword"
color="grey-7"
/>
</template>
</TextField>
</q-card-section>
<q-separator />
<q-card-actions class="new-user-dialog__actions">
<Button
variant="ghost"
label="Cancelar"
color="grey-7"
:disabled="submittingUser"
@click="closeNewUserDialog"
/>
<Button
label="Criar Usuário"
icon="sym_o_person_add"
:loading="submittingUser"
:disabled="submittingUser"
@click="handleCreateUser"
/>
</q-card-actions>
</q-card>
</q-dialog>
</div>
</template>
@@ -150,7 +257,7 @@ const columns = [
},
{
name: "lastAccess",
label: "Último acesso",
label: "Criado em",
align: "center",
field: "lastAccess",
},
@@ -181,6 +288,21 @@ export default {
name: "",
email: "",
},
showNewUserDialog: false,
showPassword: false,
submittingUser: false,
newUser: {
nome: "",
sobrenome: "",
email: "",
password: "",
},
formErrors: {
nome: "",
sobrenome: "",
email: "",
password: "",
},
};
},
computed: {
@@ -213,11 +335,18 @@ export default {
},
});
console.log("====================================");
console.log(content);
console.log("====================================");
this.rows = content.map((user) => ({
id: user.id,
name:
user.nome && user.sobrenome
? `${user.nome} ${user.sobrenome}`
: user.nome || user.sobrenome || "-",
email: user.email || "-",
role: this.formatRole(user.papel),
status: this.formatStatus(user.status),
lastAccess: user.criado_em || "-",
}));
this.rows = content;
this.pagination = {
...basePagination,
...nextPagination,
@@ -245,6 +374,140 @@ export default {
handleRefresh() {
this.handleSearch({ ...this.pagination });
},
formatRole(role) {
const roles = {
USUARIO: "Usuário",
EDITOR: "Editor",
ADMINISTRADOR: "Administrador",
};
return roles[role] || role;
},
formatStatus(status) {
const statuses = {
PENDENTE: "Pendente",
ATIVO: "Ativo",
SUSPENSO: "Suspenso",
EXCLUIDO: "Excluído",
};
return statuses[status] || status;
},
formatDate(dateString) {
if (!dateString) return "-";
if (dateString.includes("/")) {
return dateString;
}
const date = new Date(dateString);
const day = String(date.getDate()).padStart(2, "0");
const month = String(date.getMonth() + 1).padStart(2, "0");
const year = date.getFullYear();
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
return `${day}/${month}/${year} ${hours}:${minutes}`;
},
handleNewUser() {
this.showNewUserDialog = true;
},
closeNewUserDialog() {
this.showNewUserDialog = false;
this.showPassword = false;
this.newUser = {
nome: "",
sobrenome: "",
email: "",
password: "",
};
this.formErrors = {
nome: "",
sobrenome: "",
email: "",
password: "",
};
},
validateForm() {
let isValid = true;
this.formErrors = {
nome: "",
sobrenome: "",
email: "",
password: "",
};
if (!this.newUser.nome || this.newUser.nome.trim() === "") {
this.formErrors.nome = "Nome é obrigatório";
isValid = false;
} else if (this.newUser.nome.length > 244) {
this.formErrors.nome = "Nome deve ter no máximo 244 caracteres";
isValid = false;
}
if (!this.newUser.sobrenome || this.newUser.sobrenome.trim() === "") {
this.formErrors.sobrenome = "Sobrenome é obrigatório";
isValid = false;
} else if (this.newUser.sobrenome.length > 244) {
this.formErrors.sobrenome =
"Sobrenome deve ter no máximo 244 caracteres";
isValid = false;
}
if (!this.newUser.email || this.newUser.email.trim() === "") {
this.formErrors.email = "E-mail é obrigatório";
isValid = false;
} else if (this.newUser.email.length > 244) {
this.formErrors.email = "E-mail deve ter no máximo 244 caracteres";
isValid = false;
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.newUser.email)) {
this.formErrors.email = "E-mail inválido";
isValid = false;
}
if (!this.newUser.password || this.newUser.password.trim() === "") {
this.formErrors.password = "Senha é obrigatória";
isValid = false;
} else if (this.newUser.password.length < 6) {
this.formErrors.password = "Senha deve ter no mínimo 6 caracteres";
isValid = false;
} else if (this.newUser.password.length > 244) {
this.formErrors.password = "Senha deve ter no máximo 244 caracteres";
isValid = false;
}
return isValid;
},
async handleCreateUser() {
if (!this.validateForm()) {
return;
}
try {
this.submittingUser = true;
await API.post("/usuarios", this.newUser);
this.$q.notify({
type: "positive",
message: "Usuário criado com sucesso!",
position: "top",
});
this.closeNewUserDialog();
this.handleSearch({ ...this.pagination, page: 1 });
} catch (error) {
const errorMessage =
error.response?.data?.message ||
"Não foi possível criar o usuário. Tente novamente.";
this.$q.notify({
type: "negative",
message: errorMessage,
position: "top",
});
} finally {
this.submittingUser = false;
}
},
},
};
</script>
@@ -355,4 +618,77 @@ body.body--dark .users-page__cell-value {
display: block;
}
}
.new-user-dialog {
min-width: 500px;
max-width: 600px;
}
.new-user-dialog__header {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 16px;
padding: 24px;
}
.new-user-dialog__title {
margin: 0;
font-size: 20px;
font-weight: 700;
color: #101828;
}
.new-user-dialog__subtitle {
margin: 8px 0 0 0;
font-size: 14px;
color: #475467;
}
.new-user-dialog__form {
display: flex;
flex-direction: column;
gap: 20px;
padding: 24px;
}
.new-user-dialog__actions {
display: flex;
justify-content: flex-end;
gap: 12px;
padding: 16px 24px;
}
body.body--dark .new-user-dialog__title {
color: rgba(255, 255, 255, 0.92);
}
body.body--dark .new-user-dialog__subtitle {
color: rgba(255, 255, 255, 0.7);
}
@media (max-width: 768px) {
.new-user-dialog {
min-width: auto;
max-width: 100%;
width: 100%;
}
.new-user-dialog__header {
padding: 20px;
}
.new-user-dialog__form {
padding: 20px;
}
.new-user-dialog__actions {
flex-direction: column-reverse;
padding: 16px 20px;
}
.new-user-dialog__actions > * {
width: 100%;
}
}
</style>