diff --git a/apps/web/public/app.js b/apps/web/public/app.js index c988421..6e4893d 100644 --- a/apps/web/public/app.js +++ b/apps/web/public/app.js @@ -926,8 +926,8 @@ function updateLeafletMarker(location) { const icon = L.divIcon({ className: `leaflet-truck-marker truck-marker ${status.key} ${vehicleType.className} ${selectedClass}`, html: createTruckMarkerHtml(location, vehicleType, markerHeading), - iconSize: [86, 68], - iconAnchor: [43, 64], + iconSize: [104, 68], + iconAnchor: [52, 64], popupAnchor: [0, -50] }); @@ -969,7 +969,7 @@ function createTruckMarkerElement(location, status, heading) { function createTruckMarkerHtml(location, vehicleType = getVehicleType(location), heading = getLocationHeading(location)) { const label = location.vehicleNo ? location.vehicleNo.slice(-4) : location.driverId.slice(0, 4); const rotation = normalizeMarkerRotation(heading); - const markerCode = getVehicleMarkerCode(vehicleType.className); + const vehiclePictogram = createVehiclePictogramSvg(vehicleType.className); return ` - + + ${escapeHtml(label)} ${escapeHtml(vehicleType.shortLabel)} `; } -function getVehicleMarkerCode(typeClass) { - const markerCodes = { - "type-cargo": "CT", - "type-trailer": "TR", - "type-container": "CN", - "type-box": "BX", - "type-van": "V", - "type-cold": "RF", - "type-wing": "WB" - }; - return markerCodes[typeClass] || "CT"; +function createVehiclePictogramSvg(typeClass) { + if (typeClass === "type-trailer") { + return ` + + `; + } + + if (typeClass === "type-container") { + return ` + + `; + } + + if (typeClass === "type-box") { + return ` + + `; + } + + if (typeClass === "type-van") { + return ` + + `; + } + + if (typeClass === "type-cold") { + return ` + + `; + } + + if (typeClass === "type-wing") { + return ` + + `; + } + + return ` + + `; } function resolveMarkerHeading(location, fromPosition, targetPosition) { diff --git a/apps/web/public/styles.css b/apps/web/public/styles.css index c135ebb..27a8611 100644 --- a/apps/web/public/styles.css +++ b/apps/web/public/styles.css @@ -1058,8 +1058,8 @@ button:hover { position: relative; display: grid; place-items: center; - width: 86px; - min-width: 86px; + width: 104px; + min-width: 104px; height: 68px; min-height: 68px; border: 0; @@ -1176,32 +1176,11 @@ button:hover { filter: drop-shadow(0 0 0 rgba(31, 111, 235, 0.22)); } -.truck-marker__type-code { - position: absolute; - top: 19px; - left: 50%; - z-index: 3; - display: grid; - place-items: center; - width: 25px; - height: 17px; - border: 1px solid rgba(255, 255, 255, 0.72); - border-radius: 5px; - background: rgba(15, 23, 42, 0.2); - color: #ffffff; - font-size: 9px; - font-weight: 950; - line-height: 1; - letter-spacing: 0; - transform: translateX(-50%); - pointer-events: none; -} - .truck-marker__status { position: absolute; top: 33px; left: calc(50% + 16px); - z-index: 4; + z-index: 5; width: 10px; height: 10px; border: 2px solid #ffffff; @@ -1211,6 +1190,47 @@ button:hover { pointer-events: none; } +.truck-marker__body-icon { + position: absolute; + top: 15px; + left: 50%; + z-index: 4; + display: grid; + place-items: center; + width: 52px; + height: 27px; + border: 1px solid rgba(15, 23, 42, 0.1); + border-radius: 8px; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.92)); + box-shadow: + 0 6px 14px rgba(15, 23, 42, 0.2), + inset 0 1px 0 rgba(255, 255, 255, 0.95); + transform: translateX(-50%); + pointer-events: none; +} + +.truck-marker__body-icon .truck-marker__vehicle-icon { + width: 47px; + height: 25px; + filter: drop-shadow(0 1px 1px rgba(15, 23, 42, 0.24)); +} + +.truck-marker__body-icon .truck-marker__vehicle-icon .icon-load, +.truck-marker__body-icon .truck-marker__vehicle-icon .icon-cab, +.truck-marker__body-icon .truck-marker__vehicle-icon .icon-wing { + stroke-width: 1.55; +} + +.truck-marker__body-icon .truck-marker__vehicle-icon .icon-line, +.truck-marker__body-icon .truck-marker__vehicle-icon .icon-snow { + stroke-width: 1.45; +} + +.truck-marker__body-icon .truck-marker__vehicle-icon .icon-wheel { + stroke-width: 1.2; +} + .truck-marker__identity { position: absolute; left: 50%; @@ -1218,10 +1238,10 @@ button:hover { z-index: 3; display: inline-flex; align-items: center; - gap: 4px; - max-width: 84px; - min-height: 20px; - padding: 2px 7px; + gap: 5px; + max-width: 102px; + min-height: 23px; + padding: 2px 7px 2px 4px; border: 1px solid rgba(15, 23, 42, 0.12); border-radius: 7px; background: rgba(255, 255, 255, 0.96); @@ -1234,6 +1254,61 @@ button:hover { white-space: nowrap; } +.truck-marker__label-icon { + display: grid; + flex: 0 0 28px; + place-items: center; + width: 28px; + height: 17px; + border: 1px solid rgba(15, 23, 42, 0.08); + border-radius: 5px; + background: var(--marker-chip); + overflow: hidden; +} + +.truck-marker__vehicle-icon { + display: block; + width: 26px; + height: 15px; + overflow: visible; +} + +.truck-marker__vehicle-icon .icon-load, +.truck-marker__vehicle-icon .icon-cab, +.truck-marker__vehicle-icon .icon-wing { + fill: var(--marker-fill); + stroke: #ffffff; + stroke-linejoin: round; + stroke-width: 1.35; +} + +.truck-marker__vehicle-icon .icon-cab { + fill: var(--marker-dark); +} + +.truck-marker__vehicle-icon .icon-window { + fill: rgba(255, 255, 255, 0.75); +} + +.truck-marker__vehicle-icon .icon-wheel { + fill: #111827; + stroke: #ffffff; + stroke-width: 1.1; +} + +.truck-marker__vehicle-icon .icon-line, +.truck-marker__vehicle-icon .icon-snow { + fill: none; + stroke: rgba(255, 255, 255, 0.86); + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.3; +} + +.truck-marker__vehicle-icon .icon-snow { + stroke: #ffffff; +} + .truck-marker__plate { display: inline-block; min-width: 0;