feat:Implementar transição em slide para a tela de login com validação aprimorada e notificações via snackbar
- Adicionado componente de slider para transição entre as telas de introdução e login. - Validação aprimorada dos campos de e-mail e senha, com mensagens de erro.. - Substituídos os componentes do Vuetify por elementos HTML padrão nos campos de entrada. - IIntroduzido snackbar para exibição de mensagens de erro durante tentativas de login - Estilos atualizados para melhor responsividade e apelo visual.
This commit is contained in:
parent
bb33d0b20b
commit
d60af1cffc
14
package-lock.json
generated
14
package-lock.json
generated
@ -9,10 +9,12 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "^7.4.47",
|
"@mdi/font": "^7.4.47",
|
||||||
|
"animate.css": "^4.1.1",
|
||||||
"apexcharts": "^3.54.1",
|
"apexcharts": "^3.54.1",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
"dashboard": "file:",
|
"dashboard": "file:",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"gsap": "^3.12.7",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"npm-check-updates": "^17.1.11",
|
"npm-check-updates": "^17.1.11",
|
||||||
"pdf-parse": "^1.1.1",
|
"pdf-parse": "^1.1.1",
|
||||||
@ -818,6 +820,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
|
||||||
"integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
|
"integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/animate.css": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/apexcharts": {
|
"node_modules/apexcharts": {
|
||||||
"version": "3.54.1",
|
"version": "3.54.1",
|
||||||
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.54.1.tgz",
|
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.54.1.tgz",
|
||||||
@ -992,6 +1000,12 @@
|
|||||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/gsap": {
|
||||||
|
"version": "3.12.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/gsap/-/gsap-3.12.7.tgz",
|
||||||
|
"integrity": "sha512-V4GsyVamhmKefvcAKaoy0h6si0xX7ogwBoBSs2CTJwt7luW0oZzC0LhdkyuKV8PJAXr7Yaj8pMjCKD4GJ+eEMg==",
|
||||||
|
"license": "Standard 'no charge' license: https://gsap.com/standard-license. Club GSAP members get more: https://gsap.com/licensing/. Why GreenSock doesn't employ an MIT license: https://gsap.com/why-license/"
|
||||||
|
},
|
||||||
"node_modules/jwt-decode": {
|
"node_modules/jwt-decode": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
|
||||||
|
|||||||
@ -10,10 +10,12 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "^7.4.47",
|
"@mdi/font": "^7.4.47",
|
||||||
|
"animate.css": "^4.1.1",
|
||||||
"apexcharts": "^3.54.1",
|
"apexcharts": "^3.54.1",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
"dashboard": "file:",
|
"dashboard": "file:",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"gsap": "^3.12.7",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"npm-check-updates": "^17.1.11",
|
"npm-check-updates": "^17.1.11",
|
||||||
"pdf-parse": "^1.1.1",
|
"pdf-parse": "^1.1.1",
|
||||||
|
|||||||
@ -93,7 +93,9 @@ const loadHolidayData = async () => {
|
|||||||
estado: holidayData.estado || '',
|
estado: holidayData.estado || '',
|
||||||
municipio: holidayData.municipio || '',
|
municipio: holidayData.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,
|
||||||
|
adicional_he: Number(localHoliday.value.adicional_he), // Garante tipo numérico
|
||||||
|
recorrente: localHoliday.value.recorrente
|
||||||
};
|
};
|
||||||
} else if (props.holiday) {
|
} else if (props.holiday) {
|
||||||
// Fallback para os dados recebidos via props
|
// Fallback para os dados recebidos via props
|
||||||
|
|||||||
@ -19,10 +19,34 @@
|
|||||||
:rules="[v => !!v || 'Data é 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" :rules="[rules.required]" clearable required/>
|
<v-text-field v-model="localHoliday.municipio" label="Municipio" type="municipio" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
<v-text-field v-model="localHoliday.estado" label="Estado" type="estado" clearable :rules="[rules.required]" required/>
|
<v-text-field v-model="localHoliday.estado" label="Estado" type="estado" clearable />
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-switch
|
||||||
|
v-model="localHoliday.recorrente"
|
||||||
|
label="Feriado Recorrente (Anual)"
|
||||||
|
color="primary"
|
||||||
|
:true-value="true"
|
||||||
|
:false-value="false"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-text-field
|
||||||
|
v-model.number="localHoliday.adicional_he"
|
||||||
|
label="Adicional de HE (%) *"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
:rules="[
|
||||||
|
v => v !== null && v !== undefined || 'Campo obrigatório',
|
||||||
|
v => (v >= 0 && v <= 100) || 'Valor entre 0 e 100'
|
||||||
|
]"
|
||||||
|
required
|
||||||
|
@input="form?.validate()"
|
||||||
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
@ -30,8 +54,13 @@
|
|||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn text color="blue-darken-1" @click="$emit('cancel')">Cancelar</v-btn>
|
<v-btn text color="blue-darken-1" @click="$emit('cancel')">Cancelar</v-btn>
|
||||||
<v-btn text class="text-white salvar-btn" :disabled="!formValid"
|
<v-btn
|
||||||
@click="handleSave" :loading="holidayStore.loading">
|
text
|
||||||
|
class="text-white salvar-btn"
|
||||||
|
:disabled="!formValid"
|
||||||
|
@click="handleSave"
|
||||||
|
:loading="holidayStore.loading"
|
||||||
|
>
|
||||||
Salvar
|
Salvar
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
@ -64,6 +93,8 @@ const defaultHoliday = {
|
|||||||
date: '',
|
date: '',
|
||||||
estado: '',
|
estado: '',
|
||||||
municipio: '',
|
municipio: '',
|
||||||
|
recorrente: true,
|
||||||
|
adicional_he: 0,
|
||||||
parent_id: authStore.userId,
|
parent_id: authStore.userId,
|
||||||
service_instance_id: authStore.service_instance_id || 2
|
service_instance_id: authStore.service_instance_id || 2
|
||||||
};
|
};
|
||||||
@ -116,25 +147,26 @@ const closeModal = () => {
|
|||||||
|
|
||||||
// Salvar o novo feriado
|
// Salvar o novo feriado
|
||||||
const handleSave = async (event) => {
|
const handleSave = async (event) => {
|
||||||
if(form.value.validate()){
|
event.preventDefault();
|
||||||
event.preventDefault(); // Impede o comportamento padrão do botão
|
|
||||||
|
// Valida apenas o formulário (sem verificações extras)
|
||||||
|
const { valid } = await form.value.validate();
|
||||||
|
|
||||||
|
if (valid) { // ⚠️ Só depende da validação do formulário
|
||||||
try {
|
try {
|
||||||
const holidayData = {
|
await holidayStore.createHoliday({
|
||||||
...localHoliday.value,
|
...localHoliday.value,
|
||||||
parent_id: authStore.userId,
|
parent_id: authStore.userId,
|
||||||
service_instance_id: authStore.service_instance_id || 2
|
service_instance_id: authStore.service_instance_id
|
||||||
};
|
});
|
||||||
|
|
||||||
console.log('Criando novo feriado:', holidayData);
|
emit('save');
|
||||||
|
|
||||||
await holidayStore.createHoliday(holidayData);
|
|
||||||
|
|
||||||
emit('save', holidayData);
|
|
||||||
emit('update:modalValue', false);
|
emit('update:modalValue', false);
|
||||||
resetLocalHoliday();
|
resetLocalHoliday();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro ao criar feriado:', error);
|
console.error('Erro ao criar feriado:', error);
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inicialização do componente
|
// Inicialização do componente
|
||||||
|
|||||||
@ -16,8 +16,19 @@ import Holiday from '../views/Holiday.vue'
|
|||||||
import Company from '../views/Company.vue'
|
import Company from '../views/Company.vue'
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{ path: '/', redirect: '/login' },
|
{
|
||||||
{ path: '/login', component: Login },
|
path: '/',
|
||||||
|
redirect: '/login'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/login',
|
||||||
|
name: 'login',
|
||||||
|
component: Login,
|
||||||
|
meta: {
|
||||||
|
transition: 'slide',
|
||||||
|
requiresGuest: true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/dashboard',
|
path: '/dashboard',
|
||||||
component: Dashboard,
|
component: Dashboard,
|
||||||
|
|||||||
@ -102,7 +102,19 @@ export const useHolidayStore = defineStore('holidays', {
|
|||||||
this.error = null;
|
this.error = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await api.post(url, holiday, {
|
// Garantindo que o objeto holiday tem todos os campos necessários
|
||||||
|
const holidayData = {
|
||||||
|
name: holiday.name,
|
||||||
|
date: holiday.date,
|
||||||
|
estado: holiday.estado || '',
|
||||||
|
municipio: holiday.municipio || '',
|
||||||
|
recorrente: holiday.recorrente !== undefined ? holiday.recorrente : true,
|
||||||
|
adicional_he: holiday.adicional_he !== undefined ? holiday.adicional_he : 0,
|
||||||
|
type: holiday.type || '',
|
||||||
|
service_instance_id: useAuthStore().service_instance_id
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await api.post(url, holidayData, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
@ -112,7 +124,7 @@ export const useHolidayStore = defineStore('holidays', {
|
|||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.error = error?.response?.data?.message || error.message || 'Erro ao criar feriado';
|
this.error = error?.response?.data?.message || error.message || 'Erro ao criar feriado';
|
||||||
console.error('Erro ao criar turno', error);
|
console.error('Erro ao criar feriado', error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
@ -133,6 +145,7 @@ export const useHolidayStore = defineStore('holidays', {
|
|||||||
date: holiday.date,
|
date: holiday.date,
|
||||||
estado: holiday.estado,
|
estado: holiday.estado,
|
||||||
municipio: holiday.municipio,
|
municipio: holiday.municipio,
|
||||||
|
type: holiday.type || '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const index = this.holidays.findIndex((s) => s.id === id);
|
const index = this.holidays.findIndex((s) => s.id === id);
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { defineStore } from 'pinia';
|
|||||||
import api from '../services/api';
|
import api from '../services/api';
|
||||||
import router from '../routes/router';
|
import router from '../routes/router';
|
||||||
import { useAuthStore } from './auth';
|
import { useAuthStore } from './auth';
|
||||||
import { ca } from 'date-fns/locale';
|
|
||||||
|
|
||||||
export const useShiftStore = defineStore('shifts', {
|
export const useShiftStore = defineStore('shifts', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
|
|||||||
@ -1,79 +1,98 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container class="tab">
|
<div class="holiday-management">
|
||||||
<div class="image-wrapper">
|
<!-- Header da página -->
|
||||||
<img src="/image_b.png" alt="Ilustração acima da tabela" class="top-image" />
|
<div class="header-container">
|
||||||
|
<div class="header-left">
|
||||||
|
<div class="icon-wrapper">
|
||||||
|
<v-icon color="primary" size="32">mdi-clock-outline</v-icon>
|
||||||
</div>
|
</div>
|
||||||
<v-card>
|
<div class="header-title">
|
||||||
<v-toolbar class="info" flat>
|
<h1>Sistema de Ponto | Admin</h1>
|
||||||
<v-toolbar-title class="title"> Feriados</v-toolbar-title>
|
</div>
|
||||||
<v-spacer></v-spacer>
|
</div>
|
||||||
|
<div class="header-right">
|
||||||
<!-- Barra de Pesquisa com Ícone -->
|
<v-btn variant="text" prepend-icon="mdi-arrow-left" class="back-button" to="/dashboard">
|
||||||
<v-text-field
|
Voltar para Dashboard
|
||||||
v-model="filters.holiday"
|
|
||||||
:loading="loading.holiday"
|
|
||||||
prepend-inner-icon="mdi-magnify"
|
|
||||||
density="compact"
|
|
||||||
variant="outlined"
|
|
||||||
label="Pesquisar feriado"
|
|
||||||
hide-details
|
|
||||||
class="mx-2"
|
|
||||||
style="max-width: 250px;"
|
|
||||||
@update:model-value="filterholidays"
|
|
||||||
clearable
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Botão para exportar CSV
|
|
||||||
<v-btn
|
|
||||||
color="primary"
|
|
||||||
class="ml-2"
|
|
||||||
prepend-icon="mdi-file-export"
|
|
||||||
:loading="loading.export"
|
|
||||||
variant="tonal"
|
|
||||||
@click="exportToCSV"
|
|
||||||
>
|
|
||||||
Exportar
|
|
||||||
</v-btn>-->
|
|
||||||
<!-- Botão para adicionar usuário -->
|
|
||||||
<v-btn
|
|
||||||
color="primary"
|
|
||||||
class="ml-2"
|
|
||||||
prepend-icon="mdi-plus"
|
|
||||||
variant="elevated"
|
|
||||||
@click="openCreateModal"
|
|
||||||
>
|
|
||||||
Adicionar Feriado
|
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-toolbar>
|
<v-btn color="primary" prepend-icon="mdi-plus" class="new-holiday-btn" @click="openCreateModal">
|
||||||
|
Novo Feriado
|
||||||
|
</v-btn>
|
||||||
|
<v-badge dot color="error" class="notification-badge">
|
||||||
|
<v-icon>mdi-bell</v-icon>
|
||||||
|
</v-badge>
|
||||||
|
<div class="admin-profile">
|
||||||
|
<v-avatar class="mr-2" color="primary" size="40">
|
||||||
|
<v-img src="/api/placeholder/40/40" alt="Administrador"></v-img>
|
||||||
|
</v-avatar>
|
||||||
|
<div class="admin-info">
|
||||||
|
<span class="admin-name">Administrador</span>
|
||||||
|
<span class="admin-role">Gestor</span>
|
||||||
|
</div>
|
||||||
|
<v-icon>mdi-chevron-down</v-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Tabela de Dados -->
|
<!-- Título e descrição da seção -->
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>Feriados e Dias Especiais</h2>
|
||||||
|
<p class="section-description">Gerencie os feriados e dias com tratamento especial</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Card principal -->
|
||||||
|
<v-card class="main-card" elevation="1">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3>Lista de Feriados</h3>
|
||||||
|
<p class="card-description">Gerencie os feriados e dias especiais do sistema</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tabela de feriados -->
|
||||||
<v-data-table
|
<v-data-table
|
||||||
class="dados"
|
|
||||||
:headers="headers.holidays"
|
:headers="headers.holidays"
|
||||||
:items="filteredholidays"
|
:items="filteredholidays"
|
||||||
:search="filters.holiday"
|
:search="filters.holiday"
|
||||||
:loading="loading.holidays"
|
:loading="loading.holidays"
|
||||||
:items-per-page="itemsPerPage"
|
:items-per-page="itemsPerPage"
|
||||||
:page.sync="page"
|
:page.sync="page"
|
||||||
|
class="holiday-table"
|
||||||
>
|
>
|
||||||
|
<!-- Slot para campo tipo (adicional) -->
|
||||||
|
<template v-slot:item.type="{ item }">
|
||||||
|
<v-chip
|
||||||
|
:color="getTypeColor(item.type)"
|
||||||
|
text-color="white"
|
||||||
|
size="small"
|
||||||
|
class="type-chip"
|
||||||
|
>
|
||||||
|
{{ item.type || 'Nacional' }}
|
||||||
|
</v-chip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Slot para recorrente -->
|
||||||
|
<template v-slot:item.recorrente="{ item }">
|
||||||
|
<span>{{ item.recorrente ? 'Sim' : 'Não' }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Slot para adicional_he -->
|
||||||
|
<template v-slot:item.adicional_he="{ item }">
|
||||||
|
{{ item.adicional_he }}%
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Slot para ações -->
|
||||||
<template v-slot:item.actions="{ item }">
|
<template v-slot:item.actions="{ item }">
|
||||||
<v-icon
|
<div class="action-buttons">
|
||||||
size="small"
|
<v-btn icon color="primary" size="small" @click="openEditPage('holiday', item)">
|
||||||
class="mr-2"
|
<v-icon>mdi-pencil</v-icon>
|
||||||
@click="openEditPage('holiday', item)"
|
</v-btn>
|
||||||
>
|
<v-btn icon color="error" size="small" @click="confirmDelete('holiday', item)">
|
||||||
mdi-pencil
|
<v-icon>mdi-delete</v-icon>
|
||||||
</v-icon>
|
</v-btn>
|
||||||
<v-icon
|
</div>
|
||||||
size="small"
|
|
||||||
@click="confirmDelete('holiday', item)"
|
|
||||||
>
|
|
||||||
mdi-delete
|
|
||||||
</v-icon>
|
|
||||||
</template>
|
</template>
|
||||||
</v-data-table>
|
</v-data-table>
|
||||||
</v-card>
|
</v-card>
|
||||||
<!-- Diálogo de Usuário (Novo/Edição) -->
|
|
||||||
|
<!-- Modais existentes -->
|
||||||
<holidayModal
|
<holidayModal
|
||||||
v-model="dialogs.holiday"
|
v-model="dialogs.holiday"
|
||||||
:isEditMode="isEditing"
|
:isEditMode="isEditing"
|
||||||
@ -81,11 +100,13 @@
|
|||||||
@save="submitForm"
|
@save="submitForm"
|
||||||
@cancel="closeHolidayModal"
|
@cancel="closeHolidayModal"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CreateHolidayModal
|
<CreateHolidayModal
|
||||||
v-model="dialogs.createholiday"
|
v-model="dialogs.createholiday"
|
||||||
@save="SubmitFormCreate"
|
@save="SubmitFormCreate"
|
||||||
@cancel="closeCreateModal"
|
@cancel="closeCreateModal"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 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>
|
||||||
@ -94,8 +115,8 @@
|
|||||||
</v-card-title>
|
</v-card-title>
|
||||||
|
|
||||||
<v-card-text class="pt-4">
|
<v-card-text class="pt-4">
|
||||||
<p v-if="itemToDelete && itemToDelete.holidayname">
|
<p v-if="itemToDelete && itemToDelete.name">
|
||||||
Tem certeza que deseja excluir <strong>{{ itemToDelete.holidayname }}</strong>?
|
Tem certeza que deseja excluir <strong>{{ itemToDelete.name }}</strong>?
|
||||||
Esta ação não pode ser desfeita.
|
Esta ação não pode ser desfeita.
|
||||||
</p>
|
</p>
|
||||||
<p v-else>
|
<p v-else>
|
||||||
@ -135,7 +156,7 @@
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
</v-snackbar>
|
</v-snackbar>
|
||||||
</v-container>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -153,13 +174,10 @@
|
|||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
//const camera = computed(() => cameraStore.camera);
|
|
||||||
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 itemToDelete = ref(null);
|
const itemToDelete = ref(null);
|
||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
const itemsPerPage = ref(10);
|
const itemsPerPage = ref(10);
|
||||||
@ -179,7 +197,6 @@
|
|||||||
createholiday: false,
|
createholiday: false,
|
||||||
delete: false
|
delete: false
|
||||||
});
|
});
|
||||||
const editMode = ref(false)
|
|
||||||
|
|
||||||
// Filtros
|
// Filtros
|
||||||
const filters = ref({
|
const filters = ref({
|
||||||
@ -187,7 +204,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 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
|
||||||
const holidays = ref([])
|
const holidays = ref([]);
|
||||||
|
|
||||||
// Formulários
|
// Formulários
|
||||||
const forms = ref({
|
const forms = ref({
|
||||||
@ -195,19 +212,23 @@
|
|||||||
id: null,
|
id: null,
|
||||||
name: '',
|
name: '',
|
||||||
date: '',
|
date: '',
|
||||||
|
type: 'Nacional', // Adicionado campo tipo
|
||||||
estado: '',
|
estado: '',
|
||||||
municipio: '',
|
municipio: '',
|
||||||
|
recorrente: true,
|
||||||
|
adicional_he: 0,
|
||||||
loading: false
|
loading: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Headers para as tabelas
|
// Headers para as tabelas (atualizados para o novo layout)
|
||||||
const headers = ref({
|
const headers = ref({
|
||||||
holidays: [
|
holidays: [
|
||||||
{ title: 'ID', key: 'id' },
|
{ title: 'Nome', key: 'name', align: 'start' },
|
||||||
{ title: 'Nome feriado', key: 'name' },
|
{ title: 'Data', key: 'date', align: 'start' },
|
||||||
{ title: 'Data', key: 'date' },
|
{ title: 'Tipo', key: 'type', align: 'start' }, // Novo campo tipo
|
||||||
//{ title: 'Permissão', key: 'permissao' },
|
{ title: 'Recorrente', key: 'recorrente', align: 'start' },
|
||||||
|
{ title: 'Adicional H.E.', key: 'adicional_he', align: 'start' },
|
||||||
{ title: 'Ações', key: 'actions', sortable: false, align: 'end' }
|
{ title: 'Ações', key: 'actions', sortable: false, align: 'end' }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
@ -219,121 +240,67 @@
|
|||||||
color: 'success'
|
color: 'success'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Método para determinar a cor do chip baseado no tipo
|
||||||
|
const getTypeColor = (type) => {
|
||||||
|
const typeColors = {
|
||||||
|
'Nacional': 'primary',
|
||||||
|
'Estadual': 'success',
|
||||||
|
'Municipal': 'info',
|
||||||
|
'Ponto Facultativo': 'warning'
|
||||||
|
};
|
||||||
|
return typeColors[type] || 'primary';
|
||||||
|
};
|
||||||
|
|
||||||
// Computed properties
|
// Computed properties
|
||||||
const filteredholidays = computed(() => {
|
const filteredholidays = computed(() => {
|
||||||
const filtered = holidays.value.filter(holiday => !holiday.deleted);
|
return holidays.value.filter(holiday => {
|
||||||
return filtered.filter(holiday => {
|
return (
|
||||||
const holidayName = holiday.name || ''; // Garantir que seja uma string vazia se undefined
|
holiday.name.toLowerCase().includes(filters.value.holiday.toLowerCase()) &&
|
||||||
return holidayName.toLowerCase().includes(filters.value.holiday.toLowerCase())
|
!holiday.deleted
|
||||||
|
)
|
||||||
}).map(holiday => ({
|
}).map(holiday => ({
|
||||||
...holiday,
|
...holiday,
|
||||||
|
date: formatDate(holiday.date),
|
||||||
created_at: holiday.created_at ? new Date(holiday.created_at).toLocaleString() : '-'
|
created_at: holiday.created_at ? new Date(holiday.created_at).toLocaleString() : '-'
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
// Função auxiliar para formatar data
|
||||||
// Função para exportar para CSV
|
function formatDate(dateString) {
|
||||||
const exportToCSV = () => {
|
if (!dateString) return '';
|
||||||
if (filteredcameras.value.length === 0) {
|
|
||||||
showNotification('Não há dados para exportar', 'warning');
|
// Verificar se a data tem ano ou é apenas DD/MM
|
||||||
return;
|
if (dateString.includes('/') && dateString.split('/').length === 2) {
|
||||||
|
return dateString; // Já está no formato DD/MM
|
||||||
}
|
}
|
||||||
|
|
||||||
loading.value.export = true;
|
const options = { day: '2-digit', month: '2-digit' };
|
||||||
try {
|
try {
|
||||||
// Preparar dados: filtrar apenas os campos que queremos exportar
|
// Se tem ano completo, formatar como DD/MM/YYYY
|
||||||
const dataToExport = filteredcameras.value.map(camera => ({
|
if (dateString.includes('/') && dateString.split('/').length === 3) {
|
||||||
ID: camera.id,
|
return dateString;
|
||||||
Nome: camera.name,
|
|
||||||
Status: camera.status,
|
|
||||||
Descrição: camera.description,
|
|
||||||
Url: camera.url,
|
|
||||||
//Phone: camera.phone,
|
|
||||||
//Image: camera.profile_image,
|
|
||||||
//Contrato: camera.contrato,
|
|
||||||
//Grupo: camera.grupo,
|
|
||||||
//Permissao: camera.permissao
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Gerar cabeçalho do CSV
|
|
||||||
const headers = Object.keys(dataToExport[0]);
|
|
||||||
|
|
||||||
// Converter dados para linhas CSV
|
|
||||||
const csvContent = [
|
|
||||||
headers.join(','), // Cabeçalho
|
|
||||||
...dataToExport.map(row =>
|
|
||||||
headers.map(field => {
|
|
||||||
// Escapar strings que contêm vírgulas com aspas
|
|
||||||
const value = String(row[field]).replace(/"/g, '""');
|
|
||||||
return /[,"]/.test(value) ? `"${value}"` : value;
|
|
||||||
}).join(',')
|
|
||||||
)
|
|
||||||
].join('\n');
|
|
||||||
|
|
||||||
// Criar blob e link para download
|
|
||||||
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.setAttribute('href', url);
|
|
||||||
link.setAttribute('download', 'usuarios_export.csv');
|
|
||||||
link.style.visibility = 'hidden';
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
|
|
||||||
showNotification('Dados exportados com sucesso!');
|
|
||||||
} catch (error) {
|
|
||||||
showNotification('Erro ao exportar dados', 'error');
|
|
||||||
console.error('Error exporting data:', error);
|
|
||||||
} finally {
|
|
||||||
loading.value.export = false;
|
|
||||||
}
|
}
|
||||||
};
|
return new Date(dateString).toLocaleDateString('pt-BR', options);
|
||||||
*/
|
} catch (e) {
|
||||||
|
return dateString; // Retorna a string original se falhar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Métodos
|
// Métodos
|
||||||
const openDialog = (type, action, item = null) => {
|
|
||||||
if (!dialogs.value[type]) {
|
|
||||||
dialogs.value[type] = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!forms.value[type]) {
|
|
||||||
forms.value[type] = {
|
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
date: '',
|
|
||||||
loading: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
editMode.value = action === 'edit'
|
|
||||||
|
|
||||||
if (type === 'holiday') {
|
|
||||||
if (action === 'edit') {
|
|
||||||
forms.value.holiday = {
|
|
||||||
...item,
|
|
||||||
loading: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Agora sim abre o modal depois que tudo tá definido
|
|
||||||
dialogs.value.holiday = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Abrir modal de criação
|
|
||||||
const openCreateModal = () => {
|
const openCreateModal = () => {
|
||||||
isCreateModalOpen.value = true;
|
dialogs.value.createholiday = true;
|
||||||
dialogs.value.createholiday = true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeHolidayModal = () => {
|
const closeHolidayModal = () => {
|
||||||
dialogs.value.holiday = false;
|
dialogs.value.holiday = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeCreateModal = () => {
|
const closeCreateModal = () => {
|
||||||
dialogs.value.createholiday = false;
|
dialogs.value.createholiday = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
// 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 holidayData = { ...item };
|
const holidayData = { ...item };
|
||||||
@ -343,26 +310,21 @@
|
|||||||
id: holidayData.id,
|
id: holidayData.id,
|
||||||
name: holidayData.name || '',
|
name: holidayData.name || '',
|
||||||
date: holidayData.date || '',
|
date: holidayData.date || '',
|
||||||
|
type: holidayData.type || 'Nacional', // Adicionado campo tipo
|
||||||
estado: holidayData.estado || '',
|
estado: holidayData.estado || '',
|
||||||
municipio: holidayData.municipio || '',
|
municipio: holidayData.municipio || '',
|
||||||
|
recorrente: holidayData.recorrente !== undefined ? holidayData.recorrente : true,
|
||||||
|
adicional_he: holidayData.adicional_he !== undefined ? holidayData.adicional_he : 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Definir modo de edição e abrir o diálogo
|
// Definir modo de edição e abrir o diálogo
|
||||||
isEditing.value = true;
|
isEditing.value = true;
|
||||||
dialogs.value[type] = true;
|
dialogs.value[type] = true;
|
||||||
selectedholiday.value = null; // Remover a seleção do usuário
|
selectedholiday.value = null;
|
||||||
};
|
|
||||||
|
|
||||||
const handleholidayUpdated = (updatedholiday) => {
|
|
||||||
const index = holidays.value.findIndex(holiday => holiday.id === updatedholiday.id);
|
|
||||||
if (index !== -1) {
|
|
||||||
holidays.value[index] = updatedholiday;
|
|
||||||
}
|
|
||||||
showNotification('Feriado atualizado com sucesso!');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirmDelete = (type, item) => {
|
const confirmDelete = (type, item) => {
|
||||||
console.log("Item recebido para exclusão:", item); // Depuração
|
console.log("Item recebido para exclusão:", item);
|
||||||
|
|
||||||
if (!item || !item.id) {
|
if (!item || !item.id) {
|
||||||
console.error("Erro: Item inválido para exclusão.", item);
|
console.error("Erro: Item inválido para exclusão.", item);
|
||||||
@ -373,9 +335,7 @@
|
|||||||
// Armazena explicitamente o item completo
|
// Armazena explicitamente o item completo
|
||||||
itemToDelete.value = {...item};
|
itemToDelete.value = {...item};
|
||||||
|
|
||||||
// Verifica se o itemToDelete foi definido corretamente
|
|
||||||
console.log("itemToDelete definido como:", itemToDelete.value);
|
console.log("itemToDelete definido como:", itemToDelete.value);
|
||||||
|
|
||||||
dialogs.value.delete = true;
|
dialogs.value.delete = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -394,7 +354,6 @@
|
|||||||
await holidayStore.deleteHoliday(holidayId);
|
await holidayStore.deleteHoliday(holidayId);
|
||||||
|
|
||||||
// Remover o item diretamente da lista local
|
// Remover o item diretamente da lista local
|
||||||
// Esta é uma abordagem mais direta e imediata
|
|
||||||
holidays.value = holidays.value.filter(holiday => holiday.id !== holidayId);
|
holidays.value = holidays.value.filter(holiday => holiday.id !== holidayId);
|
||||||
console.log("Lista atualizada após exclusão:", holidays.value);
|
console.log("Lista atualizada após exclusão:", holidays.value);
|
||||||
|
|
||||||
@ -417,10 +376,6 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const filterholidays = () => {
|
|
||||||
// O filtro já é realizado automaticamente por meio do computed property filteredholidays
|
|
||||||
};
|
|
||||||
|
|
||||||
const submitForm = async (holidayData) => {
|
const submitForm = async (holidayData) => {
|
||||||
loading.value.submit = true;
|
loading.value.submit = true;
|
||||||
try {
|
try {
|
||||||
@ -440,12 +395,12 @@
|
|||||||
loading.value.submit = false;
|
loading.value.submit = false;
|
||||||
dialogs.value.holiday = false;
|
dialogs.value.holiday = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const SubmitFormCreate = async (holidayData) => {
|
const SubmitFormCreate = async (holidayData) => {
|
||||||
loading.value.submit = true;
|
loading.value.submit = true;
|
||||||
try {
|
try {
|
||||||
//const newItem = await holidayStore.createHoliday(holidayData);
|
const newItem = await holidayStore.createHoliday(holidayData);
|
||||||
holidays.value.push(newItem);
|
holidays.value.push(newItem);
|
||||||
showNotification('Feriado cadastrado com sucesso!');
|
showNotification('Feriado cadastrado com sucesso!');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -460,14 +415,15 @@
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
loading.value.holidays = true;
|
loading.value.holidays = true;
|
||||||
console.log('cheguei aqui')
|
|
||||||
const holidaysData = await holidayStore.fetchHolidays();
|
const holidaysData = await holidayStore.fetchHolidays();
|
||||||
holidays.value = holidaysData;
|
|
||||||
|
|
||||||
console.log("Dados recebidos da API:", holidaysData);
|
// Adicionar tipo para os dados existentes
|
||||||
|
holidays.value = holidaysData.map(holiday => ({
|
||||||
|
...holiday,
|
||||||
|
type: holiday.type || 'Nacional' // Adicionar campo tipo se não existir
|
||||||
|
}));
|
||||||
|
|
||||||
// Garanta que os dados já estão filtrados (usuários deletados removidos)
|
console.log("Dados recebidos da API:", holidays.value);
|
||||||
//holidays.value = holidaysData.filter(holiday => !holiday.deleted);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showNotification('Erro ao carregar dados da API', 'error');
|
showNotification('Erro ao carregar dados da API', 'error');
|
||||||
console.error('Error fetching feriados:', error);
|
console.error('Error fetching feriados:', error);
|
||||||
@ -493,10 +449,9 @@
|
|||||||
|
|
||||||
// Computed
|
// Computed
|
||||||
filteredholidays,
|
filteredholidays,
|
||||||
filterholidays,
|
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
openDialog,
|
getTypeColor,
|
||||||
confirmDelete,
|
confirmDelete,
|
||||||
submitForm,
|
submitForm,
|
||||||
SubmitFormCreate,
|
SubmitFormCreate,
|
||||||
@ -505,44 +460,183 @@
|
|||||||
openCreateModal,
|
openCreateModal,
|
||||||
closeHolidayModal,
|
closeHolidayModal,
|
||||||
closeCreateModal,
|
closeCreateModal,
|
||||||
// filtercameras,
|
showNotification
|
||||||
//exportToCSV,
|
|
||||||
handleholidayUpdated
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.image-wrapper {
|
.holiday-management {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
font-family: Roboto, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo do cabeçalho */
|
||||||
|
.header-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end; /* ou center, se quiser centralizar */
|
justify-content: space-between;
|
||||||
margin-bottom: 16px;
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 0 0 20px 0;
|
||||||
|
border-bottom: 1px solid #eaecef;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-image {
|
.header-left {
|
||||||
max-width: 180px;
|
display: flex;
|
||||||
height: auto;
|
align-items: center;
|
||||||
}
|
|
||||||
.info{
|
|
||||||
color: rgb(0, 0, 0);
|
|
||||||
background-color: rgba(76,201,240);
|
|
||||||
background: linear-gradient(145deg, #eeeded, #ffffff);
|
|
||||||
box-shadow: 20px 20px 60px #d9d9d9,
|
|
||||||
-20px -20px 60px #ffffff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dados{
|
.icon-wrapper {
|
||||||
font-size: 17px;
|
background-color: #e3f2fd;
|
||||||
color: rgb(0, 0, 0);
|
border-radius: 8px;
|
||||||
background-color: rgb(0, 0, 0);
|
padding: 12px;
|
||||||
background: linear-gradient(145deg, #eeeded, #ffffff);
|
margin-right: 12px;
|
||||||
box-shadow: 20px 20px 60px #d9d9d9,
|
|
||||||
-20px -20px 60px #ffffff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.header-title h1 {
|
||||||
font-size: 25px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
color: #1e293b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-button {
|
||||||
|
color: #1976d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-holiday-btn {
|
||||||
|
background-color: #1976d2;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-profile {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-name {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #1e293b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-role {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-badge {
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo da seção de título */
|
||||||
|
.section-header {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
color: #1e293b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-description {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo do card principal */
|
||||||
|
.main-card {
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: white;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
padding: 24px;
|
||||||
|
border-bottom: 1px solid #eaecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header h3 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
color: #1e293b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-description {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo da tabela */
|
||||||
|
.holiday-table {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.holiday-table :deep(th) {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1e293b;
|
||||||
|
text-transform: none;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.holiday-table :deep(td) {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1e293b;
|
||||||
|
padding: 16px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo dos chips de tipo */
|
||||||
|
.type-chip {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilo dos botões de ação */
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos para os diferentes tipos de feriados */
|
||||||
|
.holiday-type-nacional {
|
||||||
|
background-color: #1976d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.holiday-type-estadual {
|
||||||
|
background-color: #2e7d32;
|
||||||
|
}
|
||||||
|
|
||||||
|
.holiday-type-municipal {
|
||||||
|
background-color: #0288d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.holiday-type-facultativo {
|
||||||
|
background-color: #ff9800;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -1,49 +1,74 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container class="login-container fill-height" fluid>
|
<div class="slider-container">
|
||||||
<v-row no-gutters class="fill-height align-center justify-center">
|
<!-- Container de slides que se move horizontalmente -->
|
||||||
<v-col cols="12" md="10" class="d-flex align-center justify-center">
|
<div class="slides-wrapper" :style="slideStyle">
|
||||||
|
<!-- Slide 1: Tela Inicial -->
|
||||||
|
<div class="slide intro-slide">
|
||||||
|
<div class="content-container">
|
||||||
|
<!-- Card Inicial - Versão Atualizada -->
|
||||||
|
<div class="intro-card">
|
||||||
|
<div class="intro-content">
|
||||||
|
<h1 class="intro-title">Olhe Cada Detalhe</h1>
|
||||||
|
<p class="intro-subtitle">Inteligência artificial trazendo dados para o seu negócio</p>
|
||||||
|
<v-btn
|
||||||
|
color="primary"
|
||||||
|
class="access-btn"
|
||||||
|
height="44"
|
||||||
|
@click="slideToLogin"
|
||||||
|
>
|
||||||
|
Acessar
|
||||||
|
</v-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Slide 2: Tela de Login -->
|
||||||
|
<div class="slide login-slide">
|
||||||
<!-- Retângulo de fundo -->
|
<!-- Retângulo de fundo -->
|
||||||
<div class="retangulo-box">
|
<div class="retangulo-box">
|
||||||
<!-- Formulário (esquerda) -->
|
<!-- Formulário de Login -->
|
||||||
<div class="login-form-box">
|
<div class="login-form-box">
|
||||||
<h2 class="title">Bem-vindo</h2>
|
<h2 class="title">Bem-vindo</h2>
|
||||||
<p class="subtitle">Realize o login em sua conta</p>
|
<p class="subtitle">Realize o login em sua conta</p>
|
||||||
|
|
||||||
<v-form class="form" v-model="valid" ref="loginForm">
|
<v-form class="form" v-model="valid" ref="loginForm" @submit.prevent="login">
|
||||||
<v-text-field
|
<div class="input-container">
|
||||||
|
<label for="email">E-mail</label>
|
||||||
|
<input
|
||||||
|
id="email"
|
||||||
v-model="email"
|
v-model="email"
|
||||||
label="E-mail"
|
type="text"
|
||||||
:rules="emailRules"
|
:class="['custom-input', {'input-error': emailError}]"
|
||||||
required
|
@blur="validateEmail"
|
||||||
hide-details="auto"
|
/>
|
||||||
class="custom-field"
|
<div v-if="emailError" class="error-text">{{ emailError }}</div>
|
||||||
></v-text-field>
|
</div>
|
||||||
|
|
||||||
<v-text-field
|
<div class="input-container">
|
||||||
|
<label for="password">Senha</label>
|
||||||
|
<input
|
||||||
|
id="password"
|
||||||
v-model="password"
|
v-model="password"
|
||||||
label="Senha"
|
|
||||||
:rules="passwordRules"
|
|
||||||
@keyup.enter="login"
|
|
||||||
type="password"
|
type="password"
|
||||||
required
|
:class="['custom-input', {'input-error': passwordError}]"
|
||||||
hide-details="auto"
|
@blur="validatePassword"
|
||||||
class="custom-field"
|
@keyup.enter="login"
|
||||||
></v-text-field>
|
/>
|
||||||
|
<div v-if="passwordError" class="error-text">{{ passwordError }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="text-right forgot-password">
|
<div class="text-right forgot-password">
|
||||||
<a href="#">Esqueci a senha</a>
|
<a href="#">Esqueci a senha</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<v-btn
|
<button
|
||||||
block
|
|
||||||
color="primary"
|
|
||||||
class="login-btn"
|
class="login-btn"
|
||||||
height="44"
|
:disabled="!isFormValid"
|
||||||
:disabled="!valid"
|
@click.prevent="login"
|
||||||
@click="login"
|
|
||||||
>
|
>
|
||||||
Entrar
|
Entrar
|
||||||
</v-btn>
|
</button>
|
||||||
</v-form>
|
</v-form>
|
||||||
|
|
||||||
<div class="register-link">
|
<div class="register-link">
|
||||||
@ -51,82 +76,260 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Círculo (direita) -->
|
<!-- Gráfico/Círculo informativo -->
|
||||||
<div class="circle-container">
|
<div class="circle-container">
|
||||||
<img src="/image.png" alt="Círculo" class="circle-img" />
|
<img src="/image.png" alt="Círculo" class="circle-img" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</v-col>
|
</div>
|
||||||
</v-row>
|
</div>
|
||||||
</v-container>
|
</div>
|
||||||
|
|
||||||
|
<!-- Snackbar para mensagens de erro/sucesso -->
|
||||||
|
<v-snackbar
|
||||||
|
v-model="snackbar"
|
||||||
|
:color="snackbarColor"
|
||||||
|
timeout="5000"
|
||||||
|
position="top"
|
||||||
|
>
|
||||||
|
{{ snackbarText }}
|
||||||
|
|
||||||
|
<template v-slot:actions>
|
||||||
|
<v-btn
|
||||||
|
variant="text"
|
||||||
|
@click="snackbar = false"
|
||||||
|
>
|
||||||
|
Fechar
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
</v-snackbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useAuthStore } from '../stores/auth'; // Certifique-se de que o caminho da store está correto
|
import { useAuthStore } from '../stores/auth'; // Certifique-se de que o caminho da store está correto
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
|
// Estado
|
||||||
|
const currentSlide = ref(0); // 0 = intro, 1 = login
|
||||||
const email = ref('');
|
const email = ref('');
|
||||||
const password = ref('');
|
const password = ref('');
|
||||||
|
const emailError = ref('');
|
||||||
|
const passwordError = ref('');
|
||||||
|
const sliding = ref(false);
|
||||||
const valid = ref(false);
|
const valid = ref(false);
|
||||||
|
|
||||||
const emailRules = [
|
// Estado para o Snackbar
|
||||||
(v) => !!v || 'Preencha o campo', // Verifica se está preenchido
|
const snackbar = ref(false);
|
||||||
(v) =>
|
const snackbarText = ref('');
|
||||||
/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/.test(v) || /^[a-zA-Z0-9_.-]+$/.test(v) ||
|
const snackbarColor = ref('error'); // 'error', 'success', 'info', etc.
|
||||||
'Insira um e-mail válido ou um nome de usuário', // Permite emails ou usernames simples
|
|
||||||
];
|
|
||||||
|
|
||||||
const passwordRules = [(v) => !!v || 'Preencha a senha'];
|
// Validação computada
|
||||||
|
const isFormValid = computed(() => {
|
||||||
|
return email.value && password.value && !emailError.value && !passwordError.value;
|
||||||
|
});
|
||||||
|
|
||||||
const login = async () => {
|
// Estilo computado para a posição do slider
|
||||||
try {
|
const slideStyle = computed(() => {
|
||||||
await authStore.login(email.value, password.value); // Ação de login no Pinia
|
return {
|
||||||
router.push('/dashboard'); // Redireciona ao dashboard após login bem-sucedido
|
transform: `translateX(-${currentSlide.value * 100}%)`,
|
||||||
} catch (error) {
|
transition: sliding.value ? 'transform 0.8s ease-in-out' : 'none'
|
||||||
alert('Falha ao fazer login. Verifique suas credenciais.'); // Exibe erro em caso de falha
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Funções de validação
|
||||||
|
const validateEmail = () => {
|
||||||
|
if (!email.value) {
|
||||||
|
emailError.value = 'Preencha o campo';
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
if (!/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/.test(email.value) &&
|
||||||
|
!/^[a-zA-Z0-9_.-]+$/.test(email.value)) {
|
||||||
|
emailError.value = 'Insira um e-mail válido ou um nome de usuário';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emailError.value = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
const validatePassword = () => {
|
||||||
|
if (!password.value) {
|
||||||
|
passwordError.value = 'Preencha a senha';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
passwordError.value = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Métodos para navegação de slides - Melhorados
|
||||||
|
const slideToLogin = () => {
|
||||||
|
console.log('Deslizando para o login...');
|
||||||
|
sliding.value = true;
|
||||||
|
currentSlide.value = 1;
|
||||||
|
|
||||||
<style scoped>
|
// Adicionado: Garantir que o estado seja atualizado imediatamente
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log('Slide atual após timeout:', currentSlide.value);
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
.login-container {
|
const slideToIntro = () => {
|
||||||
background: linear-gradient(135deg, #2d0f44, #23408e);
|
console.log('Deslizando para a introdução...');
|
||||||
color: #fff;
|
sliding.value = true;
|
||||||
|
currentSlide.value = 0;
|
||||||
|
|
||||||
|
// Adicionado: Garantir que o estado seja atualizado imediatamente
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log('Slide atual após timeout:', currentSlide.value);
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Função de login usando o authStore do Pinia
|
||||||
|
const login = async () => {
|
||||||
|
if (!isFormValid.value) {
|
||||||
|
// Validar formulário novamente
|
||||||
|
validateEmail();
|
||||||
|
validatePassword();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('Tentando fazer login com:', email.value, password.value);
|
||||||
|
await authStore.login(email.value, password.value); // Ação de login no Pinia
|
||||||
|
|
||||||
|
// Forçar a navegação para o dashboard usando location.href
|
||||||
|
// em vez de router.push para garantir que saia do sistema de slides
|
||||||
|
window.location.href = '/dashboard';
|
||||||
|
|
||||||
|
// Alternativa: router.push com opção replace
|
||||||
|
// router.push({ path: '/dashboard', replace: true });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro de login:', error);
|
||||||
|
// Exibe o Snackbar com a mensagem de erro
|
||||||
|
snackbarText.value = 'Falha ao fazer login. Verifique suas credenciais.';
|
||||||
|
snackbarColor.value = 'error';
|
||||||
|
snackbar.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* Container principal que mantém todo o conteúdo e controla overflow */
|
||||||
|
.slider-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wrapper que desliza horizontalmente contendo ambos os slides */
|
||||||
|
.slides-wrapper {
|
||||||
|
display: flex;
|
||||||
|
width: 100vw; /* Duas vezes a largura da viewport - CORRIGIDO */
|
||||||
|
height: 100%;
|
||||||
|
will-change: transform; /* Otimiza a animação */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cada slide individual ocupa uma viewport completa */
|
||||||
|
.slide {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Estilos específicos para cada slide */
|
||||||
|
.intro-slide {
|
||||||
|
background: linear-gradient(135deg, #2d0f44, #23408e);
|
||||||
|
position: relative;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-slide {
|
||||||
|
background: linear-gradient(135deg, #3a1788, #4c82e6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container para o conteúdo centralizado em cada slide */
|
||||||
|
.content-container {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1200px;
|
||||||
|
position: relative;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cartão de introdução */
|
||||||
|
.intro-card {
|
||||||
|
background-color: rgba(252, 252, 252, 0.1);
|
||||||
|
padding: 50px 40px;
|
||||||
|
border-radius: 20px;
|
||||||
|
width: 500%;
|
||||||
|
max-width: 650px;
|
||||||
|
color: white;
|
||||||
|
margin-left: 10px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-title {
|
||||||
|
font-size: 120px;
|
||||||
|
font-weight: 120;
|
||||||
|
color: white;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-subtitle {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
color: rgba(255, 255, 255, 0.85);
|
||||||
|
font-size: 22px;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-size: 40px;
|
||||||
|
font-weight: 110;
|
||||||
|
}
|
||||||
|
|
||||||
|
.access-btn {
|
||||||
|
background: linear-gradient(to right, #5189f9, #4447f1) !important;
|
||||||
|
color: white !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
text-transform: none !important;
|
||||||
|
border-radius: 25px !important;
|
||||||
|
margin-top: 10px !important;
|
||||||
|
width: 70% !important;
|
||||||
|
height: 60px !important;
|
||||||
|
font-size: 18px !important;
|
||||||
|
letter-spacing: 0.5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Formulário de login */
|
||||||
.retangulo-box {
|
.retangulo-box {
|
||||||
background-image: url('/image_ret.png');
|
background-image: url('/image_ret.png');
|
||||||
background-repeat: no-repeat;
|
background-size: 98%;
|
||||||
background-size: 110%;
|
|
||||||
background-position: center;
|
background-position: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 110%;
|
||||||
max-width: 1200px;
|
max-width: 1500px;
|
||||||
height: 600px;
|
height: 1500px;
|
||||||
padding: 120px;
|
padding: 110px;
|
||||||
box-sizing: border-box;
|
border-radius: 30px;
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-form-box {
|
.login-form-box {
|
||||||
background-color: white;
|
width: 34%;
|
||||||
padding: 30px;
|
margin-left: 130px;
|
||||||
border-radius: 20px;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 360px;
|
|
||||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
|
||||||
color: #000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
@ -137,52 +340,247 @@ const login = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 30px;
|
||||||
color: #777;
|
color: rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-field {
|
.form {
|
||||||
margin-bottom: 20px;
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-container {
|
||||||
|
margin-bottom: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-container label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-input {
|
||||||
|
width: 100%;
|
||||||
|
height: 44px;
|
||||||
|
padding: 0 16px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: white;
|
||||||
|
font-size: 16px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #4c9ff0;
|
||||||
|
background-color: rgba(255, 255, 255, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-error {
|
||||||
|
border-color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-text {
|
||||||
|
color: #ff4d4f;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.forgot-password {
|
.forgot-password {
|
||||||
margin-bottom: 20px;
|
text-align: right;
|
||||||
|
margin-bottom: 25px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-btn {
|
.login-btn {
|
||||||
background: linear-gradient(to right, #86b6f6, #b8b4f7);
|
width: 100%;
|
||||||
|
height: 44px;
|
||||||
|
background: linear-gradient(to right, #3e7bf4, #5658f5);
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: none;
|
border: none;
|
||||||
border-radius: 25px;
|
border-radius: 20px;
|
||||||
margin-bottom: 15px;
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login-btn:hover {
|
||||||
|
background: linear-gradient(to right, #3568d4, #4a4ce5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.register-link {
|
.register-link {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #333;
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.register-link a,
|
.register-link a,
|
||||||
.forgot-password a {
|
.forgot-password a {
|
||||||
color: #4c9ff0;
|
color: #4c9ff0;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-link a:hover,
|
||||||
|
.forgot-password a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-img {
|
||||||
|
width: 270%;
|
||||||
|
max-width: 650px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsividade */
|
||||||
|
@media (max-width: 960px) {
|
||||||
|
.content-container {
|
||||||
|
flex-direction: column;
|
||||||
|
height: auto;
|
||||||
|
padding: 40px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-card {
|
||||||
|
margin: 0 0 30px 0;
|
||||||
|
max-width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retangulo-box {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 40px 20px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form-box,
|
||||||
|
.circle-container {
|
||||||
|
width: 90%;
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.intro-title {
|
||||||
|
font-size: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-subtitle {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retangulo-box {
|
||||||
|
padding: 80px;
|
||||||
|
background-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form-box {
|
||||||
|
margin-left: 50px;
|
||||||
|
width: 45%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-img {
|
||||||
|
width: 200%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 960px) {
|
||||||
|
.slides-wrapper {
|
||||||
|
flex-direction: column;
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-container {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-card {
|
||||||
|
margin: 0;
|
||||||
|
padding: 40px 20px;
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-title {
|
||||||
|
font-size: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-subtitle {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.access-btn {
|
||||||
|
width: 80% !important;
|
||||||
|
height: 50px !important;
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retangulo-box {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 40px 20px;
|
||||||
|
height: auto;
|
||||||
|
width: 95%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form-box {
|
||||||
|
width: 90%;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.circle-container {
|
.circle-container {
|
||||||
flex: 1;
|
margin-top: 30px;
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.circle-img {
|
.circle-img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 320px;
|
max-width: 300px;
|
||||||
height: auto;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.intro-title {
|
||||||
|
font-size: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-subtitle {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.access-btn {
|
||||||
|
font-size: 14px !important;
|
||||||
|
height: 44px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-btn {
|
||||||
|
font-size: 14px;
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user