Merge branch 'users_companies_migration'

This commit is contained in:
Josepablo C
2024-03-10 19:35:13 -06:00
28 changed files with 420 additions and 141 deletions

10
package-lock.json generated
View File

@@ -12,6 +12,7 @@
"chart.js": "^4.4.1", "chart.js": "^4.4.1",
"html2pdf.js": "^0.10.1", "html2pdf.js": "^0.10.1",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"polyline": "^0.2.0",
"qalendar": "^3.7.0", "qalendar": "^3.7.0",
"sass": "^1.69.5", "sass": "^1.69.5",
"sweetalert2": "^11.10.1", "sweetalert2": "^11.10.1",
@@ -1137,6 +1138,15 @@
} }
} }
}, },
"node_modules/polyline": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/polyline/-/polyline-0.2.0.tgz",
"integrity": "sha512-rCJSkIHWZ/HOUoEWgjZ1DrRjLpTeTjgaktyJV0yhm8PugM5sKoavNjUHtI/amjsTn/Tq+Q3IIAuBD/dUSsWwxQ==",
"deprecated": "This module is now under the @mapbox namespace: install @mapbox/polyline instead",
"engines": {
"node": "*"
}
},
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.31", "version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",

View File

@@ -12,6 +12,7 @@
"chart.js": "^4.4.1", "chart.js": "^4.4.1",
"html2pdf.js": "^0.10.1", "html2pdf.js": "^0.10.1",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"polyline": "^0.2.0",
"qalendar": "^3.7.0", "qalendar": "^3.7.0",
"sass": "^1.69.5", "sass": "^1.69.5",
"sweetalert2": "^11.10.1", "sweetalert2": "^11.10.1",

View File

