add: calendar view & calculator view

This commit is contained in:
Alexandro Uc Santos
2023-12-23 18:47:03 -06:00
parent 2bea640d49
commit f31104c8bb
16 changed files with 705 additions and 16 deletions

View File

@@ -0,0 +1,67 @@
<script setup>
defineProps({
budget: {
type: Object,
required: true
}
})
</script>
<template>
<div class="card-fixed card-budget">
<div>
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<p><span>Cliente:</span> {{budget.client}}</p>
<p v-if="budget.material"><span>Material:</span> {{budget.material.name}}</p>
<p><span>Origen:</span> {{budget.origin}}</p>
<p><span>Destino:</span> {{budget.destination}}</p>
<p><span>Tipo de camión:</span> {{budget.truck_type}}</p>
<p><span>Total KM recorridos:</span> {{budget.total_km_travel}}</p>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<p><span>Total Litros De Diesel Consumidos: </span> {{parseFloat( budget.total_fuel_consumed).toFixed(2)}}</p>
<p><span>Total Costo Del Diesel:</span> {{"$" + parseFloat( budget.total_cost_fuel).toFixed(2)}}</p>
<p><span>Total Antes De Iva:</span> ${{budget.total_before_tax}}</p>
<p><span>Total Utilidad Por Kilometro:</span> {{"$" + parseFloat( budget.total_utility_per_km).toFixed(2)}}</p>
<p><span>Total Utilidad:</span> {{"$" + parseFloat( budget.total_profit).toFixed(2)}}</p>
<!-- <p>{{ $t('CALCULATOR.PROFIT_PERCENTAGE') }}: {{budget.profit_percentage}}%</p> -->
<p><span>Porcentaje De Utilidad:</span> {{parseFloat(budget.profit_percentage).toFixed(2) + "%"}}</p>
</div>
</div>
</div>
<div class="card-footer">
<button class="btn-primary-sm radius-sm">
<i class="fa-solid fa-trash" /> <span class="clear-xsm">Eliminar</span>
</button>
<button class="btn-primary-sm radius-sm">
<i class="fa-solid fa-pen-to-square" /> <span class="clear-xsm">Editar</span>
</button>
<button type="button" class="btn btn-dark">
<i class="fa-solid fa-print" /> <span class="clear-xsm">Imprimir</span>
</button>
</div>
</div>
</template>
<style lang="scss" scoped>
.card-budget {
flex-direction: column;
}
p {
font-size: 1rem;
font-weight: normal;
}
p span {
font-weight: bold;
}
.card-footer {
display: flex;
justify-content: end;
gap: 1rem;
}
</style>

View File

