monolito_djanco_poonto/src/views/UserProfileView.vue
Thaís Ferreira d5b3b23e49 versão 00
2025-02-07 20:25:52 -03:00

501 lines
11 KiB
Vue

<!-- ProfilePage.vue -->
<template>
<div class="profile-container">
<div class="profile-header">
<h1 class="profile-title">Perfil do Usuário</h1>
<p class="profile-subtitle">Gerencie suas informações pessoais</p>
</div>
<form @submit.prevent="saveProfile" class="profile-form">
<div class="profile-grid">
<!-- Coluna da Foto -->
<div class="photo-section">
<div class="profile-photo-container">
<div class="photo-wrapper">
<img :src="profileData.photoUrl || defaultPhoto" alt="Foto de Perfil" class="profile-photo">
<div class="photo-overlay">
<span class="photo-text">Alterar foto</span>
</div>
</div>
<input
type="file"
@change="handlePhotoUpload"
accept="image/*"
ref="photoInput"
class="photo-input"
>
<button type="button" @click="triggerPhotoUpload" class="upload-btn">
<i class="fas fa-camera"></i>
Alterar Foto
</button>
</div>
</div>
<!-- Coluna das Informações -->
<div class="info-section">
<!-- Seção de Informações Básicas -->
<div class="section-title">
<i class="fas fa-user"></i>
<h2 class="sub-title">Informações Básicas</h2>
</div>
<div class="form-row">
<div class="form-group">
<label>ID</label>
<input type="text" v-model="profileData.id" readonly class="form-input readonly">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label>Nome</label>
<input
type="text"
v-model="profileData.firstName"
required
class="form-input"
placeholder="Digite seu nome"
>
</div>
<div class="form-group">
<label>Sobrenome</label>
<input
type="text"
v-model="profileData.lastName"
required
class="form-input"
placeholder="Digite seu sobrenome"
>
</div>
</div>
<!-- Seção de Contato -->
<div class="section-title">
<i class="fas fa-address-card"></i>
<h2>Informações de Contato</h2>
</div>
<div class="form-row">
<div class="form-group">
<label>Email</label>
<input
type="email"
v-model="profileData.email"
required
class="form-input"
placeholder="seu@email.com"
>
</div>
<div class="form-group">
<label>Telefone</label>
<input
type="tel"
v-model="profileData.phone"
v-mask="'(##) #####-####'"
class="form-input"
placeholder="(00) 00000-0000"
>
</div>
</div>
<!-- Seção Profissional -->
<div class="section-title">
<i class="fas fa-briefcase"></i>
<h2>Informações Profissionais</h2>
</div>
<div class="form-row">
<div class="form-group">
<label>Cargo</label>
<select v-model="profileData.role" class="form-select">
<option value="" disabled>Selecione um cargo</option>
<option v-for="role in roles" :key="role.id" :value="role.id">
{{ role.name }}
</option>
</select>
</div>
<div class="form-group">
<label>Grupo</label>
<select v-model="profileData.group" class="form-select">
<option value="" disabled>Selecione um grupo</option>
<option v-for="group in groups" :key="group.id" :value="group.id">
{{ group.name }}
</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label>Permissão</label>
<select v-model="profileData.permission" class="form-select">
<option value="" disabled>Selecione uma permissão</option>
<option v-for="permission in permissions" :key="permission.id" :value="permission.id">
{{ permission.name }}
</option>
</select>
</div>
<div class="form-group">
<label>Turno</label>
<select v-model="profileData.shift" class="form-select">
<option value="" disabled>Selecione um turno</option>
<option value="morning">Manhã</option>
<option value="afternoon">Tarde</option>
<option value="night">Noite</option>
</select>
</div>
</div>
</div>
</div>
<!-- Botões de Ação -->
<div class="button-group">
<button type="button" @click="resetForm" class="cancel-btn">
<i class="fas fa-times"></i>
Cancelar
</button>
<button type="submit" class="save-btn">
<i class="fas fa-save"></i>
Salvar Alterações
</button>
</div>
</form>
</div>
</template>
<script>
export default {
name: 'ProfilePage',
data() {
return {
defaultPhoto: '/path/to/default-avatar.png',
profileData: {
id: '',
photoUrl: '',
firstName: '',
lastName: '',
email: '',
phone: '',
role: '',
group: '',
permission: '',
shift: ''
},
roles: [
{ id: 1, name: 'Funcionário' },
{ id: 2, name: 'Estagiário' },
{ id: 3, name: 'Gerente' }
],
groups: [
{ id: 1, name: 'Beta' },
{ id: 2, name: 'Alfa' },
{ id: 3, name: 'Omega' }
],
permissions: [
{ id: 1, name: 'Administrador' },
{ id: 2, name: 'Editor' },
{ id: 3, name: 'Visualizador' }
]
}
},
methods: {
async loadProfile() {
try {
const response = await fetch('/api/profile');
const data = await response.json();
this.profileData = { ...data };
} catch (error) {
console.error('Erro ao carregar perfil:', error);
}
},
triggerPhotoUpload() {
this.$refs.photoInput.click();
},
handlePhotoUpload(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
this.profileData.photoUrl = e.target.result;
};
reader.readAsDataURL(file);
}
},
async saveProfile() {
try {
await fetch('/api/profile', {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.profileData)
});
this.$emit('profile-updated');
this.showNotification('Perfil atualizado com sucesso!', 'success');
} catch (error) {
console.error('Erro ao salvar perfil:', error);
this.showNotification('Erro ao salvar perfil. Tente novamente.', 'error');
}
},
resetForm() {
this.loadProfile();
},
showNotification(message,type) {
// Implementar sistema de notificação de sua preferência
alert(message);
}
},
created() {
this.loadProfile();
}
}
</script>
<style scoped>
.profile-container {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
}
.profile-header {
text-align: center;
margin-bottom: 40px;
}
.profile-title {
font-size: 2.5rem;
color: #2c3e50;
margin-bottom: 10px;
}
.profile-subtitle {
color: #7f8c8d;
font-size: 1.1rem;
}
.profile-form {
background: #fff;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.profile-grid {
display: grid;
grid-template-columns: 300px 1fr;
gap: 30px;
}
.photo-section {
padding: 30px;
background: #f8f9fa;
border-right: 1px solid #eee;
}
.info-section {
padding: 30px;
}
.photo-wrapper {
position: relative;
width: 200px;
height: 200px;
margin: 0 auto 20px;
border-radius: 50%;
overflow: hidden;
cursor: pointer;
}
.profile-photo {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.photo-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.photo-text {
color: white;
font-size: 0.9rem;
font-weight: 500;
}
.photo-wrapper:hover .photo-overlay {
opacity: 1;
}
.photo-wrapper:hover .profile-photo {
transform: scale(1.1);
}
.section-title {
display: flex;
align-items: center;
gap: 10px;
margin: 30px 0 20px;
padding-bottom: 10px;
border-bottom: 2px solid #e1e8ed;
}
.section-title i {
color: #3498db;
font-size: 1.2rem;
}
.section-title h2 {
font-size: 1.2rem;
color: #2c3e50;
margin: 0;
}
.form-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
.form-group {
margin-bottom: 0;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #34495e;
}
.form-input,
.form-select {
width: 100%;
padding: 12px;
border: 2px solid #e1e8ed;
border-radius: 8px;
font-size: 14px;
transition: all 0.3s ease;
}
.form-input:focus,
.form-select:focus {
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
outline: none;
}
.form-input.readonly {
background-color: #f8f9fa;
cursor: not-allowed;
color: #7f8c8d;
}
.photo-input {
display: none;
}
.upload-btn {
width: 100%;
padding: 12px;
background: #3498db;
color: white;
border: none;
border-radius: 8px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
transition: background 0.3s ease;
}
.upload-btn:hover {
background: #2980b9;
}
.button-group {
display: flex;
gap: 15px;
justify-content: flex-end;
padding: 30px;
background: #f8f9fa;
border-top: 1px solid #eee;
}
.save-btn,
.cancel-btn {
padding: 12px 24px;
border: none;
border-radius: 8px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
}
.save-btn {
background: #2ecc71;
color: white;
}
.save-btn:hover {
background: #27ae60;
transform: translateY(-1px);
}
.cancel-btn {
background: #e74c3c;
color: white;
}
.cancel-btn:hover {
background: #c0392b;
transform: translateY(-1px);
}
@media (max-width: 768px) {
.profile-grid {
grid-template-columns: 1fr;
}
.photo-section {
border-right: none;
border-bottom: 1px solid #eee;
}
.form-row {
grid-template-columns: 1fr;
}
.button-group {
flex-direction: column-reverse;
}
.save-btn,
.cancel-btn {
width: 100%;
justify-content: center;
}
}
</style>