Compare commits
7 Commits
master
...
e243e8397d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e243e8397d | ||
|
|
4570526ceb | ||
|
|
a9f7349039 | ||
|
|
0fbe83d737 | ||
|
|
974c34ad1c | ||
|
|
9e6e0948d4 | ||
|
|
291dbd2f35 |
@@ -3,6 +3,11 @@ body {
|
|||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Colors*/
|
||||||
|
.primary-color-eta {
|
||||||
|
color: #FBBA33;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-d-column {
|
.flex-d-column {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -35,12 +40,6 @@ body {
|
|||||||
border-radius: 3rem !important;
|
border-radius: 3rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fuentes */
|
|
||||||
.font-bold {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
/* *********** */
|
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
display: block;
|
display: block;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
@@ -130,6 +129,12 @@ body {
|
|||||||
color: #FBBA33;
|
color: #FBBA33;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-tertiary {
|
||||||
|
font-size: 1rem !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
color: rgb(181, 168, 168) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.card-info,
|
.card-info,
|
||||||
.card-fixed {
|
.card-fixed {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
15
src/assets/styles/fonts.css
Normal file
15
src/assets/styles/fonts.css
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
.font-bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fsize-1 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fsize-1-5 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fsize-2 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
@@ -121,6 +121,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card-fixed card-load mt-4">
|
<div class="card-fixed card-load mt-4">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<p v-if="load?.privacy === true && load?.company?._id === authStore?.user?.company._id && !share">
|
||||||
|
<i class="fa-solid fa-lock primary-color-eta fsize-1-5"></i> <span class="text-tertiary fsize-1">Carga privada</span>
|
||||||
|
</p>
|
||||||
<div class="col-lg-6 col-sm-12">
|
<div class="col-lg-6 col-sm-12">
|
||||||
<p>
|
<p>
|
||||||
<span>{{t('loads.origin')}}: </span>
|
<span>{{t('loads.origin')}}: </span>
|
||||||
|
|||||||
43
src/components/CustomSearchInput.vue
Normal file
43
src/components/CustomSearchInput.vue
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<script setup>
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
saerch: {
|
||||||
|
type: [String]
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
defineEmits(['update:saerch'])
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="mb-4">
|
||||||
|
<input
|
||||||
|
class="custom-search"
|
||||||
|
type="search"
|
||||||
|
name="search"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:value="saerch"
|
||||||
|
@input="$event => $emit('update:saerch', $event.target.value)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.custom-search {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border: 1px solid rgb(222, 214, 214);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-search:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: rgb(217, 202, 202);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
96
src/components/CustomSwitch.vue
Normal file
96
src/components/CustomSwitch.vue
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
|
const toggle = (event) => {
|
||||||
|
emit('update:modelValue', event.target.checked)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<label class="switch-container">
|
||||||
|
<span v-if="label" class="custom-label label-text flex1">{{ label }}</span>
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
:name="name"
|
||||||
|
:checked="modelValue"
|
||||||
|
@change="toggle"
|
||||||
|
>
|
||||||
|
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.flex1 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.switch-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ocultar input */
|
||||||
|
.switch-container input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fondo del switch */
|
||||||
|
.slider {
|
||||||
|
position: relative;
|
||||||
|
width: 45px;
|
||||||
|
height: 25px;
|
||||||
|
background-color: #ccc;
|
||||||
|
border-radius: 25px;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* circulo */
|
||||||
|
.slider::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
left: 4px;
|
||||||
|
top: 3.5px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* estado activo */
|
||||||
|
input:checked + .slider {
|
||||||
|
background-color: #5A67DD; /* tu color */
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + .slider::before {
|
||||||
|
transform: translateX(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hover */
|
||||||
|
.switch-container:hover .slider {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -198,7 +198,7 @@
|
|||||||
<option v-for="vehicle in vehiclesAvailable" :value="vehicle._id">
|
<option v-for="vehicle in vehiclesAvailable" :value="vehicle._id">
|
||||||
{{vehicle.vehicle_code?.toUpperCase()}} - {{ vehicle.truck_type }}
|
{{vehicle.vehicle_code?.toUpperCase()}} - {{ vehicle.truck_type }}
|
||||||
<span v-if="vehicle?.driver">- {{ vehicle?.driver?.first_name + ' ' + vehicle?.driver?.last_name }}</span>
|
<span v-if="vehicle?.driver">- {{ vehicle?.driver?.first_name + ' ' + vehicle?.driver?.last_name }}</span>
|
||||||
<span v-else>- Sin conductor</span>
|
<span v-else>- Sin conductor -</span>
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -159,7 +159,10 @@ const en = {
|
|||||||
loading: 'Please wait!',
|
loading: 'Please wait!',
|
||||||
savingChanes: 'Saving changes',
|
savingChanes: 'Saving changes',
|
||||||
observerWarehouse: 'Warehouse observers will receive notifications about the load location, including arrival and departure times, and will be able to view the cargo on the warehouse dashboard.',
|
observerWarehouse: 'Warehouse observers will receive notifications about the load location, including arrival and departure times, and will be able to view the cargo on the warehouse dashboard.',
|
||||||
observerClient: 'Observers will receive notifications about the load, including the loading and unloading date, as well as any changes in the load status. They can monitor the cargo on their customer dashboard.'
|
observerClient: 'Observers will receive notifications about the load, including the loading and unloading date, as well as any changes in the load status. They can monitor the cargo on their customer dashboard.',
|
||||||
|
notDriverAssign: 'This offer does not include an assigned driver. Please request that the carrier assign an operator to continue the loading process.',
|
||||||
|
changeSuccess: 'Changes successfully implemented!',
|
||||||
|
actionSuccess: 'Action successfully completed!',
|
||||||
},
|
},
|
||||||
global: {
|
global: {
|
||||||
signIn: "Sign In",
|
signIn: "Sign In",
|
||||||
@@ -208,6 +211,9 @@ const en = {
|
|||||||
delivered: 'Delivered',
|
delivered: 'Delivered',
|
||||||
downloading: 'Downloading',
|
downloading: 'Downloading',
|
||||||
add: 'Add',
|
add: 'Add',
|
||||||
|
dashboard: 'Dashboard',
|
||||||
|
notDriver: 'Without driver',
|
||||||
|
mistake: 'Mistake'
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
title: 'Sign in',
|
title: 'Sign in',
|
||||||
@@ -495,6 +501,19 @@ const en = {
|
|||||||
},
|
},
|
||||||
store: {
|
store: {
|
||||||
title: "Warehouse"
|
title: "Warehouse"
|
||||||
|
},
|
||||||
|
contacts: {
|
||||||
|
privacyList: 'Private list',
|
||||||
|
truckTypesUsed: 'Types of Used Trucks',
|
||||||
|
deleteCarrier: 'Delete carrier',
|
||||||
|
QuestionDeleteCarrier: 'Are you sure you want to remove this carrier from the private list?',
|
||||||
|
QuestionAddCarrier: 'Are you sure you want to add this carrier to the private list?',
|
||||||
|
deletedCarrier: 'Carrier removed',
|
||||||
|
deletedCarrierSuccess: 'The carrier has been removed from the private list',
|
||||||
|
deletedCarrierError: 'The removal of the carrier from the private list could not be completed.',
|
||||||
|
settingsCompany: 'Company settings',
|
||||||
|
privacyCompanyLabel: 'Activate company privacy settings',
|
||||||
|
privacyLoadLabel: 'Post as private',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -162,7 +162,10 @@ const es = {
|
|||||||
loading: 'Por favor espere!',
|
loading: 'Por favor espere!',
|
||||||
savingChanes: 'Guardando cambios',
|
savingChanes: 'Guardando cambios',
|
||||||
observerWarehouse: 'Los observadores de bodega recibirán notificaciones sobre la ubicación de la carga, incluyendo la hora de llegada y salida, podran visualizar la carga en el panel de bodega.',
|
observerWarehouse: 'Los observadores de bodega recibirán notificaciones sobre la ubicación de la carga, incluyendo la hora de llegada y salida, podran visualizar la carga en el panel de bodega.',
|
||||||
observerClient: 'Los observadores recibirán notificaciones sobre la carga, incluyendo la fecha de carga y descarga, así como cualquier cambio en el estado de la carga. podran monitorer la carga en el panel de clientes.'
|
observerClient: 'Los observadores recibirán notificaciones sobre la carga, incluyendo la fecha de carga y descarga, así como cualquier cambio en el estado de la carga. podran monitorer la carga en el panel de clientes.',
|
||||||
|
notDriverAssign: 'Oferta sin conductor asignado. Solicite al transportista que asigne un operador para continuar con el proceso de carga.',
|
||||||
|
changeSuccess: 'Cambios aplicados con exito!',
|
||||||
|
actionSuccess: 'Acción realizada con exito!',
|
||||||
},
|
},
|
||||||
global: {
|
global: {
|
||||||
signIn: 'Ingresar',
|
signIn: 'Ingresar',
|
||||||
@@ -211,6 +214,9 @@ const es = {
|
|||||||
delivered: 'Entregado',
|
delivered: 'Entregado',
|
||||||
downloading: 'Descargando',
|
downloading: 'Descargando',
|
||||||
add: 'Agregar',
|
add: 'Agregar',
|
||||||
|
dashboard: 'Panel',
|
||||||
|
notDriver: 'Sin conductor',
|
||||||
|
mistake: 'Error'
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
title: 'Iniciar sesión',
|
title: 'Iniciar sesión',
|
||||||
@@ -504,6 +510,19 @@ const es = {
|
|||||||
},
|
},
|
||||||
store: {
|
store: {
|
||||||
title: "Bodega"
|
title: "Bodega"
|
||||||
|
},
|
||||||
|
contacts: {
|
||||||
|
privacyList: 'Lista privada',
|
||||||
|
truckTypesUsed: 'Tipos de camiones usados',
|
||||||
|
deleteCarrier: 'Eliminar transportista',
|
||||||
|
QuestionDeleteCarrier: '¿Estas seguro de eliminar este transportista de la lista privada?',
|
||||||
|
QuestionAddCarrier: '¿Estas seguro de añadir a este transportista de la lista privada?',
|
||||||
|
deletedCarrier: 'Transportista eliminado',
|
||||||
|
deletedCarrierSuccess: 'Se ha eliminado el transportista de la lista privada',
|
||||||
|
deletedCarrierError: 'No se pudo completar la eliminación del transportista de la lista privada',
|
||||||
|
settingsCompany: 'Configuraciones de empresa',
|
||||||
|
privacyCompanyLabel: 'Activar configuración de privacidad de la empresa',
|
||||||
|
privacyLoadLabel: 'Publicar como privada',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import LoadingModal from '../components/ui/LoadingModal.vue';
|
import LoadingModal from '../components/ui/LoadingModal.vue';
|
||||||
import NavBar from '../components/NavBar.vue';
|
import NavBar from './components/NavBar.vue';
|
||||||
import Sidebar from '../components/Sidebar.vue';
|
import Sidebar from './components/Sidebar.vue';
|
||||||
import ProfilePopup from '../views/profile/modals/ProfilePopup.vue';
|
import ProfilePopup from '../views/profile/modals/ProfilePopup.vue';
|
||||||
import NotificationsPopup from '../components/NotificationsPopup.vue';
|
import NotificationsPopup from './components/NotificationsPopup.vue';
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -19,6 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<LoadingModal/>
|
<LoadingModal/>
|
||||||
<ProfilePopup/>
|
<ProfilePopup/>
|
||||||
|
<!-- <ConfigPopup/> -->
|
||||||
<NotificationsPopup/>
|
<NotificationsPopup/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
99
src/layouts/components/ConfigPopup.vue
Normal file
99
src/layouts/components/ConfigPopup.vue
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<script setup>
|
||||||
|
import { useNotificationsStore } from '../../stores/notifications';
|
||||||
|
import CustomSwitch from '../../components/CustomSwitch.vue'
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { onMounted } from 'vue';
|
||||||
|
import { watch } from 'vue';
|
||||||
|
import { usePrivacyStore } from '../../stores/privacy';
|
||||||
|
|
||||||
|
const lang = ref(null);
|
||||||
|
const privacy = ref(false);
|
||||||
|
|
||||||
|
const noty = useNotificationsStore();
|
||||||
|
const privacyStore = usePrivacyStore();
|
||||||
|
const { t, locale } = useI18n();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
lang.value = localStorage.getItem('lang') ?? 'es';
|
||||||
|
locale.value = lang.value;
|
||||||
|
privacy.value = privacyStore.privacy;
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(lang, () => {
|
||||||
|
locale.value = lang.value
|
||||||
|
localStorage.setItem('lang', lang.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(privacy, () => {
|
||||||
|
privacyStore.updatePrivacy(privacy.value);
|
||||||
|
})
|
||||||
|
|
||||||
|
const closePopup = () => {
|
||||||
|
noty.toggleConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="noty.openConfig"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="content-popup"
|
||||||
|
@click="closePopup()"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="profile-card">
|
||||||
|
<i class="fa-solid fa-xmark close-icon" @click="closePopup()"></i>
|
||||||
|
<br>
|
||||||
|
<CustomSwitch
|
||||||
|
label="Activar configuracion de privacidad"
|
||||||
|
v-model="privacy"
|
||||||
|
name="privacity"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.content-popup {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1000;
|
||||||
|
width: 100wv;
|
||||||
|
right: 0px;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
cursor: pointer;
|
||||||
|
bottom: 0px;
|
||||||
|
background-color: #000;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-card {
|
||||||
|
position: fixed;
|
||||||
|
flex: 1;
|
||||||
|
right: 20px;
|
||||||
|
top: 70px;
|
||||||
|
z-index: 2000;
|
||||||
|
width: 340px;
|
||||||
|
background-color: #FFF;
|
||||||
|
opacity: 1;
|
||||||
|
border-radius: 13px;
|
||||||
|
padding: 20px 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.10));
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-icon {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
top: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { RouterLink } from 'vue-router';
|
import { RouterLink } from 'vue-router';
|
||||||
import { useAuthStore } from '../stores/auth';
|
import { useAuthStore } from '../../stores/auth';
|
||||||
import { useNotificationsStore } from '../stores/notifications';
|
import { useNotificationsStore } from '../../stores/notifications';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { getNotificationsCompany } from '../services/company';
|
import { getNotificationsCompany } from '../../services/company';
|
||||||
|
|
||||||
const auth = useAuthStore();
|
const auth = useAuthStore();
|
||||||
const noty = useNotificationsStore();
|
const noty = useNotificationsStore();
|
||||||
@@ -75,7 +75,16 @@
|
|||||||
<a
|
<a
|
||||||
active-class="router-link-active"
|
active-class="router-link-active"
|
||||||
@click="noty.toggleProfile"
|
@click="noty.toggleProfile"
|
||||||
class="nav-link"><i class="fa-regular fa-user"></i></a>
|
class="nav-link">
|
||||||
|
<i class="fa-regular fa-user"></i>
|
||||||
|
</a>
|
||||||
|
<!-- <a
|
||||||
|
v-if="permission === 'role_shipper'"
|
||||||
|
active-class="router-link-active"
|
||||||
|
@click="noty.toggleConfig"
|
||||||
|
class="nav-link">
|
||||||
|
<i class="fa-solid fa-gear"></i>
|
||||||
|
</a> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -2,10 +2,10 @@
|
|||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import {getDateTime} from '../helpers/date_formats';
|
import {getDateTime} from '../../helpers/date_formats';
|
||||||
import { deleteNotification } from '../services/company';
|
import { deleteNotification } from '../../services/company';
|
||||||
import { useNotificationsStore } from '../stores/notifications';
|
import { useNotificationsStore } from '../../stores/notifications';
|
||||||
import Spiner from './ui/Spiner.vue';
|
import Spiner from '../../components/ui/Spiner.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
noty: {
|
noty: {
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useNotificationsStore } from '../stores/notifications';
|
import { useNotificationsStore } from '../../stores/notifications';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import NotificationCard from './NotificationCard.vue';
|
import NotificationCard from './NotificationCard.vue';
|
||||||
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { RouterLink, useRoute, useRouter } from 'vue-router';
|
import { RouterLink, useRoute, useRouter } from 'vue-router';
|
||||||
import { useAuthStore } from '../stores/auth';
|
import { useAuthStore } from '../../stores/auth';
|
||||||
import Swal from 'sweetalert2';
|
import Swal from 'sweetalert2';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useCompanyStore } from '../stores/company';
|
import { useCompanyStore } from '../../stores/company';
|
||||||
import { useVehiclesStore } from '../stores/vehicles';
|
import { useVehiclesStore } from '../../stores/vehicles';
|
||||||
import { useLoadsStore } from '../stores/loads';
|
import { useLoadsStore } from '../../stores/loads';
|
||||||
import { useNotificationsStore } from '../stores/notifications';
|
import { useNotificationsStore } from '../../stores/notifications';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const auth = useAuthStore();
|
const auth = useAuthStore();
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
<i class="fa-solid fa-gauge-high" :class="[route.name === 'home' ? 'router-link-active' : '']"></i>
|
<i class="fa-solid fa-gauge-high" :class="[route.name === 'home' ? 'router-link-active' : '']"></i>
|
||||||
<RouterLink
|
<RouterLink
|
||||||
active-class="router-link-active"
|
active-class="router-link-active"
|
||||||
class="nav-link" :to="{name: 'home'}">Dashboard</RouterLink>
|
class="nav-link" :to="{name: 'home'}">{{ t('global.dashboard') }}</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
@@ -159,6 +159,16 @@
|
|||||||
class="nav-link" :to="{name: 'calculator'}">{{ t('global.calculator') }}</RouterLink>
|
class="nav-link" :to="{name: 'calculator'}">{{ t('global.calculator') }}</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
<li
|
||||||
|
v-if="permission === 'role_shipper' && jobRole !== roleCheck"
|
||||||
|
:class="[route.name === 'groups' ? 'bg-nav-active' : '']">
|
||||||
|
<div>
|
||||||
|
<i class="fa-regular fa-address-book" :class="[route.name === 'groups' ? 'router-link-active' : '']"></i>
|
||||||
|
<RouterLink
|
||||||
|
active-class=""
|
||||||
|
class="nav-link" :to="{name: 'groups'}">{{ t('contacts.privacyList') }}</RouterLink>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="eta-info">
|
<div class="eta-info">
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import './assets/main.css'
|
import './assets/main.css'
|
||||||
|
import './assets/styles/fonts.css'
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
|
|||||||
@@ -200,7 +200,16 @@ const router = createRouter({
|
|||||||
path: '/:pathMatch(.*)*',
|
path: '/:pathMatch(.*)*',
|
||||||
name: 'not-found',
|
name: 'not-found',
|
||||||
component: () => import('../views/dashboard/HomeView.vue'),
|
component: () => import('../views/dashboard/HomeView.vue'),
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
path: 'lista-privada',
|
||||||
|
name: 'groups',
|
||||||
|
meta: {
|
||||||
|
permissions: ['role_shipper'],
|
||||||
|
roles: ['staff', 'manager', 'owner']
|
||||||
|
},
|
||||||
|
component: () => import('../views/contacts/ContactsView.vue'),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -202,3 +202,67 @@ export const deleteNotification = async(id) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const enablePrivacyCompany = async(formData) => {
|
||||||
|
try {
|
||||||
|
const endpoint = '/v1/companies/own';
|
||||||
|
const {data} = await api.patch(endpoint, formData);
|
||||||
|
return {
|
||||||
|
msg: 'success',
|
||||||
|
data: data
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
msg: error.response.data.error ?? "Algo salió mal, intente nás tarde",
|
||||||
|
data: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getPrivateListService = async() => {
|
||||||
|
try {
|
||||||
|
const endpoint = `/v1/groups/private`;
|
||||||
|
const {data} = await api.get(endpoint);
|
||||||
|
return {
|
||||||
|
msg: 'success',
|
||||||
|
data: data
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
msg: error.response.data.error ?? "Algo salió mal, intente nás tarde",
|
||||||
|
data: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addCompanyPrivicyListService = async(id) => {
|
||||||
|
try {
|
||||||
|
const endpoint = `/v1/groups/private/${id}`;
|
||||||
|
const {data} = await api.patch(endpoint);
|
||||||
|
return {
|
||||||
|
msg: 'success',
|
||||||
|
data: data
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
msg: error.response.data.error ?? "Algo salió mal, intente nás tarde",
|
||||||
|
data: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteCompanyPrivicyListService = async(id) => {
|
||||||
|
try {
|
||||||
|
const endpoint = `/v1/groups/private/${id}`;
|
||||||
|
const {data} = await api.delete(endpoint);
|
||||||
|
return {
|
||||||
|
msg: 'success',
|
||||||
|
data: data
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
msg: error.response.data.error ?? "Algo salió mal, intente nás tarde",
|
||||||
|
data: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ import { renewToken } from '../services/auth';
|
|||||||
import {useNotificationsStore} from './notifications';
|
import {useNotificationsStore} from './notifications';
|
||||||
import { useLoadsStore } from "./loads";
|
import { useLoadsStore } from "./loads";
|
||||||
import { updateMyUserProfile } from "../services/company";
|
import { updateMyUserProfile } from "../services/company";
|
||||||
|
import { usePrivacyStore } from "./privacy";
|
||||||
|
|
||||||
export const useAuthStore = defineStore('auth', () => {
|
export const useAuthStore = defineStore('auth', () => {
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const noty = useNotificationsStore();
|
const noty = useNotificationsStore();
|
||||||
|
const privicyStore = usePrivacyStore();
|
||||||
const loadStore = useLoadsStore();
|
const loadStore = useLoadsStore();
|
||||||
const sesion = ref('')
|
const sesion = ref('')
|
||||||
const checking = ref(false);
|
const checking = ref(false);
|
||||||
@@ -39,6 +41,7 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
if(resp.msg === 'success') {
|
if(resp.msg === 'success') {
|
||||||
user.value = resp.data.user;
|
user.value = resp.data.user;
|
||||||
sesion.value = resp.data.session_token;
|
sesion.value = resp.data.session_token;
|
||||||
|
privicyStore.privacy = resp.data.user?.company?.privacy || false;
|
||||||
token.value = resp.data.accessToken;
|
token.value = resp.data.accessToken;
|
||||||
localStorage.setItem('session', resp.data.session_token);
|
localStorage.setItem('session', resp.data.session_token);
|
||||||
localStorage.setItem('access', resp.data.accessToken);
|
localStorage.setItem('access', resp.data.accessToken);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const useNotificationsStore = defineStore('notifications', () => {
|
|||||||
const error = ref(false)
|
const error = ref(false)
|
||||||
const show = ref(false);
|
const show = ref(false);
|
||||||
const openProfile = ref(false);
|
const openProfile = ref(false);
|
||||||
|
const openConfig = ref(false);
|
||||||
const openNotifications = ref(false);
|
const openNotifications = ref(false);
|
||||||
const notifications = ref([]);
|
const notifications = ref([]);
|
||||||
const newNoty = ref(false);
|
const newNoty = ref(false);
|
||||||
@@ -26,6 +27,10 @@ export const useNotificationsStore = defineStore('notifications', () => {
|
|||||||
openProfile.value = !openProfile.value;
|
openProfile.value = !openProfile.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toggleConfig = () => {
|
||||||
|
openConfig.value = !openConfig.value;
|
||||||
|
}
|
||||||
|
|
||||||
const toggleNotifications = () => {
|
const toggleNotifications = () => {
|
||||||
openNotifications.value = !openNotifications.value;
|
openNotifications.value = !openNotifications.value;
|
||||||
}
|
}
|
||||||
@@ -39,6 +44,7 @@ export const useNotificationsStore = defineStore('notifications', () => {
|
|||||||
newNoty.value = false;
|
newNoty.value = false;
|
||||||
show.value = false;
|
show.value = false;
|
||||||
openNotifications.value = false;
|
openNotifications.value = false;
|
||||||
|
openConfig.value = false;
|
||||||
toggleProfile.value = false;
|
toggleProfile.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,8 +57,10 @@ export const useNotificationsStore = defineStore('notifications', () => {
|
|||||||
notifications,
|
notifications,
|
||||||
newNoty,
|
newNoty,
|
||||||
openProfile,
|
openProfile,
|
||||||
|
openConfig,
|
||||||
removeNoty,
|
removeNoty,
|
||||||
toggleProfile,
|
toggleProfile,
|
||||||
|
toggleConfig,
|
||||||
openNotifications,
|
openNotifications,
|
||||||
toggleNotifications,
|
toggleNotifications,
|
||||||
clear
|
clear
|
||||||
|
|||||||
76
src/stores/privacy.js
Normal file
76
src/stores/privacy.js
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import { defineStore } from "pinia"
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { addCompanyPrivicyListService, deleteCompanyPrivicyListService, enablePrivacyCompany, getPrivateListService } from "../services/company";
|
||||||
|
|
||||||
|
export const usePrivacyStore = defineStore('privacy', () => {
|
||||||
|
|
||||||
|
const privacy = ref(false);
|
||||||
|
const privateListRef = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const privateList = ref([]);
|
||||||
|
|
||||||
|
const updatePrivacy = async (value) => {
|
||||||
|
const data = {
|
||||||
|
"privacy": value
|
||||||
|
};
|
||||||
|
const response = await enablePrivacyCompany(data);
|
||||||
|
if(response.msg == 'success') {
|
||||||
|
privacy.value = response.data.privacy || false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPrivateList = async (id) => {
|
||||||
|
loading.value = true;
|
||||||
|
const response = await getPrivateListService();
|
||||||
|
loading.value = false;
|
||||||
|
if(response.msg == 'success') {
|
||||||
|
privateList.value = response.data.allowedCompanies || [];
|
||||||
|
privateListRef.value = privateList.value.map((e) => e._id);
|
||||||
|
return 'success';
|
||||||
|
} else {
|
||||||
|
return response.msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const addCompanyToPrivateList = async (id) => {
|
||||||
|
const response = await addCompanyPrivicyListService(id);
|
||||||
|
if(response.msg == 'success') {
|
||||||
|
privateListRef.value = [
|
||||||
|
...privateListRef.value,
|
||||||
|
id
|
||||||
|
];
|
||||||
|
return 'success';
|
||||||
|
} else {
|
||||||
|
return response.msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteCompanyToPrivateList = async (id) => {
|
||||||
|
const response = await deleteCompanyPrivicyListService(id);
|
||||||
|
if(response.msg == 'success') {
|
||||||
|
removeContact(id);
|
||||||
|
return 'success';
|
||||||
|
} else {
|
||||||
|
return response.msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// State
|
||||||
|
const removeContact = (id) => {
|
||||||
|
privateList.value = privateList.value.filter((e) => e._id !== id);
|
||||||
|
privateListRef.value = privateListRef.value.filter((e) => e !== id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
loading,
|
||||||
|
privacy,
|
||||||
|
privateListRef,
|
||||||
|
privateList,
|
||||||
|
removeContact,
|
||||||
|
updatePrivacy,
|
||||||
|
getPrivateList,
|
||||||
|
deleteCompanyToPrivateList,
|
||||||
|
addCompanyToPrivateList
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
|
|
||||||
localStorage.setItem('id', result.data._id);
|
localStorage.setItem('id', result.data._id);
|
||||||
localStorage.setItem('session', auth.sesion);
|
localStorage.setItem('session', auth.sesion);
|
||||||
localStorage.setItem('access', auth.accessToken);
|
localStorage.setItem('access', auth.token);
|
||||||
|
|
||||||
const userData = {
|
const userData = {
|
||||||
"first_name" : user.name,
|
"first_name" : user.name,
|
||||||
|
|||||||
@@ -8,16 +8,21 @@
|
|||||||
import EditCompanyModal from './modals/EditCompanyModal.vue';
|
import EditCompanyModal from './modals/EditCompanyModal.vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import CustomSwitch from '../../components/CustomSwitch.vue';
|
||||||
|
import { usePrivacyStore } from '../../stores/privacy';
|
||||||
|
|
||||||
const auth = useAuthStore()
|
const auth = useAuthStore()
|
||||||
|
const privacyStore = usePrivacyStore();
|
||||||
const company = useCompanyStore();
|
const company = useCompanyStore();
|
||||||
const { user } = storeToRefs(auth);
|
const { user } = storeToRefs(auth);
|
||||||
const { t, locale } = useI18n()
|
const { t, locale } = useI18n()
|
||||||
|
const privacy = ref(false);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if(user.value) {
|
if(user.value) {
|
||||||
getInitialData()
|
getInitialData()
|
||||||
}
|
}
|
||||||
|
privacy.value = privacyStore.privacy;
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(user, () => {
|
watch(user, () => {
|
||||||
@@ -26,6 +31,10 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(privacy, () => {
|
||||||
|
privacyStore.updatePrivacy(privacy.value);
|
||||||
|
})
|
||||||
|
|
||||||
const getInitialData = async() => {
|
const getInitialData = async() => {
|
||||||
await company.getCompanyData();
|
await company.getCompanyData();
|
||||||
}
|
}
|
||||||
@@ -36,7 +45,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<EditCompanyModal v-if="company.loading === false"/>
|
<EditCompanyModal v-if="company.loading === false"/>
|
||||||
<div>
|
<div>
|
||||||
<h2 class="title my-5">{{ t('company.title') }}</h2>
|
<h2 class="title my-2">{{ t('company.title') }}</h2>
|
||||||
<div class="card-info">
|
<div class="card-info">
|
||||||
<Spiner v-if="company.loading"/>
|
<Spiner v-if="company.loading"/>
|
||||||
<div v-else class="view">
|
<div v-else class="view">
|
||||||
@@ -93,6 +102,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-fixed flex-d-column"
|
||||||
|
v-if="auth.user?.job_role === 'owner' || auth.user?.job_role === 'manager'">
|
||||||
|
<h3> {{ t('contacts.settingsCompany') }} </h3>
|
||||||
|
<hr>
|
||||||
|
<CustomSwitch
|
||||||
|
:label="t('contacts.privacyCompanyLabel')"
|
||||||
|
v-model="privacy"
|
||||||
|
name="privacity"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
69
src/views/contacts/ContactsView.vue
Normal file
69
src/views/contacts/ContactsView.vue
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<script setup>
|
||||||
|
import { onMounted, ref, watch } from 'vue';
|
||||||
|
import { usePrivacyStore } from '../../stores/privacy';
|
||||||
|
import ContactCard from './components/ContactCard.vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import CustomSearchInput from '../../components/CustomSearchInput.vue';
|
||||||
|
import Spiner from '../../components/ui/Spiner.vue';
|
||||||
|
|
||||||
|
const privateStore = usePrivacyStore();
|
||||||
|
const contacts = ref([]);
|
||||||
|
const { t } = useI18n();
|
||||||
|
const query = ref('');
|
||||||
|
let timeout = null;
|
||||||
|
|
||||||
|
onMounted( async () => {
|
||||||
|
await privateStore.getPrivateList();
|
||||||
|
contacts.value = privateStore.privateList;
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(query, () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
search();
|
||||||
|
}, 400);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => privateStore.privateList,
|
||||||
|
(newValue) => {
|
||||||
|
contacts.value = newValue;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const search = () => {
|
||||||
|
if(query.value.length > 0) {
|
||||||
|
contacts.value = privateStore.privateList.filter(
|
||||||
|
(e) => e.company_name
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(query.value.toLocaleLowerCase()));
|
||||||
|
} else {
|
||||||
|
contacts.value = privateStore.privateList;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CustomSearchInput
|
||||||
|
:placeholder="t('carriers.searchByCarrier')"
|
||||||
|
v-model:saerch="query"
|
||||||
|
/>
|
||||||
|
<div class="row">
|
||||||
|
<div v-if="privateStore.loading" class="d-flex justify-content-center">
|
||||||
|
<Spiner />
|
||||||
|
</div>
|
||||||
|
<ContactCard
|
||||||
|
v-else
|
||||||
|
v-for="contact in contacts"
|
||||||
|
:key="contact.id"
|
||||||
|
:contact="contact"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
108
src/views/contacts/components/ContactCard.vue
Normal file
108
src/views/contacts/components/ContactCard.vue
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useAuthStore } from '../../../stores/auth';
|
||||||
|
import Swal from 'sweetalert2';
|
||||||
|
import { usePrivacyStore } from '../../../stores/privacy';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
contact: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
const contactsStore = usePrivacyStore();
|
||||||
|
|
||||||
|
const handleDeleteContact = async() => {
|
||||||
|
Swal.fire({
|
||||||
|
title: t('contacts.deleteCarrier'),
|
||||||
|
text: t('contacts.QuestionDeleteCarrier'),
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: t('buttons.delete'),
|
||||||
|
cancelButtonText: t('buttons.cancel'),
|
||||||
|
}).then(async(result) => {
|
||||||
|
const id = props.contact._id;
|
||||||
|
if(result.isConfirmed) {
|
||||||
|
Swal.fire({
|
||||||
|
title: t('messages.loading'),
|
||||||
|
allowOutsideClick: false,
|
||||||
|
didOpen: () => {
|
||||||
|
Swal.showLoading()
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const resp = await contactsStore.deleteCompanyToPrivateList(id);
|
||||||
|
Swal.close();
|
||||||
|
if(resp === 'success') {
|
||||||
|
Swal.fire({
|
||||||
|
text: t('messages.actionSuccess'),
|
||||||
|
icon: "success"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Swal.fire({
|
||||||
|
title: t('global.mistake'),
|
||||||
|
text: resp,
|
||||||
|
icon: "error"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const categories = computed(() => (props.contact.categories)
|
||||||
|
? props.contact.categories.map((e) => e.name).join(', ')
|
||||||
|
: ''
|
||||||
|
)
|
||||||
|
|
||||||
|
const truckTypes = computed(() => (props.contact.truck_type)
|
||||||
|
? props.contact.truck_type.join(', ')
|
||||||
|
: ''
|
||||||
|
)
|
||||||
|
|
||||||
|
const states = computed(() => (props.contact.company_state)
|
||||||
|
? props.contact.company_state.join(', ')
|
||||||
|
: ''
|
||||||
|
)
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="col-lg-6 col-12">
|
||||||
|
<div class="card-fixed flex-d-column">
|
||||||
|
<div class="d-flex">
|
||||||
|
<h2 class="flex1">{{ contact.company_name }}</h2>
|
||||||
|
<button
|
||||||
|
v-if="(authStore.user?.job_role === 'owner' || authStore.user?.job_role === 'manager')"
|
||||||
|
class="btn-primary-sm bg-danger sizeBtn"
|
||||||
|
@click="handleDeleteContact"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p><span class="font-bold">RFC: </span> {{ contact.rfc}}</p>
|
||||||
|
<p><span class="font-bold">{{ t('global.segments') }}:</span> {{ categories }}</p>
|
||||||
|
<p><span class="font-bold">{{ t('contacts.truckTypesUsed') }}: </span> {{ truckTypes }}</p>
|
||||||
|
<p><span class="font-bold">{{ t('global.states') }}: </span> {{ states }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.flex1 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sizeBtn {
|
||||||
|
width: 46px;
|
||||||
|
height: 40px;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -14,15 +14,17 @@
|
|||||||
import { useCompanyStore } from '../../../stores/company';
|
import { useCompanyStore } from '../../../stores/company';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import {getDateToLocal } from '../../../helpers/date_formats';
|
|
||||||
import { validateEmail } from '../../../helpers/validations';
|
import { validateEmail } from '../../../helpers/validations';
|
||||||
import AddressPreview from '../../../components/AddressPreview.vue';
|
import AddressPreview from '../../../components/AddressPreview.vue';
|
||||||
|
import CustomSwitch from '../../../components/CustomSwitch.vue';
|
||||||
|
import { usePrivacyStore } from '../../../stores/privacy';
|
||||||
|
|
||||||
|
|
||||||
const loadStore = useLoadsStore();
|
const loadStore = useLoadsStore();
|
||||||
const notyStore = useNotificationsStore();
|
const notyStore = useNotificationsStore();
|
||||||
const auth = useAuthStore();
|
const auth = useAuthStore();
|
||||||
const companyStore = useCompanyStore()
|
const companyStore = useCompanyStore()
|
||||||
|
const privacyStore = usePrivacyStore()
|
||||||
const windowWidth = ref(window.innerWidth);
|
const windowWidth = ref(window.innerWidth);
|
||||||
const zoom = ref(6);
|
const zoom = ref(6);
|
||||||
const heightMap = ref(768);
|
const heightMap = ref(768);
|
||||||
@@ -42,7 +44,8 @@
|
|||||||
const destinationRef = ref('')
|
const destinationRef = ref('')
|
||||||
const emails = ref([]);
|
const emails = ref([]);
|
||||||
const emailInput = ref('');
|
const emailInput = ref('');
|
||||||
|
const isPrivate = ref(false);
|
||||||
|
|
||||||
const errors = ref({
|
const errors = ref({
|
||||||
segment: null,
|
segment: null,
|
||||||
truckType: null,
|
truckType: null,
|
||||||
@@ -76,10 +79,12 @@
|
|||||||
zoom.value = 4;
|
zoom.value = 4;
|
||||||
heightMap.value = 420;
|
heightMap.value = 420;
|
||||||
}
|
}
|
||||||
|
isPrivate.value = privacyStore.privacy;
|
||||||
getLocations('unloading');
|
getLocations('unloading');
|
||||||
getLocations('loading');
|
getLocations('loading');
|
||||||
formLoad.owner = auth.user?.first_name + ' ' + auth.user?.last_name;
|
formLoad.owner = auth.user?.first_name + ' ' + auth.user?.last_name;
|
||||||
if(loadStore.currentLoad){
|
if(loadStore.currentLoad){
|
||||||
|
isPrivate.value = loadStore.currentLoad.privacy || false
|
||||||
const dateStart = loadStore.currentLoad.est_loading_date;
|
const dateStart = loadStore.currentLoad.est_loading_date;
|
||||||
const dateEnd = loadStore.currentLoad.est_unloading_date;
|
const dateEnd = loadStore.currentLoad.est_unloading_date;
|
||||||
formLoad.price = loadStore.currentLoad.actual_cost;
|
formLoad.price = loadStore.currentLoad.actual_cost;
|
||||||
@@ -257,7 +262,8 @@
|
|||||||
posted_by_name: formLoad.owner,
|
posted_by_name: formLoad.owner,
|
||||||
origin_warehouse: locationLoadSelected.value?._id || null,
|
origin_warehouse: locationLoadSelected.value?._id || null,
|
||||||
destination_warehouse: locationDownloadSelected.value?._id || null,
|
destination_warehouse: locationDownloadSelected.value?._id || null,
|
||||||
alert_list: emails.value.length > 0 ? emails.value : null
|
alert_list: emails.value.length > 0 ? emails.value : null,
|
||||||
|
privacy: isPrivate.value
|
||||||
};
|
};
|
||||||
return loadData;
|
return loadData;
|
||||||
}
|
}
|
||||||
@@ -605,6 +611,13 @@
|
|||||||
<div class="modal-footer custom-footer">
|
<div class="modal-footer custom-footer">
|
||||||
<Spiner v-if="isLoading"/>
|
<Spiner v-if="isLoading"/>
|
||||||
<div v-else class="btns-footer">
|
<div v-else class="btns-footer">
|
||||||
|
<div class="switch-container">
|
||||||
|
<CustomSwitch
|
||||||
|
:label="t('contacts.privacyLoadLabel')"
|
||||||
|
v-model="isPrivate"
|
||||||
|
name="contacts"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-danger"
|
class="btn btn-danger"
|
||||||
@@ -651,20 +664,22 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-footer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-msg {
|
.error-msg {
|
||||||
color: red;
|
color: red;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.custom-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
.btns-footer {
|
.btns-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chekmark {
|
.chekmark {
|
||||||
@@ -690,5 +705,15 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btns-footer {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-container {
|
||||||
|
flex: 1 1 100%;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -215,7 +215,7 @@
|
|||||||
<div v-if="!proposal.vehicle?.driver"
|
<div v-if="!proposal.vehicle?.driver"
|
||||||
class="box-note bg-warning mb-3"
|
class="box-note bg-warning mb-3"
|
||||||
>
|
>
|
||||||
<i class="fa-solid fa-triangle-exclamation"></i> Oferta sin conductor asignado. Solicite al transportista que asigne un operador para continuar con el proceso de carga.
|
<i class="fa-solid fa-triangle-exclamation"></i> {{ t('messages.notDriverAssign') }}
|
||||||
</div>
|
</div>
|
||||||
<Spiner v-if="isLoadingActions"/>
|
<Spiner v-if="isLoadingActions"/>
|
||||||
<div class="d-flex justify-content-end gap-3" v-else>
|
<div class="d-flex justify-content-end gap-3" v-else>
|
||||||
|
|||||||
@@ -9,7 +9,9 @@
|
|||||||
import Cities from '../../components/ui/Cities.vue';
|
import Cities from '../../components/ui/Cities.vue';
|
||||||
import Pagination from '../../components/Pagination.vue';
|
import Pagination from '../../components/Pagination.vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { usePrivacyStore } from '../../stores/privacy';
|
||||||
|
|
||||||
|
const privacyStore = usePrivacyStore();
|
||||||
const {loading, companies, getCompaniesData, companiesTotal, currentCompaniesPage} = useDirectory();
|
const {loading, companies, getCompaniesData, companiesTotal, currentCompaniesPage} = useDirectory();
|
||||||
const query = ref('');
|
const query = ref('');
|
||||||
const selectedTruckType = ref([]);
|
const selectedTruckType = ref([]);
|
||||||
@@ -22,10 +24,11 @@
|
|||||||
|
|
||||||
const limit = 10;
|
const limit = 10;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted( async () => {
|
||||||
filterQuery.value.company_type = 'carrier';
|
filterQuery.value.company_type = 'carrier';
|
||||||
filterQuery.value.limit = 'elements=' + limit;
|
filterQuery.value.limit = 'elements=' + limit;
|
||||||
filterQuery.value.page = "page=0";
|
filterQuery.value.page = "page=0";
|
||||||
|
await privacyStore.getPrivateList();
|
||||||
getCompaniesData(filterQuery.value);
|
getCompaniesData(filterQuery.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,65 @@
|
|||||||
import { RouterLink } from 'vue-router';
|
import { RouterLink } from 'vue-router';
|
||||||
import { getDateMonthDay } from '../../../helpers/date_formats';
|
import { getDateMonthDay } from '../../../helpers/date_formats';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import Swal from 'sweetalert2';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { useAuthStore } from '../../../stores/auth';
|
||||||
|
import { usePrivacyStore } from '../../../stores/privacy';
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
company: {
|
company: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
const privacyStore = usePrivacyStore();
|
||||||
|
const existInPrivateList = ref(false);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const id = props.company._id;
|
||||||
|
existInPrivateList.value = privacyStore.privateListRef.includes(id);
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleAddPrivateList = async() => {
|
||||||
|
Swal.fire({
|
||||||
|
title: t('contacts.privacyList'),
|
||||||
|
text: t('contacts.QuestionAddCarrier'),
|
||||||
|
icon: 'info',
|
||||||
|
showCancelButton: true,
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: t('buttons.yes'),
|
||||||
|
cancelButtonText: t('buttons.no'),
|
||||||
|
}).then(async(result) => {
|
||||||
|
if(result.isConfirmed) {
|
||||||
|
Swal.fire({
|
||||||
|
title: t('messages.loading'),
|
||||||
|
allowOutsideClick: false,
|
||||||
|
didOpen: () => {
|
||||||
|
Swal.showLoading()
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const response = await privacyStore.addCompanyToPrivateList(props.company._id);
|
||||||
|
Swal.close();
|
||||||
|
if(response === 'success') {
|
||||||
|
existInPrivateList.value = true;
|
||||||
|
Swal.fire({
|
||||||
|
text: t('messages.actionSuccess'),
|
||||||
|
icon: "success"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Error',
|
||||||
|
text: response,
|
||||||
|
icon: "error"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
</script>
|
</script>
|
||||||
@@ -30,9 +82,16 @@
|
|||||||
<p><span>{{ t('labels.infoCompany') }}: </span>{{company.company_description}}</p>
|
<p><span>{{ t('labels.infoCompany') }}: </span>{{company.company_description}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end gap-2">
|
||||||
|
<button
|
||||||
|
v-if="authStore.user?.permissions === 'role_shipper' && !existInPrivateList"
|
||||||
|
class="btn-primary-sm bg-dark radius-sm"
|
||||||
|
@click="handleAddPrivateList"
|
||||||
|
>
|
||||||
|
Añadir a lista privada
|
||||||
|
</button>
|
||||||
<RouterLink
|
<RouterLink
|
||||||
class="btn-primary-sm"
|
class="btn-primary-sm radius-sm"
|
||||||
:to="{name: 'public-users', params: {id: company._id}}"
|
:to="{name: 'public-users', params: {id: company._id}}"
|
||||||
>{{ t('buttons.profile') }}</RouterLink>
|
>{{ t('buttons.profile') }}</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user