@@ -85,6 +85,18 @@ body {
font-weight: 700; font-weight: 700;
} }
.btn-primary-nav {
background-color: #FBBA33;
padding: 8px 16px;
color: #323030;
font-size: 1.1rem;
border: none;
text-decoration: none;
text-align: center;
border-radius: 8px;
font-weight: 700;
}
.btn-primary-sm:hover { .btn-primary-sm:hover {
background-color: #e3a11e; background-color: #e3a11e;
transition: background-color 300ms ease; transition: background-color 300ms ease;

View File

@@ -25,7 +25,7 @@ import { ref } from 'vue';
<div v-if="open"> <div v-if="open">
<p <p
v-if="faq.answer" v-if="faq.answer"
class="answer">{{ faq.answer }}</p> class="answer" v-html="faq.answer"></p>
<ol> <ol>
<li class="step" v-for="step in faq.steps" v-html="step"></li> <li class="step" v-for="step in faq.steps" v-html="step"></li>
</ol> </ol>

View File

@@ -115,7 +115,7 @@
</p> </p>
</div> </div>
<div class="col-lg-6 col-sm-12" v-if="authStore.user?.permissions.includes('role_shipper')"> <div class="col-lg-6 col-sm-12" v-if="authStore.user?.permissions === 'role_shipper'">
<p><span>Status de la publicación:</span> <span>{{ getStatusPublished(load) }}</span></p> <p><span>Status de la publicación:</span> <span>{{ getStatusPublished(load) }}</span></p>
<p :style="{color: getStatusLoad(load).color}"><span>Status de la carga:</span> <span>{{ getStatusLoad(load).status }}</span></p> <p :style="{color: getStatusLoad(load).color}"><span>Status de la carga:</span> <span>{{ getStatusLoad(load).status }}</span></p>
</div> </div>
@@ -149,7 +149,7 @@
<div v-if="load.notes" class="box-note"> <div v-if="load.notes" class="box-note">
{{ load.notes }} {{ load.notes }}
</div> </div>
<div class="btn-row" v-if="!readOnly && authStore.user?.permissions.includes('role_shipper')"> <div class="btn-row" v-if="!readOnly && authStore.user?.permissions === 'role_shipper'">
<button <button
class="btn-primary-sm bg-dark" class="btn-primary-sm bg-dark"
@click="handleDeleteLoad" @click="handleDeleteLoad"
@@ -164,7 +164,6 @@
Evidencias Evidencias
</button> </button>
<button <button
v-if="load.load_status !== 'Delivered'"
class="btn-primary-sm" class="btn-primary-sm"
data-toggle="modal" data-target="#formLoadModal" data-toggle="modal" data-target="#formLoadModal"
@click="openEditModal" @click="openEditModal"
@@ -177,7 +176,7 @@
data-target="#proposalsModal" data-target="#proposalsModal"
>#{{ load.no_of_proposals }} Ofertas</button> >#{{ load.no_of_proposals }} Ofertas</button>
</div> </div>
<div class="btn-row" v-if="!readOnly && authStore.user?.permissions.includes('role_carrier')"> <div class="btn-row" v-if="!readOnly && authStore.user?.permissions === 'role_carrier'">
<button <button
class="btn-primary-sm bg-dark" class="btn-primary-sm bg-dark"
data-toggle="modal" data-toggle="modal"

View File

@@ -208,7 +208,7 @@
<option disabled value="">-- Seleccionar rol --</option> <option disabled value="">-- Seleccionar rol --</option>
<option value="owner">Dueño</option> <option value="owner">Dueño</option>
<option value="manager">Gerente</option> <option value="manager">Gerente</option>
<option v-if="authStore.user?.permissions.includes('role_carrier')" value="driver">Conductor</option> <option v-if="authStore.user?.permissions === 'role_carrier'" value="driver">Conductor</option>
</select> </select>
</div> </div>
<div class="mb-4 mt-3"> <div class="mb-4 mt-3">

View File

@@ -25,16 +25,16 @@
onMounted(() => { onMounted(() => {
props.data.forEach(item => { props.data.forEach(item => {
const index = dataMap.value.findIndex((e) => e.label === item); const index = dataMap.value.findIndex((e) => e.name?.toUpperCase() === item?.toUpperCase());
if(index === -1) { // Lo agrega
if(index === -1) {
if(props.dataModel) { if(props.dataModel) {
const itemModel = props.dataModel.find((e) => e[props.targetFind] === item); const itemModel = props.dataModel.find((e) => e[props.targetFind].toUpperCase() === item.toUpperCase());
dataMap.value.push({ const itemTem = {
label: (props.targetLabel) ? itemModel[props.targetLabel] : item, label: (props.targetLabel) ? itemModel[props.targetLabel] : item,
data: 1, data: 1,
...itemModel ...itemModel
}) };
dataMap.value.push(itemTem)
} else { } else {
dataMap.value.push({ dataMap.value.push({
label: item, label: item,
@@ -42,11 +42,10 @@
color: 'green' color: 'green'
}); });
} }
} else { } else { // Lo actualiza
dataMap.value[index].data += 1; dataMap.value[index].data += 1;
} }
}); });
chartData.value = { chartData.value = {
labels: dataMap.value.map((e) => e.label), labels: dataMap.value.map((e) => e.label),
datasets: [{ datasets: [{

View File

@@ -24,12 +24,13 @@
const heightMap = ref(768); const heightMap = ref(768);
const originCoords = ref(null); const originCoords = ref(null);
const destinationCoords = ref(null); const destinationCoords = ref(null);
const polylines = ref([]);
const startLocation = ref(null); const startLocation = ref(null);
const endLocation = ref(null); const endLocation = ref(null);
const isLoading = ref(false); const isLoading = ref(false);
const loadingLocations = ref(false); const loadingLocations = ref(false);
const submited = ref(false); const submited = ref(false);
const { geocodeAddress } = useDirectionsRender(); const { geocodeAddress, getDirections } = useDirectionsRender();
const formRef = ref(null); const formRef = ref(null);
const filterQueryVehicles = ref([]); const filterQueryVehicles = ref([]);
const checkLocationLoad = ref(false); const checkLocationLoad = ref(false);
@@ -46,6 +47,8 @@
stateDestination: null, stateDestination: null,
}); });
const mapKey = import.meta.env.VITE_MAP_KEY;
const clearLoad = () => { const clearLoad = () => {
loadStore.currentLoad = null; loadStore.currentLoad = null;
@@ -124,6 +127,13 @@
destinationCoords.value = await geocodeAddress(endLocation.value); destinationCoords.value = await geocodeAddress(endLocation.value);
} }
}) })
watch([originCoords, destinationCoords], async() => {
if(originCoords.value && destinationCoords.value) {
console.log('Se llama api direcciones ')
polylines.value = await getDirections(originCoords.value, destinationCoords.value);
}
})
}) })
watch(locationLoadSelected, () => { watch(locationLoadSelected, () => {
@@ -510,7 +520,7 @@
v-model="locationDownloadSelected" v-model="locationDownloadSelected"
> >
<option disabled value="">-- Seleccionar locación --</option> <option disabled value="">-- Seleccionar locación --</option>
<option v-for="loc in companyStore.locations" :value="loc">{{ loc.branch_name }}</option> <option v-for="loc in companyStore.locationsLoads" :value="loc">{{ loc.branch_name }}</option>
</select> </select>
</div> </div>
<Custominput <Custominput
@@ -566,7 +576,7 @@
</div> </div>
</form> </form>
<GoogleMap <GoogleMap
api-key="AIzaSyAJtfvrAKy7vnUSv2nzk4dYQkOs3OP4MMs" :api-key="mapKey"
:center="{lat:19.432600, lng:-99.133209}" :center="{lat:19.432600, lng:-99.133209}"
:zoom="zoom" :zoom="zoom"
:min-zoom="2" :min-zoom="2"
@@ -583,13 +593,18 @@
> >
<Marker v-if="originCoords" :options="{position: originCoords, label: 'O', title: 'Destino'}" /> <Marker v-if="originCoords" :options="{position: originCoords, label: 'O', title: 'Destino'}" />
<Marker v-if="destinationCoords" :options="{position: destinationCoords, label: 'D', title: 'Origen'}" /> <Marker v-if="destinationCoords" :options="{position: destinationCoords, label: 'D', title: 'Origen'}" />
<!-- <Polyline :options="{ <Polyline
path: polyline, v-if="polylines"
// geodesic: true, :options="{
strokeColor: '#FF0000', path: polylines,
strokeOpacity: 1.0, // geodesic: true,
strokeWeight: 2 strokeColor: '#2D90BB',
}" /> --> strokeOpacity: 0.7,
strokeWeight: 5,
clickable: true,
fillColor: '#75ad3e',
}"
/>
</GoogleMap> </GoogleMap>
</div> </div>
<div class="modal-footer custom-footer"> <div class="modal-footer custom-footer">

View File

@@ -2,15 +2,17 @@
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import CardEmpty from './CardEmpty.vue'; import CardEmpty from './CardEmpty.vue';
import Spiner from './ui/Spiner.vue'; import Spiner from './ui/Spiner.vue';
import { GoogleMap, Marker, CustomMarker } from 'vue3-google-map'; import { GoogleMap, Marker, CustomMarker, Polyline } from 'vue3-google-map';
import useDirectionsRender from '../composables/useDirectionRender'; import useDirectionsRender from '../composables/useDirectionRender';
import Cardload from './CardLoad.vue'; import Cardload from './CardLoad.vue';
import { useLoadsStore } from '../stores/loads'; import { useLoadsStore } from '../stores/loads';
const mapKey = import.meta.env.VITE_MAP_KEY;
const zoom = ref(6); const zoom = ref(6);
const heightMap = ref(768); const heightMap = ref(768);
const originCoords = ref(null); const originCoords = ref(null);
const polylines = ref([]);
const destinationCoords = ref(null); const destinationCoords = ref(null);
const isLoading = ref(false); const isLoading = ref(false);
const windowWidth = ref(window.innerWidth); const windowWidth = ref(window.innerWidth);
@@ -18,7 +20,7 @@
const vehicleLastLocation = ref(null); const vehicleLastLocation = ref(null);
const isLoadActive = ref(false); const isLoadActive = ref(false);
const { geocodeAddress } = useDirectionsRender() const { geocodeAddress, getDirections } = useDirectionsRender()
const props = defineProps({ const props = defineProps({
proposal: { proposal: {
@@ -50,6 +52,7 @@
load.value = resp.data[0]; load.value = resp.data[0];
originCoords.value = await geocodeAddress(load.value.origin_formatted_address); originCoords.value = await geocodeAddress(load.value.origin_formatted_address);
destinationCoords.value = await geocodeAddress(load.value.destination_formatted_address); destinationCoords.value = await geocodeAddress(load.value.destination_formatted_address);
polylines.value = await getDirections(originCoords.value, destinationCoords.value);
if(load.value.vehicle) { if(load.value.vehicle) {
vehicleLastLocation.value = { vehicleLastLocation.value = {
lat: parseFloat(load.value.vehicle.last_location_lat), lat: parseFloat(load.value.vehicle.last_location_lat),
@@ -113,7 +116,7 @@
<div v-if="load"> <div v-if="load">
<Cardload :load="load" :read-only="true"/> <Cardload :load="load" :read-only="true"/>
<GoogleMap <GoogleMap
api-key="AIzaSyAJtfvrAKy7vnUSv2nzk4dYQkOs3OP4MMs" :api-key="mapKey"
:center="{lat:19.432600, lng:-99.133209}" :center="{lat:19.432600, lng:-99.133209}"
:zoom="zoom" :zoom="zoom"
:min-zoom="2" :min-zoom="2"
@@ -141,13 +144,18 @@
<i class="fa-solid fa-truck" :style="{fontSize: 25 + 'px', color: 'green'}"></i> <i class="fa-solid fa-truck" :style="{fontSize: 25 + 'px', color: 'green'}"></i>
</div> </div>
</CustomMarker> </CustomMarker>
<!-- <Polyline :options="{ <Polyline
path: polyline, v-if="polylines"
// geodesic: true, :options="{
strokeColor: '#FF0000', path: polylines,
strokeOpacity: 1.0, // geodesic: true,
strokeWeight: 2 strokeColor: '#2D90BB',
}" /> --> strokeOpacity: 0.7,
strokeWeight: 5,
clickable: true,
fillColor: '#75ad3e',
}"
/>
</GoogleMap> </GoogleMap>
</div> </div>
<CardEmpty v-else text="No hay información disponible"/> <CardEmpty v-else text="No hay información disponible"/>

View File

@@ -3,7 +3,7 @@
import CardEmpty from './CardEmpty.vue'; import CardEmpty from './CardEmpty.vue';
import Spiner from './ui/Spiner.vue'; import Spiner from './ui/Spiner.vue';
import BadgeError from './ui/BadgeError.vue'; import BadgeError from './ui/BadgeError.vue';
import { GoogleMap, Marker } from 'vue3-google-map'; import { GoogleMap, Marker, Polyline } from 'vue3-google-map';
import useDirectionsRender from '../composables/useDirectionRender'; import useDirectionsRender from '../composables/useDirectionRender';
import { useAuthStore } from '../stores/auth'; import { useAuthStore } from '../stores/auth';
import { useCompanyStore } from '../stores/company'; import { useCompanyStore } from '../stores/company';
@@ -11,11 +11,13 @@
import { saveProposal } from '../services/vehicles' import { saveProposal } from '../services/vehicles'
import Swal from 'sweetalert2'; import Swal from 'sweetalert2';
const mapKey = import.meta.env.VITE_MAP_KEY;
const zoom = ref(6); const zoom = ref(6);
const heightMap = ref(768); const heightMap = ref(768);
const originCoords = ref(null); const originCoords = ref(null);
const destinationCoords = ref(null); const destinationCoords = ref(null);
const polylines = ref([]);
const isLoading = ref(false); const isLoading = ref(false);
const loadingSubmit = ref(false); const loadingSubmit = ref(false);
const windowWidth = ref(window.innerWidth); const windowWidth = ref(window.innerWidth);
@@ -28,7 +30,7 @@
comments: '', comments: '',
}); });
const { geocodeAddress } = useDirectionsRender() const { geocodeAddress, getDirections } = useDirectionsRender()
const props = defineProps({ const props = defineProps({
load: { load: {
@@ -61,6 +63,7 @@
await vehiclesStore.fetchVehicles(filterQuery); await vehiclesStore.fetchVehicles(filterQuery);
originCoords.value = await geocodeAddress(props.load.origin_formatted_address); originCoords.value = await geocodeAddress(props.load.origin_formatted_address);
destinationCoords.value = await geocodeAddress(props.load.destination_formatted_address); destinationCoords.value = await geocodeAddress(props.load.destination_formatted_address);
polylines.value = await getDirections(originCoords.value, destinationCoords.value);
isLoading.value = false; isLoading.value = false;
console.log(props.proposal); console.log(props.proposal);
if(props.proposal) { if(props.proposal) {
@@ -204,7 +207,7 @@
</form> </form>
<GoogleMap <GoogleMap
v-if="!proposal" v-if="!proposal"
api-key="AIzaSyAJtfvrAKy7vnUSv2nzk4dYQkOs3OP4MMs" :api-key="mapKey"
:center="{lat:19.432600, lng:-99.133209}" :center="{lat:19.432600, lng:-99.133209}"
:zoom="zoom" :zoom="zoom"
:min-zoom="2" :min-zoom="2"
@@ -221,13 +224,18 @@
> >
<Marker v-if="originCoords" :options="{position: originCoords, label: 'O', title: 'Destino'}" /> <Marker v-if="originCoords" :options="{position: originCoords, label: 'O', title: 'Destino'}" />
<Marker v-if="destinationCoords" :options="{position: destinationCoords, label: 'D', title: 'Origen'}" /> <Marker v-if="destinationCoords" :options="{position: destinationCoords, label: 'D', title: 'Origen'}" />
<!-- <Polyline :options="{ <Polyline
path: polyline, v-if="polylines"
// geodesic: true, :options="{
strokeColor: '#FF0000', path: polylines,
strokeOpacity: 1.0, // geodesic: true,
strokeWeight: 2 strokeColor: '#2D90BB',
}" /> --> strokeOpacity: 0.7,
strokeWeight: 5,
clickable: true,
fillColor: '#75ad3e',
}"
/>
</GoogleMap> </GoogleMap>
</div> </div>
<CardEmpty v-else text="No hay coincidencia"/> <CardEmpty v-else text="No hay coincidencia"/>

View File

@@ -10,6 +10,7 @@
const polyline = ref([]); const polyline = ref([]);
// const startLocation = ref({ lat: 37.7749, lng: -122.4194 }); // San Francisco // const startLocation = ref({ lat: 37.7749, lng: -122.4194 }); // San Francisco
// const endLocation = ref({ lat: 34.0522, lng: -118.2437 }); // Los Angeles // const endLocation = ref({ lat: 34.0522, lng: -118.2437 }); // Los Angeles
const mapKey = import.meta.env.VITE_MAP_KEY;
onMounted(async() => { onMounted(async() => {
window.addEventListener('resize', handleResize); window.addEventListener('resize', handleResize);
@@ -80,7 +81,7 @@
<template> <template>
<GoogleMap <GoogleMap
api-key="AIzaSyAJtfvrAKy7vnUSv2nzk4dYQkOs3OP4MMs" :api-key="mapKey"
:center="{lat:19.432600, lng:-99.133209}" :center="{lat:19.432600, lng:-99.133209}"
:zoom="zoom" :zoom="zoom"
:min-zoom="2" :min-zoom="2"

View File

@@ -19,17 +19,17 @@
</button> </button>
<div class="nav-options"> <div class="nav-options">
<RouterLink <RouterLink
v-if="auth.user?.permissions.includes('role_shipper')" v-if="auth.user?.permissions === 'role_shipper'"
active-class="router-link-active" active-class="router-link-active"
class="nav-link" :to="{name: 'carriers'}">Transportistas</RouterLink> class="nav-link" :to="{name: 'carriers'}">Transportistas</RouterLink>
<RouterLink <RouterLink
v-if="auth.user?.permissions.includes('role_carrier')" v-if="auth.user?.permissions === 'role_carrier'"
active-class="router-link-active" active-class="router-link-active"
class="nav-link" :to="{name: 'search-loads'}">Cargas</RouterLink> class="nav-link" :to="{name: 'search-loads'}"> <i class="fa-solid fa-truck-ramp-box me-1"></i> Cargas</RouterLink>
<RouterLink <RouterLink
v-if="auth.user?.permissions.includes('role_carrier')" v-if="auth.user?.permissions === 'role_carrier'"
active-class="router-link-active" active-class="router-link-active"
class="nav-link" :to="{name: 'shippers'}">Embarcadores</RouterLink> class="nav-link" :to="{name: 'shippers'}"><i class="fa-solid fa-book me-1"></i> Embarcadores</RouterLink>
</div> </div>
</div> </div>
</nav> </nav>
@@ -40,17 +40,21 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: end; justify-content: end;
align-items: center;
} }
.custom-navbar { .custom-navbar {
display: block; display: block;
width: calc(100vw - 220px); width: calc(100vw - 220px);
background-color: #FFF; background-color: #FFF;
padding: 16px 0px;
} }
.nav-options { .nav-options {
margin-left: 32px;
display: flex; display: flex;
margin-left: 32px;
gap: 1rem;
margin-right: 32px;
} }
.btn-menu { .btn-menu {
@@ -59,8 +63,8 @@
.nav-link{ .nav-link{
cursor: pointer; cursor: pointer;
color: #413f3c; color: #FBBA33;
font-size: 1.2rem; font-size: 1.3rem;
margin-right: 1.2rem; margin-right: 1.2rem;
font-weight: 500; font-weight: 500;
} }
@@ -83,6 +87,18 @@
@media (max-width: 768px) { @media (max-width: 768px) {
.nav-options {
margin-left: 8px;
margin-right: 8px;
gap: 0.5rem;
}
.nav-link{
font-size: 1.1rem;
margin-right: 1.2rem;
font-weight: 500;
}
.custom-navbar { .custom-navbar {
width: 100vw !important; width: 100vw !important;
} }

View File

@@ -1,20 +1,26 @@
<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';
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const auth = useAuthStore(); const auth = useAuthStore();
const handleLogout = () => { const handleLogout = () => {
// auth.$patch({ Swal.fire({
// sesion: '', title: 'Cerrar sesión',
// token: '', text: '¿Estás seguro de cerrar sesión?',
// user: {}, icon: 'question',
// }); showCancelButton: true,
// localStorage.removeItem('session'); cancelButtonColor: "#d33",
// router.push({name: 'login'}); confirmButtonText: 'Si',
auth.logout(); cancelButtonText: 'No',
}).then(async(result) => {
if(result.isConfirmed) {
auth.logout();
}
});
} }
</script> </script>
@@ -22,7 +28,9 @@
<nav id="sidebar"> <nav id="sidebar">
<div class="sidebar-header"> <div class="sidebar-header">
<div class="logo"> <div class="logo">
<img src="/images/logo-eta.png" alt="Eta viaporte" width="120"> <a href="https://etaviaporte.com/" target="_blank">
<img src="/images/logo-eta.png" alt="Eta viaporte" width="120">
</a>
</div> </div>
<h2 class="my-4">COVO</h2> <h2 class="my-4">COVO</h2>
<p><i class="fa-solid fa-user"></i> <span class="ms-2">{{ auth.user?.first_name + ' ' + auth.user?.last_name }}</span></p> <p><i class="fa-solid fa-user"></i> <span class="ms-2">{{ auth.user?.first_name + ' ' + auth.user?.last_name }}</span></p>
@@ -62,7 +70,7 @@
</div> </div>
</li> </li>
<li <li
v-if="auth.user?.permissions.includes('role_carrier')" v-if="auth.user?.permissions === 'role_carrier'"
:class="[route.name === 'vehicles' ? 'bg-nav-active' : '']"> :class="[route.name === 'vehicles' ? 'bg-nav-active' : '']">
<div> <div>
<i class="fa-solid fa-truck-fast" :class="[route.name === 'vehicles' ? 'router-link-active' : '']"></i> <i class="fa-solid fa-truck-fast" :class="[route.name === 'vehicles' ? 'router-link-active' : '']"></i>
@@ -71,7 +79,7 @@
class="nav-link" :to="{name: 'vehicles'}">Vehiculos</RouterLink> class="nav-link" :to="{name: 'vehicles'}">Vehiculos</RouterLink>
</div> </div>
</li> </li>
<li v-if="auth.user?.permissions.includes('role_shipper')" :class="[route.name === 'published-loads' ? 'bg-nav-active' : '']"> <li v-if="auth.user?.permissions === 'role_shipper'" :class="[route.name === 'published-loads' ? 'bg-nav-active' : '']">
<div> <div>
<i class="fa-solid fa-bullhorn" :class="[route.name === 'published-loads' ? 'router-link-active' : '']"></i> <i class="fa-solid fa-bullhorn" :class="[route.name === 'published-loads' ? 'router-link-active' : '']"></i>
<RouterLink <RouterLink
@@ -79,12 +87,12 @@
class="nav-link" :to="{name: 'published-loads'}">Publicaciones</RouterLink> class="nav-link" :to="{name: 'published-loads'}">Publicaciones</RouterLink>
</div> </div>
</li> </li>
<li v-if="auth.user?.permissions.includes('role_carrier')" :class="[route.name === 'published-trucks' ? 'bg-nav-active' : '']"> <li v-if="auth.user?.permissions === 'role_carrier'" :class="[route.name === 'published-trucks' ? 'bg-nav-active' : '']">
<div> <div>
<i class="fa-solid fa-bullhorn" :class="[route.name === 'published-trucks' ? 'router-link-active' : '']"></i> <i class="fa-solid fa-bullhorn" :class="[route.name === 'published-trucks' ? 'router-link-active' : '']"></i>
<RouterLink <RouterLink
active-class="" active-class=""
class="nav-link" :to="{name: 'published-trucks'}">Publicaciones</RouterLink> class="nav-link" :to="{name: 'published-trucks'}">Ofertas aceptadas</RouterLink>
</div> </div>
</li> </li>
<li :class="[route.name === 'calendar' ? 'bg-nav-active' : '']"> <li :class="[route.name === 'calendar' ? 'bg-nav-active' : '']">
@@ -96,7 +104,7 @@
</div> </div>
</li> </li>
<li <li
v-if="auth.user?.permissions.includes('role_carrier')" v-if="auth.user?.permissions === 'role_carrier'"
:class="[route.name === 'calculator' ? 'bg-nav-active' : '']"> :class="[route.name === 'calculator' ? 'bg-nav-active' : '']">
<div> <div>
<i class="fa-solid fa-calculator" :class="[route.name === 'calculator' ? 'router-link-active' : '']"></i> <i class="fa-solid fa-calculator" :class="[route.name === 'calculator' ? 'router-link-active' : '']"></i>

View File

@@ -12,9 +12,6 @@
const companyStore = useCompanyStore() const companyStore = useCompanyStore()
const notifications = useNotificationsStore() const notifications = useNotificationsStore()
console.log(companyStore.company?.categories);
const loading = ref(false); const loading = ref(false);
const msgError = ref(''); const msgError = ref('');
const companyCategories = ref([]); const companyCategories = ref([]);

View File

@@ -1,18 +1,21 @@
import { ref } from "vue"; import { ref } from "vue";
import { decode } from 'polyline';
export default function useDirectionsRender() { export default function useDirectionsRender() {
const mapKey = import.meta.env.VITE_MAP_KEY;
const originCoords = ref(null); const originCoords = ref(null);
const destinationCoords = ref(null); const destinationCoords = ref(null);
const polylines = ref([]); // const polylines = ref([]);
const geocodeAddress = async (address) => { const geocodeAddress = async (address) => {
// Utiliza la API de geocodificación de Google Maps para obtener las coordenadas // Utiliza la API de geocodificación de Google Maps para obtener las coordenadas
const apiKey = 'AIzaSyAJtfvrAKy7vnUSv2nzk4dYQkOs3OP4MMs'; // Reemplaza con tu clave de API // const apiKey = 'AIzaSyAJtfvrAKy7vnUSv2nzk4dYQkOs3OP4MMs'; // Reemplaza con tu clave de API
try { try {
const response = await fetch( const response = await fetch(
`https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent( `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(
address address
)}&key=${apiKey}` )}&key=${mapKey}`
); );
const data = await response.json(); const data = await response.json();
const location = data.results[0].geometry.location; const location = data.results[0].geometry.location;
@@ -22,26 +25,33 @@ export default function useDirectionsRender() {
} }
}; };
const getDirections = async () => { const getDirections = async (originCoords, destinationCoords) => {
const apiKey = 'AIzaSyAJtfvrAKy7vnUSv2nzk4dYQkOs3OP4MMs'; const originLatLng = `${originCoords.lat},${originCoords.lng}`;
const originLatLng = `${originCoords.value.lat},${originCoords.value.lng}`; const destinationLatLng = `${destinationCoords.lat},${destinationCoords.lng}`;
const destinationLatLng = `${destinationCoords.value.lat},${destinationCoords.value.lng}`;
try { try {
const response = await fetch( let url = `https://maps.googleapis.com/maps/api/directions/json?origin=${originLatLng}&destination=${destinationLatLng}&mode=driving&key=${mapKey}`;
`https://maps.googleapis.com/maps/api/directions/json?origin=${originLatLng}&destination=${destinationLatLng}&key=${apiKey}` const response = await fetch(url);
);
const data = await response.json(); const data = await response.json();
let polylines = [];
if (data.routes && data.routes.length > 0) { if (data.routes && data.routes.length > 0) {
const steps = data.routes[0].legs[0].steps; const steps = data.routes[0].legs[0].steps;
const routePolyline = steps.map((step) => ({ steps.forEach(item => {
lat: step.end_location.lat, const points = decode(item.polyline.points);
lng: step.end_location.lng, points.forEach(poly => {
})); polylines.push({
polylines.value = routePolyline; lat: poly[0],
lng: poly[1]
})
})
});
console.log(polylines)
return polylines;
} else {
return [];
} }
} catch (error) { } catch (error) {
console.log(error); console.log(error);
return [];
} }
}; };
@@ -49,6 +59,6 @@ export default function useDirectionsRender() {
originCoords, originCoords,
geocodeAddress, geocodeAddress,
getDirections, getDirections,
polylines // polylines
} }
} }

View File

@@ -64,7 +64,7 @@
}, },
{ {
"question": "¿Dónde puedo encontrar más ayuda y soporte si tengo otras preguntas?", "question": "¿Dónde puedo encontrar más ayuda y soporte si tengo otras preguntas?",
"answer": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Consectetur libero id faucibus nisl tincidunt eget nullam non nisi." "answer": "Puedes contactarnos por el siguiente correo: contacto@etaviaporte.com o si lo prefieres por los siguientes numeros: +52 999 200 2200, +52 9992 002 2221, nuestro horario de atención es de 9:00 - 16:00 de lunes a viernes"
} }
] ]
}, },
@@ -170,7 +170,7 @@
}, },
{ {
"question": "¿Qué debo hacer si tengo un problema con una carga o un transporte?", "question": "¿Qué debo hacer si tengo un problema con una carga o un transporte?",
"answer": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Consectetur libero id faucibus nisl tincidunt eget nullam non nisi." "answer": "Puedes contactarnos por el siguiente correo: <b>contacto@etaviaporte.com</b> o si lo prefieres por los siguientes numeros: <b>+52 999 200 2200</b>, <b>+52 9992 002 2221</b>, nuestro horario de atención es de 9:00 - 16:00 de lunes a viernes"
} }
] ]
}, },

View File

@@ -1,12 +1,28 @@
import axios from "axios"; import axios from "axios";
const baseUrl = import.meta.env.VITE_API_URL; const baseUrl = import.meta.env.VITE_API_URL;
const accessToken = localStorage.getItem('access');
const api = axios.create({ const api = axios.create({
baseURL: baseUrl, baseURL: baseUrl
headers: {
'Authorization': 'Bearer ' + accessToken
}
}); });
// Interceptar las solicitudes antes de enviarlas
api.interceptors.request.use(
(config) => {
// Obtener el token de acceso actualizado del localStorage
const accessToken = localStorage.getItem('access');
// Verificar si hay un token de acceso y agregarlo al encabezado de autorización
if (accessToken) {
config.headers.Authorization = `Bearer ${accessToken}`;
}
return config;
},
(error) => {
// Manejar errores de solicitud
return Promise.reject(error);
}
);
export default api; export default api;

9
src/lib/axiosPublic.js Normal file
View File

@@ -0,0 +1,9 @@
import axios from "axios";
const baseUrl = import.meta.env.VITE_API_URL;
const apiPublic = axios.create({
baseURL: baseUrl,
});
export default apiPublic;

View File

@@ -1,12 +1,10 @@
import api from "../lib/axios"; import apiPublic from "../lib//axiosPublic";
import {messagesError} from '../helpers/validations'; import {messagesError} from '../helpers/validations';
export const login = async(body) => { export const login = async(body) => {
try { try {
const endpoint = "/v1/account/authorize"; const endpoint = "/v1/account/authorize";
const {data} = await api.post(endpoint, body); const {data} = await apiPublic.post(endpoint, body);
console.log(data);
console.log(data.accessToken);
if(data.accessToken !== null){ if(data.accessToken !== null){
if(data.user.job_role !== 'driver'){ if(data.user.job_role !== 'driver'){
//TODO: Guardar token y datos del usuario //TODO: Guardar token y datos del usuario
@@ -37,7 +35,7 @@ export const renewToken = async() => {
const session = localStorage.getItem('session'); const session = localStorage.getItem('session');
try { try {
const endpoint = `/v1/account/authorize/${session}`; const endpoint = `/v1/account/authorize/${session}`;
const {data} = await api.get(endpoint); const {data} = await apiPublic.get(endpoint);
console.log(data); console.log(data);
if(data.accessToken !== null){ if(data.accessToken !== null){
return { return {
@@ -63,7 +61,7 @@ export const renewToken = async() => {
export const regiter = async(body) => { export const regiter = async(body) => {
try { try {
const endpoint = "/v1/account/signup"; const endpoint = "/v1/account/signup";
const {data} = await api.post(endpoint, body); const {data} = await apiPublic.post(endpoint, body);
return { return {
msg: 'success', msg: 'success',
data data
@@ -79,7 +77,7 @@ export const regiter = async(body) => {
export const regiterConfirm = async(body) => { export const regiterConfirm = async(body) => {
try { try {
const endpoint = "/v1/account/signup"; const endpoint = "/v1/account/signup";
const {data} = await api.patch(endpoint, body); const {data} = await apiPublic.patch(endpoint, body);
return { return {
msg: 'success', msg: 'success',
data data
@@ -103,7 +101,7 @@ export const regiterConfirm = async(body) => {
export const recoveryPassword = async(body) => { export const recoveryPassword = async(body) => {
try { try {
const endpoint = "/v1/account/recover"; const endpoint = "/v1/account/recover";
const {data} = await api.post(endpoint, body); const {data} = await apiPublic.post(endpoint, body);
return { return {
msg: 'success', msg: 'success',
data data
@@ -120,7 +118,7 @@ export const recoveryPassword = async(body) => {
export const recoveryPasswordConfirm = async(body) => { export const recoveryPasswordConfirm = async(body) => {
try { try {
const endpoint = "/v1/account/recover"; const endpoint = "/v1/account/recover";
const {data} = await api.patch(endpoint, body); const {data} = await apiPublic.patch(endpoint, body);
return { return {
msg: 'success', msg: 'success',
data data

View File

@@ -5,6 +5,7 @@ import { renewToken } from '../services/auth';
import {useNotificationsStore} from './notifications'; import {useNotificationsStore} from './notifications';
import {useCompanyStore} from './company'; import {useCompanyStore} from './company';
import { useLoadsStore } from "./loads"; import { useLoadsStore } from "./loads";
import { useVehiclesStore } from "./vehicles";
export const useAuthStore = defineStore('auth', () => { export const useAuthStore = defineStore('auth', () => {
@@ -12,6 +13,7 @@ export const useAuthStore = defineStore('auth', () => {
const noty = useNotificationsStore(); const noty = useNotificationsStore();
const company = useCompanyStore(); const company = useCompanyStore();
const loadStore = useLoadsStore(); const loadStore = useLoadsStore();
const vehiclesStore = useVehiclesStore();
const sesion = ref('') const sesion = ref('')
const checking = ref(false); const checking = ref(false);
const authStatus = ref('checking'); const authStatus = ref('checking');
@@ -54,16 +56,20 @@ export const useAuthStore = defineStore('auth', () => {
}); });
const logout = () => { const logout = () => {
console.log('logoo....');
sesion.value = '';
token.value = '';
company.clear();
localStorage.clear();
user.value = null;
console.log(company.company);
localStorage.removeItem('access'); localStorage.removeItem('access');
localStorage.removeItem('id'); localStorage.removeItem('id');
localStorage.removeItem('session'); localStorage.removeItem('session');
sesion.value = '';
token.value = '';
user.value = null;
checking.value = false;
authStatus.value = 'checking'
company.clear();
loadStore.clear();
vehiclesStore.clear();
router.push({name: 'login'}); router.push({name: 'login'});
} }

View File

@@ -25,6 +25,7 @@ export const useCompanyStore = defineStore('company', () => {
const getCompanyData = async() => { const getCompanyData = async() => {
const companyId = localStorage.getItem('id'); const companyId = localStorage.getItem('id');
console.log({companyId});
loading.value = true; loading.value = true;
if(!company.value) { if(!company.value) {
loading.value = true; loading.value = true;
@@ -139,15 +140,19 @@ export const useCompanyStore = defineStore('company', () => {
const clear = () => { //Cuando se cierra la sesion const clear = () => { //Cuando se cierra la sesion
company.value = null; company.value = null;
users.value = []; users.value = [];
drivers.value = [];
usersTotal.value = 0; usersTotal.value = 0;
usersCurrentPage.value = 1; usersCurrentPage.value = 1;
drivers.value = [];
budgets.value = []; budgets.value = [];
proposals.value = []; budgetsTotal.value = 0;
budgetsCurrentPage.value = 1;
locations.value = []; locations.value = [];
locationsLoads.value = []; locationsLoads.value = [];
locationsTotal.value = 0; locationsTotal.value = 0;
locationsCurrentPage.value = 1; locationsCurrentPage.value = 1;
proposals.value = [];
proposalsTotal.value = 0;
proposalsCurrentPage.value = 1;
// companyid = null; // companyid = null;
loading.value = false; loading.value = false;
} }

View File

@@ -6,6 +6,7 @@ export const useLoadsStore = defineStore('load', () => {
const currentLoad = ref(null); const currentLoad = ref(null);
const loads = ref([]) const loads = ref([])
const loadsDashboard = ref([]);
const loadsTotal = ref(0) const loadsTotal = ref(0)
const loadsCurrentPage = ref(1) const loadsCurrentPage = ref(1)
const proposalsOfLoads = ref([]); const proposalsOfLoads = ref([]);
@@ -13,6 +14,32 @@ export const useLoadsStore = defineStore('load', () => {
const openAttachmentsModal = ref(false); const openAttachmentsModal = ref(false);
const openProposalsModal = ref(false); const openProposalsModal = ref(false);
const getLoadsAll = async(reload = false) => {
const companyid = localStorage.getItem('id');
if(loadsDashboard.value.length <= 0 || reload) {
try {
const endpoint = `/loads?company=${companyid}`;
const {data} = await api.get(endpoint);
loadsDashboard.value = data.data;
} catch (error) {
loadsDashboard.value = [];
console.log(error);
}
}
}
const getProposalCompanyAll = async(reload = false) => {
const companyId = localStorage.getItem('id');
try {
if(loadsDashboard.value.length <= 0 || reload) {
const endpoint = `/proposals?carrier=${companyId}`;
const {data} = await api.get(endpoint);
loadsDashboard.value = data.data.map( (e) => e.load);
}
} catch (error) {
loadsDashboard.value = [];
}
}
const getCompanyLoads = async(filterQuery, reload = false) => { const getCompanyLoads = async(filterQuery, reload = false) => {
const companyid = localStorage.getItem('id'); const companyid = localStorage.getItem('id');
@@ -123,6 +150,9 @@ export const useLoadsStore = defineStore('load', () => {
const clear = () => { const clear = () => {
currentLoad.value = null; currentLoad.value = null;
loads.value = []; loads.value = [];
loadsDashboard.value = [];
loadsTotal.value = 0;
loadsCurrentPage.value = 1;
proposalsOfLoads.value = []; proposalsOfLoads.value = [];
openModalEdit.value = false; openModalEdit.value = false;
openAttachmentsModal.value = false; openAttachmentsModal.value = false;
@@ -137,6 +167,9 @@ export const useLoadsStore = defineStore('load', () => {
openAttachmentsModal, openAttachmentsModal,
getProposalsOfLoads, getProposalsOfLoads,
getCompanyLoads, getCompanyLoads,
getLoadsAll,
getProposalCompanyAll,
loadsDashboard,
deleteLoad, deleteLoad,
getLoad, getLoad,
saveLoad, saveLoad,

View File

@@ -68,6 +68,11 @@ export const useVehiclesStore = defineStore('vehicles', () => {
} }
} }
const clear = () => {
vehicles.value = [];
vehiclesTotal.value = 0;
vehiclesCurrentPage.value = 1;
}
return { return {
@@ -77,6 +82,7 @@ export const useVehiclesStore = defineStore('vehicles', () => {
fetchVehicles, fetchVehicles,
createVehicleCompany, createVehicleCompany,
updateVehicleCompany, updateVehicleCompany,
deleteVehicleCompany deleteVehicleCompany,
clear
} }
}); });

View File

@@ -6,7 +6,7 @@
import CardBudget from '../components/CardBudget.vue'; import CardBudget from '../components/CardBudget.vue';
import CardEmpty from '../components/CardEmpty.vue'; import CardEmpty from '../components/CardEmpty.vue';
import CreateBudgetModal from '../components/CreateBudgetModal.vue'; import CreateBudgetModal from '../components/CreateBudgetModal.vue';
import Pagination from '../components/Pagination.vue'; import Pagination from '../components/Pagination.vue';
const companyStore = useCompanyStore(); const companyStore = useCompanyStore();
const authStore = useAuthStore(); const authStore = useAuthStore();

View File

@@ -3,16 +3,80 @@
import loadsType from '../data/loadsType.json'; import loadsType from '../data/loadsType.json';
import BarChartStatistics from '../components/BarChartStatistics.vue'; import BarChartStatistics from '../components/BarChartStatistics.vue';
import DoughnutChartStatistics from '../components/DoughnutChartStatistics.vue'; import DoughnutChartStatistics from '../components/DoughnutChartStatistics.vue';
import { useLoadsStore } from '../stores/loads';
import { onMounted, ref, watch } from 'vue';
import Spiner from '../components/ui/Spiner.vue';
import { useAuthStore } from '../stores/auth';
import { storeToRefs } from 'pinia';
const auth = useAuthStore();
const { checking, user } = storeToRefs(auth);
const loads = useLoadsStore();
const loading = ref(false);
const loadsData = ref([]);
const segmentsData = ref([]);
const cities = ref([]);
const states = ref([]);
const vehicles = ref([]);
const nOfLoads = ref(0);
onMounted(() => {
if(user.value) {
getData();
}
})
watch(user, async() => {
if(user.value) {
getData();
}
});
const getData = async() => {
loading.value = true;
if(user.value?.permissions?.includes("role_carrier")) {
await loads.getProposalCompanyAll();
} else {
await loads.getLoadsAll();
}
dataMap();
loading.value = false;
}
const dataMap = () => {
nOfLoads.value = loads.loadsDashboard.length;
loads.loadsDashboard.map((e) => {
if(e?.load_status) {
loadsData.value.push(e.load_status);
}
if(user.value?.permissions?.includes("role_shipper") && e?.categories) {
segmentsData.value.push(e?.categories[0].name)
}
if(user.value?.permissions?.includes("role_shipper") && e?.origin?.city) {
cities.value.push(e?.origin.city)
}
if(e?.origin?.state){
states.value.push(e?.origin.state)
}
if(e?.truck_type){
vehicles.value.push(e?.truck_type)
}
});
}
</script> </script>
<template> <template>
<h1 class="title my-4">Dashboard Administrativo</h1> <h1 class="title my-4">Dashboard Administrativo</h1>
<div class="container-dashboard"> <div class="container-dashboard">
<div class="card-fixed card-dashboard"> <div class="card-fixed"
:class="[user?.permissions?.includes('role_shipper') ? 'card-dashboard' : 'card-dashboard-carrier']"
>
<h3>Total de cargas este mes</h3> <h3>Total de cargas este mes</h3>
<div class="main-info"> <div class="main-info">
35 {{ nOfLoads }}
<div class="indicator-text" style="color: green;"> <div class="indicator-text" style="color: green;">
<i class="fa-solid fa-arrow-up"></i> <i class="fa-solid fa-arrow-up"></i>
<!-- <i class="fa-solid fa-arrow-down"></i> --> <!-- <i class="fa-solid fa-arrow-down"></i> -->
@@ -21,22 +85,30 @@
</div> </div>
</div> </div>
<!-- <ChartLoad/> --> <!-- <ChartLoad/> -->
<div class="card-fixed card-dashboard"> <div class="card-fixed"
:class="[user?.permissions?.includes('role_shipper') ? 'card-dashboard' : 'card-dashboard-carrier']"
>
<h3>Cargas activas</h3> <h3>Cargas activas</h3>
<div class="card-chart"> <div class="card-chart">
<Spiner v-if="loading"/>
<DoughnutChartStatistics <DoughnutChartStatistics
:data="['Published', 'Transit', 'Delivered', 'Published', 'Downloading', 'Loading']" v-else
:data="loadsData"
:data-model="loadsType" :data-model="loadsType"
target-find="name" target-find="name"
target-label="status" target-label="status"
/> />
</div> </div>
</div> </div>
<div class="card-fixed card-dashboard"> <div class="card-fixed"
:class="[user?.permissions?.includes('role_shipper') ? 'card-dashboard' : 'card-dashboard-carrier']"
v-if="user?.permissions?.includes('role_shipper')">
<h3>Segmentos más usados</h3> <h3>Segmentos más usados</h3>
<div class="card-chart"> <div class="card-chart">
<Spiner v-if="loading"/>
<DoughnutChartStatistics <DoughnutChartStatistics
:data="['Agricola', 'Agricola', 'Cemento', 'Agricola', 'Intermoadal', 'Agricola']" v-else
:data="segmentsData"
:data-model="segments" :data-model="segments"
target-find="name" target-find="name"
/> />
@@ -44,30 +116,42 @@
</div> </div>
<!-- </div> <!-- </div>
<div class="container-dashboard"> --> <div class="container-dashboard"> -->
<div class="card-fixed card-dashboard"> <div class="card-fixed"
:class="[user?.permissions?.includes('role_shipper') ? 'card-dashboard' : 'card-dashboard-carrier']"
>
<h3>Estados más usados</h3> <h3>Estados más usados</h3>
<div class="card-chart"> <div class="card-chart">
<Spiner v-if="loading"/>
<BarChartStatistics <BarChartStatistics
label="Ciuades" v-else
:data="['Yucatán', 'Guadalajara', 'Colima', 'Yucatán', 'Nuevo león', 'Yucatán', 'Guadalajara']" label="Estados"
:data="states"
/> />
</div> </div>
</div> </div>
<div class="card-fixed card-dashboard"> <div class="card-fixed"
:class="[user?.permissions?.includes('role_shipper') ? 'card-dashboard' : 'card-dashboard-carrier']"
v-if="user?.permissions?.includes('role_shipper')">
<h3>Ciudades más usadas</h3> <h3>Ciudades más usadas</h3>
<div class="card-chart"> <div class="card-chart">
<Spiner v-if="loading"/>
<BarChartStatistics <BarChartStatistics
label="Estados" v-else
:data="['Mérida', 'Guadalajara', 'Colima', 'Guadalajara', 'Monterrey', 'Izamal', 'Mérida']" label="Ciudades"
:data="cities"
/> />
</div> </div>
</div> </div>
<div class="card-fixed card-dashboard"> <div class="card-fixed"
:class="[user?.permissions?.includes('role_shipper') ? 'card-dashboard' : 'card-dashboard-carrier']"
>
<h3>Tipo de transporte más usados</h3> <h3>Tipo de transporte más usados</h3>
<div class="card-chart"> <div class="card-chart">
<Spiner v-if="loading"/>
<BarChartStatistics <BarChartStatistics
v-else
label="Vehiculos" label="Vehiculos"
:data="['FULL / DOBLE REMOLQUE', 'FULL', 'FULL / DOBLE REMOLQUE', 'FULL', 'FULL / DOBLE REMOLQUE', 'FULL', 'FULL / DOBLE REMOLQUE', 'Auto']" :data="vehicles"
/> />
</div> </div>
</div> </div>
@@ -92,8 +176,17 @@
flex-direction: column; flex-direction: column;
} }
.card-dashboard-carrier {
width: 48%;
min-height: 300px;
max-height: 500px;
display: flex;
flex-direction: column;
}
.card-chart { .card-chart {
width: 100%; width: 100%;
/* max-height: 350px; */
/* max-width: 333px; */ /* max-width: 333px; */
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -138,5 +231,9 @@
.card-dashboard { .card-dashboard {
width: 100%; width: 100%;
} }
.card-dashboard-carrier {
width: 100%;
}
} }
</style> </style>

View File

@@ -38,7 +38,7 @@
const resp = await login(data); const resp = await login(data);
if(resp.msg === 'success') { if(resp.msg === 'success') {
console.log(resp.data.user); console.log(resp.data.user);
if(resp.data.user.first_name && resp.data.user.last_name) { if(resp.data.user.isVerified) {
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);
localStorage.setItem('id', resp.data.user.company); localStorage.setItem('id', resp.data.user.company);

View File

@@ -6,16 +6,28 @@
import {getTypeCompany} from '../helpers/type_company' import {getTypeCompany} from '../helpers/type_company'
import {getDateMonthDay} from '../helpers/date_formats' import {getDateMonthDay} from '../helpers/date_formats'
import EditCompanyModal from '../components/ui/EditCompanyModal.vue'; import EditCompanyModal from '../components/ui/EditCompanyModal.vue';
import { storeToRefs } from 'pinia';
const auth = useAuthStore() const auth = useAuthStore()
const company = useCompanyStore(); const company = useCompanyStore();
const { user, authStatus } = storeToRefs(auth);
onMounted(() => { onMounted(() => {
getInitialData() if(user.value) {
getInitialData()
}
}); });
watch(user, () => {
if(user.value) {
getInitialData();
}
})
const getInitialData = async() => { const getInitialData = async() => {
await auth.authenticationPromise; await auth.authenticationPromise;
// await authenticationPromise;
await company.getCompanyData(); await company.getCompanyData();
} }

View File

@@ -5,12 +5,14 @@
import Spiner from '../components/ui/Spiner.vue'; import Spiner from '../components/ui/Spiner.vue';
import CardLoad from '../components/CardLoad.vue'; import CardLoad from '../components/CardLoad.vue';
import useDirectionsRender from '../composables/useDirectionRender'; import useDirectionsRender from '../composables/useDirectionRender';
import { GoogleMap, Marker, CustomMarker } from 'vue3-google-map'; import { GoogleMap, Marker, CustomMarker, Polyline } from 'vue3-google-map';
import CardEmpty from '../components/CardEmpty.vue'; import CardEmpty from '../components/CardEmpty.vue';
const mapKey = import.meta.env.VITE_MAP_KEY;
const isLoading = ref(true); const isLoading = ref(true);
const loadStore = useLoadsStore(); const loadStore = useLoadsStore();
const { geocodeAddress } = useDirectionsRender() const { geocodeAddress, getDirections } = useDirectionsRender()
const route = useRoute(); const route = useRoute();
const load = ref(null); const load = ref(null);
const zoom = ref(6); const zoom = ref(6);
@@ -18,6 +20,7 @@
const vehicleLastLocation = ref(null); const vehicleLastLocation = ref(null);
const originCoords = ref(null); const originCoords = ref(null);
const destinationCoords = ref(null); const destinationCoords = ref(null);
const polylines = ref([]);
const isLoadActive = ref(false); const isLoadActive = ref(false);
const windowWidth = ref(window.innerWidth); const windowWidth = ref(window.innerWidth);
@@ -38,13 +41,18 @@
load.value = resp.data[0]; load.value = resp.data[0];
originCoords.value = await geocodeAddress(load.value.origin_formatted_address); originCoords.value = await geocodeAddress(load.value.origin_formatted_address);
destinationCoords.value = await geocodeAddress(load.value.destination_formatted_address); destinationCoords.value = await geocodeAddress(load.value.destination_formatted_address);
console.log(load.value.vehicle)
if(load.value.vehicle) { if(load.value.vehicle) {
vehicleLastLocation.value = { vehicleLastLocation.value = {
lat: parseFloat(load.value.vehicle.last_location_lat), lat: parseFloat(load.value.vehicle.last_location_lat),
lng: parseFloat(load.value.vehicle.last_location_lng) lng: parseFloat(load.value.vehicle.last_location_lng)
} }
console.log(vehicleLastLocation);
} }
polylines.value = await getDirections(originCoords.value, destinationCoords.value);
console.log(load.value.load_status);
switch (load.value.load_status) { switch (load.value.load_status) {
case 'Loading': case 'Loading':
isLoadActive.value = true; isLoadActive.value = true;
@@ -84,11 +92,11 @@
<div v-if="load"> <div v-if="load">
<CardLoad :load="load" :read-only="true"/> <CardLoad :load="load" :read-only="true"/>
<GoogleMap <GoogleMap
api-key="AIzaSyAJtfvrAKy7vnUSv2nzk4dYQkOs3OP4MMs" :api-key="mapKey"
:center="{lat:19.432600, lng:-99.133209}" :center="{lat:19.432600, lng:-99.133209}"
:zoom="zoom" :zoom="zoom"
:min-zoom="2" :min-zoom="2"
:max-zoom="12" :max-zoom="20"
:style="{width: 100 + '%', height: heightMap + 'px'}" :style="{width: 100 + '%', height: heightMap + 'px'}"
:options="{ :options="{
zoomControl: true, zoomControl: true,
@@ -112,13 +120,18 @@
<i class="fa-solid fa-truck" :style="{fontSize: 25 + 'px', color: 'green'}"></i> <i class="fa-solid fa-truck" :style="{fontSize: 25 + 'px', color: 'green'}"></i>
</div> </div>
</CustomMarker> </CustomMarker>
<!-- <Polyline :options="{ <Polyline
path: polyline, v-if="polylines"
// geodesic: true, :options="{
strokeColor: '#FF0000', path: polylines,
strokeOpacity: 1.0, // geodesic: true,
strokeWeight: 2 strokeColor: '#2D90BB',
}" /> --> strokeOpacity: 0.7,
strokeWeight: 5,
clickable: true,
fillColor: '#75ad3e',
}"
/>
</GoogleMap> </GoogleMap>
</div> </div>
<CardEmpty v-else text="No hay información disponible"/> <CardEmpty v-else text="No hay información disponible"/>