@@ -1,11 +1,14 @@
<script setup>
import { ref, onMounted } from 'vue';
import { ref, onMounted, reactive } from 'vue';
import CardEmpty from './CardEmpty.vue';
import Spiner from './ui/Spiner.vue';
import BadgeError from './ui/BadgeError.vue';
import { GoogleMap, Marker } from 'vue3-google-map';
import useDirectionsRender from '../composables/useDirectionRender';
import { useAuthStore } from '../stores/auth';
import { useVehiclesStore } from '../stores/vehicles';
import { saveProposal } from '../services/vehicles'
import Swal from 'sweetalert2';
const zoom = ref(6);
@@ -13,11 +16,16 @@
const originCoords = ref(null);
const destinationCoords = ref(null);
const isLoading = ref(false);
const loadingSubmit = ref(false);
const windowWidth = ref(window.innerWidth);
const authStore = useAuthStore();
const vehiclesStore = useVehiclesStore();
const vehicle = ref(null);
const comments = ref('');
const msgError = ref('');
const form = reactive({
vehicle: "",
comments: '',
});
const { geocodeAddress } = useDirectionsRender()
@@ -58,6 +66,48 @@
heightMap.value = 768;
}
}
const handleSumit = async() => {
if(form.vehicle === ""){
msgError.value = 'Selecciona vehiculo para continuar';
setTimeout(() => {
msgError.value = '';
}, 5000);
return;
} else if (form.comments.trim().length <= 0) {
msgError.value = 'Agrega un comentario';
setTimeout(() => {
msgError.value = '';
}, 5000);
return;
}
msgError.value = '';
let formData = {
carrier: authStore.user.company,
bidder : authStore.user._id,
comment: form.comments,
vehicle : form.vehicle,
load : props.load._id
}
loadingSubmit.value = true;
const result = await saveProposal(formData);
if(result !== null) {
document.getElementById('btnClosemakeProposalModal').click();
Swal.fire({
title: '<strong>Oferta creada con éxito!</strong>',
icon: 'success'
})
} else {
Swal.fire({
title: '<strong>Oferta no se pudo crear!</strong>',
icon: 'error'
})
}
loadingSubmit.value = false;
}
</script>
<template>
@@ -65,7 +115,7 @@
<div class="modal-dialog modal-dialog-centered modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="title mt-2 mb-3">Ofertas</h2>
<h2 class="title mt-2 mb-3">Realizar oferta</h2>
<button
id="btnClosemakeProposalModal"
type="button"
@@ -81,15 +131,15 @@
<Spiner v-if="isLoading"/>
<div v-else>
<div v-if="load">
<form class="box-form mb-4">
<form @submit.prevent="handleSumit" class="box-form mb-4">
<BadgeError :msg="msgError"/>
<div class="custom-selected-field">
<label class="custom-label" for="vehicle">Vehiculo:</label>
<select
class="custom-input-light"
name="vehicle"
id="vehicle"
:value="vehicle"
@input="$event => $emit('update:vehicle', $event.target.value)"
v-model="form.vehicle"
>
<option disabled value="">-- Seleccionar vehículo --</option>
<option v-for="vehicle in vehiclesStore.vehicles" :value="vehicle._id">{{vehicle.vehicle_code}}</option>
@@ -102,12 +152,13 @@
name="comment"
id="comment"
placeholder="Escribe aqui..."
:value="comments"
@input="$event => $emit('update:comments', $event.target.value)"
v-model="form.comments"
></textarea>
</div>
<div class="box-btns">
<input
<Spiner v-if="loadingSubmit"/>
<input
v-else
type="submit"
class="btn-primary-sm"
value="Enviar"

View File

@@ -44,7 +44,10 @@ import CardEmpty from './CardEmpty.vue';
if(load != null) {
const index = loadsStore.loads.findIndex((load) => load._id === load_id);
loadsStore.loads[index] = load;
loadsStore.loads[index] = {
...loadsStore.loads[index],
...load
};
const proposal_id = proposal._id;
let formData = {
@@ -106,7 +109,10 @@ import CardEmpty from './CardEmpty.vue';
let load = await loadsStore.updateLoad(load_id, loadData);
if(load) {
const index = loadsStore.loads.findIndex((load) => load._id === load_id);
loadsStore.loads[index] = load;
loadsStore.loads[index] = {
...loadsStore.loads[index],
...load
};
let formData = {
accepted_by : null,
accepted_date : null,

View File

@@ -0,0 +1,56 @@
<script setup>
defineProps({
msg: {
type: String,
required: true,
},
isError: {
type: Boolean,
default: true,
},
showIcon: {
type: Boolean,
default: true,
}
})
</script>
<template>
<div v-if="msg.length > 0" class="badge" :class="[isError ? 'badge-error' : 'badge-success']">
<span>
<i v-if="showIcon && isError" class="fa-solid fa-circle-exclamation me-2"></i>
<i v-if="showIcon && !isError" class="fa-solid fa-circle-check"></i>
{{ msg }}
</span>
</div>
</template>
<style scoped>
.badge {
display: flex;
width: 100%;
color: #FFF;
font-size: 1rem;
font-weight: 700;
border-radius: 8px;
justify-content: center;
padding: 10px 16px;
margin-bottom: 12px;
}
.badge-error {
background-color: rgb(238, 101, 101);
}
.badge-success {
background-color: rgb(29, 162, 113);
}
@media (max-width: 768px) {
.badge {
font-size: 0.8rem;
font-weight: 400;
border-radius: 8px;
padding: 10px 12px;
}
}
</style>