@aggdirect/coolmap 5.0.7 → 5.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -229,11 +229,11 @@ class JobDetailsComponent {
229
229
  this.isDragging = false;
230
230
  }
231
231
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: JobDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
232
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: JobDetailsComponent, isStandalone: true, selector: "lib-job-details", inputs: { modalOpen: { classPropertyName: "modalOpen", publicName: "modalOpen", isSignal: true, isRequired: false, transformFunction: null }, routeData: { classPropertyName: "routeData", publicName: "routeData", isSignal: true, isRequired: false, transformFunction: null }, noBackdrop: { classPropertyName: "noBackdrop", publicName: "noBackdrop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { modalOpenChange: "modalOpenChange" }, host: { listeners: { "document:mousemove": "onMouseMove($event)", "document:mouseup": "onMouseUp()" } }, ngImport: i0, template: "@if (modalOpen()) {\n<div \n class=\"z-[111] xl:z-[80] bottom-0 lg:left-[350px] fixed lg:absolute inset-0 overflow-y-auto\"\n [class.pointer-events-none]=\"noBackdrop()\"\n>\n @if (!noBackdrop()) {\n <div class=\"fixed inset-0 bg-black/50\" (click)=\"close()\"></div>\n }\n <div class=\"flex min-h-full lg:items-end lg:justify-start items-center justify-center p-3\">\n <div\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl w-[350px] pointer-events-auto\"\n [style.transform]=\"'translate(' + dragX() + 'px, ' + dragY() + 'px)'\"\n [style.will-change]=\"'transform'\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"startDrag($event)\"\n >\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b cursor-move border-gray-200 dark:border-slate-700 dark:bg-slate-900 rounded-t-lg select-none\"\n >\n <h3 class=\"flex items-center gap-1 font-medium text-gray-900 dark:text-white text-[13px]\">\n Job Details\n </h3>\n <button\n (click)=\"close()\"\n class=\"p-2 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors text-gray-500\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"20\"></lucide-icon>\n </button>\n </div>\n <div class=\"max-h-[50vh] overflow-y-auto p-2\">\n <div class=\"stats-row\">\n <div class=\"stat-item completed\">\n <span class=\"stat-count\">{{ routeData()?.values?.Done || 0 }}</span>\n <span class=\"stat-label\">Done</span>\n </div>\n\n <div class=\"stat-item pending\">\n <span class=\"stat-count\">{{ routeData()?.values?.Ongoing || 0 }}</span>\n <span class=\"stat-label\">Ongoing</span>\n </div>\n\n <div class=\"stat-item active\">\n <span class=\"stat-count\">{{ routeData()?.values?.Open || 0 }}</span>\n <span class=\"stat-label\">Open</span>\n </div>\n </div>\n <div\n class=\"location-flow bg-gray-100 dark:bg-slate-900 border border-gray-300 dark:border-slate-700 px-2 py-2 rounded-lg mt-4\"\n >\n <span class=\"pickup truncate block\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"inline mr-1 text-green-500\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n Pickup: {{ routeData()?.pickup_location || 'N/A' }}\n </span>\n <span class=\"delivery truncate block mt-1\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"inline mr-1 text-blue-500\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n Delivery: {{ routeData()?.delivery_location || 'N/A' }}\n </span>\n </div>\n <div class=\"device-info mt-2\">\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Jobcode</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.order_number || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Customer</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.customer_name || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Project Name</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.project || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Job Type</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.unit || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Material</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.material || 'General Freight' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Customer Contact</span>\n <span class=\"font-medium\">{{ routeData()?.customer_contact || 'None' }}</span>\n </div>\n <div class=\"flex justify-between py-2 text-xs\">\n <span class=\"text-gray-500 dark:text-slate-500\">Delivery Contact</span>\n <span class=\"font-medium\">{{ routeData()?.delivery_contact || 'None' }}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n}\n", styles: [".stats-row{display:flex;align-items:center;gap:30px;font-size:12px;margin:0 10px 0 60px}.stat-item{display:flex;align-items:center;gap:6px;cursor:default}.stat-count{font-size:15px;font-weight:700;line-height:1}.stat-item.active .stat-count{color:#60a5fa}.stat-item.completed .stat-count{color:#4ade80}.stat-item.declined .stat-count{color:#f87171}.stat-item.scheduled .stat-count{color:#a78bfa}.stat-item.pending .stat-count{color:#fbbf24}.location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:center;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px}.location-flow .delivery{display:flex;align-items:center;gap:3px;color:#ef4444}.location-flow .delivery svg{width:8px;height:8px}@keyframes slide-up{0%{opacity:0;transform:translateY(10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.animate-fade-in{animation:fade-in .2s ease-out}.animate-slide-up{animation:slide-up .2s ease-out}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }] });
232
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: JobDetailsComponent, isStandalone: true, selector: "lib-job-details", inputs: { modalOpen: { classPropertyName: "modalOpen", publicName: "modalOpen", isSignal: true, isRequired: false, transformFunction: null }, routeData: { classPropertyName: "routeData", publicName: "routeData", isSignal: true, isRequired: false, transformFunction: null }, noBackdrop: { classPropertyName: "noBackdrop", publicName: "noBackdrop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { modalOpenChange: "modalOpenChange" }, host: { listeners: { "document:mousemove": "onMouseMove($event)", "document:mouseup": "onMouseUp()" } }, ngImport: i0, template: "@if (modalOpen()) {\n<div \n class=\"z-[11] xl:z-[80] bottom-0 lg:left-[350px] fixed lg:absolute inset-0 overflow-y-auto\"\n [class.pointer-events-none]=\"noBackdrop()\"\n>\n @if (!noBackdrop()) {\n <div class=\"fixed inset-0 bg-black/50\" (click)=\"close()\"></div>\n }\n <div class=\"flex min-h-full lg:items-end lg:justify-start items-center justify-center p-3\">\n <div\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl w-[350px] pointer-events-auto\"\n [style.transform]=\"'translate(' + dragX() + 'px, ' + dragY() + 'px)'\"\n [style.will-change]=\"'transform'\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"startDrag($event)\"\n >\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b cursor-move border-gray-200 dark:border-slate-700 dark:bg-slate-900 rounded-t-lg select-none\"\n >\n <h3 class=\"flex items-center gap-1 font-medium text-gray-900 dark:text-white text-[13px]\">\n Job Details\n </h3>\n <button\n (click)=\"close()\"\n class=\"p-2 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors text-gray-500\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"20\"></lucide-icon>\n </button>\n </div>\n <div class=\"max-h-[50vh] overflow-y-auto p-2\">\n <div class=\"stats-row\">\n <div class=\"stat-item completed\">\n <span class=\"stat-count\">{{ routeData()?.values?.Done || 0 }}</span>\n <span class=\"stat-label\">Done</span>\n </div>\n\n <div class=\"stat-item pending\">\n <span class=\"stat-count\">{{ routeData()?.values?.Ongoing || 0 }}</span>\n <span class=\"stat-label\">Ongoing</span>\n </div>\n\n <div class=\"stat-item active\">\n <span class=\"stat-count\">{{ routeData()?.values?.Open || 0 }}</span>\n <span class=\"stat-label\">Open</span>\n </div>\n </div>\n <div\n class=\"location-flow bg-gray-100 dark:bg-slate-900 border border-gray-300 dark:border-slate-700 px-2 py-2 rounded-lg mt-4\"\n >\n <span class=\"pickup truncate block\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"inline mr-1 text-green-500\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n Pickup: {{ routeData()?.pickup_location || 'N/A' }}\n </span>\n <span class=\"delivery truncate block mt-1\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"inline mr-1 text-blue-500\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n Delivery: {{ routeData()?.delivery_location || 'N/A' }}\n </span>\n </div>\n <div class=\"device-info mt-2\">\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Jobcode</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.order_number || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Customer</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.customer_name || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Project Name</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.project || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Job Type</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.unit || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Material</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.material || 'General Freight' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Customer Contact</span>\n <span class=\"font-medium\">{{ routeData()?.customer_contact || 'None' }}</span>\n </div>\n <div class=\"flex justify-between py-2 text-xs\">\n <span class=\"text-gray-500 dark:text-slate-500\">Delivery Contact</span>\n <span class=\"font-medium\">{{ routeData()?.delivery_contact || 'None' }}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n}\n", styles: [".stats-row{display:flex;align-items:center;gap:30px;font-size:12px;margin:0 10px 0 60px}.stat-item{display:flex;align-items:center;gap:6px;cursor:default}.stat-count{font-size:15px;font-weight:700;line-height:1}.stat-item.active .stat-count{color:#60a5fa}.stat-item.completed .stat-count{color:#4ade80}.stat-item.declined .stat-count{color:#f87171}.stat-item.scheduled .stat-count{color:#a78bfa}.stat-item.pending .stat-count{color:#fbbf24}.location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:center;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px}.location-flow .delivery{display:flex;align-items:center;gap:3px;color:#ef4444}.location-flow .delivery svg{width:8px;height:8px}@keyframes slide-up{0%{opacity:0;transform:translateY(10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.animate-fade-in{animation:fade-in .2s ease-out}.animate-slide-up{animation:slide-up .2s ease-out}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }] });
233
233
  }
234
234
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: JobDetailsComponent, decorators: [{
235
235
  type: Component,
236
- args: [{ selector: 'lib-job-details', standalone: true, imports: [LucideAngularModule, NgClass], template: "@if (modalOpen()) {\n<div \n class=\"z-[111] xl:z-[80] bottom-0 lg:left-[350px] fixed lg:absolute inset-0 overflow-y-auto\"\n [class.pointer-events-none]=\"noBackdrop()\"\n>\n @if (!noBackdrop()) {\n <div class=\"fixed inset-0 bg-black/50\" (click)=\"close()\"></div>\n }\n <div class=\"flex min-h-full lg:items-end lg:justify-start items-center justify-center p-3\">\n <div\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl w-[350px] pointer-events-auto\"\n [style.transform]=\"'translate(' + dragX() + 'px, ' + dragY() + 'px)'\"\n [style.will-change]=\"'transform'\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"startDrag($event)\"\n >\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b cursor-move border-gray-200 dark:border-slate-700 dark:bg-slate-900 rounded-t-lg select-none\"\n >\n <h3 class=\"flex items-center gap-1 font-medium text-gray-900 dark:text-white text-[13px]\">\n Job Details\n </h3>\n <button\n (click)=\"close()\"\n class=\"p-2 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors text-gray-500\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"20\"></lucide-icon>\n </button>\n </div>\n <div class=\"max-h-[50vh] overflow-y-auto p-2\">\n <div class=\"stats-row\">\n <div class=\"stat-item completed\">\n <span class=\"stat-count\">{{ routeData()?.values?.Done || 0 }}</span>\n <span class=\"stat-label\">Done</span>\n </div>\n\n <div class=\"stat-item pending\">\n <span class=\"stat-count\">{{ routeData()?.values?.Ongoing || 0 }}</span>\n <span class=\"stat-label\">Ongoing</span>\n </div>\n\n <div class=\"stat-item active\">\n <span class=\"stat-count\">{{ routeData()?.values?.Open || 0 }}</span>\n <span class=\"stat-label\">Open</span>\n </div>\n </div>\n <div\n class=\"location-flow bg-gray-100 dark:bg-slate-900 border border-gray-300 dark:border-slate-700 px-2 py-2 rounded-lg mt-4\"\n >\n <span class=\"pickup truncate block\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"inline mr-1 text-green-500\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n Pickup: {{ routeData()?.pickup_location || 'N/A' }}\n </span>\n <span class=\"delivery truncate block mt-1\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"inline mr-1 text-blue-500\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n Delivery: {{ routeData()?.delivery_location || 'N/A' }}\n </span>\n </div>\n <div class=\"device-info mt-2\">\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Jobcode</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.order_number || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Customer</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.customer_name || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Project Name</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.project || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Job Type</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.unit || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Material</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.material || 'General Freight' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Customer Contact</span>\n <span class=\"font-medium\">{{ routeData()?.customer_contact || 'None' }}</span>\n </div>\n <div class=\"flex justify-between py-2 text-xs\">\n <span class=\"text-gray-500 dark:text-slate-500\">Delivery Contact</span>\n <span class=\"font-medium\">{{ routeData()?.delivery_contact || 'None' }}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n}\n", styles: [".stats-row{display:flex;align-items:center;gap:30px;font-size:12px;margin:0 10px 0 60px}.stat-item{display:flex;align-items:center;gap:6px;cursor:default}.stat-count{font-size:15px;font-weight:700;line-height:1}.stat-item.active .stat-count{color:#60a5fa}.stat-item.completed .stat-count{color:#4ade80}.stat-item.declined .stat-count{color:#f87171}.stat-item.scheduled .stat-count{color:#a78bfa}.stat-item.pending .stat-count{color:#fbbf24}.location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:center;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px}.location-flow .delivery{display:flex;align-items:center;gap:3px;color:#ef4444}.location-flow .delivery svg{width:8px;height:8px}@keyframes slide-up{0%{opacity:0;transform:translateY(10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.animate-fade-in{animation:fade-in .2s ease-out}.animate-slide-up{animation:slide-up .2s ease-out}\n"] }]
236
+ args: [{ selector: 'lib-job-details', standalone: true, imports: [LucideAngularModule, NgClass], template: "@if (modalOpen()) {\n<div \n class=\"z-[11] xl:z-[80] bottom-0 lg:left-[350px] fixed lg:absolute inset-0 overflow-y-auto\"\n [class.pointer-events-none]=\"noBackdrop()\"\n>\n @if (!noBackdrop()) {\n <div class=\"fixed inset-0 bg-black/50\" (click)=\"close()\"></div>\n }\n <div class=\"flex min-h-full lg:items-end lg:justify-start items-center justify-center p-3\">\n <div\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl w-[350px] pointer-events-auto\"\n [style.transform]=\"'translate(' + dragX() + 'px, ' + dragY() + 'px)'\"\n [style.will-change]=\"'transform'\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"startDrag($event)\"\n >\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b cursor-move border-gray-200 dark:border-slate-700 dark:bg-slate-900 rounded-t-lg select-none\"\n >\n <h3 class=\"flex items-center gap-1 font-medium text-gray-900 dark:text-white text-[13px]\">\n Job Details\n </h3>\n <button\n (click)=\"close()\"\n class=\"p-2 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors text-gray-500\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"20\"></lucide-icon>\n </button>\n </div>\n <div class=\"max-h-[50vh] overflow-y-auto p-2\">\n <div class=\"stats-row\">\n <div class=\"stat-item completed\">\n <span class=\"stat-count\">{{ routeData()?.values?.Done || 0 }}</span>\n <span class=\"stat-label\">Done</span>\n </div>\n\n <div class=\"stat-item pending\">\n <span class=\"stat-count\">{{ routeData()?.values?.Ongoing || 0 }}</span>\n <span class=\"stat-label\">Ongoing</span>\n </div>\n\n <div class=\"stat-item active\">\n <span class=\"stat-count\">{{ routeData()?.values?.Open || 0 }}</span>\n <span class=\"stat-label\">Open</span>\n </div>\n </div>\n <div\n class=\"location-flow bg-gray-100 dark:bg-slate-900 border border-gray-300 dark:border-slate-700 px-2 py-2 rounded-lg mt-4\"\n >\n <span class=\"pickup truncate block\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"inline mr-1 text-green-500\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n Pickup: {{ routeData()?.pickup_location || 'N/A' }}\n </span>\n <span class=\"delivery truncate block mt-1\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"inline mr-1 text-blue-500\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n Delivery: {{ routeData()?.delivery_location || 'N/A' }}\n </span>\n </div>\n <div class=\"device-info mt-2\">\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Jobcode</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.order_number || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Customer</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.customer_name || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Project Name</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.project || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Job Type</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.unit || 'N/A' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Material</span>\n <span class=\"font-medium truncate max-w-[65%] text-right\">{{ routeData()?.material || 'General Freight' }}</span>\n </div>\n <div\n class=\"flex justify-between py-2 border-b border-gray-200 dark:border-slate-600 text-xs\"\n >\n <span class=\"text-gray-500 dark:text-slate-500\">Customer Contact</span>\n <span class=\"font-medium\">{{ routeData()?.customer_contact || 'None' }}</span>\n </div>\n <div class=\"flex justify-between py-2 text-xs\">\n <span class=\"text-gray-500 dark:text-slate-500\">Delivery Contact</span>\n <span class=\"font-medium\">{{ routeData()?.delivery_contact || 'None' }}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n}\n", styles: [".stats-row{display:flex;align-items:center;gap:30px;font-size:12px;margin:0 10px 0 60px}.stat-item{display:flex;align-items:center;gap:6px;cursor:default}.stat-count{font-size:15px;font-weight:700;line-height:1}.stat-item.active .stat-count{color:#60a5fa}.stat-item.completed .stat-count{color:#4ade80}.stat-item.declined .stat-count{color:#f87171}.stat-item.scheduled .stat-count{color:#a78bfa}.stat-item.pending .stat-count{color:#fbbf24}.location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:center;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px}.location-flow .delivery{display:flex;align-items:center;gap:3px;color:#ef4444}.location-flow .delivery svg{width:8px;height:8px}@keyframes slide-up{0%{opacity:0;transform:translateY(10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.animate-fade-in{animation:fade-in .2s ease-out}.animate-slide-up{animation:slide-up .2s ease-out}\n"] }]
237
237
  }], propDecorators: { modalOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "modalOpen", required: false }] }], routeData: [{ type: i0.Input, args: [{ isSignal: true, alias: "routeData", required: false }] }], noBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "noBackdrop", required: false }] }], modalOpenChange: [{
238
238
  type: Output
239
239
  }], onMouseMove: [{
@@ -327,11 +327,11 @@ class JobCodeComponent {
327
327
  }
328
328
  }
329
329
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: JobCodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
330
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: JobCodeComponent, isStandalone: true, selector: "lib-job-code", inputs: { listMode: "listMode", collapsible: "collapsible", routes: "routes", selectedRouteIds: "selectedRouteIds", isLoading: "isLoading" }, outputs: { routeSelect: "routeSelect" }, host: { listeners: { "document:keydown.escape": "icons()" } }, ngImport: i0, template: "<div\n class=\"cards-list-container\"\n [class.floating]=\"listMode === 'floating'\"\n [class.sidebar]=\"listMode === 'sidebar'\"\n [class.inline]=\"listMode === 'inline'\"\n [class.collapsed]=\"collapsed\"\n>\n <div class=\"list-header\">\n <div class=\"header-title\">\n <span class=\"title-text\">Routes</span>\n <span class=\"routes-count\">({{ routes.length || 0 }})</span>\n </div>\n <button\n class=\"collapse-btn\"\n (click)=\"toggleCollapse()\"\n [title]=\"collapsed ? 'Expand' : 'Collapse'\"\n >\n @if (collapsed) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n } @else {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n }\n </button>\n </div>\n @if (!collapsed) {\n <div class=\"cards-scroll-container\" #scrollContainer>\n @if (isLoading) {\n <div class=\"list-loader\">\n <lucide-icon [img]=\"icons.LoaderCircle\" [size]=\"32\" class=\"animate-spin text-amber-500\"></lucide-icon>\n </div>\n }\n @if(routes.length){\n <div class=\"cards-list\">\n @for (route of routes; track $index) {\n <div class=\"card-wrapper\" (click)=\"toggleRouteSelection(route)\">\n <div\n class=\"route-card bg-white dark:bg-slate-800 border transition-all duration-200\"\n [class.border-brand-blue]=\"selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.border-gray-300]=\"!selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.dark:border-slate-700]=\"!selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.selected]=\"selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n >\n <div class=\"task-header justify-between\">\n <span class=\"job-code\">{{ route.order_number || 'N/A' }}</span>\n <div class=\"flex gap-2\">\n <div class=\"statusunit text-white\" [ngClass]=\"route.unit || ''\">{{ route.unit?.charAt(0) || 'U' }}</div>\n @if (config.repository !== 'customer') {\n <div\n class=\"statusunit bg-slate-900 dark:bg-white text-white dark:text-black flex items-center justify-center cursor-pointer hover:opacity-80\"\n (click)=\"showDriverModal = true; toggleCollapse(); $event.stopPropagation()\"\n >\n <lucide-icon [img]=\"icons.CarFront\" [size]=\"15\"></lucide-icon>\n </div>\n }\n <div\n class=\"text-black dark:text-white flex items-center justify-center cursor-pointer hover:opacity-80\"\n (click)=\"openDetail(route, true); $event.stopPropagation()\"\n (mouseenter)=\"openDetail(route, false)\"\n (mouseleave)=\"closeDetail(true)\"\n >\n <lucide-icon [img]=\"icons.Info\" [size]=\"20\"></lucide-icon>\n </div>\n </div>\n </div>\n <div class=\"customer-name font-semibold truncate\">{{ route.customer_name }}</div>\n <div class=\"material-info truncate text-gray-600 dark:text-gray-300\">{{ route.project || 'No Project' }}</div>\n <div class=\"location-flow mt-2 text-sm flex items-center gap-2\">\n <span class=\"pickup flex items-center gap-1 truncate max-w-[40%] text-green-600 dark:text-green-400\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.pickup_location || '').split('|')[0] || 'Unknown' }}\n </span>\n <span class=\"arrow text-gray-400\">\u2192</span>\n <span class=\"delivery truncate max-w-[40%] text-brand-blue\">{{ (route.delivery_location || '').split('|')[0] || 'Unknown' }}</span>\n </div>\n <div class=\"material-info mt-2 truncate font-medium\">{{ route.material || '' }}</div>\n <div class=\"driver-row-4 mt-3 flex items-center gap-2\">\n <div class=\"progress-bar flex-1 h-1.5 bg-gray-200 dark:bg-slate-700 rounded-full overflow-hidden flex\">\n <div class=\"progress-segment completed h-full bg-green-500 transition-all duration-300\" [style.width.%]=\"calculateStatusPercentage('done', route)\"></div>\n <div class=\"progress-segment ongoing h-full transition-all duration-300\" [style.backgroundColor]=\"'#fc0'\" [style.width.%]=\"calculateStatusPercentage('ongoing', route)\"></div>\n <div class=\"progress-segment open h-full bg-gray-300 dark:bg-slate-600 transition-all duration-300\" [style.width.%]=\"calculateStatusPercentage('open', route)\"></div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <div class=\"text-gray-600 dark:text-gray-400 mt-2 text-center\">No Job code found.</div>\n </div>\n }\n </div>\n }\n</div>\n<lib-driver-list\n [(modalOpen)]=\"showDriverModal\"\n [driverListcollapse]=\"driverListcollapse()\"\n></lib-driver-list>\n<lib-job-details \n [modalOpen]=\"showDetailModal\" \n (modalOpenChange)=\"$event ? null : closeDetail(false)\" \n [routeData]=\"selectedJobDetail()\" \n [noBackdrop]=\"!isClickTriggered\"\n></lib-job-details>\n", styles: [":host{display:block}.cards-list-container{display:flex;flex-direction:column;height:100%;background:var(--bg-primary, white)}.cards-list-container.floating{position:absolute;top:12px;left:12px;width:280px;max-height:calc(100% - 24px);border-radius:12px;box-shadow:0 4px 24px #00000026;z-index:100;overflow:hidden}.cards-list-container.floating.collapsed{width:48px}.cards-list-container.sidebar{width:100%;border-right:1px solid var(--border-color, #e2e8f0)}.cards-list-container.inline{width:160px;min-width:160px;border-right:1px solid var(--border-color, #e2e8f0)}:host-context(.dark) .cards-list-container{background-color:#1e293b}:host-context(.dark) .cards-list-container.sidebar,:host-context(.dark) .cards-list-container.inline{border-color:#334155}.list-header{display:flex;align-items:center;justify-content:space-between;padding:12px;border-bottom:1px solid var(--border-color, #e2e8f0);background:var(--bg-secondary, #f8fafc)}:host-context(.dark) .list-header{background-color:#0f172a;border-color:#334155}.collapsed .list-header{padding:12px 8px;justify-content:center}.header-title{display:flex;align-items:center;gap:6px}.collapsed .header-title{display:none}.title-text{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b)}:host-context(.dark) .title-text{color:#f1f5f9}.routes-count{font-size:12px;color:var(--text-secondary, #64748b)}.collapse-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;color:var(--text-secondary, #64748b);cursor:pointer;border-radius:6px;transition:all .15s ease}.collapse-btn:hover{background:var(--hover-bg, #e2e8f0);color:var(--text-primary, #1e293b)}:host-context(.dark) .collapse-btn:hover{background-color:#334155;color:#f1f5f9}.cards-scroll-container{flex:1;overflow-y:auto;overflow-x:hidden}.cards-list{display:flex;flex-direction:column;gap:8px;padding:8px}.card-wrapper{border-radius:8px;transition:all .2s ease}.route-card{position:relative;padding:6px 10px;display:flex;flex-direction:column;gap:2px;border-radius:8px;cursor:pointer;transition:all .15s ease;min-height:72px}.route-card:hover{border-color:var(--accent-color, #3b82f6);box-shadow:0 2px 8px #00000014}.route-card.selected{border-color:var(--accent-color, #3b82f6);background:#3b82f60d}.task-header{display:flex;align-items:center;gap:6px;margin-bottom:4px}.job-code{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b)}:host-context(.dark) .job-code{color:#f1f5f9}.customer-name{font-size:12px;color:var(--text-secondary, #64748b);margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.material-info{font-size:11px;color:var(--text-tertiary, #94a3b8);margin-bottom:6px;font-weight:500}.location-flow{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:center;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px}.location-flow .arrow{color:var(--text-tertiary, #94a3b8)}.location-flow .delivery{color:#ef4444}.driver-row-4{display:flex;align-items:center;gap:4px;margin-top:2px}.progress-bar{display:flex;gap:2px}.progress-segment{height:6px;border-radius:2px;position:relative;cursor:pointer}.progress-segment.completed{background:#22c55e}.progress-segment.in_progress{background:#f59e0b}.progress-segment.pending{background:#cbd5e1}.progress-segment.incomplete{background:#ef4444}.progress-segment:after{content:attr(data-tooltip);position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%);background:#1e293b;color:#fff;padding:6px 10px;border-radius:6px;font-size:10px;white-space:pre-line;min-width:120px;max-width:180px;box-shadow:0 3px 10px #0003;z-index:1000;opacity:0;visibility:hidden;transition:opacity .15s ease;pointer-events:none}.progress-segment:hover:after{opacity:1;visibility:visible}.task-count{font-size:10px;font-weight:600;color:var(--text-secondary, #64748b);min-width:24px;text-align:right}.on-time-indicator{font-size:10px;color:#22c55e}.on-time-indicator.late{color:#ef4444}.statusunit{border-radius:30px;font-size:12px;text-transform:capitalize;font-weight:600;width:20px;height:20px;text-align:center;line-height:20px}.statusunit.Ton{background:#22c55e}.statusunit.Load{background:#3b82f6}.statusunit.Hourly{background:#f59e0b}.list-loader{position:absolute;inset:0;background:#fff6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:50;border-radius:0 0 12px 12px}:host-context(.dark) .list-loader{background:#0f172a66}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: DriverListComponent, selector: "lib-driver-list", inputs: ["modalOpen", "driverListcollapse"], outputs: ["modalOpenChange"] }, { kind: "component", type: JobDetailsComponent, selector: "lib-job-details", inputs: ["modalOpen", "routeData", "noBackdrop"], outputs: ["modalOpenChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
330
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: JobCodeComponent, isStandalone: true, selector: "lib-job-code", inputs: { listMode: "listMode", collapsible: "collapsible", routes: "routes", selectedRouteIds: "selectedRouteIds", isLoading: "isLoading" }, outputs: { routeSelect: "routeSelect" }, host: { listeners: { "document:keydown.escape": "icons()" } }, ngImport: i0, template: "<div\n class=\"cards-list-container\"\n [class.floating]=\"listMode === 'floating'\"\n [class.sidebar]=\"listMode === 'sidebar'\"\n [class.inline]=\"listMode === 'inline'\"\n [class.collapsed]=\"collapsed\"\n>\n <div class=\"list-header\">\n <div class=\"header-title\">\n <span class=\"title-text\">Routes</span>\n <span class=\"routes-count\">({{ routes.length || 0 }})</span>\n </div>\n <button\n class=\"collapse-btn\"\n (click)=\"toggleCollapse()\"\n [title]=\"collapsed ? 'Expand' : 'Collapse'\"\n >\n @if (collapsed) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n } @else {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n }\n </button>\n </div>\n @if (!collapsed) {\n <div class=\"cards-scroll-container\" #scrollContainer>\n @if (routes.length && isLoading) {\n <div class=\"list-loader\">\n <lucide-icon [img]=\"icons.LoaderCircle\" [size]=\"32\" class=\"animate-spin text-amber-500\"></lucide-icon>\n </div>\n }\n @if(routes.length){\n <div class=\"cards-list\">\n @for (route of routes; track $index) {\n <div class=\"card-wrapper\" (click)=\"toggleRouteSelection(route)\">\n <div\n class=\"route-card bg-white dark:bg-slate-800 border transition-all duration-200\"\n [class.border-brand-blue]=\"selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.border-gray-300]=\"!selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.dark:border-slate-700]=\"!selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.selected]=\"selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n >\n <div class=\"task-header justify-between\">\n <span class=\"job-code\">{{ route.order_number || 'N/A' }}</span>\n <div class=\"flex gap-2\">\n <div class=\"statusunit text-white\" [ngClass]=\"route.unit || ''\">{{ route.unit?.charAt(0) || 'U' }}</div>\n @if (config.repository !== 'customer') {\n <div\n class=\"statusunit bg-slate-900 dark:bg-white text-white dark:text-black flex items-center justify-center cursor-pointer hover:opacity-80\"\n (click)=\"showDriverModal = true; toggleCollapse(); $event.stopPropagation()\"\n >\n <lucide-icon [img]=\"icons.CarFront\" [size]=\"15\"></lucide-icon>\n </div>\n }\n <div\n class=\"text-black dark:text-white flex items-center justify-center cursor-pointer hover:opacity-80\"\n (click)=\"openDetail(route, true); $event.stopPropagation()\"\n (mouseenter)=\"openDetail(route, false)\"\n (mouseleave)=\"closeDetail(true)\"\n >\n <lucide-icon [img]=\"icons.Info\" [size]=\"20\"></lucide-icon>\n </div>\n </div>\n </div>\n <div class=\"customer-name font-semibold truncate\">{{ route.customer_name }}</div>\n <div class=\"material-info truncate text-gray-600 dark:text-gray-300\">{{ route.project || 'No Project' }}</div>\n <div class=\"location-flow mt-2 text-sm flex items-center gap-2\">\n <span class=\"pickup flex items-center gap-1 truncate max-w-[40%] text-green-600 dark:text-green-400\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.pickup_location || '').split('|')[0] || 'Unknown' }}\n </span>\n <span class=\"arrow text-gray-400\">\u2192</span>\n <span class=\"delivery truncate max-w-[40%] text-brand-blue\">{{ (route.delivery_location || '').split('|')[0] || 'Unknown' }}</span>\n </div>\n <div class=\"material-info mt-2 truncate font-medium\">{{ route.material || '' }}</div>\n <div class=\"driver-row-4 mt-3 flex items-center gap-2\">\n <div class=\"progress-bar flex-1 h-1.5 bg-gray-200 dark:bg-slate-700 rounded-full overflow-hidden flex\">\n <div class=\"progress-segment completed h-full bg-green-500 transition-all duration-300\" [style.width.%]=\"calculateStatusPercentage('done', route)\"></div>\n <div class=\"progress-segment ongoing h-full transition-all duration-300\" [style.backgroundColor]=\"'#fc0'\" [style.width.%]=\"calculateStatusPercentage('ongoing', route)\"></div>\n <div class=\"progress-segment open h-full bg-gray-300 dark:bg-slate-600 transition-all duration-300\" [style.width.%]=\"calculateStatusPercentage('open', route)\"></div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <div class=\"text-gray-600 dark:text-gray-400 mt-2 text-center\">No Job code found.</div>\n </div>\n }\n </div>\n }\n</div>\n<lib-driver-list\n [(modalOpen)]=\"showDriverModal\"\n [driverListcollapse]=\"driverListcollapse()\"\n></lib-driver-list>\n<lib-job-details \n [modalOpen]=\"showDetailModal\" \n (modalOpenChange)=\"$event ? null : closeDetail(false)\" \n [routeData]=\"selectedJobDetail()\" \n [noBackdrop]=\"!isClickTriggered\"\n></lib-job-details>\n", styles: [":host{display:block}.cards-list-container{display:flex;flex-direction:column;height:100%;background:var(--bg-primary, white)}.cards-list-container.floating{position:absolute;top:12px;left:12px;width:280px;max-height:calc(100% - 24px);border-radius:12px;box-shadow:0 4px 24px #00000026;z-index:100;overflow:hidden}.cards-list-container.floating.collapsed{width:48px}.cards-list-container.sidebar{width:100%;border-right:1px solid var(--border-color, #e2e8f0)}.cards-list-container.inline{width:160px;min-width:160px;border-right:1px solid var(--border-color, #e2e8f0)}:host-context(.dark) .cards-list-container{background-color:#1e293b}:host-context(.dark) .cards-list-container.sidebar,:host-context(.dark) .cards-list-container.inline{border-color:#334155}.list-header{display:flex;align-items:center;justify-content:space-between;padding:12px;border-bottom:1px solid var(--border-color, #e2e8f0);background:var(--bg-secondary, #f8fafc)}:host-context(.dark) .list-header{background-color:#0f172a;border-color:#334155}.collapsed .list-header{padding:12px 8px;justify-content:center}.header-title{display:flex;align-items:center;gap:6px}.collapsed .header-title{display:none}.title-text{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b)}:host-context(.dark) .title-text{color:#f1f5f9}.routes-count{font-size:12px;color:var(--text-secondary, #64748b)}.collapse-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;color:var(--text-secondary, #64748b);cursor:pointer;border-radius:6px;transition:all .15s ease}.collapse-btn:hover{background:var(--hover-bg, #e2e8f0);color:var(--text-primary, #1e293b)}:host-context(.dark) .collapse-btn:hover{background-color:#334155;color:#f1f5f9}.cards-scroll-container{flex:1;overflow-y:auto;overflow-x:hidden}.cards-list{display:flex;flex-direction:column;gap:8px;padding:8px}.card-wrapper{border-radius:8px;transition:all .2s ease}.route-card{position:relative;padding:6px 10px;display:flex;flex-direction:column;gap:2px;border-radius:8px;cursor:pointer;transition:all .15s ease;min-height:72px}.route-card:hover{border-color:var(--accent-color, #3b82f6);box-shadow:0 2px 8px #00000014}.route-card.selected{border-color:var(--accent-color, #3b82f6);background:#3b82f60d}.task-header{display:flex;align-items:center;gap:6px;margin-bottom:4px}.job-code{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b)}:host-context(.dark) .job-code{color:#f1f5f9}.customer-name{font-size:12px;color:var(--text-secondary, #64748b);margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.material-info{font-size:11px;color:var(--text-tertiary, #94a3b8);margin-bottom:6px;font-weight:500}.location-flow{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:center;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px}.location-flow .arrow{color:var(--text-tertiary, #94a3b8)}.location-flow .delivery{color:#ef4444}.driver-row-4{display:flex;align-items:center;gap:4px;margin-top:2px}.progress-bar{display:flex;gap:2px}.progress-segment{height:6px;border-radius:2px;position:relative;cursor:pointer}.progress-segment.completed{background:#22c55e}.progress-segment.in_progress{background:#f59e0b}.progress-segment.pending{background:#cbd5e1}.progress-segment.incomplete{background:#ef4444}.progress-segment:after{content:attr(data-tooltip);position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%);background:#1e293b;color:#fff;padding:6px 10px;border-radius:6px;font-size:10px;white-space:pre-line;min-width:120px;max-width:180px;box-shadow:0 3px 10px #0003;z-index:1000;opacity:0;visibility:hidden;transition:opacity .15s ease;pointer-events:none}.progress-segment:hover:after{opacity:1;visibility:visible}.task-count{font-size:10px;font-weight:600;color:var(--text-secondary, #64748b);min-width:24px;text-align:right}.on-time-indicator{font-size:10px;color:#22c55e}.on-time-indicator.late{color:#ef4444}.statusunit{border-radius:30px;font-size:12px;text-transform:capitalize;font-weight:600;width:20px;height:20px;text-align:center;line-height:20px}.statusunit.Ton{background:#22c55e}.statusunit.Load{background:#3b82f6}.statusunit.Hourly{background:#f59e0b}.list-loader{position:absolute;inset:0;background:#fff6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:50;border-radius:0 0 12px 12px}:host-context(.dark) .list-loader{background:#0f172a66}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: DriverListComponent, selector: "lib-driver-list", inputs: ["modalOpen", "driverListcollapse"], outputs: ["modalOpenChange"] }, { kind: "component", type: JobDetailsComponent, selector: "lib-job-details", inputs: ["modalOpen", "routeData", "noBackdrop"], outputs: ["modalOpenChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
331
331
  }
332
332
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: JobCodeComponent, decorators: [{
333
333
  type: Component,
334
- args: [{ selector: 'lib-job-code', standalone: true, imports: [LucideAngularModule, DriverListComponent, JobDetailsComponent, NgClass], template: "<div\n class=\"cards-list-container\"\n [class.floating]=\"listMode === 'floating'\"\n [class.sidebar]=\"listMode === 'sidebar'\"\n [class.inline]=\"listMode === 'inline'\"\n [class.collapsed]=\"collapsed\"\n>\n <div class=\"list-header\">\n <div class=\"header-title\">\n <span class=\"title-text\">Routes</span>\n <span class=\"routes-count\">({{ routes.length || 0 }})</span>\n </div>\n <button\n class=\"collapse-btn\"\n (click)=\"toggleCollapse()\"\n [title]=\"collapsed ? 'Expand' : 'Collapse'\"\n >\n @if (collapsed) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n } @else {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n }\n </button>\n </div>\n @if (!collapsed) {\n <div class=\"cards-scroll-container\" #scrollContainer>\n @if (isLoading) {\n <div class=\"list-loader\">\n <lucide-icon [img]=\"icons.LoaderCircle\" [size]=\"32\" class=\"animate-spin text-amber-500\"></lucide-icon>\n </div>\n }\n @if(routes.length){\n <div class=\"cards-list\">\n @for (route of routes; track $index) {\n <div class=\"card-wrapper\" (click)=\"toggleRouteSelection(route)\">\n <div\n class=\"route-card bg-white dark:bg-slate-800 border transition-all duration-200\"\n [class.border-brand-blue]=\"selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.border-gray-300]=\"!selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.dark:border-slate-700]=\"!selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.selected]=\"selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n >\n <div class=\"task-header justify-between\">\n <span class=\"job-code\">{{ route.order_number || 'N/A' }}</span>\n <div class=\"flex gap-2\">\n <div class=\"statusunit text-white\" [ngClass]=\"route.unit || ''\">{{ route.unit?.charAt(0) || 'U' }}</div>\n @if (config.repository !== 'customer') {\n <div\n class=\"statusunit bg-slate-900 dark:bg-white text-white dark:text-black flex items-center justify-center cursor-pointer hover:opacity-80\"\n (click)=\"showDriverModal = true; toggleCollapse(); $event.stopPropagation()\"\n >\n <lucide-icon [img]=\"icons.CarFront\" [size]=\"15\"></lucide-icon>\n </div>\n }\n <div\n class=\"text-black dark:text-white flex items-center justify-center cursor-pointer hover:opacity-80\"\n (click)=\"openDetail(route, true); $event.stopPropagation()\"\n (mouseenter)=\"openDetail(route, false)\"\n (mouseleave)=\"closeDetail(true)\"\n >\n <lucide-icon [img]=\"icons.Info\" [size]=\"20\"></lucide-icon>\n </div>\n </div>\n </div>\n <div class=\"customer-name font-semibold truncate\">{{ route.customer_name }}</div>\n <div class=\"material-info truncate text-gray-600 dark:text-gray-300\">{{ route.project || 'No Project' }}</div>\n <div class=\"location-flow mt-2 text-sm flex items-center gap-2\">\n <span class=\"pickup flex items-center gap-1 truncate max-w-[40%] text-green-600 dark:text-green-400\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.pickup_location || '').split('|')[0] || 'Unknown' }}\n </span>\n <span class=\"arrow text-gray-400\">\u2192</span>\n <span class=\"delivery truncate max-w-[40%] text-brand-blue\">{{ (route.delivery_location || '').split('|')[0] || 'Unknown' }}</span>\n </div>\n <div class=\"material-info mt-2 truncate font-medium\">{{ route.material || '' }}</div>\n <div class=\"driver-row-4 mt-3 flex items-center gap-2\">\n <div class=\"progress-bar flex-1 h-1.5 bg-gray-200 dark:bg-slate-700 rounded-full overflow-hidden flex\">\n <div class=\"progress-segment completed h-full bg-green-500 transition-all duration-300\" [style.width.%]=\"calculateStatusPercentage('done', route)\"></div>\n <div class=\"progress-segment ongoing h-full transition-all duration-300\" [style.backgroundColor]=\"'#fc0'\" [style.width.%]=\"calculateStatusPercentage('ongoing', route)\"></div>\n <div class=\"progress-segment open h-full bg-gray-300 dark:bg-slate-600 transition-all duration-300\" [style.width.%]=\"calculateStatusPercentage('open', route)\"></div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <div class=\"text-gray-600 dark:text-gray-400 mt-2 text-center\">No Job code found.</div>\n </div>\n }\n </div>\n }\n</div>\n<lib-driver-list\n [(modalOpen)]=\"showDriverModal\"\n [driverListcollapse]=\"driverListcollapse()\"\n></lib-driver-list>\n<lib-job-details \n [modalOpen]=\"showDetailModal\" \n (modalOpenChange)=\"$event ? null : closeDetail(false)\" \n [routeData]=\"selectedJobDetail()\" \n [noBackdrop]=\"!isClickTriggered\"\n></lib-job-details>\n", styles: [":host{display:block}.cards-list-container{display:flex;flex-direction:column;height:100%;background:var(--bg-primary, white)}.cards-list-container.floating{position:absolute;top:12px;left:12px;width:280px;max-height:calc(100% - 24px);border-radius:12px;box-shadow:0 4px 24px #00000026;z-index:100;overflow:hidden}.cards-list-container.floating.collapsed{width:48px}.cards-list-container.sidebar{width:100%;border-right:1px solid var(--border-color, #e2e8f0)}.cards-list-container.inline{width:160px;min-width:160px;border-right:1px solid var(--border-color, #e2e8f0)}:host-context(.dark) .cards-list-container{background-color:#1e293b}:host-context(.dark) .cards-list-container.sidebar,:host-context(.dark) .cards-list-container.inline{border-color:#334155}.list-header{display:flex;align-items:center;justify-content:space-between;padding:12px;border-bottom:1px solid var(--border-color, #e2e8f0);background:var(--bg-secondary, #f8fafc)}:host-context(.dark) .list-header{background-color:#0f172a;border-color:#334155}.collapsed .list-header{padding:12px 8px;justify-content:center}.header-title{display:flex;align-items:center;gap:6px}.collapsed .header-title{display:none}.title-text{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b)}:host-context(.dark) .title-text{color:#f1f5f9}.routes-count{font-size:12px;color:var(--text-secondary, #64748b)}.collapse-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;color:var(--text-secondary, #64748b);cursor:pointer;border-radius:6px;transition:all .15s ease}.collapse-btn:hover{background:var(--hover-bg, #e2e8f0);color:var(--text-primary, #1e293b)}:host-context(.dark) .collapse-btn:hover{background-color:#334155;color:#f1f5f9}.cards-scroll-container{flex:1;overflow-y:auto;overflow-x:hidden}.cards-list{display:flex;flex-direction:column;gap:8px;padding:8px}.card-wrapper{border-radius:8px;transition:all .2s ease}.route-card{position:relative;padding:6px 10px;display:flex;flex-direction:column;gap:2px;border-radius:8px;cursor:pointer;transition:all .15s ease;min-height:72px}.route-card:hover{border-color:var(--accent-color, #3b82f6);box-shadow:0 2px 8px #00000014}.route-card.selected{border-color:var(--accent-color, #3b82f6);background:#3b82f60d}.task-header{display:flex;align-items:center;gap:6px;margin-bottom:4px}.job-code{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b)}:host-context(.dark) .job-code{color:#f1f5f9}.customer-name{font-size:12px;color:var(--text-secondary, #64748b);margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.material-info{font-size:11px;color:var(--text-tertiary, #94a3b8);margin-bottom:6px;font-weight:500}.location-flow{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:center;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px}.location-flow .arrow{color:var(--text-tertiary, #94a3b8)}.location-flow .delivery{color:#ef4444}.driver-row-4{display:flex;align-items:center;gap:4px;margin-top:2px}.progress-bar{display:flex;gap:2px}.progress-segment{height:6px;border-radius:2px;position:relative;cursor:pointer}.progress-segment.completed{background:#22c55e}.progress-segment.in_progress{background:#f59e0b}.progress-segment.pending{background:#cbd5e1}.progress-segment.incomplete{background:#ef4444}.progress-segment:after{content:attr(data-tooltip);position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%);background:#1e293b;color:#fff;padding:6px 10px;border-radius:6px;font-size:10px;white-space:pre-line;min-width:120px;max-width:180px;box-shadow:0 3px 10px #0003;z-index:1000;opacity:0;visibility:hidden;transition:opacity .15s ease;pointer-events:none}.progress-segment:hover:after{opacity:1;visibility:visible}.task-count{font-size:10px;font-weight:600;color:var(--text-secondary, #64748b);min-width:24px;text-align:right}.on-time-indicator{font-size:10px;color:#22c55e}.on-time-indicator.late{color:#ef4444}.statusunit{border-radius:30px;font-size:12px;text-transform:capitalize;font-weight:600;width:20px;height:20px;text-align:center;line-height:20px}.statusunit.Ton{background:#22c55e}.statusunit.Load{background:#3b82f6}.statusunit.Hourly{background:#f59e0b}.list-loader{position:absolute;inset:0;background:#fff6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:50;border-radius:0 0 12px 12px}:host-context(.dark) .list-loader{background:#0f172a66}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
334
+ args: [{ selector: 'lib-job-code', standalone: true, imports: [LucideAngularModule, DriverListComponent, JobDetailsComponent, NgClass], template: "<div\n class=\"cards-list-container\"\n [class.floating]=\"listMode === 'floating'\"\n [class.sidebar]=\"listMode === 'sidebar'\"\n [class.inline]=\"listMode === 'inline'\"\n [class.collapsed]=\"collapsed\"\n>\n <div class=\"list-header\">\n <div class=\"header-title\">\n <span class=\"title-text\">Routes</span>\n <span class=\"routes-count\">({{ routes.length || 0 }})</span>\n </div>\n <button\n class=\"collapse-btn\"\n (click)=\"toggleCollapse()\"\n [title]=\"collapsed ? 'Expand' : 'Collapse'\"\n >\n @if (collapsed) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n } @else {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n }\n </button>\n </div>\n @if (!collapsed) {\n <div class=\"cards-scroll-container\" #scrollContainer>\n @if (routes.length && isLoading) {\n <div class=\"list-loader\">\n <lucide-icon [img]=\"icons.LoaderCircle\" [size]=\"32\" class=\"animate-spin text-amber-500\"></lucide-icon>\n </div>\n }\n @if(routes.length){\n <div class=\"cards-list\">\n @for (route of routes; track $index) {\n <div class=\"card-wrapper\" (click)=\"toggleRouteSelection(route)\">\n <div\n class=\"route-card bg-white dark:bg-slate-800 border transition-all duration-200\"\n [class.border-brand-blue]=\"selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.border-gray-300]=\"!selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.dark:border-slate-700]=\"!selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n [class.selected]=\"selectedRouteIds.includes(route.job_id || route.route_id || route.route_details_id || '')\"\n >\n <div class=\"task-header justify-between\">\n <span class=\"job-code\">{{ route.order_number || 'N/A' }}</span>\n <div class=\"flex gap-2\">\n <div class=\"statusunit text-white\" [ngClass]=\"route.unit || ''\">{{ route.unit?.charAt(0) || 'U' }}</div>\n @if (config.repository !== 'customer') {\n <div\n class=\"statusunit bg-slate-900 dark:bg-white text-white dark:text-black flex items-center justify-center cursor-pointer hover:opacity-80\"\n (click)=\"showDriverModal = true; toggleCollapse(); $event.stopPropagation()\"\n >\n <lucide-icon [img]=\"icons.CarFront\" [size]=\"15\"></lucide-icon>\n </div>\n }\n <div\n class=\"text-black dark:text-white flex items-center justify-center cursor-pointer hover:opacity-80\"\n (click)=\"openDetail(route, true); $event.stopPropagation()\"\n (mouseenter)=\"openDetail(route, false)\"\n (mouseleave)=\"closeDetail(true)\"\n >\n <lucide-icon [img]=\"icons.Info\" [size]=\"20\"></lucide-icon>\n </div>\n </div>\n </div>\n <div class=\"customer-name font-semibold truncate\">{{ route.customer_name }}</div>\n <div class=\"material-info truncate text-gray-600 dark:text-gray-300\">{{ route.project || 'No Project' }}</div>\n <div class=\"location-flow mt-2 text-sm flex items-center gap-2\">\n <span class=\"pickup flex items-center gap-1 truncate max-w-[40%] text-green-600 dark:text-green-400\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.pickup_location || '').split('|')[0] || 'Unknown' }}\n </span>\n <span class=\"arrow text-gray-400\">\u2192</span>\n <span class=\"delivery truncate max-w-[40%] text-brand-blue\">{{ (route.delivery_location || '').split('|')[0] || 'Unknown' }}</span>\n </div>\n <div class=\"material-info mt-2 truncate font-medium\">{{ route.material || '' }}</div>\n <div class=\"driver-row-4 mt-3 flex items-center gap-2\">\n <div class=\"progress-bar flex-1 h-1.5 bg-gray-200 dark:bg-slate-700 rounded-full overflow-hidden flex\">\n <div class=\"progress-segment completed h-full bg-green-500 transition-all duration-300\" [style.width.%]=\"calculateStatusPercentage('done', route)\"></div>\n <div class=\"progress-segment ongoing h-full transition-all duration-300\" [style.backgroundColor]=\"'#fc0'\" [style.width.%]=\"calculateStatusPercentage('ongoing', route)\"></div>\n <div class=\"progress-segment open h-full bg-gray-300 dark:bg-slate-600 transition-all duration-300\" [style.width.%]=\"calculateStatusPercentage('open', route)\"></div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <div class=\"text-gray-600 dark:text-gray-400 mt-2 text-center\">No Job code found.</div>\n </div>\n }\n </div>\n }\n</div>\n<lib-driver-list\n [(modalOpen)]=\"showDriverModal\"\n [driverListcollapse]=\"driverListcollapse()\"\n></lib-driver-list>\n<lib-job-details \n [modalOpen]=\"showDetailModal\" \n (modalOpenChange)=\"$event ? null : closeDetail(false)\" \n [routeData]=\"selectedJobDetail()\" \n [noBackdrop]=\"!isClickTriggered\"\n></lib-job-details>\n", styles: [":host{display:block}.cards-list-container{display:flex;flex-direction:column;height:100%;background:var(--bg-primary, white)}.cards-list-container.floating{position:absolute;top:12px;left:12px;width:280px;max-height:calc(100% - 24px);border-radius:12px;box-shadow:0 4px 24px #00000026;z-index:100;overflow:hidden}.cards-list-container.floating.collapsed{width:48px}.cards-list-container.sidebar{width:100%;border-right:1px solid var(--border-color, #e2e8f0)}.cards-list-container.inline{width:160px;min-width:160px;border-right:1px solid var(--border-color, #e2e8f0)}:host-context(.dark) .cards-list-container{background-color:#1e293b}:host-context(.dark) .cards-list-container.sidebar,:host-context(.dark) .cards-list-container.inline{border-color:#334155}.list-header{display:flex;align-items:center;justify-content:space-between;padding:12px;border-bottom:1px solid var(--border-color, #e2e8f0);background:var(--bg-secondary, #f8fafc)}:host-context(.dark) .list-header{background-color:#0f172a;border-color:#334155}.collapsed .list-header{padding:12px 8px;justify-content:center}.header-title{display:flex;align-items:center;gap:6px}.collapsed .header-title{display:none}.title-text{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b)}:host-context(.dark) .title-text{color:#f1f5f9}.routes-count{font-size:12px;color:var(--text-secondary, #64748b)}.collapse-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;color:var(--text-secondary, #64748b);cursor:pointer;border-radius:6px;transition:all .15s ease}.collapse-btn:hover{background:var(--hover-bg, #e2e8f0);color:var(--text-primary, #1e293b)}:host-context(.dark) .collapse-btn:hover{background-color:#334155;color:#f1f5f9}.cards-scroll-container{flex:1;overflow-y:auto;overflow-x:hidden}.cards-list{display:flex;flex-direction:column;gap:8px;padding:8px}.card-wrapper{border-radius:8px;transition:all .2s ease}.route-card{position:relative;padding:6px 10px;display:flex;flex-direction:column;gap:2px;border-radius:8px;cursor:pointer;transition:all .15s ease;min-height:72px}.route-card:hover{border-color:var(--accent-color, #3b82f6);box-shadow:0 2px 8px #00000014}.route-card.selected{border-color:var(--accent-color, #3b82f6);background:#3b82f60d}.task-header{display:flex;align-items:center;gap:6px;margin-bottom:4px}.job-code{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b)}:host-context(.dark) .job-code{color:#f1f5f9}.customer-name{font-size:12px;color:var(--text-secondary, #64748b);margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.material-info{font-size:11px;color:var(--text-tertiary, #94a3b8);margin-bottom:6px;font-weight:500}.location-flow{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:center;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px}.location-flow .arrow{color:var(--text-tertiary, #94a3b8)}.location-flow .delivery{color:#ef4444}.driver-row-4{display:flex;align-items:center;gap:4px;margin-top:2px}.progress-bar{display:flex;gap:2px}.progress-segment{height:6px;border-radius:2px;position:relative;cursor:pointer}.progress-segment.completed{background:#22c55e}.progress-segment.in_progress{background:#f59e0b}.progress-segment.pending{background:#cbd5e1}.progress-segment.incomplete{background:#ef4444}.progress-segment:after{content:attr(data-tooltip);position:absolute;bottom:calc(100% + 8px);left:50%;transform:translate(-50%);background:#1e293b;color:#fff;padding:6px 10px;border-radius:6px;font-size:10px;white-space:pre-line;min-width:120px;max-width:180px;box-shadow:0 3px 10px #0003;z-index:1000;opacity:0;visibility:hidden;transition:opacity .15s ease;pointer-events:none}.progress-segment:hover:after{opacity:1;visibility:visible}.task-count{font-size:10px;font-weight:600;color:var(--text-secondary, #64748b);min-width:24px;text-align:right}.on-time-indicator{font-size:10px;color:#22c55e}.on-time-indicator.late{color:#ef4444}.statusunit{border-radius:30px;font-size:12px;text-transform:capitalize;font-weight:600;width:20px;height:20px;text-align:center;line-height:20px}.statusunit.Ton{background:#22c55e}.statusunit.Load{background:#3b82f6}.statusunit.Hourly{background:#f59e0b}.list-loader{position:absolute;inset:0;background:#fff6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:50;border-radius:0 0 12px 12px}:host-context(.dark) .list-loader{background:#0f172a66}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
335
335
  }], ctorParameters: () => [], propDecorators: { listMode: [{
336
336
  type: Input
337
337
  }], collapsible: [{
@@ -372,11 +372,11 @@ class RouteInfoCardComponent {
372
372
  X,
373
373
  };
374
374
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RouteInfoCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
375
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: RouteInfoCardComponent, isStandalone: true, selector: "lib-route-info-card", inputs: { modalOpen: { classPropertyName: "modalOpen", publicName: "modalOpen", isSignal: true, isRequired: false, transformFunction: null }, routeData: { classPropertyName: "routeData", publicName: "routeData", isSignal: true, isRequired: false, transformFunction: null }, repository: { classPropertyName: "repository", publicName: "repository", isSignal: true, isRequired: false, transformFunction: null }, displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: false, transformFunction: null }, noBackdrop: { classPropertyName: "noBackdrop", publicName: "noBackdrop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { modalOpenChange: "modalOpenChange", edit: "edit" }, ngImport: i0, template: "@if (modalOpen()) {\n<div \n class=\"z-[112] bottom-0 fixed lg:absolute inset-0 overflow-y-auto\"\n [ngClass]=\"displayMode() === 'catalog' ? 'lg:left-[350px]' : 'lg:right-[350px]'\"\n [class.pointer-events-none]=\"noBackdrop()\"\n>\n <div \n class=\"flex min-h-full lg:items-end items-center justify-center p-3\"\n [ngClass]=\"displayMode() === 'catalog' ? 'lg:justify-start' : 'lg:justify-end'\"\n >\n <div\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl animate-slide-up w-[350px] pointer-events-auto\"\n (click)=\"$event.stopPropagation()\"\n >\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b border-gray-200 dark:border-slate-700 dark:bg-slate-900 rounded-t-lg\"\n >\n <h3 class=\"flex items-center gap-1 font-medium text-gray-900 dark:text-white text-[13px]\">\n Route Info\n </h3>\n <button\n (click)=\"close()\"\n class=\"p-2 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"20\"></lucide-icon>\n </button>\n </div>\n <div class=\"max-h-[60vh] overflow-y-auto p-3\">\n <div class=\"space-y-2 bg-gray-50 dark:bg-slate-900/50 border border-gray-200 dark:border-slate-700 p-3 rounded-lg mb-4\">\n <p class=\"text-xs\">\n <b class=\"text-gray-900 dark:text-white\">Pickup:</b> \n <span class=\"text-gray-600 dark:text-gray-400\">\n {{ (routeData()?.pickup_location || '').split('|')[1] || routeData()?.pickup_location || 'N/A' }}\n </span>\n </p>\n <p class=\"text-xs\">\n <b class=\"text-gray-900 dark:text-white\">Delivery:</b> \n <span class=\"text-gray-600 dark:text-gray-400\">\n {{ (routeData()?.delivery_location || '').split('|')[1] || routeData()?.delivery_location || 'N/A' }}\n </span>\n </p>\n </div>\n\n <div class=\"space-y-2.5\">\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Name:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.route_name || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Customer:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.customer_name || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Type:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.unit || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Distance:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.estimated_distance || '0' }} Miles</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Travel Time:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.estimated_time || '0' }} Min</span>\n </div>\n\n @if (repository() !== 'customer') {\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Trucker Pay Estimate:</b>\n <span class=\"text-brand-blue font-medium text-right ml-4\">{{ routeData()?.trucker_pay_estimate | currency }}</span>\n </div>\n }\n\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Customer Price Estimate:</b>\n <span class=\"text-brand-blue font-medium text-right ml-4\">{{ routeData()?.customer_price_estimate | currency }}</span>\n </div>\n\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Notes:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4 italic\">{{ routeData()?.note || 'None' }}</span>\n </div>\n </div>\n\n <div class=\"mt-4 pt-3 border-t border-gray-100 dark:border-slate-700 flex justify-between items-center\">\n <p class=\"text-[10px] text-gray-400 italic\">\n Created by {{ routeData()?.created_by_name || routeData()?.user || 'System' }} on {{ formattedDate() }}\n </p>\n @if (displayMode() === 'catalog') {\n <button \n type=\"button\"\n (click)=\"edit.emit(); close()\"\n class=\"px-3 py-1 text-[11px] font-bold uppercase tracking-wider bg-orange-500 hover:bg-orange-600 text-white rounded transition-colors\"\n >\n Edit\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n}", styles: [".location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:flex-start;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px;margin-top:4px}.location-flow .delivery{display:flex;align-items:flex-start;gap:3px;color:#ef4444}.location-flow .delivery svg{width:8px;height:8px;margin-top:4px}@keyframes slide-up{0%{opacity:0;transform:translateY(10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.animate-fade-in{animation:fade-in .2s ease-out}.animate-slide-up{animation:slide-up .2s ease-out}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i2.CurrencyPipe, name: "currency" }] });
375
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: RouteInfoCardComponent, isStandalone: true, selector: "lib-route-info-card", inputs: { modalOpen: { classPropertyName: "modalOpen", publicName: "modalOpen", isSignal: true, isRequired: false, transformFunction: null }, routeData: { classPropertyName: "routeData", publicName: "routeData", isSignal: true, isRequired: false, transformFunction: null }, repository: { classPropertyName: "repository", publicName: "repository", isSignal: true, isRequired: false, transformFunction: null }, displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: false, transformFunction: null }, noBackdrop: { classPropertyName: "noBackdrop", publicName: "noBackdrop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { modalOpenChange: "modalOpenChange", edit: "edit" }, ngImport: i0, template: "@if (modalOpen()) {\n<div \n class=\"z-[112] bottom-0 fixed lg:absolute inset-0 overflow-y-auto\"\n [ngClass]=\"displayMode() === 'catalog' ? 'lg:left-[350px]' : 'lg:right-[350px]'\"\n [class.pointer-events-none]=\"noBackdrop()\"\n>\n <div \n class=\"flex min-h-full lg:items-end items-center justify-center p-3\"\n [ngClass]=\"displayMode() === 'catalog' ? 'lg:justify-start' : 'lg:justify-end'\"\n >\n <div\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl animate-slide-up w-[350px] pointer-events-auto\"\n (click)=\"$event.stopPropagation()\"\n >\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b border-gray-200 dark:border-slate-700 dark:bg-slate-900 rounded-t-lg\"\n >\n <h3 class=\"flex items-center gap-1 font-medium text-gray-900 dark:text-white text-[13px]\">\n Route Info\n </h3>\n <button\n (click)=\"close()\"\n class=\"p-2 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"20\"></lucide-icon>\n </button>\n </div>\n <div class=\"max-h-[60vh] overflow-y-auto p-3\">\n <div class=\"space-y-2 bg-gray-50 dark:bg-slate-900/50 border border-gray-200 dark:border-slate-700 p-3 rounded-lg mb-4\">\n <p class=\"text-xs\">\n <b class=\"text-gray-900 dark:text-white\">Pickup:</b> \n <span class=\"text-gray-600 dark:text-gray-400\">\n {{ (routeData()?.pickup_location || '').split('|')[1] || routeData()?.pickup_location || 'N/A' }}\n </span>\n </p>\n <p class=\"text-xs\">\n <b class=\"text-gray-900 dark:text-white\">Delivery:</b> \n <span class=\"text-gray-600 dark:text-gray-400\">\n {{ (routeData()?.delivery_location || '').split('|')[1] || routeData()?.delivery_location || 'N/A' }}\n </span>\n </p>\n </div>\n\n <div class=\"space-y-2.5\">\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Name:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.route_name || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Customer:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.customer_name || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Type:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.unit || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Distance:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.estimated_distance || '0' }} Miles</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Travel Time:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.estimated_time || '0' }} Min</span>\n </div>\n\n @if (repository() !== 'customer') {\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Trucker Pay Estimate:</b>\n <span class=\"text-brand-blue font-medium text-right ml-4\">{{ routeData()?.trucker_pay_estimate | currency }}</span>\n </div>\n }\n\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Customer Price Estimate:</b>\n <span class=\"text-brand-blue font-medium text-right ml-4\">{{ routeData()?.customer_price_estimate | currency }}</span>\n </div>\n\n <div class=\"flex justify-between items-start text-xs dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Notes:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4 italic\">{{ routeData()?.note || 'None' }}</span>\n </div>\n </div>\n\n <div class=\"mt-4 pt-3 border-t border-gray-100 dark:border-slate-700 flex justify-between items-center\">\n <p class=\"text-[10px] text-gray-400 italic\">\n Created by {{ routeData()?.created_by_name || routeData()?.user || 'System' }} on {{ formattedDate() }}\n </p>\n @if (displayMode() === 'catalog') {\n <button \n type=\"button\"\n (click)=\"edit.emit(); close()\"\n class=\"px-3 py-1 text-[11px] font-bold uppercase tracking-wider bg-orange-500 hover:bg-orange-600 text-white rounded transition-colors\"\n >\n Edit\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n}", styles: [".location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:flex-start;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px;margin-top:4px}.location-flow .delivery{display:flex;align-items:flex-start;gap:3px;color:#ef4444}.location-flow .delivery svg{width:8px;height:8px;margin-top:4px}@keyframes slide-up{0%{opacity:0;transform:translateY(10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.animate-fade-in{animation:fade-in .2s ease-out}.animate-slide-up{animation:slide-up .2s ease-out}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i2.CurrencyPipe, name: "currency" }] });
376
376
  }
377
377
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RouteInfoCardComponent, decorators: [{
378
378
  type: Component,
379
- args: [{ selector: 'lib-route-info-card', standalone: true, imports: [LucideAngularModule, CommonModule, CurrencyPipe], template: "@if (modalOpen()) {\n<div \n class=\"z-[112] bottom-0 fixed lg:absolute inset-0 overflow-y-auto\"\n [ngClass]=\"displayMode() === 'catalog' ? 'lg:left-[350px]' : 'lg:right-[350px]'\"\n [class.pointer-events-none]=\"noBackdrop()\"\n>\n <div \n class=\"flex min-h-full lg:items-end items-center justify-center p-3\"\n [ngClass]=\"displayMode() === 'catalog' ? 'lg:justify-start' : 'lg:justify-end'\"\n >\n <div\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl animate-slide-up w-[350px] pointer-events-auto\"\n (click)=\"$event.stopPropagation()\"\n >\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b border-gray-200 dark:border-slate-700 dark:bg-slate-900 rounded-t-lg\"\n >\n <h3 class=\"flex items-center gap-1 font-medium text-gray-900 dark:text-white text-[13px]\">\n Route Info\n </h3>\n <button\n (click)=\"close()\"\n class=\"p-2 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"20\"></lucide-icon>\n </button>\n </div>\n <div class=\"max-h-[60vh] overflow-y-auto p-3\">\n <div class=\"space-y-2 bg-gray-50 dark:bg-slate-900/50 border border-gray-200 dark:border-slate-700 p-3 rounded-lg mb-4\">\n <p class=\"text-xs\">\n <b class=\"text-gray-900 dark:text-white\">Pickup:</b> \n <span class=\"text-gray-600 dark:text-gray-400\">\n {{ (routeData()?.pickup_location || '').split('|')[1] || routeData()?.pickup_location || 'N/A' }}\n </span>\n </p>\n <p class=\"text-xs\">\n <b class=\"text-gray-900 dark:text-white\">Delivery:</b> \n <span class=\"text-gray-600 dark:text-gray-400\">\n {{ (routeData()?.delivery_location || '').split('|')[1] || routeData()?.delivery_location || 'N/A' }}\n </span>\n </p>\n </div>\n\n <div class=\"space-y-2.5\">\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Name:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.route_name || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Customer:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.customer_name || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Type:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.unit || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Distance:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.estimated_distance || '0' }} Miles</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Travel Time:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.estimated_time || '0' }} Min</span>\n </div>\n\n @if (repository() !== 'customer') {\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Trucker Pay Estimate:</b>\n <span class=\"text-brand-blue font-medium text-right ml-4\">{{ routeData()?.trucker_pay_estimate | currency }}</span>\n </div>\n }\n\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Customer Price Estimate:</b>\n <span class=\"text-brand-blue font-medium text-right ml-4\">{{ routeData()?.customer_price_estimate | currency }}</span>\n </div>\n\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Notes:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4 italic\">{{ routeData()?.note || 'None' }}</span>\n </div>\n </div>\n\n <div class=\"mt-4 pt-3 border-t border-gray-100 dark:border-slate-700 flex justify-between items-center\">\n <p class=\"text-[10px] text-gray-400 italic\">\n Created by {{ routeData()?.created_by_name || routeData()?.user || 'System' }} on {{ formattedDate() }}\n </p>\n @if (displayMode() === 'catalog') {\n <button \n type=\"button\"\n (click)=\"edit.emit(); close()\"\n class=\"px-3 py-1 text-[11px] font-bold uppercase tracking-wider bg-orange-500 hover:bg-orange-600 text-white rounded transition-colors\"\n >\n Edit\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n}", styles: [".location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:flex-start;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px;margin-top:4px}.location-flow .delivery{display:flex;align-items:flex-start;gap:3px;color:#ef4444}.location-flow .delivery svg{width:8px;height:8px;margin-top:4px}@keyframes slide-up{0%{opacity:0;transform:translateY(10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.animate-fade-in{animation:fade-in .2s ease-out}.animate-slide-up{animation:slide-up .2s ease-out}\n"] }]
379
+ args: [{ selector: 'lib-route-info-card', standalone: true, imports: [LucideAngularModule, CommonModule, CurrencyPipe], template: "@if (modalOpen()) {\n<div \n class=\"z-[112] bottom-0 fixed lg:absolute inset-0 overflow-y-auto\"\n [ngClass]=\"displayMode() === 'catalog' ? 'lg:left-[350px]' : 'lg:right-[350px]'\"\n [class.pointer-events-none]=\"noBackdrop()\"\n>\n <div \n class=\"flex min-h-full lg:items-end items-center justify-center p-3\"\n [ngClass]=\"displayMode() === 'catalog' ? 'lg:justify-start' : 'lg:justify-end'\"\n >\n <div\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl animate-slide-up w-[350px] pointer-events-auto\"\n (click)=\"$event.stopPropagation()\"\n >\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b border-gray-200 dark:border-slate-700 dark:bg-slate-900 rounded-t-lg\"\n >\n <h3 class=\"flex items-center gap-1 font-medium text-gray-900 dark:text-white text-[13px]\">\n Route Info\n </h3>\n <button\n (click)=\"close()\"\n class=\"p-2 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"20\"></lucide-icon>\n </button>\n </div>\n <div class=\"max-h-[60vh] overflow-y-auto p-3\">\n <div class=\"space-y-2 bg-gray-50 dark:bg-slate-900/50 border border-gray-200 dark:border-slate-700 p-3 rounded-lg mb-4\">\n <p class=\"text-xs\">\n <b class=\"text-gray-900 dark:text-white\">Pickup:</b> \n <span class=\"text-gray-600 dark:text-gray-400\">\n {{ (routeData()?.pickup_location || '').split('|')[1] || routeData()?.pickup_location || 'N/A' }}\n </span>\n </p>\n <p class=\"text-xs\">\n <b class=\"text-gray-900 dark:text-white\">Delivery:</b> \n <span class=\"text-gray-600 dark:text-gray-400\">\n {{ (routeData()?.delivery_location || '').split('|')[1] || routeData()?.delivery_location || 'N/A' }}\n </span>\n </p>\n </div>\n\n <div class=\"space-y-2.5\">\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Name:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.route_name || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Customer:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.customer_name || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Type:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.unit || 'N/A' }}</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Distance:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.estimated_distance || '0' }} Miles</span>\n </div>\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Travel Time:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4\">{{ routeData()?.estimated_time || '0' }} Min</span>\n </div>\n\n @if (repository() !== 'customer') {\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Trucker Pay Estimate:</b>\n <span class=\"text-brand-blue font-medium text-right ml-4\">{{ routeData()?.trucker_pay_estimate | currency }}</span>\n </div>\n }\n\n <div class=\"flex justify-between items-start text-xs border-b border-gray-100 dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Customer Price Estimate:</b>\n <span class=\"text-brand-blue font-medium text-right ml-4\">{{ routeData()?.customer_price_estimate | currency }}</span>\n </div>\n\n <div class=\"flex justify-between items-start text-xs dark:border-slate-700/50 pb-2\">\n <b class=\"text-gray-900 dark:text-white whitespace-nowrap\">Notes:</b>\n <span class=\"text-gray-600 dark:text-gray-400 text-right ml-4 italic\">{{ routeData()?.note || 'None' }}</span>\n </div>\n </div>\n\n <div class=\"mt-4 pt-3 border-t border-gray-100 dark:border-slate-700 flex justify-between items-center\">\n <p class=\"text-[10px] text-gray-400 italic\">\n Created by {{ routeData()?.created_by_name || routeData()?.user || 'System' }} on {{ formattedDate() }}\n </p>\n @if (displayMode() === 'catalog') {\n <button \n type=\"button\"\n (click)=\"edit.emit(); close()\"\n class=\"px-3 py-1 text-[11px] font-bold uppercase tracking-wider bg-orange-500 hover:bg-orange-600 text-white rounded transition-colors\"\n >\n Edit\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n}", styles: [".location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:4px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:flex;align-items:flex-start;gap:3px;color:#22c55e}.location-flow .pickup svg{width:8px;height:8px;margin-top:4px}.location-flow .delivery{display:flex;align-items:flex-start;gap:3px;color:#ef4444}.location-flow .delivery svg{width:8px;height:8px;margin-top:4px}@keyframes slide-up{0%{opacity:0;transform:translateY(10px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.animate-fade-in{animation:fade-in .2s ease-out}.animate-slide-up{animation:slide-up .2s ease-out}\n"] }]
380
380
  }], propDecorators: { modalOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "modalOpen", required: false }] }], routeData: [{ type: i0.Input, args: [{ isSignal: true, alias: "routeData", required: false }] }], repository: [{ type: i0.Input, args: [{ isSignal: true, alias: "repository", required: false }] }], displayMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayMode", required: false }] }], noBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "noBackdrop", required: false }] }], modalOpenChange: [{
381
381
  type: Output
382
382
  }], edit: [{
@@ -585,11 +585,11 @@ class JobRouteListComponent {
585
585
  LoaderCircle
586
586
  };
587
587
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: JobRouteListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
588
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: JobRouteListComponent, isStandalone: true, selector: "lib-job-route-list", inputs: { customerRepoDetails: { classPropertyName: "customerRepoDetails", publicName: "customerRepoDetails", isSignal: false, isRequired: false, transformFunction: null }, selectedRouteIds: { classPropertyName: "selectedRouteIds", publicName: "selectedRouteIds", isSignal: true, isRequired: false, transformFunction: null }, modalOpen: { classPropertyName: "modalOpen", publicName: "modalOpen", isSignal: true, isRequired: false, transformFunction: null }, initialRoutes: { classPropertyName: "initialRoutes", publicName: "initialRoutes", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { modalOpenChange: "modalOpenChange", routeSelect: "routeSelect", masterToggleEvent: "masterToggleEvent", shareRoute: "shareRoute" }, ngImport: i0, template: "@if (modalOpen()) {\n<div class=\"fixed z-[111] route-list\">\n <!-- <div class=\"fixed inset-0 bg-black/50\" (click)=\"close()\"></div> -->\n <aside class=\"detail-drawer top-[0] sm:top-[115px]\" (click)=\"$event.stopPropagation()\">\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b border-gray-200 dark:border-slate-700 dark:bg-slate-900\"\n >\n <h3 class=\"flex items-center gap-1 font-semibold text-gray-900 dark:text-white text-[14px]\">\n List of Routes\n <span class=\"text-xs font-normal text-gray-400\">({{ filteredRoutes().length }})</span>\n </h3>\n <button\n type=\"button\"\n (click)=\"onMasterToggle()\"\n [disabled]=\"isAnyPlotting()\"\n class=\"inline-flex items-center justify-center gap-2 px-3 sm:px-4 py-1.5 bg-brand-blue hover:bg-blue-700 disabled:opacity-50 text-white font-medium rounded-md transition-colors text-[12px]\"\n >\n {{ allSelected() ? 'Uncheck All' : 'Check All' }}\n </button>\n <button\n (click)=\"close()\"\n class=\"p-1.5 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"18\"></lucide-icon>\n </button>\n </div>\n <div class=\"p-2\">\n <div class=\"relative w-full\">\n <div class=\"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none\">\n <lucide-icon [img]=\"hasFilter ? icons.Info : icons.Search\" class=\"text-gray-400\" [size]=\"18\"></lucide-icon>\n </div>\n <input\n type=\"text\"\n #searchinput\n [value]=\"searchTerm()\"\n (input)=\"handleSearchInput(searchinput.value)\"\n (focus)=\"showSuggestions.set(true)\"\n (blur)=\"onSearchBlur()\"\n placeholder=\"Search...\"\n class=\"w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n\n <!-- Autocomplete Suggestions Dropdown -->\n @if (showSuggestions() && suggestions().length > 0) {\n <div class=\"absolute z-50 w-full mt-1 bg-white dark:bg-gray-800 rounded-lg shadow-xl border border-gray-200 dark:border-gray-700 max-h-60 overflow-y-auto\">\n <ul class=\"py-1 text-sm text-gray-700 dark:text-gray-200\">\n @for (option of suggestions(); track option.label + option.type) {\n <li (click)=\"addFilter(option)\"\n class=\"px-4 py-2 hover:bg-brand-blue/10 dark:hover:bg-brand-blue/20 cursor-pointer flex justify-between items-center group\">\n <span>\n <span class=\"capitalize\">{{option.type}}:</span> \n {{option.label}}\n </span>\n <lucide-icon [img]=\"icons.CheckCircle\" class=\"opacity-0 group-hover:opacity-100 text-brand-blue transition-opacity\" [size]=\"16\"></lucide-icon>\n </li>\n }\n </ul>\n </div>\n }\n </div>\n\n <!-- Active Filter Chips -->\n @if (hasFilter) {\n <div class=\"flex flex-wrap gap-2 mt-2 px-1\">\n @for (filter of filters(); track filter.name + filter.type) {\n <div class=\"inline-flex items-center gap-1.5 px-3 py-1 bg-brand-blue/10 border border-brand-blue/20 text-black dark:text-white rounded-full text-xs font-medium\">\n <span class=\"capitalize\">{{filter.type}}:</span>\n <span class=\"truncate max-w-[150px]\">{{filter.name}}</span>\n <button (click)=\"removeFilter()\" class=\"hover:text-red-500 transition-colors\">\n <lucide-icon [img]=\"icons.X\" [size]=\"14\"></lucide-icon>\n </button>\n </div>\n }\n </div>\n }\n </div>\n <div class=\"overflow-y-auto p-2 drawer-listing-box\">\n <cdk-virtual-scroll-viewport itemSize=\"60\" class=\"routeList-viewport h-[calc(100vh-230px)]\">\n @if (filteredRoutes().length > 0) {\n <ul class=\"route-list-ul gap-2 flex flex-col\">\n @for (route of filteredRoutes(); track getRouteId(route)) {\n <li \n class=\"route-li-v1 bg-white dark:bg-slate-800 border border-gray-300 dark:border-slate-700\" \n [class.selected]=\"isRouteSelected(route)\" \n [class.pointer-events-none]=\"isAnyPlotting()\"\n [class.opacity-60]=\"isAnyPlotting()\"\n (click)=\"toggleRoute(route)\">\n <div class=\"task-header justify-between\">\n <span class=\"job-code\"> {{route.route_name || route.order_number}} </span>\n @if (config.repository === 'coolmap') {\n <span class=\"job-code\">{{route.customer_name}}</span>\n }\n <div class=\"iconprt\">\n @if (isPlotting(route)) {\n <div class=\"plotting-spinner\">\n <lucide-icon [img]=\"icons.LoaderCircle\" class=\"animate-spin text-black dark:text-white flex items-center justify-center relative z-10\" [size]=\"18\"></lucide-icon>\n </div>\n }\n <div class=\"statusunit text-white\" [ngClass]=\"route.unit || ''\">\n {{ route.unit?.charAt(0) || 'U' }}\n </div>\n <div class=\"infoicon\" \n (click)=\"$event.stopPropagation(); openDetail(route, true)\"\n (mouseenter)=\"openDetail(route, false)\"\n (mouseleave)=\"closeDetail(true)\">\n <lucide-icon [img]=\"icons.Info\" [size]=\"18\" class=\"text-gray-400\"></lucide-icon>\n </div>\n @if (config.repository === 'customer') {\n <div class=\"infoicon hover:opacity-80\" (click)=\"$event.stopPropagation(); shareRoute.emit(route)\">\n <lucide-icon [img]=\"icons.Share2\" [size]=\"16\" class=\"text-gray-400\"></lucide-icon>\n </div>\n }\n </div>\n </div>\n \n <div class=\"location-flow bg-gray-100 dark:bg-slate-900 px-2 py-2 pb-3 rounded-lg\">\n <span class=\"pickup\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.pickup_location || '').split('|')[1] ? (route.pickup_location || '').split('|')[1] : (route.pickup_location || '') }}\n </span>\n <span class=\"delivery\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.delivery_location || '').split('|')[1] ? (route.delivery_location || '').split('|')[1] : (route.delivery_location || '') }}\n </span>\n </div>\n </li>\n }\n </ul>\n } @else if (routes().length === 0) {\n <div class=\"p-8 text-center text-gray-400\">\n No routes available for this perspective.\n </div>\n }\n </cdk-virtual-scroll-viewport>\n </div>\n </aside>\n</div>\n}\n<lib-route-info-card [modalOpen]=\"showRouteModal\" (modalOpenChange)=\"$event ? null : closeDetail(false)\" [routeData]=\"selectedRoute()\" [repository]=\"config.repository\" displayMode=\"dispatch\" [noBackdrop]=\"!isClickTriggered\"></lib-route-info-card>\n", styles: [".detail-drawer{position:fixed;right:0;bottom:36px;width:280px;background:var(--bg-primary, white);border-left:1px solid var(--border-color, #e2e8f0);display:flex;flex-direction:column;z-index:501;animation:slideIn .2s ease;height:100vh}:host-context(.dark) .detail-drawer{background-color:#1e293b;border-color:#334155}.drawer-listing-box{flex:1;overflow:hidden;padding:0!important}.routeList-viewport{width:100%}.route-list-ul{list-style:none;padding:10px;margin:0}.route-li-v1{position:relative;padding:6px 10px;display:flex;flex-direction:column;gap:2px;border-radius:8px;cursor:pointer;transition:all .15s ease;min-height:72px}.route-li-v1:hover{background:#ffffff0d}.route-li-v1.selected{border:1px solid #3b82f6}.task-header{display:flex;align-items:center;gap:6px;margin-bottom:4px}.job-code{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b);white-space:nowrap;text-overflow:ellipsis;max-width:190px;overflow:hidden}:host-context(.dark) .job-code{color:#f1f5f9}.iconprt{display:flex;flex-shrink:0;gap:5px}.plotting-spinner{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#1e293bb3;border-radius:4px;z-index:10}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.statusunit{border-radius:30px;font-size:11px;text-transform:capitalize;font-weight:600;width:18px;height:18px;text-align:center;line-height:18px}.statusunit.Ton{background:#ef4444}.statusunit.Load{background:#3b82f6}.statusunit.Hourly{background:#f59e0b}.pickprtbox{flex:1;min-width:0}.pickprtbox h2{font-size:14px;font-weight:600;color:#fff;margin:0;line-height:1.2}.pickprtbox h3{font-size:12px;color:#94a3b8;margin:2px 0 6px;font-weight:400}.pickdropprt{display:flex;flex-direction:column;gap:4px}.pickdropprt .pickprt,.pickdropprt .dropprt{color:#cbd5e1;font-size:11px}.pickdropprt .pickprt h4,.pickdropprt .dropprt h4{margin:0;font-weight:500;color:#94a3b8}.pickdropprt .pickprt.pickprt h4,.pickdropprt .dropprt.pickprt h4{color:#22c55e}.pickdropprt .pickprt.dropprt h4,.pickdropprt .dropprt.dropprt h4{color:#3b82f6}.infoicon{cursor:pointer}.infoicon:hover lucide-icon{color:#fff}@keyframes slideIn{0%{transform:translate(100%)}to{transform:translate(0)}}.animate-slide-in{animation:slideIn .2s ease}.location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:2px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:inline;align-items:center;gap:3px;color:#22c55e;white-space:nowrap;text-overflow:ellipsis;max-width:200px;overflow:hidden;position:relative;padding-left:15px}.location-flow .pickup svg{width:8px;height:8px;position:absolute;left:0;top:5px}.location-flow .delivery{display:inline;align-items:center;gap:3px;color:#ef4444;white-space:nowrap;text-overflow:ellipsis;max-width:200px;overflow:hidden;position:relative;padding-left:15px;top:5px}.location-flow .delivery svg{width:8px;height:8px;position:absolute;left:0;top:5px}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: RouteInfoCardComponent, selector: "lib-route-info-card", inputs: ["modalOpen", "routeData", "repository", "displayMode", "noBackdrop"], outputs: ["modalOpenChange", "edit"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i2$1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "component", type: i2$1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }] });
588
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: JobRouteListComponent, isStandalone: true, selector: "lib-job-route-list", inputs: { customerRepoDetails: { classPropertyName: "customerRepoDetails", publicName: "customerRepoDetails", isSignal: false, isRequired: false, transformFunction: null }, selectedRouteIds: { classPropertyName: "selectedRouteIds", publicName: "selectedRouteIds", isSignal: true, isRequired: false, transformFunction: null }, modalOpen: { classPropertyName: "modalOpen", publicName: "modalOpen", isSignal: true, isRequired: false, transformFunction: null }, initialRoutes: { classPropertyName: "initialRoutes", publicName: "initialRoutes", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { modalOpenChange: "modalOpenChange", routeSelect: "routeSelect", masterToggleEvent: "masterToggleEvent", shareRoute: "shareRoute" }, ngImport: i0, template: "@if (modalOpen()) {\n<div class=\"fixed z-[11] route-list\">\n <!-- <div class=\"fixed inset-0 bg-black/50\" (click)=\"close()\"></div> -->\n <aside class=\"detail-drawer top-[0] sm:top-[115px]\" (click)=\"$event.stopPropagation()\">\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b border-gray-200 dark:border-slate-700 dark:bg-slate-900\"\n >\n <h3 class=\"flex items-center gap-1 font-semibold text-gray-900 dark:text-white text-[14px]\">\n List of Routes\n <span class=\"text-xs font-normal text-gray-400\">({{ filteredRoutes().length }})</span>\n </h3>\n <button\n type=\"button\"\n (click)=\"onMasterToggle()\"\n [disabled]=\"isAnyPlotting()\"\n class=\"inline-flex items-center justify-center gap-2 px-3 sm:px-4 py-1.5 bg-brand-blue hover:bg-blue-700 disabled:opacity-50 text-white font-medium rounded-md transition-colors text-[12px]\"\n >\n {{ allSelected() ? 'Uncheck All' : 'Check All' }}\n </button>\n <button\n (click)=\"close()\"\n class=\"p-1.5 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"18\"></lucide-icon>\n </button>\n </div>\n <div class=\"p-2\">\n <div class=\"relative w-full\">\n <div class=\"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none\">\n <lucide-icon [img]=\"hasFilter ? icons.Info : icons.Search\" class=\"text-gray-400\" [size]=\"18\"></lucide-icon>\n </div>\n <input\n type=\"text\"\n #searchinput\n [value]=\"searchTerm()\"\n (input)=\"handleSearchInput(searchinput.value)\"\n (focus)=\"showSuggestions.set(true)\"\n (blur)=\"onSearchBlur()\"\n placeholder=\"Search...\"\n class=\"w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n\n <!-- Autocomplete Suggestions Dropdown -->\n @if (showSuggestions() && suggestions().length > 0) {\n <div class=\"absolute z-50 w-full mt-1 bg-white dark:bg-gray-800 rounded-lg shadow-xl border border-gray-200 dark:border-gray-700 max-h-60 overflow-y-auto\">\n <ul class=\"py-1 text-sm text-gray-700 dark:text-gray-200\">\n @for (option of suggestions(); track option.label + option.type) {\n <li (click)=\"addFilter(option)\"\n class=\"px-4 py-2 hover:bg-brand-blue/10 dark:hover:bg-brand-blue/20 cursor-pointer flex justify-between items-center group\">\n <span>\n <span class=\"capitalize\">{{option.type}}:</span> \n {{option.label}}\n </span>\n <lucide-icon [img]=\"icons.CheckCircle\" class=\"opacity-0 group-hover:opacity-100 text-brand-blue transition-opacity\" [size]=\"16\"></lucide-icon>\n </li>\n }\n </ul>\n </div>\n }\n </div>\n\n <!-- Active Filter Chips -->\n @if (hasFilter) {\n <div class=\"flex flex-wrap gap-2 mt-2 px-1\">\n @for (filter of filters(); track filter.name + filter.type) {\n <div class=\"inline-flex items-center gap-1.5 px-3 py-1 bg-brand-blue/10 border border-brand-blue/20 text-black dark:text-white rounded-full text-xs font-medium\">\n <span class=\"capitalize\">{{filter.type}}:</span>\n <span class=\"truncate max-w-[150px]\">{{filter.name}}</span>\n <button (click)=\"removeFilter()\" class=\"hover:text-red-500 transition-colors\">\n <lucide-icon [img]=\"icons.X\" [size]=\"14\"></lucide-icon>\n </button>\n </div>\n }\n </div>\n }\n </div>\n <div class=\"overflow-y-auto p-2 drawer-listing-box\">\n <cdk-virtual-scroll-viewport itemSize=\"60\" class=\"routeList-viewport h-[calc(100vh-230px)]\">\n @if (filteredRoutes().length > 0) {\n <ul class=\"route-list-ul gap-2 flex flex-col\">\n @for (route of filteredRoutes(); track getRouteId(route)) {\n <li \n class=\"route-li-v1 bg-white dark:bg-slate-800 border border-gray-300 dark:border-slate-700\" \n [class.selected]=\"isRouteSelected(route)\" \n [class.pointer-events-none]=\"isAnyPlotting()\"\n [class.opacity-60]=\"isAnyPlotting()\"\n (click)=\"toggleRoute(route)\">\n <div class=\"task-header justify-between\">\n <span class=\"job-code\"> {{route.route_name || route.order_number}} </span>\n @if (config.repository === 'coolmap') {\n <span class=\"job-code\">{{route.customer_name}}</span>\n }\n <div class=\"iconprt\">\n @if (isPlotting(route)) {\n <div class=\"plotting-spinner\">\n <lucide-icon [img]=\"icons.LoaderCircle\" class=\"animate-spin text-black dark:text-white flex items-center justify-center relative z-10\" [size]=\"18\"></lucide-icon>\n </div>\n }\n <div class=\"statusunit text-white\" [ngClass]=\"route.unit || ''\">\n {{ route.unit?.charAt(0) || 'U' }}\n </div>\n <div class=\"infoicon\" \n (click)=\"$event.stopPropagation(); openDetail(route, true)\"\n (mouseenter)=\"openDetail(route, false)\"\n (mouseleave)=\"closeDetail(true)\">\n <lucide-icon [img]=\"icons.Info\" [size]=\"18\" class=\"text-gray-400\"></lucide-icon>\n </div>\n @if (config.repository === 'customer') {\n <div class=\"infoicon hover:opacity-80\" (click)=\"$event.stopPropagation(); shareRoute.emit(route)\">\n <lucide-icon [img]=\"icons.Share2\" [size]=\"16\" class=\"text-gray-400\"></lucide-icon>\n </div>\n }\n </div>\n </div>\n \n <div class=\"location-flow bg-gray-100 dark:bg-slate-900 px-2 py-2 pb-3 rounded-lg\">\n <span class=\"pickup\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.pickup_location || '').split('|')[1] ? (route.pickup_location || '').split('|')[1] : (route.pickup_location || '') }}\n </span>\n <span class=\"delivery\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.delivery_location || '').split('|')[1] ? (route.delivery_location || '').split('|')[1] : (route.delivery_location || '') }}\n </span>\n </div>\n </li>\n }\n </ul>\n } @else if (routes().length === 0) {\n <div class=\"p-8 text-center text-gray-400\">\n No routes available for this perspective.\n </div>\n }\n </cdk-virtual-scroll-viewport>\n </div>\n </aside>\n</div>\n}\n<lib-route-info-card [modalOpen]=\"showRouteModal\" (modalOpenChange)=\"$event ? null : closeDetail(false)\" [routeData]=\"selectedRoute()\" [repository]=\"config.repository\" displayMode=\"dispatch\" [noBackdrop]=\"!isClickTriggered\"></lib-route-info-card>\n", styles: [".detail-drawer{position:fixed;right:0;bottom:36px;width:280px;background:var(--bg-primary, white);border-left:1px solid var(--border-color, #e2e8f0);display:flex;flex-direction:column;z-index:501;animation:slideIn .2s ease;height:100vh}:host-context(.dark) .detail-drawer{background-color:#1e293b;border-color:#334155}.drawer-listing-box{flex:1;overflow:hidden;padding:0!important}.routeList-viewport{width:100%}.route-list-ul{list-style:none;padding:10px;margin:0}.route-li-v1{position:relative;padding:6px 10px;display:flex;flex-direction:column;gap:2px;border-radius:8px;cursor:pointer;transition:all .15s ease;min-height:72px}.route-li-v1:hover{background:#ffffff0d}.route-li-v1.selected{border:1px solid #3b82f6}.task-header{display:flex;align-items:center;gap:6px;margin-bottom:4px}.job-code{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b);white-space:nowrap;text-overflow:ellipsis;max-width:190px;overflow:hidden}:host-context(.dark) .job-code{color:#f1f5f9}.iconprt{display:flex;flex-shrink:0;gap:5px}.plotting-spinner{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#1e293bb3;border-radius:4px;z-index:10}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.statusunit{border-radius:30px;font-size:11px;text-transform:capitalize;font-weight:600;width:18px;height:18px;text-align:center;line-height:18px}.statusunit.Ton{background:#ff7272}.statusunit.Load{background:#a3c52e}.statusunit.Hourly{background:#ae23d1}.pickprtbox{flex:1;min-width:0}.pickprtbox h2{font-size:14px;font-weight:600;color:#fff;margin:0;line-height:1.2}.pickprtbox h3{font-size:12px;color:#94a3b8;margin:2px 0 6px;font-weight:400}.pickdropprt{display:flex;flex-direction:column;gap:4px}.pickdropprt .pickprt,.pickdropprt .dropprt{color:#cbd5e1;font-size:11px}.pickdropprt .pickprt h4,.pickdropprt .dropprt h4{margin:0;font-weight:500;color:#94a3b8}.pickdropprt .pickprt.pickprt h4,.pickdropprt .dropprt.pickprt h4{color:#22c55e}.pickdropprt .pickprt.dropprt h4,.pickdropprt .dropprt.dropprt h4{color:#3b82f6}.infoicon{cursor:pointer}.infoicon:hover lucide-icon{color:#fff}@keyframes slideIn{0%{transform:translate(100%)}to{transform:translate(0)}}.animate-slide-in{animation:slideIn .2s ease}.location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:2px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:inline;align-items:center;gap:3px;color:#22c55e;white-space:nowrap;text-overflow:ellipsis;max-width:200px;overflow:hidden;position:relative;padding-left:15px}.location-flow .pickup svg{width:8px;height:8px;position:absolute;left:0;top:5px}.location-flow .delivery{display:inline;align-items:center;gap:3px;color:#ef4444;white-space:nowrap;text-overflow:ellipsis;max-width:200px;overflow:hidden;position:relative;padding-left:15px;top:5px}.location-flow .delivery svg{width:8px;height:8px;position:absolute;left:0;top:5px}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: RouteInfoCardComponent, selector: "lib-route-info-card", inputs: ["modalOpen", "routeData", "repository", "displayMode", "noBackdrop"], outputs: ["modalOpenChange", "edit"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i2$1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "component", type: i2$1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }] });
589
589
  }
590
590
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: JobRouteListComponent, decorators: [{
591
591
  type: Component,
592
- args: [{ selector: 'lib-job-route-list', standalone: true, imports: [LucideAngularModule, RouteInfoCardComponent, NgClass, ScrollingModule], template: "@if (modalOpen()) {\n<div class=\"fixed z-[111] route-list\">\n <!-- <div class=\"fixed inset-0 bg-black/50\" (click)=\"close()\"></div> -->\n <aside class=\"detail-drawer top-[0] sm:top-[115px]\" (click)=\"$event.stopPropagation()\">\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b border-gray-200 dark:border-slate-700 dark:bg-slate-900\"\n >\n <h3 class=\"flex items-center gap-1 font-semibold text-gray-900 dark:text-white text-[14px]\">\n List of Routes\n <span class=\"text-xs font-normal text-gray-400\">({{ filteredRoutes().length }})</span>\n </h3>\n <button\n type=\"button\"\n (click)=\"onMasterToggle()\"\n [disabled]=\"isAnyPlotting()\"\n class=\"inline-flex items-center justify-center gap-2 px-3 sm:px-4 py-1.5 bg-brand-blue hover:bg-blue-700 disabled:opacity-50 text-white font-medium rounded-md transition-colors text-[12px]\"\n >\n {{ allSelected() ? 'Uncheck All' : 'Check All' }}\n </button>\n <button\n (click)=\"close()\"\n class=\"p-1.5 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"18\"></lucide-icon>\n </button>\n </div>\n <div class=\"p-2\">\n <div class=\"relative w-full\">\n <div class=\"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none\">\n <lucide-icon [img]=\"hasFilter ? icons.Info : icons.Search\" class=\"text-gray-400\" [size]=\"18\"></lucide-icon>\n </div>\n <input\n type=\"text\"\n #searchinput\n [value]=\"searchTerm()\"\n (input)=\"handleSearchInput(searchinput.value)\"\n (focus)=\"showSuggestions.set(true)\"\n (blur)=\"onSearchBlur()\"\n placeholder=\"Search...\"\n class=\"w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n\n <!-- Autocomplete Suggestions Dropdown -->\n @if (showSuggestions() && suggestions().length > 0) {\n <div class=\"absolute z-50 w-full mt-1 bg-white dark:bg-gray-800 rounded-lg shadow-xl border border-gray-200 dark:border-gray-700 max-h-60 overflow-y-auto\">\n <ul class=\"py-1 text-sm text-gray-700 dark:text-gray-200\">\n @for (option of suggestions(); track option.label + option.type) {\n <li (click)=\"addFilter(option)\"\n class=\"px-4 py-2 hover:bg-brand-blue/10 dark:hover:bg-brand-blue/20 cursor-pointer flex justify-between items-center group\">\n <span>\n <span class=\"capitalize\">{{option.type}}:</span> \n {{option.label}}\n </span>\n <lucide-icon [img]=\"icons.CheckCircle\" class=\"opacity-0 group-hover:opacity-100 text-brand-blue transition-opacity\" [size]=\"16\"></lucide-icon>\n </li>\n }\n </ul>\n </div>\n }\n </div>\n\n <!-- Active Filter Chips -->\n @if (hasFilter) {\n <div class=\"flex flex-wrap gap-2 mt-2 px-1\">\n @for (filter of filters(); track filter.name + filter.type) {\n <div class=\"inline-flex items-center gap-1.5 px-3 py-1 bg-brand-blue/10 border border-brand-blue/20 text-black dark:text-white rounded-full text-xs font-medium\">\n <span class=\"capitalize\">{{filter.type}}:</span>\n <span class=\"truncate max-w-[150px]\">{{filter.name}}</span>\n <button (click)=\"removeFilter()\" class=\"hover:text-red-500 transition-colors\">\n <lucide-icon [img]=\"icons.X\" [size]=\"14\"></lucide-icon>\n </button>\n </div>\n }\n </div>\n }\n </div>\n <div class=\"overflow-y-auto p-2 drawer-listing-box\">\n <cdk-virtual-scroll-viewport itemSize=\"60\" class=\"routeList-viewport h-[calc(100vh-230px)]\">\n @if (filteredRoutes().length > 0) {\n <ul class=\"route-list-ul gap-2 flex flex-col\">\n @for (route of filteredRoutes(); track getRouteId(route)) {\n <li \n class=\"route-li-v1 bg-white dark:bg-slate-800 border border-gray-300 dark:border-slate-700\" \n [class.selected]=\"isRouteSelected(route)\" \n [class.pointer-events-none]=\"isAnyPlotting()\"\n [class.opacity-60]=\"isAnyPlotting()\"\n (click)=\"toggleRoute(route)\">\n <div class=\"task-header justify-between\">\n <span class=\"job-code\"> {{route.route_name || route.order_number}} </span>\n @if (config.repository === 'coolmap') {\n <span class=\"job-code\">{{route.customer_name}}</span>\n }\n <div class=\"iconprt\">\n @if (isPlotting(route)) {\n <div class=\"plotting-spinner\">\n <lucide-icon [img]=\"icons.LoaderCircle\" class=\"animate-spin text-black dark:text-white flex items-center justify-center relative z-10\" [size]=\"18\"></lucide-icon>\n </div>\n }\n <div class=\"statusunit text-white\" [ngClass]=\"route.unit || ''\">\n {{ route.unit?.charAt(0) || 'U' }}\n </div>\n <div class=\"infoicon\" \n (click)=\"$event.stopPropagation(); openDetail(route, true)\"\n (mouseenter)=\"openDetail(route, false)\"\n (mouseleave)=\"closeDetail(true)\">\n <lucide-icon [img]=\"icons.Info\" [size]=\"18\" class=\"text-gray-400\"></lucide-icon>\n </div>\n @if (config.repository === 'customer') {\n <div class=\"infoicon hover:opacity-80\" (click)=\"$event.stopPropagation(); shareRoute.emit(route)\">\n <lucide-icon [img]=\"icons.Share2\" [size]=\"16\" class=\"text-gray-400\"></lucide-icon>\n </div>\n }\n </div>\n </div>\n \n <div class=\"location-flow bg-gray-100 dark:bg-slate-900 px-2 py-2 pb-3 rounded-lg\">\n <span class=\"pickup\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.pickup_location || '').split('|')[1] ? (route.pickup_location || '').split('|')[1] : (route.pickup_location || '') }}\n </span>\n <span class=\"delivery\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.delivery_location || '').split('|')[1] ? (route.delivery_location || '').split('|')[1] : (route.delivery_location || '') }}\n </span>\n </div>\n </li>\n }\n </ul>\n } @else if (routes().length === 0) {\n <div class=\"p-8 text-center text-gray-400\">\n No routes available for this perspective.\n </div>\n }\n </cdk-virtual-scroll-viewport>\n </div>\n </aside>\n</div>\n}\n<lib-route-info-card [modalOpen]=\"showRouteModal\" (modalOpenChange)=\"$event ? null : closeDetail(false)\" [routeData]=\"selectedRoute()\" [repository]=\"config.repository\" displayMode=\"dispatch\" [noBackdrop]=\"!isClickTriggered\"></lib-route-info-card>\n", styles: [".detail-drawer{position:fixed;right:0;bottom:36px;width:280px;background:var(--bg-primary, white);border-left:1px solid var(--border-color, #e2e8f0);display:flex;flex-direction:column;z-index:501;animation:slideIn .2s ease;height:100vh}:host-context(.dark) .detail-drawer{background-color:#1e293b;border-color:#334155}.drawer-listing-box{flex:1;overflow:hidden;padding:0!important}.routeList-viewport{width:100%}.route-list-ul{list-style:none;padding:10px;margin:0}.route-li-v1{position:relative;padding:6px 10px;display:flex;flex-direction:column;gap:2px;border-radius:8px;cursor:pointer;transition:all .15s ease;min-height:72px}.route-li-v1:hover{background:#ffffff0d}.route-li-v1.selected{border:1px solid #3b82f6}.task-header{display:flex;align-items:center;gap:6px;margin-bottom:4px}.job-code{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b);white-space:nowrap;text-overflow:ellipsis;max-width:190px;overflow:hidden}:host-context(.dark) .job-code{color:#f1f5f9}.iconprt{display:flex;flex-shrink:0;gap:5px}.plotting-spinner{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#1e293bb3;border-radius:4px;z-index:10}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.statusunit{border-radius:30px;font-size:11px;text-transform:capitalize;font-weight:600;width:18px;height:18px;text-align:center;line-height:18px}.statusunit.Ton{background:#ef4444}.statusunit.Load{background:#3b82f6}.statusunit.Hourly{background:#f59e0b}.pickprtbox{flex:1;min-width:0}.pickprtbox h2{font-size:14px;font-weight:600;color:#fff;margin:0;line-height:1.2}.pickprtbox h3{font-size:12px;color:#94a3b8;margin:2px 0 6px;font-weight:400}.pickdropprt{display:flex;flex-direction:column;gap:4px}.pickdropprt .pickprt,.pickdropprt .dropprt{color:#cbd5e1;font-size:11px}.pickdropprt .pickprt h4,.pickdropprt .dropprt h4{margin:0;font-weight:500;color:#94a3b8}.pickdropprt .pickprt.pickprt h4,.pickdropprt .dropprt.pickprt h4{color:#22c55e}.pickdropprt .pickprt.dropprt h4,.pickdropprt .dropprt.dropprt h4{color:#3b82f6}.infoicon{cursor:pointer}.infoicon:hover lucide-icon{color:#fff}@keyframes slideIn{0%{transform:translate(100%)}to{transform:translate(0)}}.animate-slide-in{animation:slideIn .2s ease}.location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:2px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:inline;align-items:center;gap:3px;color:#22c55e;white-space:nowrap;text-overflow:ellipsis;max-width:200px;overflow:hidden;position:relative;padding-left:15px}.location-flow .pickup svg{width:8px;height:8px;position:absolute;left:0;top:5px}.location-flow .delivery{display:inline;align-items:center;gap:3px;color:#ef4444;white-space:nowrap;text-overflow:ellipsis;max-width:200px;overflow:hidden;position:relative;padding-left:15px;top:5px}.location-flow .delivery svg{width:8px;height:8px;position:absolute;left:0;top:5px}\n"] }]
592
+ args: [{ selector: 'lib-job-route-list', standalone: true, imports: [LucideAngularModule, RouteInfoCardComponent, NgClass, ScrollingModule], template: "@if (modalOpen()) {\n<div class=\"fixed z-[11] route-list\">\n <!-- <div class=\"fixed inset-0 bg-black/50\" (click)=\"close()\"></div> -->\n <aside class=\"detail-drawer top-[0] sm:top-[115px]\" (click)=\"$event.stopPropagation()\">\n <div\n class=\"flex items-center justify-between px-[12px] py-[10px] border-b border-gray-200 dark:border-slate-700 dark:bg-slate-900\"\n >\n <h3 class=\"flex items-center gap-1 font-semibold text-gray-900 dark:text-white text-[14px]\">\n List of Routes\n <span class=\"text-xs font-normal text-gray-400\">({{ filteredRoutes().length }})</span>\n </h3>\n <button\n type=\"button\"\n (click)=\"onMasterToggle()\"\n [disabled]=\"isAnyPlotting()\"\n class=\"inline-flex items-center justify-center gap-2 px-3 sm:px-4 py-1.5 bg-brand-blue hover:bg-blue-700 disabled:opacity-50 text-white font-medium rounded-md transition-colors text-[12px]\"\n >\n {{ allSelected() ? 'Uncheck All' : 'Check All' }}\n </button>\n <button\n (click)=\"close()\"\n class=\"p-1.5 hover:bg-gray-100 dark:hover:bg-slate-700 rounded-lg transition-colors\"\n >\n <lucide-icon [img]=\"icons.X\" [size]=\"18\"></lucide-icon>\n </button>\n </div>\n <div class=\"p-2\">\n <div class=\"relative w-full\">\n <div class=\"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none\">\n <lucide-icon [img]=\"hasFilter ? icons.Info : icons.Search\" class=\"text-gray-400\" [size]=\"18\"></lucide-icon>\n </div>\n <input\n type=\"text\"\n #searchinput\n [value]=\"searchTerm()\"\n (input)=\"handleSearchInput(searchinput.value)\"\n (focus)=\"showSuggestions.set(true)\"\n (blur)=\"onSearchBlur()\"\n placeholder=\"Search...\"\n class=\"w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n\n <!-- Autocomplete Suggestions Dropdown -->\n @if (showSuggestions() && suggestions().length > 0) {\n <div class=\"absolute z-50 w-full mt-1 bg-white dark:bg-gray-800 rounded-lg shadow-xl border border-gray-200 dark:border-gray-700 max-h-60 overflow-y-auto\">\n <ul class=\"py-1 text-sm text-gray-700 dark:text-gray-200\">\n @for (option of suggestions(); track option.label + option.type) {\n <li (click)=\"addFilter(option)\"\n class=\"px-4 py-2 hover:bg-brand-blue/10 dark:hover:bg-brand-blue/20 cursor-pointer flex justify-between items-center group\">\n <span>\n <span class=\"capitalize\">{{option.type}}:</span> \n {{option.label}}\n </span>\n <lucide-icon [img]=\"icons.CheckCircle\" class=\"opacity-0 group-hover:opacity-100 text-brand-blue transition-opacity\" [size]=\"16\"></lucide-icon>\n </li>\n }\n </ul>\n </div>\n }\n </div>\n\n <!-- Active Filter Chips -->\n @if (hasFilter) {\n <div class=\"flex flex-wrap gap-2 mt-2 px-1\">\n @for (filter of filters(); track filter.name + filter.type) {\n <div class=\"inline-flex items-center gap-1.5 px-3 py-1 bg-brand-blue/10 border border-brand-blue/20 text-black dark:text-white rounded-full text-xs font-medium\">\n <span class=\"capitalize\">{{filter.type}}:</span>\n <span class=\"truncate max-w-[150px]\">{{filter.name}}</span>\n <button (click)=\"removeFilter()\" class=\"hover:text-red-500 transition-colors\">\n <lucide-icon [img]=\"icons.X\" [size]=\"14\"></lucide-icon>\n </button>\n </div>\n }\n </div>\n }\n </div>\n <div class=\"overflow-y-auto p-2 drawer-listing-box\">\n <cdk-virtual-scroll-viewport itemSize=\"60\" class=\"routeList-viewport h-[calc(100vh-230px)]\">\n @if (filteredRoutes().length > 0) {\n <ul class=\"route-list-ul gap-2 flex flex-col\">\n @for (route of filteredRoutes(); track getRouteId(route)) {\n <li \n class=\"route-li-v1 bg-white dark:bg-slate-800 border border-gray-300 dark:border-slate-700\" \n [class.selected]=\"isRouteSelected(route)\" \n [class.pointer-events-none]=\"isAnyPlotting()\"\n [class.opacity-60]=\"isAnyPlotting()\"\n (click)=\"toggleRoute(route)\">\n <div class=\"task-header justify-between\">\n <span class=\"job-code\"> {{route.route_name || route.order_number}} </span>\n @if (config.repository === 'coolmap') {\n <span class=\"job-code\">{{route.customer_name}}</span>\n }\n <div class=\"iconprt\">\n @if (isPlotting(route)) {\n <div class=\"plotting-spinner\">\n <lucide-icon [img]=\"icons.LoaderCircle\" class=\"animate-spin text-black dark:text-white flex items-center justify-center relative z-10\" [size]=\"18\"></lucide-icon>\n </div>\n }\n <div class=\"statusunit text-white\" [ngClass]=\"route.unit || ''\">\n {{ route.unit?.charAt(0) || 'U' }}\n </div>\n <div class=\"infoicon\" \n (click)=\"$event.stopPropagation(); openDetail(route, true)\"\n (mouseenter)=\"openDetail(route, false)\"\n (mouseleave)=\"closeDetail(true)\">\n <lucide-icon [img]=\"icons.Info\" [size]=\"18\" class=\"text-gray-400\"></lucide-icon>\n </div>\n @if (config.repository === 'customer') {\n <div class=\"infoicon hover:opacity-80\" (click)=\"$event.stopPropagation(); shareRoute.emit(route)\">\n <lucide-icon [img]=\"icons.Share2\" [size]=\"16\" class=\"text-gray-400\"></lucide-icon>\n </div>\n }\n </div>\n </div>\n \n <div class=\"location-flow bg-gray-100 dark:bg-slate-900 px-2 py-2 pb-3 rounded-lg\">\n <span class=\"pickup\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.pickup_location || '').split('|')[1] ? (route.pickup_location || '').split('|')[1] : (route.pickup_location || '') }}\n </span>\n <span class=\"delivery\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"8\" />\n </svg>\n {{ (route.delivery_location || '').split('|')[1] ? (route.delivery_location || '').split('|')[1] : (route.delivery_location || '') }}\n </span>\n </div>\n </li>\n }\n </ul>\n } @else if (routes().length === 0) {\n <div class=\"p-8 text-center text-gray-400\">\n No routes available for this perspective.\n </div>\n }\n </cdk-virtual-scroll-viewport>\n </div>\n </aside>\n</div>\n}\n<lib-route-info-card [modalOpen]=\"showRouteModal\" (modalOpenChange)=\"$event ? null : closeDetail(false)\" [routeData]=\"selectedRoute()\" [repository]=\"config.repository\" displayMode=\"dispatch\" [noBackdrop]=\"!isClickTriggered\"></lib-route-info-card>\n", styles: [".detail-drawer{position:fixed;right:0;bottom:36px;width:280px;background:var(--bg-primary, white);border-left:1px solid var(--border-color, #e2e8f0);display:flex;flex-direction:column;z-index:501;animation:slideIn .2s ease;height:100vh}:host-context(.dark) .detail-drawer{background-color:#1e293b;border-color:#334155}.drawer-listing-box{flex:1;overflow:hidden;padding:0!important}.routeList-viewport{width:100%}.route-list-ul{list-style:none;padding:10px;margin:0}.route-li-v1{position:relative;padding:6px 10px;display:flex;flex-direction:column;gap:2px;border-radius:8px;cursor:pointer;transition:all .15s ease;min-height:72px}.route-li-v1:hover{background:#ffffff0d}.route-li-v1.selected{border:1px solid #3b82f6}.task-header{display:flex;align-items:center;gap:6px;margin-bottom:4px}.job-code{font-size:13px;font-weight:600;color:var(--text-primary, #1e293b);white-space:nowrap;text-overflow:ellipsis;max-width:190px;overflow:hidden}:host-context(.dark) .job-code{color:#f1f5f9}.iconprt{display:flex;flex-shrink:0;gap:5px}.plotting-spinner{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#1e293bb3;border-radius:4px;z-index:10}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.statusunit{border-radius:30px;font-size:11px;text-transform:capitalize;font-weight:600;width:18px;height:18px;text-align:center;line-height:18px}.statusunit.Ton{background:#ff7272}.statusunit.Load{background:#a3c52e}.statusunit.Hourly{background:#ae23d1}.pickprtbox{flex:1;min-width:0}.pickprtbox h2{font-size:14px;font-weight:600;color:#fff;margin:0;line-height:1.2}.pickprtbox h3{font-size:12px;color:#94a3b8;margin:2px 0 6px;font-weight:400}.pickdropprt{display:flex;flex-direction:column;gap:4px}.pickdropprt .pickprt,.pickdropprt .dropprt{color:#cbd5e1;font-size:11px}.pickdropprt .pickprt h4,.pickdropprt .dropprt h4{margin:0;font-weight:500;color:#94a3b8}.pickdropprt .pickprt.pickprt h4,.pickdropprt .dropprt.pickprt h4{color:#22c55e}.pickdropprt .pickprt.dropprt h4,.pickdropprt .dropprt.dropprt h4{color:#3b82f6}.infoicon{cursor:pointer}.infoicon:hover lucide-icon{color:#fff}@keyframes slideIn{0%{transform:translate(100%)}to{transform:translate(0)}}.animate-slide-in{animation:slideIn .2s ease}.location-flow{display:flex;flex-direction:column;align-items:flex-start;gap:2px;font-size:11px;color:var(--text-secondary, #64748b);margin-bottom:6px}.location-flow .pickup{display:inline;align-items:center;gap:3px;color:#22c55e;white-space:nowrap;text-overflow:ellipsis;max-width:200px;overflow:hidden;position:relative;padding-left:15px}.location-flow .pickup svg{width:8px;height:8px;position:absolute;left:0;top:5px}.location-flow .delivery{display:inline;align-items:center;gap:3px;color:#ef4444;white-space:nowrap;text-overflow:ellipsis;max-width:200px;overflow:hidden;position:relative;padding-left:15px;top:5px}.location-flow .delivery svg{width:8px;height:8px;position:absolute;left:0;top:5px}\n"] }]
593
593
  }], ctorParameters: () => [], propDecorators: { customerRepoDetails: [{
594
594
  type: Input
595
595
  }], selectedRouteIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedRouteIds", required: false }] }], modalOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "modalOpen", required: false }] }], initialRoutes: [{
@@ -1611,11 +1611,11 @@ class ShareRouteComponent {
1611
1611
  this.isDragging = false;
1612
1612
  }
1613
1613
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ShareRouteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1614
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: ShareRouteComponent, isStandalone: true, selector: "lib-share-route", inputs: { openShareRouteDetails: { classPropertyName: "openShareRouteDetails", publicName: "openShareRouteDetails", isSignal: true, isRequired: false, transformFunction: null }, userDetails: { classPropertyName: "userDetails", publicName: "userDetails", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closePopupEmit: "closePopupEmit" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:mousemove": "onMouseMove($event)", "document:mouseup": "onMouseUp()" } }, viewQueries: [{ propertyName: "filterPickup", first: true, predicate: ["filterPickup"], descendants: true }, { propertyName: "filterDelivery", first: true, predicate: ["filterDelivery"], descendants: true }], ngImport: i0, template: "<div\n class=\"absolute inset-0 z-[120] flex items-center justify-center p-4 w-[800px] bottom-[50%] left-[50%]\"\n style=\"transform: translate(-50%)\"\n>\n <div class=\"flex lg:items-start lg:justify-start items-center justify-center p-3 h-[1200px]\">\n <form\n [formGroup]=\"shareRouteForm\"\n (ngSubmit)=\"saveShareRoute()\"\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl w-[800px] pointer-events-auto\"\n [style.transform]=\"'translate(' + dragX() + 'px, ' + dragY() + 'px)'\"\n [style.will-change]=\"'transform'\"\n (click)=\"$event.stopPropagation()\"\n >\n <div\n class=\"flex items-center justify-between p-4 border-b border-gray-200 dark:border-slate-700 cursor-move\"\n (mousedown)=\"startDrag($event)\"\n >\n <h3 class=\"flex items-center gap-1 text-lg font-semibold text-gray-900 dark:text-white\">\n Share Route\n </h3>\n <div class=\"flex items-center gap-4\">\n <button\n type=\"submit\"\n [disabled]=\"shareRouteForm.invalid || showLoader()\"\n class=\"flex items-center gap-2 px-8 py-2.5 rounded-lg bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-bold text-sm shadow-lg shadow-amber-500/20 transition-all active:scale-95\"\n >\n @if (showLoader()) {\n <lucide-icon [img]=\"icons.LoaderCircle\" class=\"animate-spin\" [size]=\"18\"></lucide-icon> } @else { Send }\n </button>\n <button\n type=\"button\"\n class=\"inline-flex items-center gap-2 px-4 py-2.5 bg-gray-600 text-white hover:bg-gray-700 font-medium rounded-lg transition-colors text-sm\"\n (click)=\"closePopup()\"\n >\n Close\n </button>\n </div>\n </div>\n\n <div class=\"p-4 overflow-y-auto max-h-[60vh]\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Route Name -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Route Name\n </label>\n <input\n formControlName=\"routeName\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Enter route name\"\n />\n </div>\n\n <!-- Unit Type -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Unit Type\n </label>\n <select\n formControlName=\"units\"\n (change)=\"checkAndFetchRouteInformation()\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n >\n <option value=\"\" disabled>Select Unit</option>\n @for (unit of unitsList(); track unit.type) {\n <option [value]=\"unit.type\">{{ unit.type }}</option>\n }\n </select>\n </div>\n\n <!-- Pickup Location -->\n <div class=\"relative autocomplete-field\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Pickup\n </label>\n <input\n formControlName=\"pickupLocation\"\n #filterPickup\n (input)=\"onInputChange($event, 'pickup')\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Search pickup location...\"\n autocomplete=\"off\"\n />\n @if (showPickupSuggestions() && pickupSuggestions().length > 0) {\n <div\n class=\"absolute z-[110] w-full mt-1 bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-lg shadow-xl max-h-48 overflow-y-auto\"\n >\n @for (suggestion of pickupSuggestions(); track\n suggestion.placePrediction?.text?.toString() || $index) {\n <div\n class=\"px-4 py-2.5 hover:bg-amber-50 dark:hover:bg-amber-900/20 cursor-pointer text-sm text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-slate-700 last:border-0 transition-colors\"\n (click)=\"onSuggestionClick(suggestion, 'pickup')\"\n >\n {{ suggestion.placePrediction?.text?.toString() }}\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Delivery Location -->\n <div class=\"relative autocomplete-field\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Delivery\n </label>\n <input\n formControlName=\"deliveryLocation\"\n #filterDelivery\n (input)=\"onInputChange($event, 'delivery')\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Search delivery location...\"\n autocomplete=\"off\"\n />\n @if (showDeliverySuggestions() && deliverySuggestions().length > 0) {\n <div\n class=\"absolute z-[110] w-full mt-1 bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-lg shadow-xl max-h-48 overflow-y-auto\"\n >\n @for (suggestion of deliverySuggestions(); track\n suggestion.placePrediction?.text?.toString() || $index) {\n <div\n class=\"px-4 py-2.5 hover:bg-amber-50 dark:hover:bg-amber-900/20 cursor-pointer text-sm text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-slate-700 last:border-0 transition-colors\"\n (click)=\"onSuggestionClick(suggestion, 'delivery')\"\n >\n {{ suggestion.placePrediction?.text?.toString() }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-[1rem] mt-[1rem]\">\n <!-- Notes -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\"\n >Notes</label\n >\n <textarea\n formControlName=\"routeNotes\"\n rows=\"2\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm resize-none\"\n placeholder=\"List Material and Details\"\n ></textarea>\n </div>\n </div>\n\n <div class=\"grid grid-cols-2 gap-4 mb-[1rem]\">\n <!-- Date Requested -->\n <div class=\"relative\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Date Requested\n </label>\n <div class=\"relative group\">\n <input\n type=\"text\"\n readonly\n [value]=\"displayDate()\"\n (click)=\"dateInput.showPicker()\"\n placeholder=\"MM/DD/YYYY\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <input\n #dateInput\n type=\"date\"\n [value]=\"dateValue()\"\n (change)=\"onDateChange($event)\"\n class=\"absolute inset-0 w-0 h-0 opacity-0 pointer-events-none\"\n />\n </div>\n </div>\n\n <!-- Quantity Requested -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Quantity Requested\n </label>\n <input\n type=\"number\"\n formControlName=\"quantity\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"0\"\n />\n </div>\n\n <!-- Price -->\n <div class=\"relative -top-[20px]\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Customer Haul Price\n </label>\n <div class=\"relative\">\n <input\n formControlName=\"price\"\n readonly\n class=\"w-full px-3 py-3 pl-[47px] rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <lucide-icon\n [img]=\"icons.DollarSign\"\n class=\"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400\"\n [size]=\"16\"\n ></lucide-icon>\n </div>\n </div>\n\n <!-- Unit Type Display -->\n <div class=\"relative -top-[20px]\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Unit type\n </label>\n <div\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n >\n {{ shareRouteForm.value.units || 'N/A' }}\n </div>\n </div>\n\n <!-- Contact Info Section Title -->\n <div class=\"md:col-span-2 border-t border-gray-100 dark:border-slate-800\">\n <h3 class=\"flex items-center gap-1 text-md font-semibold text-gray-900 dark:text-white\">\n Customer Information\n </h3>\n </div>\n\n <!-- Contact Name -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Name\n </label>\n <input\n formControlName=\"contactName\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Contact Phone -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Phone\n </label>\n <input\n formControlName=\"contactPhone\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Contact Email -->\n <div class=\"space-y-1.5 md:col-span-2\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Email\n </label>\n <input\n formControlName=\"contactEmail\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Special Pricing Checkbox -->\n <div class=\"md:col-span-2 pt-2 flex items-center gap-3\">\n <label class=\"relative flex h-5 w-5 cursor-pointer\">\n <input\n type=\"checkbox\"\n formControlName=\"special_price\"\n (change)=\"setValidators(shareRouteForm.value.special_price)\"\n class=\"h-full w-full appearance-none rounded-md border border-gray-300 dark:border-slate-700 transition-all checked:bg-amber-500 checked:border-amber-500 outline-none cursor-pointer\"\n />\n <lucide-icon\n [img]=\"icons.Check\"\n [size]=\"14\"\n [class.opacity-100]=\"shareRouteForm.get('special_price')?.value\"\n [class.opacity-0]=\"!shareRouteForm.get('special_price')?.value\"\n class=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-white transition-opacity pointer-events-none\"\n ></lucide-icon>\n </label>\n <span class=\"text-sm font-medium text-gray-700 dark:text-gray-300\"\n >Request special pricing</span\n >\n </div>\n\n <!-- Special Price Input (Conditional) -->\n @if (shareRouteForm.value.special_price) {\n <div class=\"space-y-1.5 animate-fade-in md:col-span-1\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Requested Price\n </label>\n <div class=\"relative\">\n <input\n formControlName=\"customerEstimatedPrice\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <lucide-icon\n [img]=\"icons.DollarSign\"\n class=\"absolute left-3 top-1/2 -translate-y-1/2 text-amber-500\"\n [size]=\"16\"\n ></lucide-icon>\n </div>\n </div>\n }\n </div>\n </div>\n </form>\n </div>\n</div>\n", styles: ["@keyframes slide-up{0%{opacity:0;transform:translateY(20px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.animate-slide-up{animation:slide-up .3s cubic-bezier(.16,1,.3,1) forwards}.animate-fade-in{animation:fade-in .2s ease-out forwards}:host{display:block}input[type=date]::-webkit-calendar-picker-indicator{filter:invert(.5);cursor:pointer}.dark input[type=date]::-webkit-calendar-picker-indicator{filter:invert(1)}form::-webkit-scrollbar{width:6px}form::-webkit-scrollbar-track{background:transparent}form::-webkit-scrollbar-thumb{background:#e2e8f0;border-radius:10px}.dark form::-webkit-scrollbar-thumb{background:#334155}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
1614
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: ShareRouteComponent, isStandalone: true, selector: "lib-share-route", inputs: { openShareRouteDetails: { classPropertyName: "openShareRouteDetails", publicName: "openShareRouteDetails", isSignal: true, isRequired: false, transformFunction: null }, userDetails: { classPropertyName: "userDetails", publicName: "userDetails", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closePopupEmit: "closePopupEmit" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:mousemove": "onMouseMove($event)", "document:mouseup": "onMouseUp()" } }, viewQueries: [{ propertyName: "filterPickup", first: true, predicate: ["filterPickup"], descendants: true }, { propertyName: "filterDelivery", first: true, predicate: ["filterDelivery"], descendants: true }], ngImport: i0, template: "<div\n class=\"fixed inset-0 z-[120] flex items-end justify-center p-4 w-full pointer-events-none\"\n \n>\n <div class=\"flex lg:items-start lg:justify-start items-center justify-center p-3\">\n <form\n [formGroup]=\"shareRouteForm\"\n (ngSubmit)=\"saveShareRoute()\"\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl w-[1000px] pointer-events-auto\"\n [style.transform]=\"'translate(' + dragX() + 'px, ' + dragY() + 'px)'\"\n [style.will-change]=\"'transform'\"\n (click)=\"$event.stopPropagation()\"\n >\n <div\n class=\"flex items-center justify-between p-4 border-b border-gray-200 dark:border-slate-700 cursor-move\"\n (mousedown)=\"startDrag($event)\"\n >\n <h3 class=\"flex items-center gap-1 text-lg font-semibold text-gray-900 dark:text-white\">\n Share Route\n </h3>\n <div class=\"flex items-center gap-4\">\n <button\n type=\"submit\"\n [disabled]=\"shareRouteForm.invalid || showLoader()\"\n class=\"flex items-center gap-2 px-4 py-2.5 rounded-lg bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-bold text-sm shadow-lg shadow-amber-500/20 transition-all active:scale-95\"\n >\n @if (showLoader()) {\n <lucide-icon [img]=\"icons.LoaderCircle\" class=\"animate-spin\" [size]=\"18\"></lucide-icon> } @else { Send }\n </button>\n <button\n type=\"button\"\n class=\"inline-flex items-center gap-2 px-4 py-2.5 bg-gray-600 text-white hover:bg-gray-700 font-medium rounded-lg transition-colors text-sm\"\n (click)=\"closePopup()\"\n >\n Close\n </button>\n </div>\n </div>\n\n <div class=\"p-4 overflow-y-auto max-h-[50vh]\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Route Name -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Route Name\n </label>\n <input\n formControlName=\"routeName\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Enter route name\"\n />\n </div>\n\n <!-- Unit Type -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Unit Type\n </label>\n <select\n formControlName=\"units\"\n (change)=\"checkAndFetchRouteInformation()\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n >\n <option value=\"\" disabled>Select Unit</option>\n @for (unit of unitsList(); track unit.type) {\n <option [value]=\"unit.type\">{{ unit.type }}</option>\n }\n </select>\n </div>\n\n <!-- Pickup Location -->\n <div class=\"relative autocomplete-field\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Pickup\n </label>\n <input\n formControlName=\"pickupLocation\"\n #filterPickup\n (input)=\"onInputChange($event, 'pickup')\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Search pickup location...\"\n autocomplete=\"off\"\n />\n @if (showPickupSuggestions() && pickupSuggestions().length > 0) {\n <div\n class=\"absolute z-[110] w-full mt-1 bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-lg shadow-xl max-h-48 overflow-y-auto\"\n >\n @for (suggestion of pickupSuggestions(); track\n suggestion.placePrediction?.text?.toString() || $index) {\n <div\n class=\"px-4 py-2.5 hover:bg-amber-50 dark:hover:bg-amber-900/20 cursor-pointer text-sm text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-slate-700 last:border-0 transition-colors\"\n (click)=\"onSuggestionClick(suggestion, 'pickup')\"\n >\n {{ suggestion.placePrediction?.text?.toString() }}\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Delivery Location -->\n <div class=\"relative autocomplete-field\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Delivery\n </label>\n <input\n formControlName=\"deliveryLocation\"\n #filterDelivery\n (input)=\"onInputChange($event, 'delivery')\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Search delivery location...\"\n autocomplete=\"off\"\n />\n @if (showDeliverySuggestions() && deliverySuggestions().length > 0) {\n <div\n class=\"absolute z-[110] w-full mt-1 bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-lg shadow-xl max-h-48 overflow-y-auto\"\n >\n @for (suggestion of deliverySuggestions(); track\n suggestion.placePrediction?.text?.toString() || $index) {\n <div\n class=\"px-4 py-2.5 hover:bg-amber-50 dark:hover:bg-amber-900/20 cursor-pointer text-sm text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-slate-700 last:border-0 transition-colors\"\n (click)=\"onSuggestionClick(suggestion, 'delivery')\"\n >\n {{ suggestion.placePrediction?.text?.toString() }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-[1rem] mt-[1rem]\">\n <!-- Notes -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\"\n >Notes</label\n >\n <textarea\n formControlName=\"routeNotes\"\n rows=\"2\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm resize-none\"\n placeholder=\"List Material and Details\"\n ></textarea>\n </div>\n </div>\n\n <div class=\"grid grid-cols-2 gap-4 mb-[1rem]\">\n <!-- Date Requested -->\n <div class=\"relative\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Date Requested\n </label>\n <div class=\"relative group\">\n <input\n type=\"text\"\n readonly\n [value]=\"displayDate()\"\n (click)=\"dateInput.showPicker()\"\n placeholder=\"MM/DD/YYYY\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <input\n #dateInput\n type=\"date\"\n [value]=\"dateValue()\"\n (change)=\"onDateChange($event)\"\n class=\"absolute inset-0 w-0 h-0 opacity-0 pointer-events-none\"\n />\n </div>\n </div>\n\n <!-- Quantity Requested -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Quantity Requested\n </label>\n <input\n type=\"number\"\n formControlName=\"quantity\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"0\"\n />\n </div>\n\n <!-- Price -->\n <div class=\"relative -top-[20px]\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Customer Haul Price\n </label>\n <div class=\"relative\">\n <input\n formControlName=\"price\"\n readonly\n class=\"w-full px-3 py-3 pl-[47px] rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <lucide-icon\n [img]=\"icons.DollarSign\"\n class=\"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400\"\n [size]=\"16\"\n ></lucide-icon>\n </div>\n </div>\n\n <!-- Unit Type Display -->\n <div class=\"relative -top-[20px]\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Unit type\n </label>\n <div\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n >\n {{ shareRouteForm.value.units || 'N/A' }}\n </div>\n </div>\n\n <!-- Contact Info Section Title -->\n <div class=\"md:col-span-2 border-t border-gray-100 dark:border-slate-800\">\n <h3 class=\"flex items-center gap-1 text-md font-semibold text-gray-900 dark:text-white\">\n Customer Information\n </h3>\n </div>\n\n <!-- Contact Name -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Name\n </label>\n <input\n formControlName=\"contactName\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Contact Phone -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Phone\n </label>\n <input\n formControlName=\"contactPhone\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Contact Email -->\n <div class=\"space-y-1.5 md:col-span-2\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Email\n </label>\n <input\n formControlName=\"contactEmail\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Special Pricing Checkbox -->\n <div class=\"md:col-span-2 pt-2 flex items-center gap-3\">\n <label class=\"relative flex h-5 w-5 cursor-pointer\">\n <input\n type=\"checkbox\"\n formControlName=\"special_price\"\n (change)=\"setValidators(shareRouteForm.value.special_price)\"\n class=\"h-full w-full appearance-none rounded-md border border-gray-300 dark:border-slate-700 transition-all checked:bg-amber-500 checked:border-amber-500 outline-none cursor-pointer\"\n />\n <lucide-icon\n [img]=\"icons.Check\"\n [size]=\"14\"\n [class.opacity-100]=\"shareRouteForm.get('special_price')?.value\"\n [class.opacity-0]=\"!shareRouteForm.get('special_price')?.value\"\n class=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-white transition-opacity pointer-events-none\"\n ></lucide-icon>\n </label>\n <span class=\"text-sm font-medium text-gray-700 dark:text-gray-300\"\n >Request special pricing</span\n >\n </div>\n\n <!-- Special Price Input (Conditional) -->\n @if (shareRouteForm.value.special_price) {\n <div class=\"space-y-1.5 animate-fade-in md:col-span-1\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Requested Price\n </label>\n <div class=\"relative\">\n <input\n formControlName=\"customerEstimatedPrice\"\n class=\"w-full px-3 py-3 pl-[47px] rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <lucide-icon\n [img]=\"icons.DollarSign\"\n class=\"absolute left-3 top-1/2 -translate-y-1/2 text-amber-500\"\n [size]=\"16\"\n ></lucide-icon>\n </div>\n </div>\n }\n </div>\n </div>\n </form>\n </div>\n</div>\n", styles: ["@keyframes slide-up{0%{opacity:0;transform:translateY(20px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.animate-slide-up{animation:slide-up .3s cubic-bezier(.16,1,.3,1) forwards}.animate-fade-in{animation:fade-in .2s ease-out forwards}:host{display:block}input[type=date]::-webkit-calendar-picker-indicator{filter:invert(.5);cursor:pointer}.dark input[type=date]::-webkit-calendar-picker-indicator{filter:invert(1)}form::-webkit-scrollbar{width:6px}form::-webkit-scrollbar-track{background:transparent}form::-webkit-scrollbar-thumb{background:#e2e8f0;border-radius:10px}.dark form::-webkit-scrollbar-thumb{background:#334155}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
1615
1615
  }
1616
1616
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ShareRouteComponent, decorators: [{
1617
1617
  type: Component,
1618
- args: [{ selector: 'lib-share-route', standalone: true, imports: [LucideAngularModule, ReactiveFormsModule, NgClass, CurrencyPipe], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div\n class=\"absolute inset-0 z-[120] flex items-center justify-center p-4 w-[800px] bottom-[50%] left-[50%]\"\n style=\"transform: translate(-50%)\"\n>\n <div class=\"flex lg:items-start lg:justify-start items-center justify-center p-3 h-[1200px]\">\n <form\n [formGroup]=\"shareRouteForm\"\n (ngSubmit)=\"saveShareRoute()\"\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl w-[800px] pointer-events-auto\"\n [style.transform]=\"'translate(' + dragX() + 'px, ' + dragY() + 'px)'\"\n [style.will-change]=\"'transform'\"\n (click)=\"$event.stopPropagation()\"\n >\n <div\n class=\"flex items-center justify-between p-4 border-b border-gray-200 dark:border-slate-700 cursor-move\"\n (mousedown)=\"startDrag($event)\"\n >\n <h3 class=\"flex items-center gap-1 text-lg font-semibold text-gray-900 dark:text-white\">\n Share Route\n </h3>\n <div class=\"flex items-center gap-4\">\n <button\n type=\"submit\"\n [disabled]=\"shareRouteForm.invalid || showLoader()\"\n class=\"flex items-center gap-2 px-8 py-2.5 rounded-lg bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-bold text-sm shadow-lg shadow-amber-500/20 transition-all active:scale-95\"\n >\n @if (showLoader()) {\n <lucide-icon [img]=\"icons.LoaderCircle\" class=\"animate-spin\" [size]=\"18\"></lucide-icon> } @else { Send }\n </button>\n <button\n type=\"button\"\n class=\"inline-flex items-center gap-2 px-4 py-2.5 bg-gray-600 text-white hover:bg-gray-700 font-medium rounded-lg transition-colors text-sm\"\n (click)=\"closePopup()\"\n >\n Close\n </button>\n </div>\n </div>\n\n <div class=\"p-4 overflow-y-auto max-h-[60vh]\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Route Name -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Route Name\n </label>\n <input\n formControlName=\"routeName\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Enter route name\"\n />\n </div>\n\n <!-- Unit Type -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Unit Type\n </label>\n <select\n formControlName=\"units\"\n (change)=\"checkAndFetchRouteInformation()\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n >\n <option value=\"\" disabled>Select Unit</option>\n @for (unit of unitsList(); track unit.type) {\n <option [value]=\"unit.type\">{{ unit.type }}</option>\n }\n </select>\n </div>\n\n <!-- Pickup Location -->\n <div class=\"relative autocomplete-field\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Pickup\n </label>\n <input\n formControlName=\"pickupLocation\"\n #filterPickup\n (input)=\"onInputChange($event, 'pickup')\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Search pickup location...\"\n autocomplete=\"off\"\n />\n @if (showPickupSuggestions() && pickupSuggestions().length > 0) {\n <div\n class=\"absolute z-[110] w-full mt-1 bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-lg shadow-xl max-h-48 overflow-y-auto\"\n >\n @for (suggestion of pickupSuggestions(); track\n suggestion.placePrediction?.text?.toString() || $index) {\n <div\n class=\"px-4 py-2.5 hover:bg-amber-50 dark:hover:bg-amber-900/20 cursor-pointer text-sm text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-slate-700 last:border-0 transition-colors\"\n (click)=\"onSuggestionClick(suggestion, 'pickup')\"\n >\n {{ suggestion.placePrediction?.text?.toString() }}\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Delivery Location -->\n <div class=\"relative autocomplete-field\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Delivery\n </label>\n <input\n formControlName=\"deliveryLocation\"\n #filterDelivery\n (input)=\"onInputChange($event, 'delivery')\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Search delivery location...\"\n autocomplete=\"off\"\n />\n @if (showDeliverySuggestions() && deliverySuggestions().length > 0) {\n <div\n class=\"absolute z-[110] w-full mt-1 bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-lg shadow-xl max-h-48 overflow-y-auto\"\n >\n @for (suggestion of deliverySuggestions(); track\n suggestion.placePrediction?.text?.toString() || $index) {\n <div\n class=\"px-4 py-2.5 hover:bg-amber-50 dark:hover:bg-amber-900/20 cursor-pointer text-sm text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-slate-700 last:border-0 transition-colors\"\n (click)=\"onSuggestionClick(suggestion, 'delivery')\"\n >\n {{ suggestion.placePrediction?.text?.toString() }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-[1rem] mt-[1rem]\">\n <!-- Notes -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\"\n >Notes</label\n >\n <textarea\n formControlName=\"routeNotes\"\n rows=\"2\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm resize-none\"\n placeholder=\"List Material and Details\"\n ></textarea>\n </div>\n </div>\n\n <div class=\"grid grid-cols-2 gap-4 mb-[1rem]\">\n <!-- Date Requested -->\n <div class=\"relative\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Date Requested\n </label>\n <div class=\"relative group\">\n <input\n type=\"text\"\n readonly\n [value]=\"displayDate()\"\n (click)=\"dateInput.showPicker()\"\n placeholder=\"MM/DD/YYYY\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <input\n #dateInput\n type=\"date\"\n [value]=\"dateValue()\"\n (change)=\"onDateChange($event)\"\n class=\"absolute inset-0 w-0 h-0 opacity-0 pointer-events-none\"\n />\n </div>\n </div>\n\n <!-- Quantity Requested -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Quantity Requested\n </label>\n <input\n type=\"number\"\n formControlName=\"quantity\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"0\"\n />\n </div>\n\n <!-- Price -->\n <div class=\"relative -top-[20px]\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Customer Haul Price\n </label>\n <div class=\"relative\">\n <input\n formControlName=\"price\"\n readonly\n class=\"w-full px-3 py-3 pl-[47px] rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <lucide-icon\n [img]=\"icons.DollarSign\"\n class=\"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400\"\n [size]=\"16\"\n ></lucide-icon>\n </div>\n </div>\n\n <!-- Unit Type Display -->\n <div class=\"relative -top-[20px]\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Unit type\n </label>\n <div\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n >\n {{ shareRouteForm.value.units || 'N/A' }}\n </div>\n </div>\n\n <!-- Contact Info Section Title -->\n <div class=\"md:col-span-2 border-t border-gray-100 dark:border-slate-800\">\n <h3 class=\"flex items-center gap-1 text-md font-semibold text-gray-900 dark:text-white\">\n Customer Information\n </h3>\n </div>\n\n <!-- Contact Name -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Name\n </label>\n <input\n formControlName=\"contactName\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Contact Phone -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Phone\n </label>\n <input\n formControlName=\"contactPhone\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Contact Email -->\n <div class=\"space-y-1.5 md:col-span-2\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Email\n </label>\n <input\n formControlName=\"contactEmail\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Special Pricing Checkbox -->\n <div class=\"md:col-span-2 pt-2 flex items-center gap-3\">\n <label class=\"relative flex h-5 w-5 cursor-pointer\">\n <input\n type=\"checkbox\"\n formControlName=\"special_price\"\n (change)=\"setValidators(shareRouteForm.value.special_price)\"\n class=\"h-full w-full appearance-none rounded-md border border-gray-300 dark:border-slate-700 transition-all checked:bg-amber-500 checked:border-amber-500 outline-none cursor-pointer\"\n />\n <lucide-icon\n [img]=\"icons.Check\"\n [size]=\"14\"\n [class.opacity-100]=\"shareRouteForm.get('special_price')?.value\"\n [class.opacity-0]=\"!shareRouteForm.get('special_price')?.value\"\n class=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-white transition-opacity pointer-events-none\"\n ></lucide-icon>\n </label>\n <span class=\"text-sm font-medium text-gray-700 dark:text-gray-300\"\n >Request special pricing</span\n >\n </div>\n\n <!-- Special Price Input (Conditional) -->\n @if (shareRouteForm.value.special_price) {\n <div class=\"space-y-1.5 animate-fade-in md:col-span-1\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Requested Price\n </label>\n <div class=\"relative\">\n <input\n formControlName=\"customerEstimatedPrice\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <lucide-icon\n [img]=\"icons.DollarSign\"\n class=\"absolute left-3 top-1/2 -translate-y-1/2 text-amber-500\"\n [size]=\"16\"\n ></lucide-icon>\n </div>\n </div>\n }\n </div>\n </div>\n </form>\n </div>\n</div>\n", styles: ["@keyframes slide-up{0%{opacity:0;transform:translateY(20px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.animate-slide-up{animation:slide-up .3s cubic-bezier(.16,1,.3,1) forwards}.animate-fade-in{animation:fade-in .2s ease-out forwards}:host{display:block}input[type=date]::-webkit-calendar-picker-indicator{filter:invert(.5);cursor:pointer}.dark input[type=date]::-webkit-calendar-picker-indicator{filter:invert(1)}form::-webkit-scrollbar{width:6px}form::-webkit-scrollbar-track{background:transparent}form::-webkit-scrollbar-thumb{background:#e2e8f0;border-radius:10px}.dark form::-webkit-scrollbar-thumb{background:#334155}\n"] }]
1618
+ args: [{ selector: 'lib-share-route', standalone: true, imports: [LucideAngularModule, ReactiveFormsModule, NgClass, CurrencyPipe], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div\n class=\"fixed inset-0 z-[120] flex items-end justify-center p-4 w-full pointer-events-none\"\n \n>\n <div class=\"flex lg:items-start lg:justify-start items-center justify-center p-3\">\n <form\n [formGroup]=\"shareRouteForm\"\n (ngSubmit)=\"saveShareRoute()\"\n class=\"relative bg-white dark:bg-slate-800 rounded-lg shadow-xl w-[1000px] pointer-events-auto\"\n [style.transform]=\"'translate(' + dragX() + 'px, ' + dragY() + 'px)'\"\n [style.will-change]=\"'transform'\"\n (click)=\"$event.stopPropagation()\"\n >\n <div\n class=\"flex items-center justify-between p-4 border-b border-gray-200 dark:border-slate-700 cursor-move\"\n (mousedown)=\"startDrag($event)\"\n >\n <h3 class=\"flex items-center gap-1 text-lg font-semibold text-gray-900 dark:text-white\">\n Share Route\n </h3>\n <div class=\"flex items-center gap-4\">\n <button\n type=\"submit\"\n [disabled]=\"shareRouteForm.invalid || showLoader()\"\n class=\"flex items-center gap-2 px-4 py-2.5 rounded-lg bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-bold text-sm shadow-lg shadow-amber-500/20 transition-all active:scale-95\"\n >\n @if (showLoader()) {\n <lucide-icon [img]=\"icons.LoaderCircle\" class=\"animate-spin\" [size]=\"18\"></lucide-icon> } @else { Send }\n </button>\n <button\n type=\"button\"\n class=\"inline-flex items-center gap-2 px-4 py-2.5 bg-gray-600 text-white hover:bg-gray-700 font-medium rounded-lg transition-colors text-sm\"\n (click)=\"closePopup()\"\n >\n Close\n </button>\n </div>\n </div>\n\n <div class=\"p-4 overflow-y-auto max-h-[50vh]\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Route Name -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Route Name\n </label>\n <input\n formControlName=\"routeName\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Enter route name\"\n />\n </div>\n\n <!-- Unit Type -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Unit Type\n </label>\n <select\n formControlName=\"units\"\n (change)=\"checkAndFetchRouteInformation()\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n >\n <option value=\"\" disabled>Select Unit</option>\n @for (unit of unitsList(); track unit.type) {\n <option [value]=\"unit.type\">{{ unit.type }}</option>\n }\n </select>\n </div>\n\n <!-- Pickup Location -->\n <div class=\"relative autocomplete-field\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Pickup\n </label>\n <input\n formControlName=\"pickupLocation\"\n #filterPickup\n (input)=\"onInputChange($event, 'pickup')\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Search pickup location...\"\n autocomplete=\"off\"\n />\n @if (showPickupSuggestions() && pickupSuggestions().length > 0) {\n <div\n class=\"absolute z-[110] w-full mt-1 bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-lg shadow-xl max-h-48 overflow-y-auto\"\n >\n @for (suggestion of pickupSuggestions(); track\n suggestion.placePrediction?.text?.toString() || $index) {\n <div\n class=\"px-4 py-2.5 hover:bg-amber-50 dark:hover:bg-amber-900/20 cursor-pointer text-sm text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-slate-700 last:border-0 transition-colors\"\n (click)=\"onSuggestionClick(suggestion, 'pickup')\"\n >\n {{ suggestion.placePrediction?.text?.toString() }}\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Delivery Location -->\n <div class=\"relative autocomplete-field\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Delivery\n </label>\n <input\n formControlName=\"deliveryLocation\"\n #filterDelivery\n (input)=\"onInputChange($event, 'delivery')\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"Search delivery location...\"\n autocomplete=\"off\"\n />\n @if (showDeliverySuggestions() && deliverySuggestions().length > 0) {\n <div\n class=\"absolute z-[110] w-full mt-1 bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-700 rounded-lg shadow-xl max-h-48 overflow-y-auto\"\n >\n @for (suggestion of deliverySuggestions(); track\n suggestion.placePrediction?.text?.toString() || $index) {\n <div\n class=\"px-4 py-2.5 hover:bg-amber-50 dark:hover:bg-amber-900/20 cursor-pointer text-sm text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-slate-700 last:border-0 transition-colors\"\n (click)=\"onSuggestionClick(suggestion, 'delivery')\"\n >\n {{ suggestion.placePrediction?.text?.toString() }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-[1rem] mt-[1rem]\">\n <!-- Notes -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\"\n >Notes</label\n >\n <textarea\n formControlName=\"routeNotes\"\n rows=\"2\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm resize-none\"\n placeholder=\"List Material and Details\"\n ></textarea>\n </div>\n </div>\n\n <div class=\"grid grid-cols-2 gap-4 mb-[1rem]\">\n <!-- Date Requested -->\n <div class=\"relative\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Date Requested\n </label>\n <div class=\"relative group\">\n <input\n type=\"text\"\n readonly\n [value]=\"displayDate()\"\n (click)=\"dateInput.showPicker()\"\n placeholder=\"MM/DD/YYYY\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <input\n #dateInput\n type=\"date\"\n [value]=\"dateValue()\"\n (change)=\"onDateChange($event)\"\n class=\"absolute inset-0 w-0 h-0 opacity-0 pointer-events-none\"\n />\n </div>\n </div>\n\n <!-- Quantity Requested -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Quantity Requested\n </label>\n <input\n type=\"number\"\n formControlName=\"quantity\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n placeholder=\"0\"\n />\n </div>\n\n <!-- Price -->\n <div class=\"relative -top-[20px]\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Customer Haul Price\n </label>\n <div class=\"relative\">\n <input\n formControlName=\"price\"\n readonly\n class=\"w-full px-3 py-3 pl-[47px] rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <lucide-icon\n [img]=\"icons.DollarSign\"\n class=\"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400\"\n [size]=\"16\"\n ></lucide-icon>\n </div>\n </div>\n\n <!-- Unit Type Display -->\n <div class=\"relative -top-[20px]\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Unit type\n </label>\n <div\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n >\n {{ shareRouteForm.value.units || 'N/A' }}\n </div>\n </div>\n\n <!-- Contact Info Section Title -->\n <div class=\"md:col-span-2 border-t border-gray-100 dark:border-slate-800\">\n <h3 class=\"flex items-center gap-1 text-md font-semibold text-gray-900 dark:text-white\">\n Customer Information\n </h3>\n </div>\n\n <!-- Contact Name -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Name\n </label>\n <input\n formControlName=\"contactName\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Contact Phone -->\n <div>\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Phone\n </label>\n <input\n formControlName=\"contactPhone\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Contact Email -->\n <div class=\"space-y-1.5 md:col-span-2\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Contact Email\n </label>\n <input\n formControlName=\"contactEmail\"\n class=\"w-full px-3 py-3 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n </div>\n\n <!-- Special Pricing Checkbox -->\n <div class=\"md:col-span-2 pt-2 flex items-center gap-3\">\n <label class=\"relative flex h-5 w-5 cursor-pointer\">\n <input\n type=\"checkbox\"\n formControlName=\"special_price\"\n (change)=\"setValidators(shareRouteForm.value.special_price)\"\n class=\"h-full w-full appearance-none rounded-md border border-gray-300 dark:border-slate-700 transition-all checked:bg-amber-500 checked:border-amber-500 outline-none cursor-pointer\"\n />\n <lucide-icon\n [img]=\"icons.Check\"\n [size]=\"14\"\n [class.opacity-100]=\"shareRouteForm.get('special_price')?.value\"\n [class.opacity-0]=\"!shareRouteForm.get('special_price')?.value\"\n class=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-white transition-opacity pointer-events-none\"\n ></lucide-icon>\n </label>\n <span class=\"text-sm font-medium text-gray-700 dark:text-gray-300\"\n >Request special pricing</span\n >\n </div>\n\n <!-- Special Price Input (Conditional) -->\n @if (shareRouteForm.value.special_price) {\n <div class=\"space-y-1.5 animate-fade-in md:col-span-1\">\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n Requested Price\n </label>\n <div class=\"relative\">\n <input\n formControlName=\"customerEstimatedPrice\"\n class=\"w-full px-3 py-3 pl-[47px] rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm\"\n />\n <lucide-icon\n [img]=\"icons.DollarSign\"\n class=\"absolute left-3 top-1/2 -translate-y-1/2 text-amber-500\"\n [size]=\"16\"\n ></lucide-icon>\n </div>\n </div>\n }\n </div>\n </div>\n </form>\n </div>\n</div>\n", styles: ["@keyframes slide-up{0%{opacity:0;transform:translateY(20px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.animate-slide-up{animation:slide-up .3s cubic-bezier(.16,1,.3,1) forwards}.animate-fade-in{animation:fade-in .2s ease-out forwards}:host{display:block}input[type=date]::-webkit-calendar-picker-indicator{filter:invert(.5);cursor:pointer}.dark input[type=date]::-webkit-calendar-picker-indicator{filter:invert(1)}form::-webkit-scrollbar{width:6px}form::-webkit-scrollbar-track{background:transparent}form::-webkit-scrollbar-thumb{background:#e2e8f0;border-radius:10px}.dark form::-webkit-scrollbar-thumb{background:#334155}\n"] }]
1619
1619
  }], ctorParameters: () => [], propDecorators: { openShareRouteDetails: [{ type: i0.Input, args: [{ isSignal: true, alias: "openShareRouteDetails", required: false }] }], userDetails: [{ type: i0.Input, args: [{ isSignal: true, alias: "userDetails", required: false }] }], closePopupEmit: [{
1620
1620
  type: Output
1621
1621
  }], filterPickup: [{
@@ -2183,7 +2183,7 @@ class CoolmapComponent {
2183
2183
  this.showShareModal.set(true);
2184
2184
  }
2185
2185
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: CoolmapComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2186
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: CoolmapComponent, isStandalone: true, selector: "lib-coolmap", inputs: { mobileMode: { classPropertyName: "mobileMode", publicName: "mobileMode", isSignal: false, isRequired: false, transformFunction: null }, activeSection: { classPropertyName: "activeSection", publicName: "activeSection", isSignal: true, isRequired: false, transformFunction: null }, customerRepoDetails: { classPropertyName: "customerRepoDetails", publicName: "customerRepoDetails", isSignal: false, isRequired: false, transformFunction: null }, userDetails: { classPropertyName: "userDetails", publicName: "userDetails", isSignal: false, isRequired: false, transformFunction: null }, darkMode: { classPropertyName: "darkMode", publicName: "darkMode", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onClick($event)" } }, viewQueries: [{ propertyName: "mapContainer", first: true, predicate: ["mapContainer"], descendants: true }, { propertyName: "searchContainer", first: true, predicate: ["searchContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"center-area\">\n <div [formGroup]=\"filterForm\" class=\"toolbar flex flex-col sm:flex-row md:h-[55px] h-auto py-2 px-2 gap-3 items-center\">\n <div class=\"toolbar-left flex items-center gap-3 flex-1\">\n @if (activeSection() === 'Jobcode') {\n <div class=\"relative w-full sm:w-auto group\">\n <input\n type=\"text\"\n [value]=\"displayDate()\"\n readonly\n [disabled]=\"coolmapService.isLoading()\"\n (click)=\"dateInput.showPicker()\"\n class=\"w-full lg:w-[200px] pl-3 pr-10 py-2 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer\"\n />\n <lucide-icon \n [img]=\"icons.Calendar\" \n [size]=\"18\" \n (click)=\"!coolmapService.isLoading() && dateInput.showPicker()\"\n [class.pointer-events-none]=\"coolmapService.isLoading()\"\n [class.opacity-50]=\"coolmapService.isLoading()\"\n class=\"absolute right-3 top-1/2 -translate-y-1/2 text-white-400 group-hover:text-brand-blue transition-colors cursor-pointer\"\n ></lucide-icon>\n <input\n #dateInput\n type=\"date\"\n [value]=\"dateValue()\"\n (change)=\"onDateChange($event)\"\n [disabled]=\"coolmapService.isLoading()\"\n class=\"absolute inset-0 w-0 h-0 opacity-0 pointer-events-none\"\n />\n </div>\n <span class=\"toolbar-divider hidden sm:flex h-6 w-[1px] bg-gray-200 dark:bg-slate-700\"></span>\n }\n <div #searchContainer class=\"relative items-center flex-1\">\n <lucide-icon [img]=\"icons.Search\" [size]=\"18\" class=\"absolute left-[0.55rem] top-[50%] -translate-y-1/2 text-gray-400\"></lucide-icon>\n <input\n type=\"text\"\n formControlName=\"search\"\n [attr.disabled]=\"coolmapService.isLoading() ? true : null\"\n placeholder=\"Search routes...\"\n class=\"w-full pl-10 pr-10 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-amber-500 focus:border-transparent text-sm disabled:opacity-50 disabled:cursor-not-allowed\"\n (focus)=\"onSearchFocus()\"\n />\n\n @if (filterForm.value.search) {\n <button (click)=\"filterForm.controls.search.setValue('')\" class=\"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600\">\n <lucide-icon [img]=\"icons.X\" [size]=\"16\"></lucide-icon>\n </button>\n }\n\n <!-- Autocomplete Dropdown -->\n @if (dropdownOpen() && filteredOptions().length > 0) {\n <div class=\"absolute z-70 left-0 right-0 top-full mt-1 max-h-60 overflow-y-auto bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-600 rounded shadow-lg\">\n @for (option of filteredOptions(); track option.value + option.type) {\n <div (click)=\"selectFilter(option)\" class=\"px-4 py-2 hover:bg-gray-100 dark:hover:bg-slate-700 cursor-pointer text-xs font-medium border-b border-gray-100 dark:border-slate-700 last:border-0 dark:text-white\">\n <span class=\"capitalize\">{{ option.type }}:</span>\n {{ option.label }}\n </div>\n }\n </div>\n }\n </div>\n\n @if (filters().length > 0) {\n <div class=\"flex flex-wrap gap-2 ml-2\">\n @for (filter of filters(); track filter.value + filter.type) {\n <div class=\"inline-flex items-center gap-1 px-2 py-1 rounded bg-slate-200 dark:bg-slate-700 text-gray-800 dark:text-gray-200 text-xs font-medium border border-gray-300 dark:border-slate-600\">\n <span class=\"capitalize opacity-80\">{{ filter.type }}:</span> {{ filter.name }}\n <button type=\"button\" (click)=\"removeFilter(filter)\" class=\"hover:opacity-75 transition-opacity ml-1\">\n <lucide-icon [img]=\"icons.X\" [size]=\"12\"></lucide-icon>\n </button>\n </div>\n }\n </div>\n }\n </div>\n <div class=\"toolbar-right\">\n @if (selectedRouteIds().length > 0) {\n <button\n type=\"button\"\n (click)=\"clearSelection()\"\n [disabled]=\"coolmapService.isLoading()\"\n class=\"inline-flex items-center justify-center gap-2 px-5 sm:px-6 py-2 bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors text-xs md:text-sm\"\n >\n Show all routes ({{ selectedRouteIds().length }})\n </button>\n }\n @if (activeSection() === 'ViewRoute') {\n <button\n type=\"button\"\n class=\"inline-flex items-center justify-center gap-2 px-5 sm:px-6 py-2 bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors text-xs md:text-sm\"\n [disabled]=\"coolmapService.isLoading()\"\n (click)=\"openAddRouteModal()\">\n <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n Add Route\n </button>\n }\n\n @if(activeSection() === 'Jobcode'){\n <button\n class=\"inline-flex items-center gap-2 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed relative group\"\n (click)=\"showRouteList = true\"\n [disabled]=\"coolmapService.isLoading()\">\n <lucide-icon [img]=\"icons.Route\" [size]=\"20\"></lucide-icon>\n <div\n class=\"absolute top-full right-0 mt-2 group-hover:block hidden bg-gray-800 dark:bg-white text-white dark:text-black text-[10px] rounded py-1 px-2 whitespace-nowrap\">\n Show Route List\n <div\n class=\"absolute -top-[8px] left-[60px] border-4 border-transparent border-b-gray-800 dark:border-b-white\">\n </div>\n </div>\n </button>}\n </div>\n </div>\n <div class=\"view-content\">\n <div class=\"full-view\">\n <div class=\"map-container\">\n <div class=\"mapbox-container\" #mapContainer></div>\n </div>\n </div>\n\n <!-- FOR JOBCODE -->\n @if (activeSection() === 'Jobcode') {\n <lib-job-code \n listMode=\"floating\" \n [routes]=\"activeFilteredRoutes()\"\n [selectedRouteIds]=\"selectedRouteIds()\"\n [isLoading]=\"coolmapService.isLoading()\"\n (routeSelect)=\"toggleSelection($event)\">\n </lib-job-code>\n }\n\n <!-- FOR VIEWROUTE -->\n @if (activeSection() === 'ViewRoute') {\n <lib-view-route-list \n listMode=\"floating\" \n [routes]=\"activeFilteredRoutes()\"\n [selectedRouteIds]=\"selectedRouteIds()\"\n (routeSelect)=\"toggleSelection($event)\"\n (editRoute)=\"openEditModal($event)\"\n ></lib-view-route-list>\n }\n </div>\n @if (config.repository === 'coolmap') {\n <div class=\"status-bar\">\n <div class=\"stats-row\">\n <div class=\"stat-item active\" title=\"Active routes (assigned + in progress)\">\n <span class=\"stat-count\">{{ masterStats().Done }}</span>\n <span class=\"stat-label\">Done</span>\n </div>\n\n <div class=\"stat-item completed\" title=\"Completed tasks\">\n <span class=\"stat-count\">{{ masterStats().Incomplete }}</span>\n <span class=\"stat-label\">Incomplete</span>\n </div>\n\n <div class=\"stat-item declined\" title=\"Declined routes - needs attention\">\n <span class=\"stat-count\">{{ masterStats().Ongoing }}</span>\n <span class=\"stat-label\">Ongoing</span>\n </div>\n\n <div class=\"stat-item scheduled\" title=\"Scheduled jobs for today\">\n <span class=\"stat-count\">{{ masterStats().Open }}</span>\n <span class=\"stat-label\">Open</span>\n </div>\n </div>\n </div>\n }\n</div>\n<lib-job-route-list \n [initialRoutes]=\"viewRoutesList()\"\n [(modalOpen)]=\"showRouteList\"\n [selectedRouteIds]=\"modalPlottedIds()\"\n (routeSelect)=\"toggleModalRoute($event)\"\n (masterToggleEvent)=\"modalMasterToggle($event)\"\n [customerRepoDetails]=\"customerRepoDetails\"\n (shareRoute)=\"handleShareRoute($event)\"\n></lib-job-route-list>\n<lib-add-route \n [modalOpen]=\"addRouteModal\"\n (modalOpenChange)=\"onAddRouteModalChange($event)\"\n (routeSaved)=\"onRouteSaved($event)\"\n (routeDeleted)=\"onRouteDeleted($event)\"\n [customerRepoDetails]=\"customerRepoDetails\"\n [routeData]=\"selectedRouteForEdit()\"\n></lib-add-route>\n\n@if (showShareModal()) {\n <lib-share-route\n [openShareRouteDetails]=\"shareRouteData()\"\n [userDetails]=\"userDetails\"\n (closePopupEmit)=\"showShareModal.set(false)\" class=\"relative\"\n ></lib-share-route>\n}\n\n<ag-toast-container></ag-toast-container>\n", styles: [":host{display:block;width:100%;height:100%;min-height:400px}.center-area{height:100%;display:flex;flex-direction:column;overflow:hidden}.view-content{flex:1;position:relative;overflow:hidden;z-index:10}.full-view{position:absolute;inset:0}.map-container,.mapbox-container{width:100%;height:100%}.toolbar{align-items:center;justify-content:space-between;background:var(--bg-primary, white);border-bottom:1px solid var(--border-color, #e2e8f0);flex-shrink:0;gap:8px;position:relative;z-index:12}:host-context(.dark) .toolbar{background:var(--bg-dark-primary, #1e293b);border-color:var(--border-dark, #334155);box-shadow:0 1px 3px #0000004d}.toolbar-left{display:flex;align-items:center;gap:12px;flex-shrink:0}.toolbar-divider{width:1px;height:20px;background:var(--border-color, #e2e8f0);margin:0 2px;flex-shrink:0}:host-context(.dark) .toolbar-divider{background:#475569}.toolbar-right{display:flex;align-items:center;gap:10px;flex-shrink:0}.status-bar{display:flex;align-items:center;height:100%;padding:0 16px;background:var(--status-bar-bg, #1e293b);color:#fff;font-size:12px;gap:20px;flex-shrink:0;height:36px}.stats-row{display:flex;align-items:center;gap:20px}.stat-item{display:flex;align-items:center;gap:6px;cursor:default}.stat-count{font-size:15px;font-weight:700;line-height:1}.stat-item.active .stat-count{color:#60a5fa}.stat-item.completed .stat-count{color:#4ade80}.stat-item.declined .stat-count{color:#f87171}.stat-item.scheduled .stat-count{color:#a78bfa}.stat-item.pending .stat-count{color:#fbbf24}.route-list-wrapper{position:absolute;top:10px;left:10px;bottom:10px;width:380px;z-index:20;pointer-events:none;display:flex;flex-direction:column}@media (max-width: 1024px){.route-list-wrapper{width:320px}}.route-list-wrapper>*{pointer-events:auto}.list-loader{position:absolute;inset:0;background:#fff6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:100;border-radius:12px;border:1px solid rgba(255,255,255,.2);box-shadow:0 8px 32px #1f268712}:host-context(.dark) .list-loader{background:#0f172a66;border-color:#ffffff1a}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: JobCodeComponent, selector: "lib-job-code", inputs: ["listMode", "collapsible", "routes", "selectedRouteIds", "isLoading"], outputs: ["routeSelect"] }, { kind: "component", type: ViewRouteListComponent, selector: "lib-view-route-list", inputs: ["listMode", "collapsible", "routes", "selectedRouteIds"], outputs: ["routeSelect", "editRoute"] }, { kind: "component", type: JobRouteListComponent, selector: "lib-job-route-list", inputs: ["customerRepoDetails", "selectedRouteIds", "modalOpen", "initialRoutes"], outputs: ["modalOpenChange", "routeSelect", "masterToggleEvent", "shareRoute"] }, { kind: "component", type: AddRouteComponent, selector: "lib-add-route", inputs: ["modalOpen", "routeData", "customerRepoDetails"], outputs: ["modalOpenChange", "routeDeleted", "routeSaved"] }, { kind: "component", type: ShareRouteComponent, selector: "lib-share-route", inputs: ["openShareRouteDetails", "userDetails"], outputs: ["closePopupEmit"] }, { kind: "component", type: AgToastContainerComponent, selector: "ag-toast-container" }] });
2186
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: CoolmapComponent, isStandalone: true, selector: "lib-coolmap", inputs: { mobileMode: { classPropertyName: "mobileMode", publicName: "mobileMode", isSignal: false, isRequired: false, transformFunction: null }, activeSection: { classPropertyName: "activeSection", publicName: "activeSection", isSignal: true, isRequired: false, transformFunction: null }, customerRepoDetails: { classPropertyName: "customerRepoDetails", publicName: "customerRepoDetails", isSignal: false, isRequired: false, transformFunction: null }, userDetails: { classPropertyName: "userDetails", publicName: "userDetails", isSignal: false, isRequired: false, transformFunction: null }, darkMode: { classPropertyName: "darkMode", publicName: "darkMode", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onClick($event)" } }, viewQueries: [{ propertyName: "mapContainer", first: true, predicate: ["mapContainer"], descendants: true }, { propertyName: "searchContainer", first: true, predicate: ["searchContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"center-area\">\n <div [formGroup]=\"filterForm\" class=\"toolbar flex flex-col sm:flex-row md:h-[55px] h-auto py-2 px-2 gap-3 items-center\">\n <div class=\"toolbar-left flex items-center gap-3 flex-1\">\n @if (activeSection() === 'Jobcode') {\n <div class=\"relative w-full sm:w-auto group mt-[25px]\">\n <input\n type=\"text\"\n [value]=\"displayDate()\"\n readonly\n [disabled]=\"coolmapService.isLoading()\"\n (click)=\"dateInput.showPicker()\"\n class=\"w-full pl-3 pr-10 py-2 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer\"\n />\n <lucide-icon \n [img]=\"icons.Calendar\" \n [size]=\"18\" \n (click)=\"!coolmapService.isLoading() && dateInput.showPicker()\"\n [class.pointer-events-none]=\"coolmapService.isLoading()\"\n [class.opacity-50]=\"coolmapService.isLoading()\"\n class=\"absolute right-[6px] top-[5px] text-white-400 group-hover:text-brand-blue transition-colors cursor-pointer\"\n ></lucide-icon>\n <input\n #dateInput\n type=\"date\"\n [value]=\"dateValue()\"\n (change)=\"onDateChange($event)\"\n [disabled]=\"coolmapService.isLoading()\"\n class=\"absolute inset-0 w-0 h-0 opacity-0 pointer-events-none\"\n />\n </div>\n <span class=\"toolbar-divider hidden sm:flex h-6 w-[1px] bg-gray-200 dark:bg-slate-700\"></span>\n }\n <div #searchContainer class=\"relative items-center flex-1\">\n <lucide-icon [img]=\"icons.Search\" [size]=\"18\" class=\"absolute left-[0.55rem] top-[50%] -translate-y-1/2 text-gray-400\"></lucide-icon>\n <input\n type=\"text\"\n formControlName=\"search\"\n [attr.disabled]=\"coolmapService.isLoading() ? true : null\"\n placeholder=\"Search routes...\"\n class=\"w-full pl-10 pr-10 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-amber-500 focus:border-transparent text-sm disabled:opacity-50 disabled:cursor-not-allowed\"\n (focus)=\"onSearchFocus()\"\n />\n\n @if (filterForm.value.search) {\n <button (click)=\"filterForm.controls.search.setValue('')\" class=\"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600\">\n <lucide-icon [img]=\"icons.X\" [size]=\"16\"></lucide-icon>\n </button>\n }\n\n <!-- Autocomplete Dropdown -->\n @if (dropdownOpen() && filteredOptions().length > 0) {\n <div class=\"absolute z-70 left-0 right-0 top-full mt-1 max-h-60 overflow-y-auto bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-600 rounded shadow-lg\">\n @for (option of filteredOptions(); track option.value + option.type) {\n <div (click)=\"selectFilter(option)\" class=\"px-4 py-2 hover:bg-gray-100 dark:hover:bg-slate-700 cursor-pointer text-xs font-medium border-b border-gray-100 dark:border-slate-700 last:border-0 dark:text-white\">\n <span class=\"capitalize\">{{ option.type }}:</span>\n {{ option.label }}\n </div>\n }\n </div>\n }\n </div>\n\n @if (filters().length > 0) {\n <div class=\"flex flex-wrap gap-2 ml-2\">\n @for (filter of filters(); track filter.value + filter.type) {\n <div class=\"inline-flex items-center gap-1 px-2 py-1 rounded bg-slate-200 dark:bg-slate-700 text-gray-800 dark:text-gray-200 text-xs font-medium border border-gray-300 dark:border-slate-600\">\n <span class=\"capitalize opacity-80\">{{ filter.type }}:</span> {{ filter.name }}\n <button type=\"button\" (click)=\"removeFilter(filter)\" class=\"hover:opacity-75 transition-opacity ml-1\">\n <lucide-icon [img]=\"icons.X\" [size]=\"12\"></lucide-icon>\n </button>\n </div>\n }\n </div>\n }\n </div>\n <div class=\"toolbar-right\">\n @if (selectedRouteIds().length > 0) {\n <button\n type=\"button\"\n (click)=\"clearSelection()\"\n [disabled]=\"coolmapService.isLoading()\"\n class=\"inline-flex items-center justify-center gap-2 px-5 sm:px-6 py-2 bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors text-xs md:text-sm\"\n >\n Show all routes ({{ selectedRouteIds().length }})\n </button>\n }\n @if (activeSection() === 'ViewRoute') {\n <button\n type=\"button\"\n class=\"inline-flex items-center justify-center gap-2 px-5 sm:px-6 py-2 bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors text-xs md:text-sm\"\n [disabled]=\"coolmapService.isLoading()\"\n (click)=\"openAddRouteModal()\">\n <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n Add Route\n </button>\n }\n\n @if(activeSection() === 'Jobcode'){\n <button\n class=\"inline-flex items-center gap-2 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed relative group\"\n (click)=\"showRouteList = true\"\n [disabled]=\"coolmapService.isLoading()\">\n <lucide-icon [img]=\"icons.Route\" [size]=\"20\"></lucide-icon>\n <div\n class=\"absolute top-full right-0 mt-2 group-hover:block hidden bg-gray-800 dark:bg-white text-white dark:text-black text-[10px] rounded py-1 px-2 whitespace-nowrap\">\n Show Route List\n <div\n class=\"absolute -top-[8px] left-[60px] border-4 border-transparent border-b-gray-800 dark:border-b-white\">\n </div>\n </div>\n </button>}\n </div>\n </div>\n <div class=\"view-content\">\n <div class=\"full-view\">\n <div class=\"map-container\">\n <div class=\"mapbox-container\" #mapContainer></div>\n </div>\n </div>\n\n <!-- FOR JOBCODE -->\n @if (activeSection() === 'Jobcode') {\n <lib-job-code \n listMode=\"floating\" \n [routes]=\"activeFilteredRoutes()\"\n [selectedRouteIds]=\"selectedRouteIds()\"\n [isLoading]=\"coolmapService.isLoading()\"\n (routeSelect)=\"toggleSelection($event)\">\n </lib-job-code>\n }\n\n <!-- FOR VIEWROUTE -->\n @if (activeSection() === 'ViewRoute') {\n <lib-view-route-list \n listMode=\"floating\" \n [routes]=\"activeFilteredRoutes()\"\n [selectedRouteIds]=\"selectedRouteIds()\"\n (routeSelect)=\"toggleSelection($event)\"\n (editRoute)=\"openEditModal($event)\"\n ></lib-view-route-list>\n }\n </div>\n @if (config.repository === 'coolmap') {\n <div class=\"status-bar\">\n <div class=\"stats-row\">\n <div class=\"stat-item active\" title=\"Active routes (assigned + in progress)\">\n <span class=\"stat-count\">{{ masterStats().Done }}</span>\n <span class=\"stat-label\">Done</span>\n </div>\n\n <div class=\"stat-item completed\" title=\"Completed tasks\">\n <span class=\"stat-count\">{{ masterStats().Incomplete }}</span>\n <span class=\"stat-label\">Incomplete</span>\n </div>\n\n <div class=\"stat-item declined\" title=\"Declined routes - needs attention\">\n <span class=\"stat-count\">{{ masterStats().Ongoing }}</span>\n <span class=\"stat-label\">Ongoing</span>\n </div>\n\n <div class=\"stat-item scheduled\" title=\"Scheduled jobs for today\">\n <span class=\"stat-count\">{{ masterStats().Open }}</span>\n <span class=\"stat-label\">Open</span>\n </div>\n </div>\n </div>\n }\n</div>\n<lib-job-route-list \n [initialRoutes]=\"viewRoutesList()\"\n [(modalOpen)]=\"showRouteList\"\n [selectedRouteIds]=\"modalPlottedIds()\"\n (routeSelect)=\"toggleModalRoute($event)\"\n (masterToggleEvent)=\"modalMasterToggle($event)\"\n [customerRepoDetails]=\"customerRepoDetails\"\n (shareRoute)=\"handleShareRoute($event)\"\n></lib-job-route-list>\n<lib-add-route \n [modalOpen]=\"addRouteModal\"\n (modalOpenChange)=\"onAddRouteModalChange($event)\"\n (routeSaved)=\"onRouteSaved($event)\"\n (routeDeleted)=\"onRouteDeleted($event)\"\n [customerRepoDetails]=\"customerRepoDetails\"\n [routeData]=\"selectedRouteForEdit()\"\n></lib-add-route>\n\n@if (showShareModal()) {\n <lib-share-route\n [openShareRouteDetails]=\"shareRouteData()\"\n [userDetails]=\"userDetails\"\n (closePopupEmit)=\"showShareModal.set(false)\" class=\"relative\"\n ></lib-share-route>\n}\n\n<ag-toast-container></ag-toast-container>\n", styles: [":host{display:block;width:100%;height:100%;min-height:400px}.center-area{height:100%;display:flex;flex-direction:column;overflow:hidden}.view-content{flex:1;position:relative;overflow:hidden;z-index:10}.full-view{position:absolute;inset:0}.map-container,.mapbox-container{width:100%;height:100%}.toolbar{align-items:center;justify-content:space-between;background:var(--bg-primary, white);border-bottom:1px solid var(--border-color, #e2e8f0);flex-shrink:0;gap:8px;position:relative;z-index:12}:host-context(.dark) .toolbar{background:var(--bg-dark-primary, #1e293b);border-color:var(--border-dark, #334155);box-shadow:0 1px 3px #0000004d}.toolbar-left{display:flex;align-items:center;gap:12px;flex-shrink:0}.toolbar-divider{width:1px;height:20px;background:var(--border-color, #e2e8f0);margin:0 2px;flex-shrink:0}:host-context(.dark) .toolbar-divider{background:#475569}.toolbar-right{display:flex;align-items:center;gap:10px;flex-shrink:0}.status-bar{display:flex;align-items:center;height:100%;padding:0 16px;background:var(--status-bar-bg, #1e293b);color:#fff;font-size:12px;gap:20px;flex-shrink:0;height:36px}.stats-row{display:flex;align-items:center;gap:20px}.stat-item{display:flex;align-items:center;gap:6px;cursor:default}.stat-count{font-size:15px;font-weight:700;line-height:1}.stat-item.active .stat-count{color:#60a5fa}.stat-item.completed .stat-count{color:#4ade80}.stat-item.declined .stat-count{color:#f87171}.stat-item.scheduled .stat-count{color:#a78bfa}.stat-item.pending .stat-count{color:#fbbf24}.route-list-wrapper{position:absolute;top:10px;left:10px;bottom:10px;width:380px;z-index:20;pointer-events:none;display:flex;flex-direction:column}@media (max-width: 1024px){.route-list-wrapper{width:320px}}.route-list-wrapper>*{pointer-events:auto}.list-loader{position:absolute;inset:0;background:#fff6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:100;border-radius:12px;border:1px solid rgba(255,255,255,.2);box-shadow:0 8px 32px #1f268712}:host-context(.dark) .list-loader{background:#0f172a66;border-color:#ffffff1a}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: JobCodeComponent, selector: "lib-job-code", inputs: ["listMode", "collapsible", "routes", "selectedRouteIds", "isLoading"], outputs: ["routeSelect"] }, { kind: "component", type: ViewRouteListComponent, selector: "lib-view-route-list", inputs: ["listMode", "collapsible", "routes", "selectedRouteIds"], outputs: ["routeSelect", "editRoute"] }, { kind: "component", type: JobRouteListComponent, selector: "lib-job-route-list", inputs: ["customerRepoDetails", "selectedRouteIds", "modalOpen", "initialRoutes"], outputs: ["modalOpenChange", "routeSelect", "masterToggleEvent", "shareRoute"] }, { kind: "component", type: AddRouteComponent, selector: "lib-add-route", inputs: ["modalOpen", "routeData", "customerRepoDetails"], outputs: ["modalOpenChange", "routeDeleted", "routeSaved"] }, { kind: "component", type: ShareRouteComponent, selector: "lib-share-route", inputs: ["openShareRouteDetails", "userDetails"], outputs: ["closePopupEmit"] }, { kind: "component", type: AgToastContainerComponent, selector: "ag-toast-container" }] });
2187
2187
  }
2188
2188
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: CoolmapComponent, decorators: [{
2189
2189
  type: Component,
@@ -2197,7 +2197,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
2197
2197
  AddRouteComponent,
2198
2198
  ShareRouteComponent,
2199
2199
  AgToastContainerComponent,
2200
- ], template: "<div class=\"center-area\">\n <div [formGroup]=\"filterForm\" class=\"toolbar flex flex-col sm:flex-row md:h-[55px] h-auto py-2 px-2 gap-3 items-center\">\n <div class=\"toolbar-left flex items-center gap-3 flex-1\">\n @if (activeSection() === 'Jobcode') {\n <div class=\"relative w-full sm:w-auto group\">\n <input\n type=\"text\"\n [value]=\"displayDate()\"\n readonly\n [disabled]=\"coolmapService.isLoading()\"\n (click)=\"dateInput.showPicker()\"\n class=\"w-full lg:w-[200px] pl-3 pr-10 py-2 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer\"\n />\n <lucide-icon \n [img]=\"icons.Calendar\" \n [size]=\"18\" \n (click)=\"!coolmapService.isLoading() && dateInput.showPicker()\"\n [class.pointer-events-none]=\"coolmapService.isLoading()\"\n [class.opacity-50]=\"coolmapService.isLoading()\"\n class=\"absolute right-3 top-1/2 -translate-y-1/2 text-white-400 group-hover:text-brand-blue transition-colors cursor-pointer\"\n ></lucide-icon>\n <input\n #dateInput\n type=\"date\"\n [value]=\"dateValue()\"\n (change)=\"onDateChange($event)\"\n [disabled]=\"coolmapService.isLoading()\"\n class=\"absolute inset-0 w-0 h-0 opacity-0 pointer-events-none\"\n />\n </div>\n <span class=\"toolbar-divider hidden sm:flex h-6 w-[1px] bg-gray-200 dark:bg-slate-700\"></span>\n }\n <div #searchContainer class=\"relative items-center flex-1\">\n <lucide-icon [img]=\"icons.Search\" [size]=\"18\" class=\"absolute left-[0.55rem] top-[50%] -translate-y-1/2 text-gray-400\"></lucide-icon>\n <input\n type=\"text\"\n formControlName=\"search\"\n [attr.disabled]=\"coolmapService.isLoading() ? true : null\"\n placeholder=\"Search routes...\"\n class=\"w-full pl-10 pr-10 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-amber-500 focus:border-transparent text-sm disabled:opacity-50 disabled:cursor-not-allowed\"\n (focus)=\"onSearchFocus()\"\n />\n\n @if (filterForm.value.search) {\n <button (click)=\"filterForm.controls.search.setValue('')\" class=\"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600\">\n <lucide-icon [img]=\"icons.X\" [size]=\"16\"></lucide-icon>\n </button>\n }\n\n <!-- Autocomplete Dropdown -->\n @if (dropdownOpen() && filteredOptions().length > 0) {\n <div class=\"absolute z-70 left-0 right-0 top-full mt-1 max-h-60 overflow-y-auto bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-600 rounded shadow-lg\">\n @for (option of filteredOptions(); track option.value + option.type) {\n <div (click)=\"selectFilter(option)\" class=\"px-4 py-2 hover:bg-gray-100 dark:hover:bg-slate-700 cursor-pointer text-xs font-medium border-b border-gray-100 dark:border-slate-700 last:border-0 dark:text-white\">\n <span class=\"capitalize\">{{ option.type }}:</span>\n {{ option.label }}\n </div>\n }\n </div>\n }\n </div>\n\n @if (filters().length > 0) {\n <div class=\"flex flex-wrap gap-2 ml-2\">\n @for (filter of filters(); track filter.value + filter.type) {\n <div class=\"inline-flex items-center gap-1 px-2 py-1 rounded bg-slate-200 dark:bg-slate-700 text-gray-800 dark:text-gray-200 text-xs font-medium border border-gray-300 dark:border-slate-600\">\n <span class=\"capitalize opacity-80\">{{ filter.type }}:</span> {{ filter.name }}\n <button type=\"button\" (click)=\"removeFilter(filter)\" class=\"hover:opacity-75 transition-opacity ml-1\">\n <lucide-icon [img]=\"icons.X\" [size]=\"12\"></lucide-icon>\n </button>\n </div>\n }\n </div>\n }\n </div>\n <div class=\"toolbar-right\">\n @if (selectedRouteIds().length > 0) {\n <button\n type=\"button\"\n (click)=\"clearSelection()\"\n [disabled]=\"coolmapService.isLoading()\"\n class=\"inline-flex items-center justify-center gap-2 px-5 sm:px-6 py-2 bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors text-xs md:text-sm\"\n >\n Show all routes ({{ selectedRouteIds().length }})\n </button>\n }\n @if (activeSection() === 'ViewRoute') {\n <button\n type=\"button\"\n class=\"inline-flex items-center justify-center gap-2 px-5 sm:px-6 py-2 bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors text-xs md:text-sm\"\n [disabled]=\"coolmapService.isLoading()\"\n (click)=\"openAddRouteModal()\">\n <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n Add Route\n </button>\n }\n\n @if(activeSection() === 'Jobcode'){\n <button\n class=\"inline-flex items-center gap-2 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed relative group\"\n (click)=\"showRouteList = true\"\n [disabled]=\"coolmapService.isLoading()\">\n <lucide-icon [img]=\"icons.Route\" [size]=\"20\"></lucide-icon>\n <div\n class=\"absolute top-full right-0 mt-2 group-hover:block hidden bg-gray-800 dark:bg-white text-white dark:text-black text-[10px] rounded py-1 px-2 whitespace-nowrap\">\n Show Route List\n <div\n class=\"absolute -top-[8px] left-[60px] border-4 border-transparent border-b-gray-800 dark:border-b-white\">\n </div>\n </div>\n </button>}\n </div>\n </div>\n <div class=\"view-content\">\n <div class=\"full-view\">\n <div class=\"map-container\">\n <div class=\"mapbox-container\" #mapContainer></div>\n </div>\n </div>\n\n <!-- FOR JOBCODE -->\n @if (activeSection() === 'Jobcode') {\n <lib-job-code \n listMode=\"floating\" \n [routes]=\"activeFilteredRoutes()\"\n [selectedRouteIds]=\"selectedRouteIds()\"\n [isLoading]=\"coolmapService.isLoading()\"\n (routeSelect)=\"toggleSelection($event)\">\n </lib-job-code>\n }\n\n <!-- FOR VIEWROUTE -->\n @if (activeSection() === 'ViewRoute') {\n <lib-view-route-list \n listMode=\"floating\" \n [routes]=\"activeFilteredRoutes()\"\n [selectedRouteIds]=\"selectedRouteIds()\"\n (routeSelect)=\"toggleSelection($event)\"\n (editRoute)=\"openEditModal($event)\"\n ></lib-view-route-list>\n }\n </div>\n @if (config.repository === 'coolmap') {\n <div class=\"status-bar\">\n <div class=\"stats-row\">\n <div class=\"stat-item active\" title=\"Active routes (assigned + in progress)\">\n <span class=\"stat-count\">{{ masterStats().Done }}</span>\n <span class=\"stat-label\">Done</span>\n </div>\n\n <div class=\"stat-item completed\" title=\"Completed tasks\">\n <span class=\"stat-count\">{{ masterStats().Incomplete }}</span>\n <span class=\"stat-label\">Incomplete</span>\n </div>\n\n <div class=\"stat-item declined\" title=\"Declined routes - needs attention\">\n <span class=\"stat-count\">{{ masterStats().Ongoing }}</span>\n <span class=\"stat-label\">Ongoing</span>\n </div>\n\n <div class=\"stat-item scheduled\" title=\"Scheduled jobs for today\">\n <span class=\"stat-count\">{{ masterStats().Open }}</span>\n <span class=\"stat-label\">Open</span>\n </div>\n </div>\n </div>\n }\n</div>\n<lib-job-route-list \n [initialRoutes]=\"viewRoutesList()\"\n [(modalOpen)]=\"showRouteList\"\n [selectedRouteIds]=\"modalPlottedIds()\"\n (routeSelect)=\"toggleModalRoute($event)\"\n (masterToggleEvent)=\"modalMasterToggle($event)\"\n [customerRepoDetails]=\"customerRepoDetails\"\n (shareRoute)=\"handleShareRoute($event)\"\n></lib-job-route-list>\n<lib-add-route \n [modalOpen]=\"addRouteModal\"\n (modalOpenChange)=\"onAddRouteModalChange($event)\"\n (routeSaved)=\"onRouteSaved($event)\"\n (routeDeleted)=\"onRouteDeleted($event)\"\n [customerRepoDetails]=\"customerRepoDetails\"\n [routeData]=\"selectedRouteForEdit()\"\n></lib-add-route>\n\n@if (showShareModal()) {\n <lib-share-route\n [openShareRouteDetails]=\"shareRouteData()\"\n [userDetails]=\"userDetails\"\n (closePopupEmit)=\"showShareModal.set(false)\" class=\"relative\"\n ></lib-share-route>\n}\n\n<ag-toast-container></ag-toast-container>\n", styles: [":host{display:block;width:100%;height:100%;min-height:400px}.center-area{height:100%;display:flex;flex-direction:column;overflow:hidden}.view-content{flex:1;position:relative;overflow:hidden;z-index:10}.full-view{position:absolute;inset:0}.map-container,.mapbox-container{width:100%;height:100%}.toolbar{align-items:center;justify-content:space-between;background:var(--bg-primary, white);border-bottom:1px solid var(--border-color, #e2e8f0);flex-shrink:0;gap:8px;position:relative;z-index:12}:host-context(.dark) .toolbar{background:var(--bg-dark-primary, #1e293b);border-color:var(--border-dark, #334155);box-shadow:0 1px 3px #0000004d}.toolbar-left{display:flex;align-items:center;gap:12px;flex-shrink:0}.toolbar-divider{width:1px;height:20px;background:var(--border-color, #e2e8f0);margin:0 2px;flex-shrink:0}:host-context(.dark) .toolbar-divider{background:#475569}.toolbar-right{display:flex;align-items:center;gap:10px;flex-shrink:0}.status-bar{display:flex;align-items:center;height:100%;padding:0 16px;background:var(--status-bar-bg, #1e293b);color:#fff;font-size:12px;gap:20px;flex-shrink:0;height:36px}.stats-row{display:flex;align-items:center;gap:20px}.stat-item{display:flex;align-items:center;gap:6px;cursor:default}.stat-count{font-size:15px;font-weight:700;line-height:1}.stat-item.active .stat-count{color:#60a5fa}.stat-item.completed .stat-count{color:#4ade80}.stat-item.declined .stat-count{color:#f87171}.stat-item.scheduled .stat-count{color:#a78bfa}.stat-item.pending .stat-count{color:#fbbf24}.route-list-wrapper{position:absolute;top:10px;left:10px;bottom:10px;width:380px;z-index:20;pointer-events:none;display:flex;flex-direction:column}@media (max-width: 1024px){.route-list-wrapper{width:320px}}.route-list-wrapper>*{pointer-events:auto}.list-loader{position:absolute;inset:0;background:#fff6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:100;border-radius:12px;border:1px solid rgba(255,255,255,.2);box-shadow:0 8px 32px #1f268712}:host-context(.dark) .list-loader{background:#0f172a66;border-color:#ffffff1a}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
2200
+ ], template: "<div class=\"center-area\">\n <div [formGroup]=\"filterForm\" class=\"toolbar flex flex-col sm:flex-row md:h-[55px] h-auto py-2 px-2 gap-3 items-center\">\n <div class=\"toolbar-left flex items-center gap-3 flex-1\">\n @if (activeSection() === 'Jobcode') {\n <div class=\"relative w-full sm:w-auto group mt-[25px]\">\n <input\n type=\"text\"\n [value]=\"displayDate()\"\n readonly\n [disabled]=\"coolmapService.isLoading()\"\n (click)=\"dateInput.showPicker()\"\n class=\"w-full pl-3 pr-10 py-2 rounded-lg border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-blue focus:border-transparent text-sm disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer\"\n />\n <lucide-icon \n [img]=\"icons.Calendar\" \n [size]=\"18\" \n (click)=\"!coolmapService.isLoading() && dateInput.showPicker()\"\n [class.pointer-events-none]=\"coolmapService.isLoading()\"\n [class.opacity-50]=\"coolmapService.isLoading()\"\n class=\"absolute right-[6px] top-[5px] text-white-400 group-hover:text-brand-blue transition-colors cursor-pointer\"\n ></lucide-icon>\n <input\n #dateInput\n type=\"date\"\n [value]=\"dateValue()\"\n (change)=\"onDateChange($event)\"\n [disabled]=\"coolmapService.isLoading()\"\n class=\"absolute inset-0 w-0 h-0 opacity-0 pointer-events-none\"\n />\n </div>\n <span class=\"toolbar-divider hidden sm:flex h-6 w-[1px] bg-gray-200 dark:bg-slate-700\"></span>\n }\n <div #searchContainer class=\"relative items-center flex-1\">\n <lucide-icon [img]=\"icons.Search\" [size]=\"18\" class=\"absolute left-[0.55rem] top-[50%] -translate-y-1/2 text-gray-400\"></lucide-icon>\n <input\n type=\"text\"\n formControlName=\"search\"\n [attr.disabled]=\"coolmapService.isLoading() ? true : null\"\n placeholder=\"Search routes...\"\n class=\"w-full pl-10 pr-10 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-amber-500 focus:border-transparent text-sm disabled:opacity-50 disabled:cursor-not-allowed\"\n (focus)=\"onSearchFocus()\"\n />\n\n @if (filterForm.value.search) {\n <button (click)=\"filterForm.controls.search.setValue('')\" class=\"absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600\">\n <lucide-icon [img]=\"icons.X\" [size]=\"16\"></lucide-icon>\n </button>\n }\n\n <!-- Autocomplete Dropdown -->\n @if (dropdownOpen() && filteredOptions().length > 0) {\n <div class=\"absolute z-70 left-0 right-0 top-full mt-1 max-h-60 overflow-y-auto bg-white dark:bg-slate-800 border border-gray-200 dark:border-slate-600 rounded shadow-lg\">\n @for (option of filteredOptions(); track option.value + option.type) {\n <div (click)=\"selectFilter(option)\" class=\"px-4 py-2 hover:bg-gray-100 dark:hover:bg-slate-700 cursor-pointer text-xs font-medium border-b border-gray-100 dark:border-slate-700 last:border-0 dark:text-white\">\n <span class=\"capitalize\">{{ option.type }}:</span>\n {{ option.label }}\n </div>\n }\n </div>\n }\n </div>\n\n @if (filters().length > 0) {\n <div class=\"flex flex-wrap gap-2 ml-2\">\n @for (filter of filters(); track filter.value + filter.type) {\n <div class=\"inline-flex items-center gap-1 px-2 py-1 rounded bg-slate-200 dark:bg-slate-700 text-gray-800 dark:text-gray-200 text-xs font-medium border border-gray-300 dark:border-slate-600\">\n <span class=\"capitalize opacity-80\">{{ filter.type }}:</span> {{ filter.name }}\n <button type=\"button\" (click)=\"removeFilter(filter)\" class=\"hover:opacity-75 transition-opacity ml-1\">\n <lucide-icon [img]=\"icons.X\" [size]=\"12\"></lucide-icon>\n </button>\n </div>\n }\n </div>\n }\n </div>\n <div class=\"toolbar-right\">\n @if (selectedRouteIds().length > 0) {\n <button\n type=\"button\"\n (click)=\"clearSelection()\"\n [disabled]=\"coolmapService.isLoading()\"\n class=\"inline-flex items-center justify-center gap-2 px-5 sm:px-6 py-2 bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors text-xs md:text-sm\"\n >\n Show all routes ({{ selectedRouteIds().length }})\n </button>\n }\n @if (activeSection() === 'ViewRoute') {\n <button\n type=\"button\"\n class=\"inline-flex items-center justify-center gap-2 px-5 sm:px-6 py-2 bg-amber-500 hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors text-xs md:text-sm\"\n [disabled]=\"coolmapService.isLoading()\"\n (click)=\"openAddRouteModal()\">\n <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n Add Route\n </button>\n }\n\n @if(activeSection() === 'Jobcode'){\n <button\n class=\"inline-flex items-center gap-2 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed relative group\"\n (click)=\"showRouteList = true\"\n [disabled]=\"coolmapService.isLoading()\">\n <lucide-icon [img]=\"icons.Route\" [size]=\"20\"></lucide-icon>\n <div\n class=\"absolute top-full right-0 mt-2 group-hover:block hidden bg-gray-800 dark:bg-white text-white dark:text-black text-[10px] rounded py-1 px-2 whitespace-nowrap\">\n Show Route List\n <div\n class=\"absolute -top-[8px] left-[60px] border-4 border-transparent border-b-gray-800 dark:border-b-white\">\n </div>\n </div>\n </button>}\n </div>\n </div>\n <div class=\"view-content\">\n <div class=\"full-view\">\n <div class=\"map-container\">\n <div class=\"mapbox-container\" #mapContainer></div>\n </div>\n </div>\n\n <!-- FOR JOBCODE -->\n @if (activeSection() === 'Jobcode') {\n <lib-job-code \n listMode=\"floating\" \n [routes]=\"activeFilteredRoutes()\"\n [selectedRouteIds]=\"selectedRouteIds()\"\n [isLoading]=\"coolmapService.isLoading()\"\n (routeSelect)=\"toggleSelection($event)\">\n </lib-job-code>\n }\n\n <!-- FOR VIEWROUTE -->\n @if (activeSection() === 'ViewRoute') {\n <lib-view-route-list \n listMode=\"floating\" \n [routes]=\"activeFilteredRoutes()\"\n [selectedRouteIds]=\"selectedRouteIds()\"\n (routeSelect)=\"toggleSelection($event)\"\n (editRoute)=\"openEditModal($event)\"\n ></lib-view-route-list>\n }\n </div>\n @if (config.repository === 'coolmap') {\n <div class=\"status-bar\">\n <div class=\"stats-row\">\n <div class=\"stat-item active\" title=\"Active routes (assigned + in progress)\">\n <span class=\"stat-count\">{{ masterStats().Done }}</span>\n <span class=\"stat-label\">Done</span>\n </div>\n\n <div class=\"stat-item completed\" title=\"Completed tasks\">\n <span class=\"stat-count\">{{ masterStats().Incomplete }}</span>\n <span class=\"stat-label\">Incomplete</span>\n </div>\n\n <div class=\"stat-item declined\" title=\"Declined routes - needs attention\">\n <span class=\"stat-count\">{{ masterStats().Ongoing }}</span>\n <span class=\"stat-label\">Ongoing</span>\n </div>\n\n <div class=\"stat-item scheduled\" title=\"Scheduled jobs for today\">\n <span class=\"stat-count\">{{ masterStats().Open }}</span>\n <span class=\"stat-label\">Open</span>\n </div>\n </div>\n </div>\n }\n</div>\n<lib-job-route-list \n [initialRoutes]=\"viewRoutesList()\"\n [(modalOpen)]=\"showRouteList\"\n [selectedRouteIds]=\"modalPlottedIds()\"\n (routeSelect)=\"toggleModalRoute($event)\"\n (masterToggleEvent)=\"modalMasterToggle($event)\"\n [customerRepoDetails]=\"customerRepoDetails\"\n (shareRoute)=\"handleShareRoute($event)\"\n></lib-job-route-list>\n<lib-add-route \n [modalOpen]=\"addRouteModal\"\n (modalOpenChange)=\"onAddRouteModalChange($event)\"\n (routeSaved)=\"onRouteSaved($event)\"\n (routeDeleted)=\"onRouteDeleted($event)\"\n [customerRepoDetails]=\"customerRepoDetails\"\n [routeData]=\"selectedRouteForEdit()\"\n></lib-add-route>\n\n@if (showShareModal()) {\n <lib-share-route\n [openShareRouteDetails]=\"shareRouteData()\"\n [userDetails]=\"userDetails\"\n (closePopupEmit)=\"showShareModal.set(false)\" class=\"relative\"\n ></lib-share-route>\n}\n\n<ag-toast-container></ag-toast-container>\n", styles: [":host{display:block;width:100%;height:100%;min-height:400px}.center-area{height:100%;display:flex;flex-direction:column;overflow:hidden}.view-content{flex:1;position:relative;overflow:hidden;z-index:10}.full-view{position:absolute;inset:0}.map-container,.mapbox-container{width:100%;height:100%}.toolbar{align-items:center;justify-content:space-between;background:var(--bg-primary, white);border-bottom:1px solid var(--border-color, #e2e8f0);flex-shrink:0;gap:8px;position:relative;z-index:12}:host-context(.dark) .toolbar{background:var(--bg-dark-primary, #1e293b);border-color:var(--border-dark, #334155);box-shadow:0 1px 3px #0000004d}.toolbar-left{display:flex;align-items:center;gap:12px;flex-shrink:0}.toolbar-divider{width:1px;height:20px;background:var(--border-color, #e2e8f0);margin:0 2px;flex-shrink:0}:host-context(.dark) .toolbar-divider{background:#475569}.toolbar-right{display:flex;align-items:center;gap:10px;flex-shrink:0}.status-bar{display:flex;align-items:center;height:100%;padding:0 16px;background:var(--status-bar-bg, #1e293b);color:#fff;font-size:12px;gap:20px;flex-shrink:0;height:36px}.stats-row{display:flex;align-items:center;gap:20px}.stat-item{display:flex;align-items:center;gap:6px;cursor:default}.stat-count{font-size:15px;font-weight:700;line-height:1}.stat-item.active .stat-count{color:#60a5fa}.stat-item.completed .stat-count{color:#4ade80}.stat-item.declined .stat-count{color:#f87171}.stat-item.scheduled .stat-count{color:#a78bfa}.stat-item.pending .stat-count{color:#fbbf24}.route-list-wrapper{position:absolute;top:10px;left:10px;bottom:10px;width:380px;z-index:20;pointer-events:none;display:flex;flex-direction:column}@media (max-width: 1024px){.route-list-wrapper{width:320px}}.route-list-wrapper>*{pointer-events:auto}.list-loader{position:absolute;inset:0;background:#fff6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:100;border-radius:12px;border:1px solid rgba(255,255,255,.2);box-shadow:0 8px 32px #1f268712}:host-context(.dark) .list-loader{background:#0f172a66;border-color:#ffffff1a}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
2201
2201
  }], ctorParameters: () => [], propDecorators: { mobileMode: [{
2202
2202
  type: Input
2203
2203
  }], activeSection: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeSection", required: false }] }], customerRepoDetails: [{