diff --git a/src/components/FormModel.vue b/src/components/FormModel.vue index 2e580257c..a8e8c0a1f 100644 --- a/src/components/FormModel.vue +++ b/src/components/FormModel.vue @@ -97,7 +97,7 @@ const $props = defineProps({ }); const emit = defineEmits(['onFetch', 'onDataSaved']); const modelValue = computed( - () => $props.model ?? `formModel_${route?.meta?.title ?? route.name}` + () => $props.model ?? `formModel_${route?.meta?.title ?? route.name}`, ).value; const componentIsRendered = ref(false); const arrayData = useArrayData(modelValue); @@ -148,7 +148,7 @@ onMounted(async () => { JSON.stringify(newVal) !== JSON.stringify(originalData.value); isResetting.value = false; }, - { deep: true } + { deep: true }, ); } }); @@ -156,7 +156,7 @@ onMounted(async () => { if (!$props.url) watch( () => arrayData.store.data, - (val) => updateAndEmit('onFetch', val) + (val) => updateAndEmit('onFetch', val), ); watch( @@ -165,7 +165,7 @@ watch( originalData.value = null; reset(); await fetch(); - } + }, ); onBeforeRouteLeave((to, from, next) => { @@ -254,7 +254,7 @@ function filter(value, update, filterOptions) { (ref) => { ref.setOptionIndex(-1); ref.moveOptionSelection(1, true); - } + }, ); } diff --git a/src/components/ui/CardDescriptor.vue b/src/components/ui/CardDescriptor.vue index 43dc15e9b..d526b2728 100644 --- a/src/components/ui/CardDescriptor.vue +++ b/src/components/ui/CardDescriptor.vue @@ -73,7 +73,7 @@ onBeforeMount(async () => { () => [$props.url, $props.filter], async () => { if (!isSameDataKey.value) await getData(); - } + }, ); }); @@ -108,7 +108,7 @@ const iconModule = computed(() => route.matched[1].meta.icon); const toModule = computed(() => route.matched[1].path.split('/').length > 2 ? route.matched[1].redirect - : route.matched[1].children[0].redirect + : route.matched[1].children[0].redirect, ); diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue index c815b8e16..9d108c1f8 100644 --- a/src/components/ui/CardSummary.vue +++ b/src/components/ui/CardSummary.vue @@ -208,4 +208,13 @@ async function fetch() { .summaryHeader { color: $white; } + +.cardSummary :deep(.q-card__section[content]) { + display: flex; + flex-wrap: wrap; + padding: 0; + > * { + flex: 1; + } +} diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue index 93f069cc6..80128018a 100644 --- a/src/components/ui/VnFilterPanel.vue +++ b/src/components/ui/VnFilterPanel.vue @@ -114,7 +114,7 @@ async function clearFilters() { arrayData.resetPagination(); // Filtrar los params no removibles const removableFilters = Object.keys(userParams.value).filter((param) => - $props.unremovableParams.includes(param) + $props.unremovableParams.includes(param), ); const newParams = {}; // Conservar solo los params que no son removibles @@ -162,13 +162,13 @@ const formatTags = (tags) => { const tags = computed(() => { const filteredTags = tagsList.value.filter( - (tag) => !($props.customTags || []).includes(tag.label) + (tag) => !($props.customTags || []).includes(tag.label), ); return formatTags(filteredTags); }); const customTags = computed(() => - tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label)) + tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label)), ); async function remove(key) { @@ -188,10 +188,13 @@ function formatValue(value) { const getLocale = (label) => { const param = label.split('.').at(-1); const globalLocale = `globals.params.${param}`; + const moduleName = route.meta.moduleName; + const moduleLocale = `${moduleName.toLowerCase()}.${param}`; if (te(globalLocale)) return t(globalLocale); - else if (te(t(`params.${param}`))); + else if (te(moduleLocale)) return t(moduleLocale); else { - const camelCaseModuleName = route.meta.moduleName.charAt(0).toLowerCase() + route.meta.moduleName.slice(1); + const camelCaseModuleName = + moduleName.charAt(0).toLowerCase() + moduleName.slice(1); return t(`${camelCaseModuleName}.params.${param}`); } }; diff --git a/src/css/app.scss b/src/css/app.scss index 7296b079f..59e945f05 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -212,6 +212,10 @@ select:-webkit-autofill { justify-content: center; } +.q-card__section[dense] { + padding: 0; +} + input[type='number'] { -moz-appearance: textfield; } diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml index d1fbdc312..f8af27953 100644 --- a/src/i18n/locale/en.yml +++ b/src/i18n/locale/en.yml @@ -332,10 +332,13 @@ globals: wasteRecalc: Waste recaclulate operator: Operator parking: Parking + vehicleList: Vehicles + vehicle: Vehicle unsavedPopup: title: Unsaved changes will be lost subtitle: Are you sure exit without saving? params: + description: Description clientFk: Client id salesPersonFk: Sales person warehouseFk: Warehouse @@ -358,7 +361,13 @@ globals: correctingFk: Rectificative daysOnward: Days onward countryFk: Country + countryCodeFk: Country companyFk: Company + model: Model + fuel: Fuel + active: Active + inactive: Inactive + deliveryPoint: Delivery point errors: statusUnauthorized: Access denied statusInternalServerError: An internal server error has ocurred diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml index acfe181fe..ed1f8eceb 100644 --- a/src/i18n/locale/es.yml +++ b/src/i18n/locale/es.yml @@ -332,10 +332,13 @@ globals: wasteRecalc: Recalcular mermas operator: Operario parking: Parking + vehicleList: Vehículos + vehicle: Vehículo unsavedPopup: title: Los cambios que no haya guardado se perderán subtitle: ¿Seguro que quiere salir sin guardar? params: + description: Descripción clientFk: Id cliente salesPersonFk: Comercial warehouseFk: Almacén @@ -356,6 +359,7 @@ globals: daysOnward: Días adelante packing: ITP countryFk: País + countryCodeFk: País companyFk: Empresa errors: statusUnauthorized: Acceso denegado diff --git a/src/pages/Department/Card/DepartmentDescriptor.vue b/src/pages/Department/Card/DepartmentDescriptor.vue index b219ccfe1..214e2bcbd 100644 --- a/src/pages/Department/Card/DepartmentDescriptor.vue +++ b/src/pages/Department/Card/DepartmentDescriptor.vue @@ -74,7 +74,7 @@ const { openConfirmationModal } = useVnConfirm(); openConfirmationModal( t('Are you sure you want to delete it?'), t('Delete department'), - removeDepartment + removeDepartment, ) " > diff --git a/src/pages/Route/Card/RouteFilter.vue b/src/pages/Route/Card/RouteFilter.vue index 72bfed1da..21858102b 100644 --- a/src/pages/Route/Card/RouteFilter.vue +++ b/src/pages/Route/Card/RouteFilter.vue @@ -100,7 +100,7 @@ const emit = defineEmits(['search']); { [ create: true, component: 'select', attrs: { - url: 'vehicles', - fields: ['id', 'numberPlate'], + url: 'vehicles/active', optionLabel: 'numberPlate', optionFilterValue: 'numberPlate', find: { diff --git a/src/pages/Route/Vehicle/Card/VehicleBasicData.vue b/src/pages/Route/Vehicle/Card/VehicleBasicData.vue new file mode 100644 index 000000000..e78bc6edd --- /dev/null +++ b/src/pages/Route/Vehicle/Card/VehicleBasicData.vue @@ -0,0 +1,162 @@ + + diff --git a/src/pages/Route/Vehicle/Card/VehicleCard.vue b/src/pages/Route/Vehicle/Card/VehicleCard.vue new file mode 100644 index 000000000..852879651 --- /dev/null +++ b/src/pages/Route/Vehicle/Card/VehicleCard.vue @@ -0,0 +1,13 @@ + + diff --git a/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue b/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue new file mode 100644 index 000000000..f31ffe847 --- /dev/null +++ b/src/pages/Route/Vehicle/Card/VehicleDescriptor.vue @@ -0,0 +1,50 @@ + + + +es: + Vehicle removed: Vehículo eliminado + diff --git a/src/pages/Route/Vehicle/Card/VehicleSummary.vue b/src/pages/Route/Vehicle/Card/VehicleSummary.vue new file mode 100644 index 000000000..981870cb2 --- /dev/null +++ b/src/pages/Route/Vehicle/Card/VehicleSummary.vue @@ -0,0 +1,127 @@ + + diff --git a/src/pages/Route/Vehicle/VehicleFilter.js b/src/pages/Route/Vehicle/VehicleFilter.js new file mode 100644 index 000000000..cbf5cc621 --- /dev/null +++ b/src/pages/Route/Vehicle/VehicleFilter.js @@ -0,0 +1,76 @@ +export default { + fields: [ + 'id', + 'description', + 'isActive', + 'isKmTruckRate', + 'warehouseFk', + 'companyFk', + 'numberPlate', + 'chassis', + 'supplierFk', + 'supplierCoolerFk', + 'tradeMark', + 'fuelTypeFk', + 'import', + 'importCooler', + 'vin', + 'model', + 'ppeFk', + 'countryCodeFk', + 'leasing', + 'bankPolicyFk', + 'vehicleTypeFk', + 'deliveryPointFk', + ], + include: [ + { + relation: 'warehouse', + scope: { + fields: ['id', 'name'], + }, + }, + { + relation: 'company', + scope: { + fields: ['id', 'code'], + }, + }, + { + relation: 'supplier', + scope: { + fields: ['id', 'name'], + }, + }, + { + relation: 'supplierCooler', + scope: { + fields: ['id', 'name'], + }, + }, + { + relation: 'fuelType', + scope: { + fields: ['id', 'name'], + }, + }, + { + relation: 'bankPolicy', + scope: { + fields: ['id', 'ref', 'dmsFk'], + }, + }, + { + relation: 'ppe', + scope: { + fields: ['id'], + }, + }, + { + relation: 'deliveryPoint', + scope: { + fields: ['id', 'name'], + }, + }, + ], +}; diff --git a/src/pages/Route/Vehicle/VehicleList.vue b/src/pages/Route/Vehicle/VehicleList.vue new file mode 100644 index 000000000..de6aaba5f --- /dev/null +++ b/src/pages/Route/Vehicle/VehicleList.vue @@ -0,0 +1,224 @@ + + diff --git a/src/pages/Route/Vehicle/locale/en.yml b/src/pages/Route/Vehicle/locale/en.yml new file mode 100644 index 000000000..c92022f9d --- /dev/null +++ b/src/pages/Route/Vehicle/locale/en.yml @@ -0,0 +1,20 @@ +vehicle: + tradeMark: Trade Mark + numberPlate: Nº Plate + chassis: Chassis + leasing: Leasing + isKmTruckRate: Trailer + delete: Delete Vehicle + supplierCooler: Supplier Cooler + vin: VIN + ppe: Ppe + isActive: Active + nLeasing: Nº Leasing + create: Create Vehicle + amountCooler: Amount cooler + remove: Vehicle removed + search: Search Vehicle + searchInfo: Search by id or number plate + params: + vehicleTypeFk: Type + vehicleStateFk: State diff --git a/src/pages/Route/Vehicle/locale/es.yml b/src/pages/Route/Vehicle/locale/es.yml new file mode 100644 index 000000000..c878f97ac --- /dev/null +++ b/src/pages/Route/Vehicle/locale/es.yml @@ -0,0 +1,20 @@ +vehicle: + tradeMark: Marca + numberPlate: Matrícula + chassis: Nº de bastidor + leasing: Leasing + isKmTruckRate: Trailer + delete: Eliminar vehículo + supplierCooler: Proveedor Frío + vin: VIN + ppe: Nº Inmovilizado + create: Crear vehículo + amountCooler: Importe frío + isActive: Activo + nLeasing: Nº leasing + remove: Vehículo eliminado + search: Buscar Vehículo + searchInfo: Buscar por id o matrícula + params: + vehicleTypeFk: Tipo + vehicleStateFk: Estado diff --git a/src/router/modules/route.js b/src/router/modules/route.js index 946ad3e15..835324d20 100644 --- a/src/router/modules/route.js +++ b/src/router/modules/route.js @@ -160,6 +160,36 @@ const roadmapCard = { ], }; +const vehicleCard = { + path: ':id', + name: 'VehicleCard', + component: () => import('src/pages/Route/Vehicle/Card/VehicleCard.vue'), + redirect: { name: 'VehicleSummary' }, + meta: { + menu: ['VehicleBasicData'], + }, + children: [ + { + name: 'VehicleSummary', + path: 'summary', + meta: { + title: 'summary', + icon: 'view_list', + }, + component: () => import('src/pages/Route/Vehicle/Card/VehicleSummary.vue'), + }, + { + name: 'VehicleBasicData', + path: 'basic-data', + meta: { + title: 'basicData', + icon: 'vn:settings', + }, + component: () => import('src/pages/Route/Vehicle/Card/VehicleBasicData.vue'), + }, + ], +}; + export default { name: 'Route', path: '/route', @@ -174,6 +204,7 @@ export default { 'RouteRoadmap', 'CmrList', 'AgencyList', + 'VehicleList', ], }, component: RouterView, @@ -280,6 +311,27 @@ export default { agencyCard, ], }, + { + path: 'vehicle', + name: 'RouteVehicle', + redirect: { name: 'VehicleList' }, + meta: { + title: 'vehicle', + icon: 'directions_car', + }, + component: () => import('src/pages/Route/Vehicle/VehicleList.vue'), + children: [ + { + path: 'list', + name: 'VehicleList', + meta: { + title: 'vehicleList', + icon: 'directions_car', + }, + }, + vehicleCard, + ], + }, ], }, ], diff --git a/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js b/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js new file mode 100644 index 000000000..64b9ca0a0 --- /dev/null +++ b/test/cypress/integration/route/vehicle/vehicleDescriptor.spec.js @@ -0,0 +1,13 @@ +describe('Vehicle', () => { + beforeEach(() => { + cy.viewport(1920, 1080); + cy.login('deliveryAssistant'); + cy.visit(`/#/route/vehicle/7`); + }); + + it('should delete a vehicle', () => { + cy.openActionsDescriptor(); + cy.get('[data-cy="delete"]').click(); + cy.checkNotification('Vehicle removed'); + }); +}); diff --git a/test/cypress/integration/zone/zoneBasicData.spec.js b/test/cypress/integration/zone/zoneBasicData.spec.js index 95a075fb3..70ded3f79 100644 --- a/test/cypress/integration/zone/zoneBasicData.spec.js +++ b/test/cypress/integration/zone/zoneBasicData.spec.js @@ -1,5 +1,6 @@ describe('ZoneBasicData', () => { const priceBasicData = '[data-cy="Price_input"]'; + const saveBtn = '.q-btn-group > .q-btn--standard'; beforeEach(() => { cy.viewport(1280, 720); @@ -8,20 +9,27 @@ describe('ZoneBasicData', () => { }); it('should throw an error if the name is empty', () => { - cy.get('[data-cy="zone-basic-data-name"] input').type('{selectall}{backspace}'); - cy.get('.q-btn-group > .q-btn--standard').click(); + cy.intercept('GET', /\/api\/Zones\/4./).as('zone'); + + cy.wait('@zone').then(() => { + cy.get('[data-cy="zone-basic-data-name"] input').type( + '{selectall}{backspace}', + ); + }); + + cy.get(saveBtn).click(); cy.checkNotification("can't be blank"); }); it('should throw an error if the price is empty', () => { cy.get(priceBasicData).clear(); - cy.get('.q-btn-group > .q-btn--standard').click(); + cy.get(saveBtn).click(); cy.checkNotification('cannot be blank'); }); it("should edit the basicData's zone", () => { cy.get('.q-card > :nth-child(1)').type(' modified'); - cy.get('.q-btn-group > .q-btn--standard').click(); + cy.get(saveBtn).click(); cy.checkNotification('Data saved'); }); });