From cea26e1f6eb7039bf0f9bf13780ed7ca94cbd84c Mon Sep 17 00:00:00 2001 From: Alexandro Uc Santos Date: Thu, 7 Dec 2023 18:04:17 -0600 Subject: [PATCH] add: Form create load --- package-lock.json | 54 +++- package.json | 3 +- src/assets/main.css | 16 +- src/components/AttachmentsModal.vue | 97 +++++++ src/components/CardLoad.vue | 142 +++++++++++ src/components/CardProposal.vue | 117 +++++++++ src/components/FormLoadModal.vue | 376 ++++++++++++++++++++++++++++ src/components/NavBar.vue | 4 +- src/components/Sidebar.vue | 23 +- src/components/directionsRender.js | 38 +++ src/components/ui/CustomInput.vue | 2 +- src/components/ui/LoadingModal.vue | 1 + src/components/ui/Products.vue | 61 +++++ src/composables/useAttachments.js | 30 +++ src/helpers/status.js | 58 +++++ src/layouts/AdminLayout.vue | 2 +- src/lib/axios.js | 7 +- src/router/index.js | 10 +- src/services/auth.js | 2 +- src/services/company.js | 13 +- src/services/public.js | 15 +- src/stores/auth.js | 4 + src/stores/company.js | 58 ++++- src/stores/loads.js | 11 + src/views/LoadsPublishedView.vue | 142 +++++++++++ src/views/LoadsView.vue | 13 - src/views/LoginView.vue | 3 +- src/views/PublishedView.vue | 13 - src/views/TrucksPublishedView.vue | 36 +++ 29 files changed, 1292 insertions(+), 59 deletions(-) create mode 100644 src/components/AttachmentsModal.vue create mode 100644 src/components/CardLoad.vue create mode 100644 src/components/CardProposal.vue create mode 100644 src/components/FormLoadModal.vue create mode 100644 src/components/directionsRender.js create mode 100644 src/components/ui/Products.vue create mode 100644 src/composables/useAttachments.js create mode 100644 src/helpers/status.js create mode 100644 src/stores/loads.js create mode 100644 src/views/LoadsPublishedView.vue delete mode 100644 src/views/LoadsView.vue delete mode 100644 src/views/PublishedView.vue create mode 100644 src/views/TrucksPublishedView.vue diff --git a/package-lock.json b/package-lock.json index 21e7932..299f90b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,8 @@ "sass": "^1.69.5", "vue": "^3.3.4", "vue-multiselect": "^3.0.0-beta.3", - "vue-router": "^4.2.5" + "vue-router": "^4.2.5", + "vue3-google-map": "^0.18.0" }, "devDependencies": { "@vitejs/plugin-vue": "^4.4.0", @@ -383,6 +384,23 @@ "node": ">=12" } }, + "node_modules/@googlemaps/js-api-loader": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.2.tgz", + "integrity": "sha512-psGw5u0QM6humao48Hn4lrChOM2/rA43ZCm3tKK9qQsEj1/VzqkCqnvGfEOshDbBQflydfaRovbKwZMF4AyqbA==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, + "node_modules/@googlemaps/markerclusterer": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.5.1.tgz", + "integrity": "sha512-TLASLyWPoJiTdbuPtqIzQS8t/+JIvd+whoNkeSxWpP2eIoTscgsWt72Is3Cu5I68GuX3qn+oUSxqagFYc1O+wg==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "supercluster": "^8.0.1" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", @@ -646,6 +664,11 @@ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -756,6 +779,11 @@ "node": ">=0.12.0" } }, + "node_modules/kdbush": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", + "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==" + }, "node_modules/magic-string": { "version": "0.30.5", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", @@ -960,6 +988,14 @@ "node": ">=0.10.0" } }, + "node_modules/supercluster": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "dependencies": { + "kdbush": "^4.0.2" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1068,6 +1104,22 @@ "peerDependencies": { "vue": "^3.2.0" } + }, + "node_modules/vue3-google-map": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/vue3-google-map/-/vue3-google-map-0.18.0.tgz", + "integrity": "sha512-dhDlXK5XxKxH3Mj6n6C7y99M5LRwPDHlgGWgfLkmzVMpwlxBhaSxDhSTaduAFUjeHVusEfYdPxJSSP7yPJr8sg==", + "dependencies": { + "@googlemaps/js-api-loader": "^1.16.2", + "@googlemaps/markerclusterer": "^2.4.0", + "fast-deep-equal": "^3.1.3" + }, + "engines": { + "node": ">=16.11.0" + }, + "peerDependencies": { + "vue": "^3" + } } } } diff --git a/package.json b/package.json index 2ec4eea..0d4ad48 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "sass": "^1.69.5", "vue": "^3.3.4", "vue-multiselect": "^3.0.0-beta.3", - "vue-router": "^4.2.5" + "vue-router": "^4.2.5", + "vue3-google-map": "^0.18.0" }, "devDependencies": { "@vitejs/plugin-vue": "^4.4.0", diff --git a/src/assets/main.css b/src/assets/main.css index 549383e..2e7552d 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -182,6 +182,9 @@ td { font-size: 12px; font-weight: 300; } + .clear-md { + display: none; + } } @media (max-width: 768px) { @@ -189,6 +192,11 @@ td { padding: 16px 16px; } + .card-fixed { + padding: 16px 16px; + } + + .card-info h2{ font-size: 1.2rem; font-weight: 700; @@ -206,7 +214,7 @@ td { .btn-primary-lg { padding: 8px 15px; border: none; - border-radius: 13px; + border-radius: 8px; font-size: 16px; font-weight: 700; } @@ -214,9 +222,13 @@ td { padding: 8px 12px; font-size: 14px; border: none; - border-radius: 13px; + border-radius: 8px; font-weight: 700; } + + .clear-sm { + display: none !important; + } } @media (max-width: 568px) { diff --git a/src/components/AttachmentsModal.vue b/src/components/AttachmentsModal.vue new file mode 100644 index 0000000..e0bb95d --- /dev/null +++ b/src/components/AttachmentsModal.vue @@ -0,0 +1,97 @@ + + + + + \ No newline at end of file diff --git a/src/components/CardLoad.vue b/src/components/CardLoad.vue new file mode 100644 index 0000000..28d7ac6 --- /dev/null +++ b/src/components/CardLoad.vue @@ -0,0 +1,142 @@ + + + + + \ No newline at end of file diff --git a/src/components/CardProposal.vue b/src/components/CardProposal.vue new file mode 100644 index 0000000..bf68d7b --- /dev/null +++ b/src/components/CardProposal.vue @@ -0,0 +1,117 @@ + + + + + \ No newline at end of file diff --git a/src/components/FormLoadModal.vue b/src/components/FormLoadModal.vue new file mode 100644 index 0000000..ee34e68 --- /dev/null +++ b/src/components/FormLoadModal.vue @@ -0,0 +1,376 @@ + + + + + \ No newline at end of file diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 5ba71f4..d47c7bc 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -21,11 +21,11 @@ Transporte + class="nav-link" :to="{name: 'carriers'}">Transportistas Cargas + class="nav-link" :to="{name: 'shippers'}">Embarcadores diff --git a/src/components/Sidebar.vue b/src/components/Sidebar.vue index 23b1c6e..8136bce 100644 --- a/src/components/Sidebar.vue +++ b/src/components/Sidebar.vue @@ -70,12 +70,20 @@ class="nav-link" :to="{name: 'vehicles'}">Vehiculos -
  • +
  • - + Publicaciones + class="nav-link" :to="{name: 'published-loads'}">Publicaciones +
    +
  • +
  • +
    + + Publicaciones
  • @@ -172,6 +180,11 @@ margin-bottom: 5px; background-color: #323030; } + + .bg-nav-active { + opacity: 0.4; + transition: opacity 500ms ease-in-out; + } #sidebar ul li div{ display: flex; @@ -201,6 +214,10 @@ margin-right: 1.2rem; font-weight: 500; } + + .router-link-active{ + color: #FFF; + } .nav-link:hover{ /* color: #413f3c; */ color: #FFF; diff --git a/src/components/directionsRender.js b/src/components/directionsRender.js new file mode 100644 index 0000000..a501d3f --- /dev/null +++ b/src/components/directionsRender.js @@ -0,0 +1,38 @@ +export default function useDirectionRender() { + + defineProps({ + origin: { type: Object }, + destination: { type: Object }, + travelMode: { type: String }, + }) + + const directionsRenderer = ref(null); + const directionsService = new window.google.maps.DirectionsService(); + + onMounted(() => { + directionsRenderer.value = new window.google.maps.DirectionsRenderer(); + + watch( + () => [props.origin, props.destination, props.travelMode], + () => { + const { origin, destination, travelMode } = props; + if (!origin || !destination || !travelMode) return; + + directionsService.route( + { + origin, + destination, + travelMode, + }, + (response, status) => { + if (status !== 'OK') return; + directionsRenderer.value.setDirections(response); + } + ); + }, + { immediate: true } + ); + }); + + return { directionsRenderer }; +} \ No newline at end of file diff --git a/src/components/ui/CustomInput.vue b/src/components/ui/CustomInput.vue index c46d273..9b5af93 100644 --- a/src/components/ui/CustomInput.vue +++ b/src/components/ui/CustomInput.vue @@ -1,7 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/src/composables/useAttachments.js b/src/composables/useAttachments.js new file mode 100644 index 0000000..cfc6bd2 --- /dev/null +++ b/src/composables/useAttachments.js @@ -0,0 +1,30 @@ +import { ref } from "vue"; +import { useLoadsStore } from "../stores/loads"; +import api from "../lib/axios"; + +export default function useAttachments() { + + const loading = ref(false); + const attachments = ref(null); + const loadStore = useLoadsStore(); + + const getAttachmentLoad = async() => { + try { + loading.value = true; + const endpoint = "/v1" + "/load-attachments/load/" + loadStore.currentLoad._id; + const {data} = await api.get(endpoint); + attachments.value = data; + } catch (error) { + attachments.value = null; + console.log(error); + } finally { + loading.value = false; + } + } + + return { + getAttachmentLoad, + loading, + attachments + } +} \ No newline at end of file diff --git a/src/helpers/status.js b/src/helpers/status.js new file mode 100644 index 0000000..6a6a4f8 --- /dev/null +++ b/src/helpers/status.js @@ -0,0 +1,58 @@ +export const getStatusLoad = (load) => { + let status; + let color; + switch (load.load_status) { + case 'Published': + status = "Publicado"; + color = "#000000"; + break; + case 'Loading': + color = "#F44336"; + status = "Cargando"; + break; + case 'Transit': + status = "En Transito"; + color = "#ffd22b" + break; + case 'Downloading': + status = "Descargando"; + color = "#428502" + break; + case 'Delivered': + status = "Entregado"; + color = "#000000"; + break; + default: + status = 'Publicado'; + color = "#428502"; + break; + } + return { + status, + color, + }; +} + +export const getStatusPublished = (load) => { + let status; + switch (load.status) { + case 'Draft': + status = "Guardado"; + break; + case 'Published': + status = "Publicado"; + break; + case 'Completed': + status = "Conectado"; + break; + case 'Closed': + status = "Completado"; + break; + default: + status = 'Guardado'; + break; + } + + return status; +} + diff --git a/src/layouts/AdminLayout.vue b/src/layouts/AdminLayout.vue index a54853a..e833761 100644 --- a/src/layouts/AdminLayout.vue +++ b/src/layouts/AdminLayout.vue @@ -52,7 +52,7 @@ width: 100wv !important; } .view { - margin: 24px 12px; + margin: 24px 0px; } } \ No newline at end of file diff --git a/src/lib/axios.js b/src/lib/axios.js index 3128540..9f857c5 100644 --- a/src/lib/axios.js +++ b/src/lib/axios.js @@ -1,9 +1,12 @@ import axios from "axios"; const baseUrl = import.meta.env.VITE_API_URL; - +const accessToken = localStorage.getItem('access'); const api = axios.create({ - baseURL: baseUrl + baseURL: baseUrl, + headers: { + 'Authorization': 'Bearer ' + accessToken + } }); export default api; \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index 565aace..315eb23 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -56,9 +56,9 @@ const router = createRouter({ component: () => import('../views/LocationsView.vue'), }, { - path: 'publicaciones', - name: 'published', - component: () => import('../views/PublishedView.vue'), + path: 'camiones', + name: 'published-trucks', + component: () => import('../views/TrucksPublishedView.vue'), }, { path: 'usuarios', @@ -82,8 +82,8 @@ const router = createRouter({ }, { path: 'cargas', - name: 'loads', - component: () => import('../views/LoadsView.vue'), + name: 'published-loads', + component: () => import('../views/LoadsPublishedView.vue'), }, { path: 'vehiculos', diff --git a/src/services/auth.js b/src/services/auth.js index f95f7f6..dd938a7 100644 --- a/src/services/auth.js +++ b/src/services/auth.js @@ -38,7 +38,7 @@ export const renewToken = async() => { try { const endpoint = `/v1/account/authorize/${session}`; const {data} = await api.get(endpoint); - console.log(data.user); + console.log(data); if(data.accessToken !== null){ return { msg: 'success', diff --git a/src/services/company.js b/src/services/company.js index 3118544..a68081d 100644 --- a/src/services/company.js +++ b/src/services/company.js @@ -21,4 +21,15 @@ export const editCompany = async(companyId, formData) => { console.log(error); return null; } -} \ No newline at end of file +} + +// export const editCompany = async(companyId, formData) => { +// try { +// const endpoint = `/companies/${companyId}`; +// const {data} = await api.patch(endpoint, formData); +// return data; +// } catch (error) { +// console.log(error); +// return null; +// } +// } \ No newline at end of file diff --git a/src/services/public.js b/src/services/public.js index baf122a..1458caa 100644 --- a/src/services/public.js +++ b/src/services/public.js @@ -76,7 +76,7 @@ export const getUsersCompany = async(filter) => { export const getSettingsQuery = async(filter) => { try { - const endpoint = "/meta-data/find?regex=" + filter.query; + const endpoint = "/v1/meta-data/find?regex=" + filter.query; const {data} = await api.get(endpoint); return data.data; } catch (error) { @@ -96,6 +96,17 @@ export const searchcategories = async(query) => { } } +export const searchProducts = async(query) => { + try { + const endpoint = "/products/?name[$regex]=" + query + "&name[$options]=i"; + const {data} = await api.get(endpoint); + return data.data; + } catch (error) { + console.log(error); + return []; + } +} + export const searchstates = async(query) => { try { const endpoint = "/v1/states/find?regex=" + query; @@ -110,7 +121,7 @@ export const searchstates = async(query) => { export const searchcities = async(query) => { try { // const endpoint = "/cities/?city_name[$regex]=" + query + "&city_name[$options]=i"; - const endpoint = "/cities/find?regex=" + query; + const endpoint = "/v1/cities/find?regex=" + query; const {data} = await api.get(endpoint); return data.data; } catch (error) { diff --git a/src/stores/auth.js b/src/stores/auth.js index 922bba4..1d794a9 100644 --- a/src/stores/auth.js +++ b/src/stores/auth.js @@ -32,6 +32,8 @@ export const useAuthStore = defineStore('auth', () => { sesion.value = resp.data.session_token; token.value = resp.data.accessToken; localStorage.setItem('session', resp.data.session_token); + localStorage.setItem('access', resp.data.accessToken); + localStorage.setItem('id', resp.data.user.company); checking.value = false; } else { noty.show = true; @@ -53,6 +55,8 @@ export const useAuthStore = defineStore('auth', () => { const logout = () => { localStorage.removeItem('session'); + localStorage.removeItem('access'); + localStorage.removeItem('id'); company.clear(); router.push({name: 'login'}); sesion.value = ''; diff --git a/src/stores/company.js b/src/stores/company.js index cffae1f..298b3e9 100644 --- a/src/stores/company.js +++ b/src/stores/company.js @@ -1,22 +1,22 @@ import { defineStore } from "pinia"; -import { ref, watch, onMounted } from "vue"; +import { ref } from "vue"; import { useAuthStore } from "./auth"; import { getCompany } from "../services/company"; +import api from "../lib/axios"; export const useCompanyStore = defineStore('company', () => { - const auth = useAuthStore(); + const companyid = localStorage.getItem('id'); const company = ref(null) + const loads = ref([]) + const proposals = ref([]) const loading = ref(false); const getCompanyData = async() => { loading.value = true; if(!company.value) { - console.log('Se ejecuta'); loading.value = true; - const companyId = auth.user?.company; - console.log({companyId}); - const resp = await getCompany(companyId); + const resp = await getCompany(companyid); console.log(resp); company.value = resp; } @@ -28,11 +28,49 @@ export const useCompanyStore = defineStore('company', () => { loading.value = false; } + const getCompanyLoads = async(filterQuery) => { + let filterArr = Object.values(filterQuery); + let cleanfilterArr = filterArr.filter(n=>n); + var filterStr = ""; + if(cleanfilterArr.length >0){ + filterStr = cleanfilterArr.join("&"); + } + console.log(filterStr); + try { + const endpoint = `/loads?company=${companyid}&${filterStr}`; + console.log(endpoint); + const {data} = await api.get(endpoint); + loads.value = data.data; + } catch (error) { + loads.value = []; + console.log(error); + } + } + + ///loads?company=64fa70c130d2650011ac4f3a&status[$ne]=Closed,posted_by_name[$regex]=ju&posted_by_name[$options]=i + + const getProposalsCompany = async() => { + try { + const endpoint = `/proposals?carrier=${companyid}`; + console.log(endpoint); + const {data} = await api.get(endpoint); + proposals.value = data.data; + console.log(data); + } catch (error) { + proposals.value = []; + console.log(error); + } + } + return { - company, - loading, - getCompanyData, - clear + getCompanyData, + getCompanyLoads, + getProposalsCompany, + clear, + loading, + loads, + proposals, + company, } }); \ No newline at end of file diff --git a/src/stores/loads.js b/src/stores/loads.js new file mode 100644 index 0000000..f961c04 --- /dev/null +++ b/src/stores/loads.js @@ -0,0 +1,11 @@ +import { defineStore } from "pinia"; +import { ref } from "vue"; + +export const useLoadsStore = defineStore('load', () => { + + const currentLoad = ref(null); + + return { + currentLoad + } +}); \ No newline at end of file diff --git a/src/views/LoadsPublishedView.vue b/src/views/LoadsPublishedView.vue new file mode 100644 index 0000000..05c52d9 --- /dev/null +++ b/src/views/LoadsPublishedView.vue @@ -0,0 +1,142 @@ + + + + + \ No newline at end of file diff --git a/src/views/LoadsView.vue b/src/views/LoadsView.vue deleted file mode 100644 index 4d4c588..0000000 --- a/src/views/LoadsView.vue +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue index 9dd36d1..d818c2e 100644 --- a/src/views/LoginView.vue +++ b/src/views/LoginView.vue @@ -8,7 +8,6 @@ import { RouterLink, useRouter } from 'vue-router'; import { useAuthStore } from '../stores/auth'; - const form = reactive({ email: 'alexandrous.dev@gmail.com', password: 'Password0', @@ -41,6 +40,8 @@ console.log(resp.data.user); if(resp.data.user.first_name && resp.data.user.last_name) { localStorage.setItem('session', resp.data.session_token); + localStorage.setItem('access', resp.data.accessToken); + localStorage.setItem('id', resp.data.user.company); router.push({name: 'home'}); auth.$patch({ sesion: resp.data.session_token, diff --git a/src/views/PublishedView.vue b/src/views/PublishedView.vue deleted file mode 100644 index 7df897f..0000000 --- a/src/views/PublishedView.vue +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/views/TrucksPublishedView.vue b/src/views/TrucksPublishedView.vue new file mode 100644 index 0000000..b000415 --- /dev/null +++ b/src/views/TrucksPublishedView.vue @@ -0,0 +1,36 @@ + + + + + \ No newline at end of file