
{"id":97876,"date":"2026-10-24T21:36:54","date_gmt":"2026-10-24T19:36:54","guid":{"rendered":"https:\/\/albanianbus.com\/wordpress\/?page_id=97876"},"modified":"2026-10-24T23:13:46","modified_gmt":"2026-10-24T21:13:46","slug":"transfers-staff-calendar","status":"publish","type":"page","link":"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/","title":{"rendered":"AlbanianBus Transfers Staff Calendar"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"97876\" class=\"elementor elementor-97876\">\n\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-ab0c1001 e-con-full e-con\" data-id=\"ab0c1001\" data-element_type=\"container\" data-settings=\"{&quot;content_width&quot;:&quot;full&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ab0c1002 elementor-widget elementor-widget-html\" data-id=\"ab0c1002\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<meta name=\"robots\" content=\"noindex,nofollow\"><iframe id=\"ab-staff-calendar\" title=\"AlbanianBus staff transfers calendar\" style=\"display:block;width:100%;height:100dvh;min-height:600px;border:0\" srcdoc=\"&lt;!doctype html&gt;\n&lt;html lang=&quot;en&quot;&gt;&lt;head&gt;&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;&gt;&lt;meta name=&quot;theme-color&quot; content=&quot;#0b2544&quot;&gt;&lt;title&gt;AlbanianBus | Transfers Admin&lt;\/title&gt;\n&lt;style&gt;\n:root{--navy:#0c294c;--navy2:#174570;--sky:#eff5fb;--paper:#fff;--ink:#1d2e43;--muted:#718195;--line:#e3eaf2;--orange:#f0a844;--mint:#2c9a78;--blue:#377bc2}\n*{box-sizing:border-box}html{font-family:system-ui,-apple-system,Segoe UI,Arial,sans-serif;background:#f5f8fc;color:var(--ink)}body{margin:0}button,input,select,textarea{font:inherit}button{cursor:pointer}button:disabled{opacity:.5;cursor:wait}.hide{display:none!important}a{color:var(--blue)}\n.top{background:var(--navy);color:white;padding:17px max(20px,calc((100vw - 1150px)\/2));display:flex;align-items:center;justify-content:space-between;gap:12px}.logo{font-weight:850;letter-spacing:.2px;font-size:21px}.logo span{color:#8dd8e8}.sub{font-size:11px;color:#a6b9cf;margin-top:2px;font-weight:500}.shell{max-width:1150px;margin:auto;padding:22px 20px 110px}\n.btn{background:var(--navy);color:white;border:0;border-radius:12px;padding:11px 16px;font-weight:700}.btn.secondary{color:var(--ink);background:#edf2f8}.btn.outline{border:1px solid #cad6e3;background:white;color:var(--navy)}.btn.negative{background:#b0393c}.iconbtn{background:none;border:0;padding:8px;color:inherit}.tiny{font-size:12px;color:var(--muted)}.card{border:1px solid var(--line);background:white;border-radius:18px;padding:18px;box-shadow:0 5px 18px rgba(24,64,113,.04)}.pill{border-radius:20px;font-size:11px;letter-spacing:.15px;padding:5px 10px;background:#f2f5f9;color:#51657d;display:inline-block;font-weight:750}.pill.confirmed,.pill.paid{background:#def4ea;color:#177758}.pill.prebooked,.pill.pending{background:#fff1d7;color:#9d6014}.pill.cancelled{background:#fbe4e4;color:#ab4545}.pill.test{background:#e9e5fc;color:#6554a5}\n.login{max-width:420px;margin:9vh auto}.login h1{margin:10px 0 6px;font-size:25px}.login p{color:var(--muted);line-height:1.45}.field{display:flex;flex-direction:column;gap:6px;font-size:12px;font-weight:750;color:#435971;margin-bottom:13px}input,select,textarea{width:100%;border:1px solid #cbd7e5;background:white;border-radius:10px;padding:12px;color:var(--ink);font-size:15px;outline:none}input:focus,select:focus,textarea:focus{border-color:#2e83cf;box-shadow:0 0 0 2px #ddebfc}.msg{background:#f0f5ff;color:#385c90;padding:10px;border-radius:10px;font-size:13px;margin:12px 0}.err{background:#fff0ec;color:#9c4242}\n.headrow{display:flex;align-items:center;justify-content:space-between;gap:13px;flex-wrap:wrap;margin-bottom:18px}.headrow h1{font-size:27px;letter-spacing:-.8px;margin:0}.toolbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.summary{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:18px}.stat{padding:16px;background:white;border:1px solid var(--line);border-radius:15px}.stat .value{font-size:27px;font-weight:850;margin-top:6px}.stat .label{color:var(--muted);font-size:12px;font-weight:650}.filters{display:flex;gap:10px;align-items:center;justify-content:space-between;flex-wrap:wrap;margin-bottom:16px}.search{width:min(320px,100%);padding:10px 12px}.tabs{display:flex;gap:5px;padding:4px;border:1px solid var(--line);border-radius:12px;background:white}.tabs button{padding:9px 15px;background:transparent;border:0;border-radius:9px;color:var(--muted);font-weight:750}.tabs button.active{background:var(--navy);color:#fff}\n.monthhead{display:flex;align-items:center;justify-content:space-between;margin:0 0 14px}.monthhead h2{margin:0;font-size:21px}.monthhead .btn{padding:8px 12px}.calgrid{display:grid;grid-template-columns:repeat(7,1fr);gap:6px}.dayname{text-align:center;font-size:11px;color:var(--muted);font-weight:750;padding:8px 0}.day{height:92px;text-align:left;border:1px solid var(--line);background:white;border-radius:12px;padding:10px 8px;display:flex;flex-direction:column;gap:6px}.day.outside{opacity:.35}.day.today{outline:2px solid var(--blue)}.day.selected{background:#edf6ff;border-color:var(--blue)}.day .number{font-size:13px;font-weight:800}.day .counter{font-size:11px;color:#236393;background:#e3f0ff;border-radius:14px;padding:3px 7px;align-self:start}.dots{font-size:12px;color:var(--mint);letter-spacing:2px}.records{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-top:16px}.booking{border:1px solid var(--line);background:white;border-radius:14px;padding:16px;text-align:left;display:flex;gap:13px;align-items:flex-start;transition:border-color .1s}.booking:hover{border-color:var(--blue)}.datebadge{background:#f0f6fc;border-radius:12px;min-width:55px;text-align:center;padding:8px;color:var(--navy)}.datebadge .big{display:block;font-size:23px;font-weight:850}.datebadge .mon{font-size:11px;letter-spacing:.5px;text-transform:uppercase}.detail{flex:1;min-width:0}.detail .name{font-weight:850;font-size:15px;margin:0 0 4px}.detail .route{font-size:13px;color:#53677c;margin-bottom:7px}.detail .meta{color:#8495a8;font-size:12px}.stack{display:flex;gap:5px;flex-wrap:wrap}.empty{padding:30px;text-align:center;color:var(--muted);border:1px dashed #bfcbda;border-radius:16px;margin-top:15px}.bottomnav{display:none}\n.overlay{position:fixed;inset:0;background:#101e30aa;z-index:9;display:flex;justify-content:center;align-items:center;padding:20px}.dialog{background:white;border-radius:20px;max-width:640px;width:100%;max-height:92vh;overflow:auto;padding:22px;box-shadow:0 20px 60px #101e3055}.dialog .title{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 14px}.dialog h2{margin:0;font-size:21px}.kv{display:grid;grid-template-columns:120px 1fr;gap:9px;font-size:13px;padding:5px 0}.kv b{color:#698098}.flex{display:flex;gap:9px;align-items:center;flex-wrap:wrap}.formgrid{display:grid;grid-template-columns:1fr 1fr;gap:0 11px}.divider{height:1px;background:var(--line);margin:16px 0}.banner{background:#eef6ff;border:1px solid #d5e6fa;border-radius:12px;padding:11px 12px;font-size:12px;color:#365c87;margin-bottom:14px}.formActions{display:flex;align-items:center;justify-content:flex-end;gap:8px;margin-top:12px}.toggle{font-size:12px;color:#65758a;display:flex;gap:6px;align-items:center}.toggle input{width:auto}.smalltitle{font-size:14px;font-weight:850;margin:16px 0 10px}.sectionlabel{margin-top:20px;font-size:13px;color:#6c7d92;font-weight:750}\n@media(max-width:760px){.top{padding:15px 16px}.shell{padding:16px 12px 102px}.summary{grid-template-columns:repeat(2,1fr);gap:8px}.stat{padding:13px}.stat .value{font-size:23px}.headrow h1{font-size:22px}.toolbar{width:100%;justify-content:space-between}.records{grid-template-columns:1fr}.day{height:66px;padding:7px 4px;border-radius:9px}.day .number{font-size:12px}.day .counter{font-size:10px;padding:2px 5px}.dots{display:none}.calgrid{gap:3px}.card{padding:13px}.dialog{padding:17px;max-height:96vh;border-radius:18px 18px 0 0}.overlay{padding:0;align-items:flex-end}.formgrid{grid-template-columns:1fr}.filters .search{flex:1}.bottomnav{display:flex;position:fixed;bottom:0;left:0;right:0;padding:9px 12px calc(9px + env(safe-area-inset-bottom));background:white;border-top:1px solid var(--line);z-index:4;gap:6px;justify-content:space-evenly}.bottomnav button{border:0;background:transparent;padding:6px 14px;color:#6b819a;font-size:12px;font-weight:750;border-radius:10px}.bottomnav button.active{background:#e8f1fb;color:var(--navy)}.bottomnav .symbol{display:block;font-size:20px}.hideOnMobile{display:none!important}.kv{grid-template-columns:110px 1fr}}\n@media print{.top,.bottomnav,.headrow,.filters,.summary,.monthhead,.calgrid,#recordSection,#dialogControls{display:none!important}.overlay{position:static;background:none;display:block;padding:0}.dialog{box-shadow:none;max-width:100%;max-height:none;overflow:visible}.hidePrint{display:none!important}body{background:white}}\n&lt;\/style&gt;&lt;meta name=&quot;robots&quot; content=&quot;noindex,nofollow&quot;&gt;&lt;style&gt;:root{--navy:#703da5;--navy2:#4c2675;--sky:#f5f2fa;--ink:#291e3d;--line:#e1d6ec;--blue:#703da5}.pill.overlap{background:#fff0d8;color:#8f5200}.overlap-note{font-size:12px;color:#8f5200;margin-top:8px}&lt;\/style&gt;&lt;style id=&quot;ab-calendar-mobile-controls&quot;&gt;\n.status-filters{display:grid;grid-template-columns:repeat(3,minmax(0,1fr)) auto;gap:10px;align-items:end;margin:0 0 16px}\n.status-filters label{display:grid;gap:5px;font-size:12px;font-weight:700;color:var(--muted);min-width:0}\n.status-filters select{min-width:0;font-size:14px;padding:10px}\n@media(max-width:760px){\n .status-filters{grid-template-columns:1fr 1fr;gap:8px}\n .status-filters label:last-of-type{grid-column:1\/-1}\n .status-filters #clearFilters{grid-column:1\/-1;padding:8px;font-size:12px;min-height:38px}\n .bottomnav{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;padding:5px 8px calc(5px + env(safe-area-inset-bottom));justify-content:normal}\n .bottomnav button{min-width:0;width:100%;min-height:44px;padding:4px 6px;font-size:11px;line-height:1.2;border-radius:8px}\n .bottomnav .symbol{font-size:17px;line-height:1.2;margin-bottom:2px}\n .formActions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;align-items:stretch}\n .formActions .btn{min-width:0;min-height:42px;padding:8px 6px;font-size:12px;line-height:1.3;white-space:normal;overflow-wrap:anywhere}\n .dialog .title h2{min-width:0;overflow-wrap:anywhere}\n}\n&lt;\/style&gt;&lt;style&gt;.pill.qr-validated{background:#d8f3e3;color:#12683c}.pill.qr-pending{background:#edf0f5;color:#65758a}.booking:has(.qr-validated){border-left:5px solid #239b5c}#reportPreview{font-size:12px;overflow:auto;margin:14px 0;max-height:45vh}#reportPreview table{border-collapse:collapse;width:100%;min-width:620px}#reportPreview td,#reportPreview th{padding:7px;border:1px solid #e1d6ec;text-align:left;vertical-align:top}#reportPreview .overlap-row{background:#fff0d8}@media(max-width:760px){.toolbar .btn{font-size:12px;padding:9px 7px;min-width:0}.status-filters{grid-template-columns:1fr 1fr}.status-filters label:last-of-type{grid-column:auto}}&lt;\/style&gt;&lt;style&gt;#cashPreview{overflow:auto;max-height:45vh;font-size:12px;margin:14px 0}#cashPreview table{width:100%;border-collapse:collapse;min-width:420px}#cashPreview td,#cashPreview th{padding:7px;border:1px solid #e1d6ec;text-align:left}.toolbar{justify-content:flex-start!important}.toolbar .btn{white-space:normal}&lt;\/style&gt;&lt;\/head&gt;\n&lt;body&gt;\n&lt;header class=&quot;top&quot;&gt;&lt;div&gt;&lt;div class=&quot;logo&quot;&gt;ALBANIAN&lt;span&gt;BUS&lt;\/span&gt; &lt;span style=&quot;font-weight:450;color:#c9d3e1&quot;&gt;\/ ADMIN&lt;\/span&gt;&lt;\/div&gt;&lt;div class=&quot;sub&quot;&gt;PRIVATE TRANSFERS \u00b7 OPERATIONS&lt;\/div&gt;&lt;\/div&gt;&lt;div class=&quot;flex&quot;&gt;&lt;span id=&quot;accountEmail&quot; class=&quot;tiny&quot; style=&quot;color:#c5d9ee&quot;&gt;&lt;\/span&gt;&lt;button id=&quot;logout&quot; class=&quot;btn secondary hide&quot; style=&quot;padding:8px 12px&quot;&gt;Sign out&lt;\/button&gt;&lt;\/div&gt;&lt;\/header&gt;\n&lt;main class=&quot;shell&quot;&gt;\n&lt;section id=&quot;login&quot; class=&quot;login card&quot;&gt;&lt;div style=&quot;font-size:29px&quot;&gt;\ud83d\uddd3\ufe0f&lt;\/div&gt;&lt;h1&gt;Transfers calendar&lt;\/h1&gt;&lt;p&gt;Secure AlbanianBus staff access. Log in using an authorized email address.&lt;\/p&gt;\n&lt;form id=&quot;loginForm&quot;&gt;&lt;label class=&quot;field&quot;&gt;Email address&lt;input id=&quot;email&quot; type=&quot;email&quot; autocomplete=&quot;username&quot; required placeholder=&quot;admin@albanianbus.com&quot;&gt;&lt;\/label&gt;&lt;label class=&quot;field&quot;&gt;Password&lt;input id=&quot;password&quot; type=&quot;password&quot; autocomplete=&quot;current-password&quot; required minlength=&quot;8&quot; placeholder=&quot;Your password&quot;&gt;&lt;\/label&gt;&lt;div class=&quot;flex&quot;&gt;&lt;button class=&quot;btn&quot; id=&quot;signin&quot; type=&quot;submit&quot;&gt;Sign in&lt;\/button&gt;&lt;button class=&quot;btn outline&quot; type=&quot;button&quot; id=&quot;signup&quot;&gt;Create account&lt;\/button&gt;&lt;\/div&gt;&lt;\/form&gt;\n&lt;div class=&quot;divider&quot;&gt;&lt;\/div&gt;&lt;button class=&quot;btn secondary&quot; type=&quot;button&quot; id=&quot;magic&quot;&gt;Email me a sign-in link&lt;\/button&gt;\n&lt;p class=&quot;tiny&quot;&gt;First-time access: create an account with your authorized email. Confirm the email address when prompted. Only explicitly approved staff accounts can open reservation data.&lt;\/p&gt;&lt;div id=&quot;loginMessage&quot; class=&quot;msg hide&quot;&gt;&lt;\/div&gt;\n&lt;\/section&gt;\n&lt;section id=&quot;dashboard&quot; class=&quot;hide&quot;&gt;\n&lt;div class=&quot;headrow&quot;&gt;&lt;div&gt;&lt;h1&gt;Transfers calendar&lt;\/h1&gt;&lt;div class=&quot;tiny&quot;&gt;Operational bookings \u00b7 Europe\/Tirane local times&lt;\/div&gt;&lt;\/div&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;button class=&quot;btn secondary&quot; id=&quot;refresh&quot;&gt;\u21bb Refresh&lt;\/button&gt;&lt;button class=&quot;btn outline&quot; id=&quot;openDirectory&quot;&gt;\ud83d\ude90 Vehicles &amp;amp; drivers&lt;\/button&gt;&lt;button class=&quot;btn outline&quot; id=&quot;openCashReport&quot;&gt;\ud83d\udcb6 Driver cash&lt;\/button&gt;&lt;button class=&quot;btn outline&quot; id=&quot;openReports&quot;&gt;\u25a4 Reports&lt;\/button&gt;&lt;button class=&quot;btn&quot; id=&quot;newBook&quot;&gt;\uff0b New reservation&lt;\/button&gt;&lt;\/div&gt;&lt;\/div&gt;\n&lt;div class=&quot;summary&quot;&gt;&lt;div class=&quot;stat&quot;&gt;&lt;div class=&quot;label&quot;&gt;Transfer legs shown&lt;\/div&gt;&lt;div id=&quot;totalCount&quot; class=&quot;value&quot;&gt;0&lt;\/div&gt;&lt;\/div&gt;&lt;div class=&quot;stat&quot;&gt;&lt;div class=&quot;label&quot;&gt;Confirmed&lt;\/div&gt;&lt;div id=&quot;confirmedCount&quot; class=&quot;value&quot;&gt;0&lt;\/div&gt;&lt;\/div&gt;&lt;div class=&quot;stat&quot;&gt;&lt;div class=&quot;label&quot;&gt;Need a vehicle&lt;\/div&gt;&lt;div id=&quot;needsCount&quot; class=&quot;value&quot;&gt;0&lt;\/div&gt;&lt;\/div&gt;&lt;div class=&quot;stat&quot;&gt;&lt;div class=&quot;label&quot;&gt;Total booked value&lt;\/div&gt;&lt;div id=&quot;revenue&quot; class=&quot;value&quot;&gt;\u20ac0&lt;\/div&gt;&lt;\/div&gt;&lt;\/div&gt;\n&lt;div class=&quot;filters&quot;&gt;&lt;div class=&quot;tabs hideOnMobile&quot;&gt;&lt;button data-view=&quot;calendar&quot; class=&quot;active&quot; type=&quot;button&quot;&gt;Calendar&lt;\/button&gt;&lt;button data-view=&quot;list&quot; type=&quot;button&quot;&gt;All bookings&lt;\/button&gt;&lt;\/div&gt;&lt;input id=&quot;search&quot; class=&quot;search&quot; placeholder=&quot;Search passenger, flight, plate, reference&quot;&gt;&lt;label class=&quot;toggle&quot;&gt;&lt;input id=&quot;showTests&quot; type=&quot;checkbox&quot;&gt; Show tests&lt;\/label&gt;&lt;\/div&gt;\n&lt;div class=&quot;status-filters&quot;&gt;\n&lt;label&gt;Booking status&lt;select id=&quot;bookingStatusFilter&quot;&gt;&lt;option value=&quot;&quot;&gt;All statuses&lt;\/option&gt;&lt;option value=&quot;confirmed&quot;&gt;Confirmed&lt;\/option&gt;&lt;option value=&quot;awaiting_payment&quot;&gt;Awaiting payment&lt;\/option&gt;&lt;option value=&quot;prebooked&quot;&gt;Prebooked&lt;\/option&gt;&lt;option value=&quot;completed&quot;&gt;Completed&lt;\/option&gt;&lt;option value=&quot;cancelled&quot;&gt;Cancelled&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;\n&lt;label&gt;Payment status&lt;select id=&quot;paymentStatusFilter&quot;&gt;&lt;option value=&quot;&quot;&gt;All payments&lt;\/option&gt;&lt;option value=&quot;paid&quot;&gt;Paid in full&lt;\/option&gt;&lt;option value=&quot;partially_paid&quot;&gt;Deposit paid&lt;\/option&gt;&lt;option value=&quot;pending&quot;&gt;Payment pending&lt;\/option&gt;&lt;option value=&quot;not_recorded&quot;&gt;Not recorded&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;\n&lt;label&gt;Vehicle \/ dispatch&lt;select id=&quot;dispatchStatusFilter&quot;&gt;&lt;option value=&quot;&quot;&gt;All vehicles&lt;\/option&gt;&lt;option value=&quot;unassigned&quot;&gt;Needs a vehicle&lt;\/option&gt;&lt;option value=&quot;assigned&quot;&gt;Assigned&lt;\/option&gt;&lt;option value=&quot;in_progress&quot;&gt;In progress&lt;\/option&gt;&lt;option value=&quot;hired&quot;&gt;Hired \/ outsourced&lt;\/option&gt;&lt;option value=&quot;overlap&quot;&gt;Possible overlap&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;\n&lt;label&gt;QR validation&lt;select id=&quot;qrStatusFilter&quot;&gt;&lt;option value=&quot;&quot;&gt;All tickets&lt;\/option&gt;&lt;option value=&quot;validated&quot;&gt;QR validated&lt;\/option&gt;&lt;option value=&quot;pending&quot;&gt;Not validated&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;button id=&quot;clearFilters&quot; type=&quot;button&quot; class=&quot;btn secondary&quot;&gt;Clear filters&lt;\/button&gt;&lt;\/div&gt;&lt;div id=&quot;calendarPanel&quot; class=&quot;card&quot;&gt;&lt;div class=&quot;monthhead&quot;&gt;&lt;div class=&quot;flex&quot;&gt;&lt;button class=&quot;btn secondary&quot; id=&quot;prevMonth&quot;&gt;\u2039&lt;\/button&gt;&lt;button class=&quot;btn secondary&quot; id=&quot;nextMonth&quot;&gt;\u203a&lt;\/button&gt;&lt;\/div&gt;&lt;h2 id=&quot;monthTitle&quot;&gt;Calendar&lt;\/h2&gt;&lt;button class=&quot;btn secondary&quot; id=&quot;todayBtn&quot;&gt;Today&lt;\/button&gt;&lt;\/div&gt;&lt;div id=&quot;calendarGrid&quot; class=&quot;calgrid&quot;&gt;&lt;\/div&gt;&lt;\/div&gt;\n&lt;div id=&quot;recordSection&quot;&gt;&lt;div class=&quot;sectionlabel&quot; id=&quot;listTitle&quot;&gt;Upcoming transfers&lt;\/div&gt;&lt;div id=&quot;recordList&quot; class=&quot;records&quot;&gt;&lt;\/div&gt;&lt;\/div&gt;\n&lt;\/section&gt;\n&lt;\/main&gt;\n&lt;nav id=&quot;bottomnav&quot; class=&quot;bottomnav hide&quot;&gt;&lt;button class=&quot;active&quot; data-view=&quot;calendar&quot;&gt;&lt;span class=&quot;symbol&quot;&gt;\ud83d\uddd3&lt;\/span&gt;Calendar&lt;\/button&gt;&lt;button data-view=&quot;list&quot;&gt;&lt;span class=&quot;symbol&quot;&gt;\u2630&lt;\/span&gt;Bookings&lt;\/button&gt;&lt;button id=&quot;mobileNew&quot;&gt;&lt;span class=&quot;symbol&quot;&gt;\uff0b&lt;\/span&gt;New&lt;\/button&gt;&lt;\/nav&gt;\n&lt;div id=&quot;overlay&quot; class=&quot;overlay hide&quot;&gt;&lt;div class=&quot;dialog&quot;&gt;&lt;div class=&quot;title&quot;&gt;&lt;h2 id=&quot;dialogTitle&quot;&gt;&lt;\/h2&gt;&lt;button class=&quot;iconbtn hidePrint&quot; id=&quot;closeDialog&quot; aria-label=&quot;Close&quot;&gt;\u2715&lt;\/button&gt;&lt;\/div&gt;&lt;div id=&quot;dialogBody&quot;&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;\/div&gt;\n&lt;script src=&quot;https:\/\/cdn.jsdelivr.net\/npm\/@supabase\/supabase-js@2.95.0\/dist\/umd\/supabase.min.js&quot;&gt;&lt;\/script&gt;\n&lt;script&gt;\n(function(){\n&quot;use strict&quot;;\nconst PROJECT_URL=&quot;https:\/\/eyhphryauiihzmnmcqlk.supabase.co&quot;;const KEY=&quot;sb_publishable_NFysUe4qKtg420wU0PbVRw_Appl5waV&quot;;const BASE=&quot;https:\/\/eyhphryauiihzmnmcqlk.supabase.co\/functions\/v1\/transfer-admin-calendar&quot;;const APP_URL=&quot;https:\/\/albanianbus.com\/wordpress\/?page_id=97876&quot;;const $=id=&gt;document.getElementById(id);\nconst esc=x=&gt;String(x==null?&quot;&quot;:x).replace(\/[&amp;&lt;&gt;&quot;&#x27;]\/g,c=&gt;({&quot;&amp;&quot;:&quot;&amp;amp;&quot;,&quot;&lt;&quot;:&quot;&amp;lt;&quot;,&quot;&gt;&quot;:&quot;&amp;gt;&quot;,&#x27;&quot;&#x27;:&quot;&amp;quot;&quot;,&quot;&#x27;&quot;:&quot;&amp;#39;&quot;}[c]));\nconst shortDate=d=&gt;d?new Date(d+&quot;T12:00:00&quot;).toLocaleDateString(&quot;en-GB&quot;,{day:&quot;numeric&quot;,month:&quot;short&quot;,year:&quot;numeric&quot;}):&quot;Date pending&quot;;\nconst monthFormat=d=&gt;d.toLocaleDateString(&quot;en-GB&quot;,{month:&quot;long&quot;,year:&quot;numeric&quot;});\nconst iso=d=&gt;d.getFullYear()+&quot;-&quot;+String(d.getMonth()+1).padStart(2,&quot;0&quot;)+&quot;-&quot;+String(d.getDate()).padStart(2,&quot;0&quot;);\nconst cash=n=&gt;&quot;\u20ac&quot;+Number(n||0).toLocaleString(&quot;en-IE&quot;,{maximumFractionDigits:2});\nlet auth=null,rows=[],month=new Date(),selectedDate=null,view=&quot;calendar&quot;,session=null,current=null,loading=false,activeTests=false;\nconst referenceTarget=new URLSearchParams(parent.location.search).get(&quot;ref&quot;);\nfunction alertLogin(msg,error){$(&quot;loginMessage&quot;).textContent=msg;$(&quot;loginMessage&quot;).className=&quot;msg&quot;+(error?&quot; err&quot;:&quot;&quot;)}\nfunction toast(msg,error){const box=document.createElement(&quot;div&quot;);box.textContent=msg;box.style.cssText=&quot;position:fixed;bottom:95px;left:12px;right:12px;max-width:450px;margin:auto;z-index:50;padding:14px 18px;border-radius:13px;box-shadow:0 5px 30px #112b4270;color:white;background:&quot;+(error?&quot;#ad3c3c&quot;:&quot;#0d3f6b&quot;);document.body.appendChild(box);setTimeout(()=&gt;box.remove(),3500)}\nasync function authInit(){if(!window.supabase){alertLogin(&quot;The login library did not load. Check your internet connection and refresh.&quot;,true);return}auth=window.supabase.createClient(PROJECT_URL,KEY,{auth:{autoRefreshToken:true,persistSession:true,detectSessionInUrl:false}});try{const hash=new URLSearchParams(parent.location.hash.slice(1));if(hash.get(&#x27;access_token&#x27;)&amp;&amp;hash.get(&#x27;refresh_token&#x27;)){await auth.auth.setSession({access_token:hash.get(&#x27;access_token&#x27;),refresh_token:hash.get(&#x27;refresh_token&#x27;)});parent.history.replaceState(null,&#x27;&#x27;,parent.location.pathname+parent.location.search)}}catch{}auth.auth.onAuthStateChange((_event,s)=&gt;{session=s;setTimeout(()=&gt;{if(s)enter();else leave()},0)});const out=await auth.auth.getSession();if(out.data.session){session=out.data.session;await enter()}else leave()}\nfunction leave(){$(&quot;login&quot;).classList.remove(&quot;hide&quot;);$(&quot;dashboard&quot;).classList.add(&quot;hide&quot;);$(&quot;logout&quot;).classList.add(&quot;hide&quot;);$(&quot;bottomnav&quot;).classList.add(&quot;hide&quot;);$(&quot;accountEmail&quot;).textContent=&quot;&quot;}\nasync function enter(){$(&quot;login&quot;).classList.add(&quot;hide&quot;);$(&quot;dashboard&quot;).classList.remove(&quot;hide&quot;);$(&quot;logout&quot;).classList.remove(&quot;hide&quot;);$(&quot;bottomnav&quot;).classList.remove(&quot;hide&quot;);$(&quot;accountEmail&quot;).textContent=session&amp;&amp;session.user?session.user.email:&quot;&quot;;await load(true)}\nasync function request(action,body){const {data}=await auth.auth.getSession();if(!data.session)throw Error(&quot;Session expired. Please sign in again.&quot;);const method=body?&quot;POST&quot;:&quot;GET&quot;;const qs=action===&quot;list&quot;?&quot;&amp;from=&quot;+iso(new Date(new Date().getFullYear()-1,0,1))+&quot;&amp;to=&quot;+iso(new Date(new Date().getFullYear()+3,11,31))+&quot;&amp;tests=&quot;+(activeTests?&quot;1&quot;:&quot;0&quot;):&quot;&quot;;const r=await fetch(BASE+&quot;?api=&quot;+action+qs,{method,headers:{&quot;Content-Type&quot;:&quot;application\/json&quot;,Authorization:&quot;Bearer &quot;+data.session.access_token},body:body?JSON.stringify(body):undefined,cache:&quot;no-store&quot;});const j=await r.json().catch(()=&gt;({}));if(!r.ok)throw Error(j.error||&quot;Request failed&quot;);return j}\nfunction itemSearch(r){return [r.customer_name,r.reference,r.flight_number,r.origin,r.destination,r.vehicle_plate,r.driver_name,r.customer_phone].join(&quot; &quot;).toLowerCase()}\nfunction bookingStatus(r){return r.dispatch_status===&#x27;cancelled&#x27;?&#x27;cancelled&#x27;:r.dispatch_status===&#x27;completed&#x27;?&#x27;completed&#x27;:r.booking_status;}\nfunction matchesFilters(r,q,booking,payment,dispatch){\n if(q&amp;&amp;!itemSearch(r).includes(q))return false;\n if(booking&amp;&amp;bookingStatus(r)!==booking)return false;\n const qr=$(&#x27;qrStatusFilter&#x27;)?.value;if(qr===&#x27;validated&#x27;&amp;&amp;!r.qr_validated_at)return false;if(qr===&#x27;pending&#x27;&amp;&amp;r.qr_validated_at)return false;\n if(payment&amp;&amp;r.payment_status!==payment)return false;\n if(dispatch===&#x27;hired&#x27;&amp;&amp;r.vehicle_source!==&#x27;hired&#x27;)return false;\n if(dispatch===&#x27;overlap&#x27;&amp;&amp;!rows.some(x=&gt;conflicts(r,x)))return false;\n if(dispatch===&#x27;unassigned&#x27;&amp;&amp;(r.booking_status===&#x27;cancelled&#x27;||r.dispatch_status===&#x27;cancelled&#x27;||r.dispatch_status===&#x27;completed&#x27;||(r.vehicle_plate&amp;&amp;r.vehicle_plate!==&#x27;UNASSIGNED&#x27;)))return false;\n if([&#x27;assigned&#x27;,&#x27;in_progress&#x27;].includes(dispatch)&amp;&amp;r.dispatch_status!==dispatch)return false;\n return true;\n}\nfunction visible(){const q=$(&#x27;search&#x27;).value.trim().toLowerCase();return rows.filter(r=&gt;matchesFilters(r,q,$(&#x27;bookingStatusFilter&#x27;).value,$(&#x27;paymentStatusFilter&#x27;).value,$(&#x27;dispatchStatusFilter&#x27;).value));}\nasync function load(first){if(loading)return;loading=true;$(&quot;refresh&quot;).disabled=true;try{const j=await request(&quot;list&quot;);rows=j.records||[];directory=(await request(&quot;directory&quot;)).items||[];if(first&amp;&amp;!selectedDate){const now=iso(new Date()),up=rows.filter(r=&gt;r.service_date&amp;&amp;r.service_date&gt;=now).sort((a,b)=&gt;a.service_date.localeCompare(b.service_date));const firstBooking=up[0]||rows[0];if(firstBooking&amp;&amp;firstBooking.service_date){month=new Date(firstBooking.service_date+&quot;T12:00:00&quot;);selectedDate=firstBooking.service_date}}paint();if(referenceTarget){const one=rows.find(r=&gt;r.reference===referenceTarget);if(one)openDetail(one.record_key)}}catch(e){toast(e.message,true);if(\/401|403|not authorized|access denied\/i.test(e.message)){$(&quot;login&quot;).classList.remove(&quot;hide&quot;);alertLogin(&quot;You are signed in but your email is not yet authorized for staff access. Ask the owner to approve this address.&quot;,true)}}finally{loading=false;$(&quot;refresh&quot;).disabled=false}}\nfunction paint(){const a=visible(),monthPrefix=iso(new Date(month.getFullYear(),month.getMonth(),1)).slice(0,7),inMonth=a.filter(r=&gt;String(r.service_date||&quot;&quot;).startsWith(monthPrefix));\n$(&quot;totalCount&quot;).textContent=inMonth.length;$(&quot;confirmedCount&quot;).textContent=inMonth.filter(r=&gt;bookingStatus(r)===&quot;confirmed&quot;).length;$(&quot;needsCount&quot;).textContent=inMonth.filter(r=&gt;!r.vehicle_plate||r.vehicle_plate===&quot;UNASSIGNED&quot;).length;$(&quot;revenue&quot;).textContent=cash(inMonth.filter(r=&gt;r.booking_status!==&quot;cancelled&quot;).reduce((s,r)=&gt;s+Number(r.agreed_price_eur||0),0));\n$(&quot;calendarPanel&quot;).classList.toggle(&quot;hide&quot;,view===&quot;list&quot;);$(&quot;monthTitle&quot;).textContent=monthFormat(month);\ndocument.querySelectorAll(&quot;[data-view]&quot;).forEach(b=&gt;b.classList.toggle(&quot;active&quot;,b.dataset.view===view));\nif(view===&quot;calendar&quot;){paintCalendar(inMonth);const todayRows=inMonth.filter(r=&gt;r.service_date===selectedDate);$(&quot;listTitle&quot;).textContent=(selectedDate?shortDate(selectedDate):&quot;Select a day&quot;)+&quot; \u00b7 &quot;+todayRows.length+&quot; transfer&quot;+(todayRows.length===1?&quot;&quot;:&quot;s&quot;);paintList(todayRows)}else{$(&quot;listTitle&quot;).textContent=&quot;All transfers \u00b7 &quot;+a.length+&quot; records&quot;;paintList(a.sort((x,y)=&gt;String(x.service_date).localeCompare(String(y.service_date))))}\n}\nfunction paintCalendar(items){const first=new Date(month.getFullYear(),month.getMonth(),1),offset=(first.getDay()+6)%7,start=new Date(month.getFullYear(),month.getMonth(),1-offset);let html=[&quot;Mon&quot;,&quot;Tue&quot;,&quot;Wed&quot;,&quot;Thu&quot;,&quot;Fri&quot;,&quot;Sat&quot;,&quot;Sun&quot;].map(x=&gt;&#x27;&lt;div class=&quot;dayname&quot;&gt;&#x27;+x+&quot;&lt;\/div&gt;&quot;).join(&quot;&quot;);for(let i=0;i&lt;42;i++){const d=new Date(start.getFullYear(),start.getMonth(),start.getDate()+i),date=iso(d),n=items.filter(r=&gt;r.service_date===date).length;html+=&#x27;&lt;button data-day=&quot;&#x27;+date+&#x27;&quot; class=&quot;day &#x27;+(d.getMonth()!==month.getMonth()?&quot;outside &quot;:&quot;&quot;)+(date===selectedDate?&quot;selected &quot;:&quot;&quot;)+(date===iso(new Date())?&quot;today&quot;:&quot;&quot;)+&#x27;&quot;&gt;&lt;span class=&quot;number&quot;&gt;&#x27;+d.getDate()+&#x27;&lt;\/span&gt;&#x27;+(n?&#x27;&lt;span class=&quot;counter&quot;&gt;&#x27;+n+&#x27; transfer&#x27;+(n&gt;1?&quot;s&quot;:&quot;&quot;)+&#x27;&lt;\/span&gt;&lt;span class=&quot;dots&quot;&gt;\u25cf \u25cf&lt;\/span&gt;&#x27;:&quot;&quot;)+&#x27;&lt;\/button&gt;&#x27;}$(&quot;calendarGrid&quot;).innerHTML=html}\nfunction paintList(items){if(!items.length){$(&quot;recordList&quot;).innerHTML=&#x27;&lt;div class=&quot;empty&quot;&gt;No reservations for this selection.&lt;br&gt;&lt;span class=&quot;tiny&quot;&gt;Try another date or clear the search.&lt;\/span&gt;&lt;\/div&gt;&#x27;;return} $(&quot;recordList&quot;).innerHTML=items.map(r=&gt;{const date=r.service_date||&quot;2000-01-01&quot;,parts=date.split(&quot;-&quot;),v=r.vehicle_plate&amp;&amp;r.vehicle_plate!==&quot;UNASSIGNED&quot;?r.vehicle_plate:&quot;No vehicle&quot;;return &#x27;&lt;button class=&quot;booking&quot; data-record=&quot;&#x27;+esc(r.record_key)+&#x27;&quot;&gt;&lt;span class=&quot;datebadge&quot;&gt;&lt;span class=&quot;big&quot;&gt;&#x27;+esc(parts[2])+&#x27;&lt;\/span&gt;&lt;span class=&quot;mon&quot;&gt;&#x27;+esc(new Date(date+&quot;T12:00:00&quot;).toLocaleDateString(&quot;en-GB&quot;,{month:&quot;short&quot;}))+&#x27;&lt;\/span&gt;&lt;\/span&gt;&lt;span class=&quot;detail&quot;&gt;&lt;div class=&quot;name&quot;&gt;&#x27;+esc(r.customer_name)+&#x27;&lt;\/div&gt;&lt;div class=&quot;route&quot;&gt;&#x27;+esc(r.origin)+&#x27; \u2192 &#x27;+esc(r.destination)+(r.leg_type===&#x27;return&#x27;?&#x27; \u00b7 RETURN&#x27;:r.leg_type===&#x27;outbound&#x27;?&#x27; \u00b7 OUTBOUND&#x27;:&#x27;&#x27;)+&#x27;&lt;\/div&gt;&lt;div class=&quot;meta&quot;&gt;&#x27;+esc(r.service_time?String(r.service_time).slice(0,5):&quot;Time TBD&quot;)+&#x27; \u00b7 &#x27;+esc(r.passenger_count)+&#x27; pax \u00b7 &#x27;+esc(v)+&#x27;&lt;\/div&gt;&lt;div class=&quot;stack&quot; style=&quot;margin-top:8px&quot;&gt;&lt;span class=&quot;pill &#x27;+esc(bookingStatus(r))+&#x27;&quot;&gt;&#x27;+esc(bookingStatus(r))+&#x27;&lt;\/span&gt;&lt;span class=&quot;pill &#x27;+esc(r.payment_status)+&#x27;&quot;&gt;&#x27;+esc(r.payment_status)+&#x27;&lt;\/span&gt;&#x27;+(r.test_mode?&#x27;&lt;span class=&quot;pill test&quot;&gt;TEST&lt;\/span&gt;&#x27;:&quot;&quot;)+(rows.some(x=&gt;conflicts(r,x))?&#x27;&lt;span class=&quot;pill overlap&quot;&gt;Possible overlap&lt;\/span&gt;&#x27;:&#x27;&#x27;)+(r.vehicle_source===&#x27;hired&#x27;?&#x27;&lt;span class=&quot;pill&quot;&gt;Hired vehicle&lt;\/span&gt;&#x27;:&#x27;&#x27;)+(r.qr_validated_at?&#x27;&lt;span class=&quot;pill qr-validated&quot;&gt;\u2713 QR validated&lt;\/span&gt;&#x27;:r.qr_issued?&#x27;&lt;span class=&quot;pill qr-pending&quot;&gt;QR not validated&lt;\/span&gt;&#x27;:&#x27;&#x27;)+&#x27;&lt;\/div&gt;&lt;\/span&gt;&lt;\/button&gt;&#x27;}).join(&quot;&quot;)}\nfunction kv(k,v){return &#x27;&lt;div class=&quot;kv&quot;&gt;&lt;b&gt;&#x27;+esc(k)+&#x27;&lt;\/b&gt;&lt;span&gt;&#x27;+esc(v||&quot;\u2014&quot;)+&#x27;&lt;\/span&gt;&lt;\/div&gt;&#x27;}\nfunction openDetail(key){const r=rows.find(x=&gt;x.record_key===key);if(!r)return;current=r;$(&quot;dialogTitle&quot;).textContent=r.customer_name+&quot; \u00b7 &quot;+shortDate(r.service_date);let h=&#x27;&lt;div class=&quot;stack&quot;&gt;&lt;span class=&quot;pill &#x27;+esc(bookingStatus(r))+&#x27;&quot;&gt;&#x27;+esc(bookingStatus(r))+&#x27;&lt;\/span&gt;&lt;span class=&quot;pill &#x27;+esc(r.payment_status)+&#x27;&quot;&gt;&#x27;+esc(r.payment_status)+&#x27;&lt;\/span&gt;&#x27;+(r.test_mode?&#x27;&lt;span class=&quot;pill test&quot;&gt;TEST MODE&lt;\/span&gt;&#x27;:&quot;&quot;)+(rows.some(x=&gt;conflicts(r,x))?&#x27;&lt;span class=&quot;pill overlap&quot;&gt;Possible vehicle overlap&lt;\/span&gt;&#x27;:&#x27;&#x27;)+&#x27;&lt;\/div&gt;&lt;div class=&quot;smalltitle&quot;&gt;Trip details&lt;\/div&gt;&#x27;+kv(&quot;Reference&quot;,r.reference)+kv(&quot;QR check-in&quot;,r.qr_validated_at?&quot;\u2713 Validated \u00b7 &quot;+albaniaLocal(r.qr_validated_at).replace(&quot;T&quot;,&quot; &quot;)+&quot; \u00b7 &quot;+(r.qr_validated_by||&quot;Driver&quot;):&quot;Not validated&quot;)+kv(&quot;Journey&quot;,r.leg_type===&quot;return&quot;?&quot;Return leg&quot;:r.leg_type===&quot;outbound&quot;?&quot;Outbound leg&quot;:&quot;One-way&quot;)+kv(&quot;Route&quot;,r.origin+&quot; \u2192 &quot;+r.destination)+kv(&quot;Date&quot;,shortDate(r.service_date))+kv(&quot;Pickup time&quot;,r.pickup_time||r.service_time||&quot;To confirm&quot;)+kv(&quot;Pickup&quot;,r.pickup_location)+kv(&quot;Drop-off&quot;,r.dropoff_location)+kv(&quot;Flight&quot;,r.flight_number)+kv(&quot;Passengers&quot;,r.passenger_count)+kv(&quot;Customer email&quot;,r.customer_email)+kv(&quot;Phone&quot;,r.customer_phone)+kv(&quot;Leg value&quot;,cash(r.agreed_price_eur))+kv(&quot;Booking total&quot;,cash(r.booking_total_eur??r.agreed_price_eur))+kv(&quot;Paid upfront (booking)&quot;,r.deposit_eur==null?&quot;\u2014&quot;:cash(r.deposit_eur))+kv(&quot;Balance after online payment&quot;,r.balance_eur==null?&quot;\u2014&quot;:cash(r.balance_eur))+kv(&quot;Cash collected (whole booking)&quot;,cash(r.cash_collected_eur||0))+kv(&quot;Still due (whole booking)&quot;,r.cash_remaining_eur==null?&quot;\u2014&quot;:cash(r.cash_remaining_eur))+&#x27;&lt;div class=&quot;divider&quot;&gt;&lt;\/div&gt;&lt;div class=&quot;smalltitle&quot;&gt;Dispatch&lt;\/div&gt;&#x27;+kv(&quot;Vehicle source&quot;,r.vehicle_source===&quot;hired&quot;?&quot;Hired \/ outsourced&quot;:&quot;Own fleet&quot;)+kv(&quot;Vehicle&quot;,r.vehicle_name)+kv(&quot;Expected finish&quot;,r.end_at?albaniaLocal(r.end_at).replace(&quot;T&quot;,&quot; &quot;):&quot;Not set&quot;)+kv(&quot;Plate&quot;,r.vehicle_plate)+kv(&quot;Capacity&quot;,r.vehicle_capacity)+kv(&quot;Driver&quot;,r.driver_name)+kv(&quot;Driver phone&quot;,r.driver_phone)+kv(&quot;Dispatch status&quot;,r.dispatch_status||&quot;unassigned&quot;)+(r.dispatch_notes?&#x27;&lt;div class=&quot;banner&quot;&gt;&#x27;+esc(r.dispatch_notes)+&#x27;&lt;\/div&gt;&#x27;:&quot;&quot;)+(r.notes?&#x27;&lt;div class=&quot;banner&quot;&gt;&#x27;+esc(r.notes)+&#x27;&lt;\/div&gt;&#x27;:&quot;&quot;);\nh+=cashHistory(r);h+=&#x27;&lt;div class=&quot;formActions hidePrint&quot; id=&quot;dialogControls&quot;&gt;&lt;button class=&quot;btn outline&quot; id=&quot;printBooking&quot;&gt;Print voucher&lt;\/button&gt;&lt;button class=&quot;btn outline&quot; id=&quot;showTicket&quot;&gt;QR ticket&lt;\/button&gt;&lt;button class=&quot;btn&quot; id=&quot;shareBooking&quot;&gt;Share on WhatsApp&lt;\/button&gt;&#x27;+(r.source_system===&quot;manual&quot;?&#x27;&lt;button class=&quot;btn secondary&quot; id=&quot;editManual&quot;&gt;Edit booking&lt;\/button&gt;&#x27;:&quot;&quot;)+&#x27;&lt;button class=&quot;btn&quot; id=&quot;editDispatch&quot;&gt;Assign vehicle&lt;\/button&gt;&#x27;+(r.source_system===&#x27;transfer_assistant&#x27;&amp;&amp;r.checkout_status===&#x27;deposit_paid&#x27;&amp;&amp;Number(r.cash_remaining_eur)&gt;0?&#x27;&lt;button class=&quot;btn&quot; id=&quot;recordCash&quot;&gt;\ud83d\udcb6 Record driver cash&lt;\/button&gt;&#x27;:&#x27;&#x27;)+&#x27;&lt;\/div&gt;&#x27;;$(&quot;dialogBody&quot;).innerHTML=h;openOverlay()}\nfunction openOverlay(){$(&quot;overlay&quot;).classList.remove(&quot;hide&quot;);document.body.style.overflow=&quot;hidden&quot;}\nfunction closeOverlay(){$(&quot;overlay&quot;).classList.add(&quot;hide&quot;);document.body.style.overflow=&quot;&quot;}\nfunction field(n,label,type,value,required,options){const id=&quot;f_&quot;+n;const val=value==null?&quot;&quot;:String(value);if(options)return &#x27;&lt;label class=&quot;field&quot;&gt;&#x27;+esc(label)+&#x27;&lt;select id=&quot;&#x27;+id+&#x27;&quot; name=&quot;&#x27;+n+&#x27;&quot;&gt;&#x27;+options.map(x=&gt;&#x27;&lt;option value=&quot;&#x27;+esc(x)+&#x27;&quot;&#x27;+(x===val?&quot; selected&quot;:&quot;&quot;)+&#x27;&gt;&#x27;+esc(x)+&#x27;&lt;\/option&gt;&#x27;).join(&quot;&quot;)+&#x27;&lt;\/select&gt;&lt;\/label&gt;&#x27;;return &#x27;&lt;label class=&quot;field&quot;&gt;&#x27;+esc(label)+&#x27;&lt;input id=&quot;&#x27;+id+&#x27;&quot; name=&quot;&#x27;+n+&#x27;&quot; type=&quot;&#x27;+(type||&quot;text&quot;)+&#x27;&quot; value=&quot;&#x27;+esc(val)+&#x27;&quot; &#x27;+(required?&quot;required&quot;:&quot;&quot;)+&#x27;&gt;&lt;\/label&gt;&#x27;}\nfunction formVal(n){return $(&quot;f_&quot;+n).value.trim()}\n\nfunction cashHistory(r){return &#x27;&lt;div class=&quot;smalltitle&quot;&gt;Driver cash history&lt;\/div&gt;&#x27;+((r.cash_entries||[]).length?(r.cash_entries||[]).map(c=&gt;&#x27;&lt;div class=&quot;banner&quot;&gt;&#x27;+esc(c.driver_name)+&#x27; \u00b7 &#x27;+cash(c.amount_cents\/100)+&#x27; \u00b7 &#x27;+esc(albaniaLocal(c.collected_at).replace(&#x27;T&#x27;,&#x27; &#x27;))+&#x27; \u00b7 &#x27;+esc(c.leg_type)+(c.voided_at?&#x27; \u00b7 VOIDED&#x27;:&#x27; &lt;button class=&quot;btn secondary&quot; data-void-cash=&quot;&#x27;+esc(c.id)+&#x27;&quot;&gt;Void incorrect entry&lt;\/button&gt;&#x27;)+&#x27;&lt;\/div&gt;&#x27;).join(&#x27;&#x27;):&#x27;&lt;p class=&quot;tiny&quot;&gt;No cash recorded. Record cash only after the driver actually receives it.&lt;\/p&gt;&#x27;);}\nfunction recordCash(r){\n if(!r.driver_name||![&#x27;assigned&#x27;,&#x27;in_progress&#x27;,&#x27;completed&#x27;].includes(r.dispatch_status)){toast(&#x27;Assign a driver first.&#x27;,true);return}\n const requestId=crypto.randomUUID();\n $(&#x27;dialogTitle&#x27;).textContent=&#x27;Record cash received&#x27;;\n $(&#x27;dialogBody&#x27;).innerHTML=&#x27;&lt;div class=&quot;banner&quot;&gt;Driver: &lt;strong&gt;&#x27;+esc(r.driver_name)+&#x27;&lt;\/strong&gt;&lt;br&gt;Booking &#x27;+esc(r.reference)+&#x27; \u00b7 &#x27;+esc(r.leg_type)+&#x27;&lt;br&gt;Remaining across the whole booking: &#x27;+cash(r.cash_remaining_eur)+&#x27;. Enter only money actually received.&lt;\/div&gt;&lt;form id=&quot;cashForm&quot;&gt;&#x27;+field(&#x27;cash_amount&#x27;,&#x27;Cash received (EUR)&#x27;,&#x27;number&#x27;,&#x27;&#x27;,true)+field(&#x27;cash_notes&#x27;,&#x27;Notes (optional)&#x27;,&#x27;text&#x27;,&#x27;&#x27;)+&#x27;&lt;div class=&quot;formActions&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn secondary&quot; id=&quot;backToBooking&quot;&gt;Back&lt;\/button&gt;&lt;button type=&quot;submit&quot; class=&quot;btn&quot; id=&quot;saveCash&quot;&gt;Confirm cash received&lt;\/button&gt;&lt;\/div&gt;&lt;\/form&gt;&#x27;;\n $(&#x27;f_cash_amount&#x27;).min=&#x27;0.01&#x27;;$(&#x27;f_cash_amount&#x27;).step=&#x27;0.01&#x27;;$(&#x27;f_cash_amount&#x27;).max=r.cash_remaining_eur;\n $(&#x27;cashForm&#x27;).onsubmit=async e=&gt;{e.preventDefault();$(&#x27;saveCash&#x27;).disabled=true;try{const amount=Math.round(Number(formVal(&#x27;cash_amount&#x27;))*100);await request(&#x27;cash&#x27;,{booking_id:r.source_record_id,leg_type:r.leg_type,amount_cents:amount,request_id:requestId,notes:formVal(&#x27;cash_notes&#x27;)});await load();openDetail(r.record_key);toast(&#x27;Driver cash recorded&#x27;);}catch(e){toast(e.message,true);if($(&#x27;saveCash&#x27;))$(&#x27;saveCash&#x27;).disabled=false;}};\n openOverlay();\n}\nasync function voidCash(id){if(!confirm(&#x27;Void this incorrect cash entry? It remains in the audit history.&#x27;))return;try{await request(&#x27;cash&#x27;,{void_id:id});await load();if(current)openDetail(current.record_key);toast(&#x27;Cash entry voided&#x27;);}catch(e){toast(e.message,true)}}\nfunction cashReportSummary(entries){const groups=new Map();for(const e of entries){if(e.voided_at)continue;const key=e.driver_phone||e.driver_name;const g=groups.get(key)||{name:e.driver_name,total:0,count:0};g.total+=e.amount_cents;g.count++;groups.set(key,g);}return [...groups.values()].sort((a,b)=&gt;a.name.localeCompare(b.name));}\nasync function cashReportsDialog(){\n $(&#x27;dialogTitle&#x27;).textContent=&#x27;Driver cash reports&#x27;;\n const selected=selectedDate||iso(new Date());\n $(&#x27;dialogBody&#x27;).innerHTML=&#x27;&lt;p class=&quot;tiny&quot;&gt;Reports use the date cash was recorded (Albania time). These totals show cash collected, not money handed back to the company. Voided entries are excluded.&lt;\/p&gt;&lt;div class=&quot;formgrid&quot;&gt;&lt;label class=&quot;field&quot;&gt;Period&lt;select id=&quot;cashPeriod&quot;&gt;&lt;option value=&quot;day&quot;&gt;Daily&lt;\/option&gt;&lt;option value=&quot;week&quot;&gt;Weekly&lt;\/option&gt;&lt;option value=&quot;month&quot;&gt;Monthly&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;label class=&quot;field&quot;&gt;Date&lt;input id=&quot;cashDate&quot; type=&quot;date&quot; value=&quot;&#x27;+esc(selected)+&#x27;&quot;&gt;&lt;\/label&gt;&lt;label class=&quot;field&quot;&gt;Driver&lt;select id=&quot;cashDriver&quot;&gt;&lt;option value=&quot;&quot;&gt;All drivers&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;div id=&quot;cashPreview&quot;&gt;&lt;\/div&gt;&lt;div class=&quot;formActions&quot;&gt;&lt;button class=&quot;btn outline&quot; id=&quot;cashPrint&quot;&gt;Print \/ Save PDF&lt;\/button&gt;&lt;button class=&quot;btn&quot; id=&quot;cashShare&quot;&gt;Share&lt;\/button&gt;&lt;button class=&quot;btn secondary&quot; id=&quot;cashCopy&quot;&gt;Copy&lt;\/button&gt;&lt;\/div&gt;&#x27;;\n openOverlay();let all=[],report=null,serial=0;\n const generate=()=&gt;{\n const from=$(&#x27;cashDate&#x27;)?.value;if(!from)return;\n const b=reportBounds($(&#x27;cashPeriod&#x27;).value,from),driver=$(&#x27;cashDriver&#x27;).value;\n const entries=all.filter(x=&gt;{const date=albaniaLocal(x.collected_at).slice(0,10);return !x.voided_at&amp;&amp;date&gt;=b.from&amp;&amp;date&lt;=b.to&amp;&amp;(!driver||(x.driver_phone||x.driver_name)===driver)}),summary=cashReportSummary(entries),total=entries.reduce((n,c)=&gt;n+c.amount_cents,0);\n const text=[&#x27;ALBANIANBUS \u00b7 RAPORT ARK\u00cbTIMESH NGA SHOFER\u00cbT&#x27;,b.from+&#x27; \u2014 &#x27;+b.to,&#x27;\ud83d\udcb6 Gjithsej: &#x27;+cash(total\/100),&#x27;&#x27;,...summary.map(g=&gt;&#x27;\ud83d\udc68\u200d\u2708\ufe0f &#x27;+g.name+&#x27; \u00b7 &#x27;+g.count+&#x27; ark\u00ebtime \u00b7 &#x27;+cash(g.total\/100)),&#x27;&#x27;,...entries.map(e=&gt;&#x27;\ud83d\udd16 &#x27;+e.transfer_bookings.reference+&#x27; \u00b7 &#x27;+e.leg_type+&#x27; \u00b7 &#x27;+e.driver_name+&#x27; \u00b7 &#x27;+cash(e.amount_cents\/100)+&#x27; \u00b7 &#x27;+albaniaLocal(e.collected_at).replace(&#x27;T&#x27;,&#x27; &#x27;))].join(&#x27;\\n&#x27;);\n const body=&#x27;&lt;h2&gt;AlbanianBus \u00b7 Driver cash&lt;\/h2&gt;&lt;p&gt;&#x27;+esc(b.from)+&#x27; \u2014 &#x27;+esc(b.to)+&#x27; \u00b7 Albania time&lt;\/p&gt;&lt;h3&gt;Total collected: &#x27;+cash(total\/100)+&#x27;&lt;\/h3&gt;&lt;p&gt;Cash collected, not driver settlement.&lt;\/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Driver&lt;\/th&gt;&lt;th&gt;Collections&lt;\/th&gt;&lt;th&gt;Cash EUR&lt;\/th&gt;&lt;\/tr&gt;&lt;\/thead&gt;&lt;tbody&gt;&#x27;+summary.map(g=&gt;&#x27;&lt;tr&gt;&lt;td&gt;&#x27;+esc(g.name)+&#x27;&lt;\/td&gt;&lt;td&gt;&#x27;+g.count+&#x27;&lt;\/td&gt;&lt;td&gt;&#x27;+cash(g.total\/100)+&#x27;&lt;\/td&gt;&lt;\/tr&gt;&#x27;).join(&#x27;&#x27;)+&#x27;&lt;\/tbody&gt;&lt;\/table&gt;&lt;h3&gt;Collection details&lt;\/h3&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Recorded&lt;\/th&gt;&lt;th&gt;Booking \/ leg&lt;\/th&gt;&lt;th&gt;Driver&lt;\/th&gt;&lt;th&gt;Cash EUR&lt;\/th&gt;&lt;\/tr&gt;&lt;\/thead&gt;&lt;tbody&gt;&#x27;+entries.map(e=&gt;&#x27;&lt;tr&gt;&lt;td&gt;&#x27;+esc(albaniaLocal(e.collected_at).replace(&#x27;T&#x27;,&#x27; &#x27;))+&#x27;&lt;\/td&gt;&lt;td&gt;&#x27;+esc(e.transfer_bookings.reference)+&#x27; \u00b7 &#x27;+esc(e.leg_type)+&#x27;&lt;\/td&gt;&lt;td&gt;&#x27;+esc(e.driver_name)+&#x27;&lt;\/td&gt;&lt;td&gt;&#x27;+cash(e.amount_cents\/100)+&#x27;&lt;\/td&gt;&lt;\/tr&gt;&#x27;).join(&#x27;&#x27;)+&#x27;&lt;\/tbody&gt;&lt;\/table&gt;&#x27;+(entries.length?&#x27;&#x27;:&#x27;&lt;p&gt;No cash collections in this period.&lt;\/p&gt;&#x27;);\n $(&#x27;cashPreview&#x27;).innerHTML=body;report={body,text,b};};\n const refresh=async()=&gt;{const n=++serial;try{const b=reportBounds($(&#x27;cashPeriod&#x27;).value,$(&#x27;cashDate&#x27;).value);const j=await request(&#x27;cash-report&amp;from=&#x27;+b.from+&#x27;&amp;to=&#x27;+b.to+&#x27;&amp;tests=&#x27;+(activeTests?&#x27;1&#x27;:&#x27;0&#x27;));if(n!==serial||!$(&#x27;cashDriver&#x27;))return;all=j.entries||[];const previous=$(&#x27;cashDriver&#x27;).value;const drivers=new Map();directory.filter(x=&gt;x.kind===&#x27;driver&#x27;).forEach(x=&gt;drivers.set(x.phone||x.name,x.name));all.forEach(x=&gt;drivers.set(x.driver_phone||x.driver_name,x.driver_name));$(&#x27;cashDriver&#x27;).innerHTML=&#x27;&lt;option value=&quot;&quot;&gt;All drivers&lt;\/option&gt;&#x27;+[...drivers].map(([key,name])=&gt;&#x27;&lt;option value=&quot;&#x27;+esc(key)+&#x27;&quot;&gt;&#x27;+esc(name)+&#x27;&lt;\/option&gt;&#x27;).join(&#x27;&#x27;);$(&#x27;cashDriver&#x27;).value=previous;generate();}catch(e){toast(e.message,true)}};\n $(&#x27;cashPeriod&#x27;).onchange=refresh;$(&#x27;cashDate&#x27;).onchange=refresh;$(&#x27;cashDriver&#x27;).onchange=generate;\n $(&#x27;cashPrint&#x27;).onclick=()=&gt;{if(!report)return;const w=window.open(&#x27;about:blank&#x27;,&#x27;_blank&#x27;);if(!w){toast(&#x27;Allow pop-ups to print.&#x27;,true);return}w.document.write(&#x27;&lt;!doctype html&gt;&lt;html&gt;&lt;head&gt;&lt;title&gt;Driver cash report&lt;\/title&gt;&lt;style&gt;body{font:13px Arial;padding:20px;color:#291e3d}table{width:100%;border-collapse:collapse}td,th{padding:8px;border:1px solid #ddd;text-align:left}thead{display:table-header-group}tr{break-inside:avoid}&lt;\/style&gt;&lt;\/head&gt;&lt;body&gt;&#x27;+report.body+&#x27;&lt;\/body&gt;&lt;\/html&gt;&#x27;);w.document.close();setTimeout(()=&gt;w.print(),200);};\n $(&#x27;cashCopy&#x27;).onclick=async()=&gt;{if(report)try{await navigator.clipboard.writeText(report.text);toast(&#x27;Copied&#x27;);}catch{toast(&#x27;Use Print \/ Save PDF.&#x27;,true)}};\n $(&#x27;cashShare&#x27;).onclick=async()=&gt;{if(!report)return;if(navigator.share){try{await navigator.share({title:&#x27;Driver cash report&#x27;,text:report.text});return}catch(e){if(e.name===&#x27;AbortError&#x27;)return;}}if(report.text.length&gt;6000){toast(&#x27;Save as PDF and attach the report.&#x27;,true);return}window.open(&#x27;https:\/\/wa.me\/?text=&#x27;+encodeURIComponent(report.text),&#x27;_blank&#x27;,&#x27;noopener,noreferrer&#x27;);};\n await refresh();\n}\n\nfunction manualForm(r){const fresh=!r;$(&quot;dialogTitle&quot;).textContent=fresh?&quot;New transfer reservation&quot;:&quot;Edit \u00b7 &quot;+r.reference;\nlet h=&#x27;&lt;form id=&quot;manualForm&quot;&gt;&lt;div class=&quot;banner&quot;&gt;Manual reservation. Payment and vehicle status can be updated here. Assistant bookings keep their checkout records separately.&lt;\/div&gt;&lt;div class=&quot;formgrid&quot;&gt;&#x27;+field(&quot;customer_name&quot;,&quot;Passenger \/ customer&quot;,&quot;text&quot;,r?.customer_name||&quot;&quot;,true)+field(&quot;customer_group&quot;,&quot;Group name&quot;,&quot;text&quot;,r?.customer_group||&quot;&quot;)+field(&quot;service_date&quot;,&quot;Service date&quot;,&quot;date&quot;,r?.service_date||iso(new Date()),true)+field(&quot;service_time&quot;,&quot;Pickup time (if confirmed)&quot;,&quot;time&quot;,r?.service_time?String(r.service_time).slice(0,5):&quot;&quot;)+field(&quot;origin&quot;,&quot;From&quot;,&quot;text&quot;,r?.origin||&quot;&quot;,true)+field(&quot;destination&quot;,&quot;To&quot;,&quot;text&quot;,r?.destination||&quot;&quot;,true)+field(&quot;pickup_location&quot;,&quot;Pickup address&quot;,&quot;text&quot;,r?.pickup_location||&quot;&quot;)+field(&quot;dropoff_location&quot;,&quot;Drop-off address&quot;,&quot;text&quot;,r?.dropoff_location||&quot;&quot;)+field(&quot;flight_number&quot;,&quot;Flight (optional)&quot;,&quot;text&quot;,r?.flight_number||&quot;&quot;)+field(&quot;passenger_count&quot;,&quot;Passengers&quot;,&quot;number&quot;,r?.passenger_count||1,true)+field(&quot;agreed_price_eur&quot;,&quot;Agreed price (\u20ac)&quot;,&quot;number&quot;,r?.agreed_price_eur||0,true)+field(&quot;booking_status&quot;,&quot;Booking status&quot;,null,r?.booking_status||&quot;prebooked&quot;,false,[&quot;prebooked&quot;,&quot;confirmed&quot;,&quot;completed&quot;,&quot;cancelled&quot;])+field(&quot;payment_status&quot;,&quot;Payment status&quot;,null,r?.payment_status||&quot;not_recorded&quot;,false,[&quot;not_recorded&quot;,&quot;pending&quot;,&quot;partially_paid&quot;,&quot;paid&quot;])+directoryPicker(&quot;vehicle&quot;)+field(&quot;vehicle_name&quot;,&quot;Vehicle&quot;,&quot;text&quot;,r?.vehicle_name===&quot;Unassigned&quot;?&quot;&quot;:r?.vehicle_name||&quot;&quot;)+field(&quot;vehicle_plate&quot;,&quot;Plate&quot;,&quot;text&quot;,r?.vehicle_plate===&quot;UNASSIGNED&quot;?&quot;&quot;:r?.vehicle_plate||&quot;&quot;)+field(&quot;vehicle_capacity&quot;,&quot;Seats&quot;,&quot;number&quot;,r?.vehicle_capacity||&quot;&quot;)+&#x27;&lt;\/div&gt;&#x27;+field(&quot;notes&quot;,&quot;Internal notes&quot;,&quot;text&quot;,r?.notes||&quot;&quot;)+&#x27;&lt;div class=&quot;formActions&quot;&gt;&lt;button class=&quot;btn secondary&quot; type=&quot;button&quot; id=&quot;cancelForm&quot;&gt;Cancel&lt;\/button&gt;&lt;button class=&quot;btn&quot; type=&quot;submit&quot;&gt;Save reservation&lt;\/button&gt;&lt;\/div&gt;&lt;\/form&gt;&#x27;;\n$(&quot;dialogBody&quot;).innerHTML=h;openOverlay();wireDirectoryPickers();$(&quot;manualForm&quot;).onsubmit=async(e)=&gt;{e.preventDefault();const names=[&quot;customer_name&quot;,&quot;customer_group&quot;,&quot;service_date&quot;,&quot;service_time&quot;,&quot;origin&quot;,&quot;destination&quot;,&quot;pickup_location&quot;,&quot;dropoff_location&quot;,&quot;flight_number&quot;,&quot;passenger_count&quot;,&quot;agreed_price_eur&quot;,&quot;booking_status&quot;,&quot;payment_status&quot;,&quot;vehicle_name&quot;,&quot;vehicle_plate&quot;,&quot;vehicle_capacity&quot;,&quot;notes&quot;];const values={};names.forEach(n=&gt;values[n]=formVal(n));try{await request(fresh?&quot;create&quot;:&quot;manual&quot;,{id:r?.source_record_id,values});closeOverlay();toast(&quot;Reservation saved&quot;);await load()}catch(e){toast(e.message,true)}}}\n\nlet directory=[];\nfunction directoryPicker(kind){return &#x27;&lt;label class=&quot;field&quot;&gt;&#x27;+(kind===&#x27;vehicle&#x27;?&#x27;\ud83d\ude90 Saved vehicle&#x27;:&#x27;\ud83d\udc68\u200d\u2708\ufe0f Saved driver&#x27;)+&#x27;&lt;select id=&quot;pick_&#x27;+kind+&#x27;&quot;&gt;&lt;option value=&quot;&quot;&gt;Type manually \/ not on the list&lt;\/option&gt;&#x27;+directory.filter(x=&gt;x.kind===kind).map(x=&gt;&#x27;&lt;option value=&quot;&#x27;+esc(x.id)+&#x27;&quot;&gt;&#x27;+esc(x.name)+(x.plate?&#x27; \u00b7 &#x27;+esc(x.plate):&#x27;&#x27;)+&#x27;&lt;\/option&gt;&#x27;).join(&#x27;&#x27;)+&#x27;&lt;\/select&gt;&lt;\/label&gt;&#x27;;}\nfunction wireDirectoryPickers(){\n for(const kind of [&#x27;vehicle&#x27;,&#x27;driver&#x27;]){const el=$(&#x27;pick_&#x27;+kind);if(!el)continue;el.onchange=()=&gt;{const x=directory.find(x=&gt;x.id===el.value);if(!x)return;\n const values=kind===&#x27;vehicle&#x27;?{vehicle_name:x.name,vehicle_plate:x.plate,vehicle_capacity:x.capacity,vehicle_source:x.vehicle_source}:{driver_name:x.name,driver_phone:x.phone};\n for(const [key,value] of Object.entries(values)){if($(&#x27;f_&#x27;+key))$(&#x27;f_&#x27;+key).value=value??&#x27;&#x27;;}if($(&#x27;f_dispatch_status&#x27;)&amp;&amp;$(&#x27;f_dispatch_status&#x27;).value===&#x27;unassigned&#x27;&amp;&amp;$(&#x27;f_driver_name&#x27;)?.value.trim()&amp;&amp;$(&#x27;f_vehicle_plate&#x27;)?.value.trim())$(&#x27;f_dispatch_status&#x27;).value=&#x27;assigned&#x27;;if(current&amp;&amp;$(&#x27;conflictWarning&#x27;))checkConflict(current);};}\n}\nasync function directoryDialog(kind=&#x27;vehicle&#x27;,editId=&#x27;&#x27;){\n try{directory=(await request(&#x27;directory&#x27;)).items||[];}catch(e){toast(e.message,true);return}\n const item=directory.find(x=&gt;x.id===editId)||{};\n $(&#x27;dialogTitle&#x27;).textContent=&#x27;Vehicles &amp; drivers&#x27;;\n $(&#x27;dialogBody&#x27;).innerHTML=&#x27;&lt;div class=&quot;flex&quot;&gt;&lt;button class=&quot;btn &#x27;+(kind===&#x27;vehicle&#x27;?&#x27;&#x27;:&#x27;secondary&#x27;)+&#x27;&quot; id=&quot;directoryVehicles&quot;&gt;\ud83d\ude90 Vehicles&lt;\/button&gt;&lt;button class=&quot;btn &#x27;+(kind===&#x27;driver&#x27;?&#x27;&#x27;:&#x27;secondary&#x27;)+&#x27;&quot; id=&quot;directoryDrivers&quot;&gt;\ud83d\udc68\u200d\u2708\ufe0f Drivers&lt;\/button&gt;&lt;\/div&gt;&lt;p class=&quot;tiny&quot;&gt;Choose saved details when assigning a booking, or type another vehicle or driver. Changes here do not rewrite existing bookings.&lt;\/p&gt;&lt;div&gt;&#x27;+directory.filter(x=&gt;x.kind===kind).map(x=&gt;&#x27;&lt;div class=&quot;card&quot; style=&quot;margin:8px 0;padding:10px;overflow-wrap:anywhere&quot;&gt;&lt;strong&gt;&#x27;+esc(x.name)+&#x27;&lt;\/strong&gt;&lt;div class=&quot;tiny&quot;&gt;&#x27;+esc(kind===&#x27;vehicle&#x27;?[x.plate||&#x27;Plate pending&#x27;,x.capacity?x.capacity+&#x27; passenger seats&#x27;:&#x27;&#x27;,x.vehicle_source,x.fuel_consumption_l100km?x.fuel_consumption_l100km+&#x27; L\/100 km&#x27;:&#x27;&#x27;].filter(Boolean).join(&#x27; \u00b7 &#x27;):x.phone||&#x27;No phone recorded&#x27;)+&#x27;&lt;\/div&gt;&lt;div class=&quot;flex&quot; style=&quot;margin-top:8px&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn secondary&quot; data-directory-edit=&quot;&#x27;+esc(x.id)+&#x27;&quot;&gt;Edit&lt;\/button&gt;&lt;button type=&quot;button&quot; class=&quot;btn outline&quot; data-directory-archive=&quot;&#x27;+esc(x.id)+&#x27;&quot;&gt;Archive&lt;\/button&gt;&lt;\/div&gt;&lt;\/div&gt;&#x27;).join(&#x27;&#x27;)+&#x27;&lt;\/div&gt;&lt;h3&gt;&#x27;+(item.id?&#x27;Edit&#x27;:&#x27;Add&#x27;)+&#x27; &#x27;+kind+&#x27;&lt;\/h3&gt;&lt;form id=&quot;directoryForm&quot;&gt;&lt;div class=&quot;formgrid&quot;&gt;&#x27;+field(&#x27;directory_name&#x27;,&#x27;Name&#x27;,&#x27;text&#x27;,item.name||&#x27;&#x27;,true)+(kind===&#x27;vehicle&#x27;?field(&#x27;directory_plate&#x27;,&#x27;Plate (if known)&#x27;,&#x27;text&#x27;,item.plate||&#x27;&#x27;)+field(&#x27;directory_capacity&#x27;,&#x27;Capacity&#x27;,&#x27;number&#x27;,item.capacity||&#x27;&#x27;)+field(&#x27;directory_source&#x27;,&#x27;Vehicle source&#x27;,null,item.vehicle_source||&#x27;own&#x27;,false,[&#x27;own&#x27;,&#x27;hired&#x27;])+field(&#x27;directory_fuel&#x27;,&#x27;Consumption (L \/ 100 km)&#x27;,&#x27;number&#x27;,item.fuel_consumption_l100km||&#x27;&#x27;):field(&#x27;directory_phone&#x27;,&#x27;Phone \/ WhatsApp&#x27;,&#x27;tel&#x27;,item.phone||&#x27;&#x27;))+&#x27;&lt;\/div&gt;&#x27;+field(&#x27;directory_notes&#x27;,&#x27;Notes \/ consumption source&#x27;,&#x27;text&#x27;,item.notes||&#x27;&#x27;)+&#x27;&lt;div class=&quot;formActions&quot;&gt;&lt;button class=&quot;btn&quot; type=&quot;submit&quot;&gt;Save &#x27;+kind+&#x27;&lt;\/button&gt;&lt;\/div&gt;&lt;\/form&gt;&#x27;;\n openOverlay();if($(&#x27;f_directory_fuel&#x27;)){$(&#x27;f_directory_fuel&#x27;).step=&#x27;0.01&#x27;;$(&#x27;f_directory_fuel&#x27;).min=&#x27;0.01&#x27;;}if($(&#x27;f_directory_capacity&#x27;))$(&#x27;f_directory_capacity&#x27;).min=&#x27;1&#x27;;$(&#x27;directoryVehicles&#x27;).onclick=()=&gt;directoryDialog(&#x27;vehicle&#x27;);$(&#x27;directoryDrivers&#x27;).onclick=()=&gt;directoryDialog(&#x27;driver&#x27;);\n $(&#x27;dialogBody&#x27;).querySelectorAll(&#x27;[data-directory-edit]&#x27;).forEach(b=&gt;b.onclick=()=&gt;directoryDialog(kind,b.dataset.directoryEdit));\n $(&#x27;dialogBody&#x27;).querySelectorAll(&#x27;[data-directory-archive]&#x27;).forEach(b=&gt;b.onclick=async()=&gt;{try{await request(&#x27;directory&#x27;,{id:b.dataset.directoryArchive,archive:true});await directoryDialog(kind);toast(&#x27;Archived; existing bookings kept&#x27;);}catch(e){toast(e.message,true)}});\n $(&#x27;directoryForm&#x27;).onsubmit=async e=&gt;{e.preventDefault();try{await request(&#x27;directory&#x27;,{id:item.id||undefined,kind,name:formVal(&#x27;directory_name&#x27;),plate:kind===&#x27;vehicle&#x27;?formVal(&#x27;directory_plate&#x27;):null,capacity:kind===&#x27;vehicle&#x27;?formVal(&#x27;directory_capacity&#x27;):null,vehicle_source:kind===&#x27;vehicle&#x27;?formVal(&#x27;directory_source&#x27;):&#x27;own&#x27;,fuel_consumption_l100km:kind===&#x27;vehicle&#x27;?formVal(&#x27;directory_fuel&#x27;):null,notes:formVal(&#x27;directory_notes&#x27;),phone:kind===&#x27;driver&#x27;?formVal(&#x27;directory_phone&#x27;):null});await directoryDialog(kind);toast(&#x27;Saved&#x27;);}catch(e){toast(e.message,true)}};\n}\n\nfunction dispatchForm(r){$(&quot;dialogTitle&quot;).textContent=&quot;Assign \u00b7 &quot;+r.customer_name;let h=&#x27;&lt;form id=&quot;dispatchForm&quot;&gt;&lt;div class=&quot;banner&quot;&gt;Assign this journey leg separately. Overlap warnings never block a booking: choose hired if you outsource the vehicle. Estimated finish times improve warnings.&lt;\/div&gt;&lt;div class=&quot;formgrid&quot;&gt;&#x27;+field(&quot;pickup_time&quot;,&quot;Confirmed vehicle pickup time&quot;,&quot;time&quot;,r.pickup_time||&quot;&quot;)+field(&quot;end_at&quot;,&quot;Estimated vehicle finish (Albania time)&quot;,&quot;datetime-local&quot;,r.end_at?albaniaLocal(r.end_at):&quot;&quot;)+field(&quot;vehicle_source&quot;,&quot;Vehicle source&quot;,null,r.vehicle_source||&quot;own&quot;,false,[&quot;own&quot;,&quot;hired&quot;])+field(&quot;dispatch_status&quot;,&quot;Dispatch status&quot;,null,r.dispatch_status||&quot;unassigned&quot;,false,[&quot;unassigned&quot;,&quot;assigned&quot;,&quot;in_progress&quot;,&quot;completed&quot;,&quot;cancelled&quot;])+directoryPicker(&quot;vehicle&quot;)+directoryPicker(&quot;driver&quot;)+field(&quot;vehicle_name&quot;,&quot;Vehicle name&quot;,&quot;text&quot;,r.vehicle_name&amp;&amp;r.vehicle_name!==&quot;Unassigned&quot;?r.vehicle_name:&quot;&quot;)+field(&quot;vehicle_plate&quot;,&quot;Vehicle plate&quot;,&quot;text&quot;,r.vehicle_plate&amp;&amp;r.vehicle_plate!==&quot;UNASSIGNED&quot;?r.vehicle_plate:&quot;&quot;)+field(&quot;vehicle_capacity&quot;,&quot;Capacity&quot;,&quot;number&quot;,r.vehicle_capacity||&quot;&quot;)+field(&quot;driver_name&quot;,&quot;Driver name&quot;,&quot;text&quot;,r.driver_name||&quot;&quot;)+field(&quot;driver_phone&quot;,&quot;Driver phone&quot;,&quot;tel&quot;,r.driver_phone||&quot;&quot;)+&#x27;&lt;\/div&gt;&#x27;+field(&quot;dispatch_notes&quot;,&quot;Dispatch notes&quot;,&quot;text&quot;,r.dispatch_notes||&quot;&quot;)+&#x27;&lt;div id=&quot;conflictWarning&quot; class=&quot;msg hide&quot;&gt;&lt;\/div&gt;&lt;div class=&quot;formActions&quot;&gt;&lt;button class=&quot;btn secondary&quot; type=&quot;button&quot; id=&quot;cancelForm&quot;&gt;Cancel&lt;\/button&gt;&lt;button class=&quot;btn&quot; type=&quot;submit&quot;&gt;Save assignment&lt;\/button&gt;&lt;\/div&gt;&lt;\/form&gt;&#x27;;$(&quot;dialogBody&quot;).innerHTML=h;openOverlay();wireDirectoryPickers();for(const n of [&quot;vehicle_plate&quot;,&quot;pickup_time&quot;,&quot;end_at&quot;])$(&quot;f_&quot;+n).addEventListener(&quot;input&quot;,()=&gt;checkConflict(r));checkConflict(r);$(&quot;dispatchForm&quot;).onsubmit=async(e)=&gt;{e.preventDefault();const values={};[&quot;pickup_time&quot;,&quot;end_at&quot;,&quot;vehicle_source&quot;,&quot;dispatch_status&quot;,&quot;vehicle_name&quot;,&quot;vehicle_plate&quot;,&quot;vehicle_capacity&quot;,&quot;driver_name&quot;,&quot;driver_phone&quot;,&quot;dispatch_notes&quot;].forEach(n=&gt;values[n]=formVal(n));if(values.end_at){const finish=Date.parse(values.end_at),start=Date.parse(r.service_date+&#x27;T&#x27;+String(values.pickup_time||r.service_time||&#x27;00:00&#x27;).slice(0,5));if(finish&lt;=start){toast(&#x27;Estimated finish must be after pickup.&#x27;,true);return;}values.end_at=albaniaIso(values.end_at);}try{await request(&quot;dispatch&quot;,{source_system:r.source_system,source_record_id:r.source_record_id,leg_type:r.leg_type,values});closeOverlay();toast(&quot;Assignment saved&quot;);await load()}catch(e){toast(e.message,true)}}}\nfunction albaniaLocal(value){return new Intl.DateTimeFormat(&#x27;sv-SE&#x27;,{timeZone:&#x27;Europe\/Tirane&#x27;,year:&#x27;numeric&#x27;,month:&#x27;2-digit&#x27;,day:&#x27;2-digit&#x27;,hour:&#x27;2-digit&#x27;,minute:&#x27;2-digit&#x27;,hourCycle:&#x27;h23&#x27;}).format(new Date(value)).replace(&#x27; &#x27;,&#x27;T&#x27;);}\nfunction albaniaIso(value){const target=Date.parse(value+&#x27;Z&#x27;);let utc=target;for(let i=0;i&lt;3;i++){const shown=Date.parse(albaniaLocal(new Date(utc).toISOString())+&#x27;:00Z&#x27;);utc+=target-shown;}return new Date(utc).toISOString();}\nfunction windowFor(r){const start=r.service_time||r.pickup_time?Date.parse(r.service_date+&#x27;T&#x27;+String(r.pickup_time||r.service_time).slice(0,5)):null;return {start,end:r.end_at?Date.parse(albaniaLocal(r.end_at)):null};}\nfunction conflicts(a,b){if(a.record_key===b.record_key||a.booking_status===&#x27;cancelled&#x27;||b.booking_status===&#x27;cancelled&#x27;||a.dispatch_status===&#x27;cancelled&#x27;||b.dispatch_status===&#x27;cancelled&#x27;)return false;const plate=String(a.vehicle_plate||&#x27;&#x27;).trim().toLowerCase();if(!plate||plate===&#x27;unassigned&#x27;||plate!==String(b.vehicle_plate||&#x27;&#x27;).trim().toLowerCase())return false;const x=windowFor(a),y=windowFor(b);if(x.start!==null&amp;&amp;x.end!==null&amp;&amp;y.start!==null&amp;&amp;y.end!==null)return x.start&lt;y.end&amp;&amp;y.start&lt;x.end;return a.service_date===b.service_date;}\nfunction checkConflict(r){const draft={...r,vehicle_plate:formVal(&#x27;vehicle_plate&#x27;),pickup_time:formVal(&#x27;pickup_time&#x27;)||r.service_time,end_at:formVal(&#x27;end_at&#x27;)?albaniaIso(formVal(&#x27;end_at&#x27;)):null};const others=rows.filter(x=&gt;conflicts(draft,x));const el=$(&#x27;conflictWarning&#x27;);if(others.length){el.classList.remove(&#x27;hide&#x27;);el.textContent=&#x27;\u26a0 Possible vehicle overlap: &#x27;+others.map(x=&gt;x.reference+&#x27; \u00b7 &#x27;+x.service_date+&#x27; &#x27;+String(x.pickup_time||x.service_time||&#x27;&#x27;)).join(&#x27;, &#x27;)+&#x27;. You can still save and accept bookings. Assign a hired vehicle if needed. Without estimated finish times, warnings are based on the same date.&#x27;;}else el.classList.add(&#x27;hide&#x27;);}\nfunction driverMessage(r){\n const statuses={confirmed:&#x27;Konfirmuar&#x27;,awaiting_payment:&#x27;N\u00eb pritje t\u00eb pages\u00ebs&#x27;,prebooked:&#x27;Rezervim paraprak&#x27;,completed:&#x27;P\u00ebrfunduar&#x27;,cancelled:&#x27;Anuluar&#x27;};\n const date=r.service_date?new Date(r.service_date+&#x27;T12:00:00&#x27;).toLocaleDateString(&#x27;sq-AL&#x27;,{day:&#x27;numeric&#x27;,month:&#x27;long&#x27;,year:&#x27;numeric&#x27;}):&#x27;P\u00ebr t\u2019u konfirmuar&#x27;;\n const time=r.pickup_time||r.service_time;\n return [\n &#x27;\ud83d\ude90 *ALBANIANBUS \u2014 TRANSFERT\u00cb*&#x27;,\n &#x27;\ud83d\udd16 *Rezervimi:* &#x27;+r.reference,\n r.leg_type===&#x27;return&#x27;?&#x27;\ud83d\udd01 *Udh\u00ebtimi i kthimit*&#x27;:r.leg_type===&#x27;outbound&#x27;?&#x27;\u27a1\ufe0f *Udh\u00ebtimi i vajtjes*&#x27;:&#x27;\u27a1\ufe0f *Vet\u00ebm vajtje*&#x27;,\n &#x27;&#x27;,\n &#x27;\ud83d\udcc5 *Data:* &#x27;+date,\n &#x27;\ud83d\udd52 *Ora e marrjes:* &#x27;+(time?String(time).slice(0,5):&#x27;P\u00ebr t\u2019u konfirmuar&#x27;)+&#x27; (ora e Shqip\u00ebris\u00eb)&#x27;,\n &#x27;&#x27;,\n &#x27;\ud83d\udccd *Marrja:* &#x27;+r.origin,\n &#x27;\ud83c\udfe8 *Adresa e marrjes:* &#x27;+(r.pickup_location||&#x27;P\u00ebr t\u2019u konfirmuar&#x27;),\n &#x27;&#x27;,\n &#x27;\ud83c\udfc1 *Destinacioni:* &#x27;+r.destination,\n &#x27;\ud83d\udccc *Adresa e mb\u00ebrritjes:* &#x27;+(r.dropoff_location||&#x27;P\u00ebr t\u2019u konfirmuar&#x27;),\n &#x27;&#x27;,\n &#x27;\ud83d\udc65 *Pasagjer\u00eb:* &#x27;+r.passenger_count,\n &#x27;\ud83d\ude4d *Klienti:* &#x27;+r.customer_name,\n r.customer_phone?&#x27;\ud83d\udcde *Telefoni i klientit:* &#x27;+r.customer_phone:null,\n r.flight_number?&#x27;\u2708\ufe0f *Fluturimi:* &#x27;+r.flight_number:null,\n &#x27;&#x27;,\n &#x27;\ud83d\ude98 *Mjeti:* &#x27;+(r.vehicle_name||&#x27;I pacaktuar&#x27;),\n &#x27;\ud83d\udd22 *Targa:* &#x27;+(r.vehicle_plate||&#x27;E pacaktuar&#x27;),\n r.vehicle_source===&#x27;hired&#x27;?&#x27;\ud83e\udd1d *Mjet i marr\u00eb me qira \/ i jasht\u00ebm*&#x27;:null,\n r.driver_name?&#x27;\ud83d\udc68\u200d\u2708\ufe0f *Shoferi:* &#x27;+r.driver_name:null,\n r.driver_phone?&#x27;\u260e\ufe0f *Telefoni i shoferit:* &#x27;+r.driver_phone:null,\n &#x27;&#x27;,\n &#x27;\ud83d\udccb *Statusi:* &#x27;+(statuses[bookingStatus(r)]||&#x27;P\u00ebr t\u2019u konfirmuar&#x27;)\n ].filter(line=&gt;line!==null).join(&#x27;\\n&#x27;);\n}\nasync function shareBooking(r){\n const popup=window.open(&#x27;about:blank&#x27;,&#x27;_blank&#x27;);try{\n let text=driverMessage(r);\n if([&#x27;confirmed&#x27;,&#x27;completed&#x27;].includes(bookingStatus(r))&amp;&amp;r.dispatch_status===&#x27;unassigned&#x27;){throw Error(&#x27;Save the driver and vehicle assignment before sharing. Open Assign vehicle and save; the status will become Assigned.&#x27;);}\n if([&#x27;confirmed&#x27;,&#x27;completed&#x27;].includes(bookingStatus(r))&amp;&amp;[&#x27;assigned&#x27;,&#x27;in_progress&#x27;,&#x27;completed&#x27;].includes(r.dispatch_status)){\n const access=await request(&#x27;driver-access&#x27;,{source_system:r.source_system,source_record_id:r.source_record_id,leg_type:r.leg_type});\n text+=&#x27;\\n\\n\ud83c\udfab *Validimi i bilet\u00ebs s\u00eb klientit*\\nHapni k\u00ebt\u00eb lidhje p\u00ebrpara udh\u00ebtimit. Pastaj skanoni QR-n\u00eb e klientit me kamer\u00ebn e telefonit ose vendosni kodin e tij n\u00eb faqe.\\n&#x27;+access.driver_url;\n }\n const url=&#x27;https:\/\/wa.me\/?text=&#x27;+encodeURIComponent(text);if(popup)popup.location.href=url;else location.href=url;\n }catch(e){if(popup)popup.close();toast(e.message,true);}\n}\nasync function showTicket(r){\n try{const t=await request(&#x27;ticket&#x27;,{source_system:r.source_system,source_record_id:r.source_record_id,leg_type:r.leg_type});\n $(&#x27;dialogTitle&#x27;).textContent=&#x27;QR ticket \u00b7 &#x27;+r.reference;\n $(&#x27;dialogBody&#x27;).innerHTML=&#x27;&lt;div style=&quot;text-align:center&quot;&gt;&lt;span class=&quot;pill &#x27;+(t.validated_at?&#x27;qr-validated&#x27;:&#x27;qr-pending&#x27;)+&#x27;&quot;&gt;&#x27;+(t.validated_at?&#x27;\u2713 QR validated&#x27;:&#x27;QR not validated&#x27;)+&#x27;&lt;\/span&gt;&lt;p&gt;&#x27;+esc(r.origin)+&#x27; \u2192 &#x27;+esc(r.destination)+&#x27;&lt;br&gt;&#x27;+esc(shortDate(r.service_date))+&#x27; \u00b7 &#x27;+esc(r.leg_type)+&#x27;&lt;\/p&gt;&lt;img alt=&quot;Transfer ticket QR code&quot; style=&quot;max-width:100%;width:280px;height:auto&quot; src=&quot;&#x27;+t.qr_data_url+&#x27;&quot;&gt;&lt;p&gt;Ticket code: &lt;strong&gt;&#x27;+esc(t.short_code)+&#x27;&lt;\/strong&gt;&lt;\/p&gt;&lt;a href=&quot;&#x27;+esc(t.ticket_url)+&#x27;&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Open ticket&lt;\/a&gt;&lt;\/div&gt;&lt;div class=&quot;formActions&quot;&gt;&lt;button class=&quot;btn outline&quot; id=&quot;backToBooking&quot;&gt;Back to booking&lt;\/button&gt;&lt;\/div&gt;&#x27;;\n openOverlay();\n }catch(e){toast(e.message,true);}\n}\n\n\nfunction reportBounds(period,date){const d=new Date(date+&#x27;T12:00:00&#x27;);let from=new Date(d),to=new Date(d);if(period===&#x27;week&#x27;){from.setDate(d.getDate()-((d.getDay()+6)%7));to=new Date(from);to.setDate(from.getDate()+6);}if(period===&#x27;month&#x27;){from=new Date(d.getFullYear(),d.getMonth(),1);to=new Date(d.getFullYear(),d.getMonth()+1,0);}return {from:iso(from),to:iso(to)};}\nfunction reportRows(period,date,plate){const bounds=reportBounds(period,date);return visible().filter(r=&gt;r.service_date&gt;=bounds.from&amp;&amp;r.service_date&lt;=bounds.to&amp;&amp;(!plate||(plate===&#x27;__unassigned&#x27;?(!r.vehicle_plate||r.vehicle_plate===&#x27;UNASSIGNED&#x27;):r.vehicle_plate===plate))).sort((a,b)=&gt;String(a.vehicle_plate||&#x27;&#x27;).localeCompare(String(b.vehicle_plate||&#x27;&#x27;))||String(a.service_date).localeCompare(String(b.service_date))||String(a.pickup_time||a.service_time||&#x27;&#x27;).localeCompare(String(b.pickup_time||b.service_time||&#x27;&#x27;)));}\nfunction reportText(items,bounds){return [&#x27;ALBANIANBUS \u00b7 RAPORT TRANSFERTASH&#x27;,bounds.from+&#x27; \u2014 &#x27;+bounds.to,&#x27;Udh\u00ebtime: &#x27;+items.length,&#x27;&#x27;].concat(items.flatMap(r=&gt;[&#x27;\ud83d\ude98 &#x27;+(r.vehicle_plate||&#x27;Mjet i pacaktuar&#x27;)+(r.vehicle_source===&#x27;hired&#x27;?&#x27; \u00b7 Me qira&#x27;:&#x27;&#x27;),&#x27;\ud83d\udcc5 &#x27;+r.service_date+&#x27; \u00b7 &#x27;+String(r.pickup_time||r.service_time||&#x27;P\u00ebr t\u2019u konfirmuar&#x27;).slice(0,5),&#x27;\ud83d\udd16 &#x27;+r.reference+&#x27; \u00b7 &#x27;+(r.leg_type===&#x27;return&#x27;?&#x27;Kthim&#x27;:r.leg_type===&#x27;outbound&#x27;?&#x27;Vajtje&#x27;:&#x27;Nj\u00eb drejtim&#x27;),&#x27;\ud83d\udccd &#x27;+r.origin+&#x27; \u2192 &#x27;+r.destination,&#x27;\ud83d\udc65 &#x27;+r.passenger_count+&#x27; \u00b7 &#x27;+r.customer_name,&#x27;\ud83d\udc68\u200d\u2708\ufe0f &#x27;+(r.driver_name||&#x27;Shofer i pacaktuar&#x27;),&#x27;\ud83d\udccb &#x27;+bookingStatus(r)+(r.qr_validated_at?&#x27; \u00b7 \u2705 QR i validuar&#x27;:&#x27;&#x27;),rows.some(x=&gt;conflicts(r,x))?&#x27;\u26a0\ufe0f Mbivendosje e mundshme \u2014 kontrolloni oraret.&#x27;:&#x27;&#x27;,&#x27;&#x27;])).join(&#x27;\\n&#x27;);}\nfunction reportsDialog(){\n $(&#x27;dialogTitle&#x27;).textContent=&#x27;Transfer reports&#x27;;\n const selected=selectedDate||new Intl.DateTimeFormat(&#x27;en-CA&#x27;,{timeZone:&#x27;Europe\/Tirane&#x27;}).format(new Date());\n const plates=[...new Set(rows.map(r=&gt;r.vehicle_plate).filter(x=&gt;x&amp;&amp;x!==&#x27;UNASSIGNED&#x27;))].sort();\n $(&#x27;dialogBody&#x27;).innerHTML=&#x27;&lt;p class=&quot;tiny&quot;&gt;Reports use your current booking, payment, dispatch, QR and search filters. Overlap warnings never block bookings.&lt;\/p&gt;&lt;div class=&quot;formgrid&quot;&gt;&lt;label class=&quot;field&quot;&gt;Period&lt;select id=&quot;reportPeriod&quot;&gt;&lt;option value=&quot;day&quot;&gt;Daily&lt;\/option&gt;&lt;option value=&quot;week&quot;&gt;Weekly (Monday\u2013Sunday)&lt;\/option&gt;&lt;option value=&quot;month&quot;&gt;Monthly&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;label class=&quot;field&quot;&gt;Date&lt;input type=&quot;date&quot; id=&quot;reportDate&quot; value=&quot;&#x27;+esc(selected)+&#x27;&quot;&gt;&lt;\/label&gt;&lt;label class=&quot;field&quot;&gt;Vehicle&lt;select id=&quot;reportVehicle&quot;&gt;&lt;option value=&quot;&quot;&gt;All vehicles \u2014 grouped by plate&lt;\/option&gt;&lt;option value=&quot;__unassigned&quot;&gt;Needs a vehicle&lt;\/option&gt;&#x27;+plates.map(p=&gt;&#x27;&lt;option value=&quot;&#x27;+esc(p)+&#x27;&quot;&gt;&#x27;+esc(p)+&#x27;&lt;\/option&gt;&#x27;).join(&#x27;&#x27;)+&#x27;&lt;\/select&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;div id=&quot;reportPreview&quot;&gt;&lt;\/div&gt;&lt;div class=&quot;formActions hidePrint&quot;&gt;&lt;button class=&quot;btn outline&quot; id=&quot;printReport&quot;&gt;Print \/ Save PDF&lt;\/button&gt;&lt;button class=&quot;btn&quot; id=&quot;shareReport&quot;&gt;Share report&lt;\/button&gt;&lt;button class=&quot;btn secondary&quot; id=&quot;copyReport&quot;&gt;Copy report text&lt;\/button&gt;&lt;\/div&gt;&#x27;;\n const generate=()=&gt;{const date=$(&#x27;reportDate&#x27;).value;if(!date)return;const bounds=reportBounds($(&#x27;reportPeriod&#x27;).value,date),items=reportRows($(&#x27;reportPeriod&#x27;).value,date,$(&#x27;reportVehicle&#x27;).value),overlaps=items.filter(r=&gt;rows.some(x=&gt;conflicts(r,x))).length;\n const body=&#x27;&lt;h2&gt;AlbanianBus \u00b7 Transfer report&lt;\/h2&gt;&lt;p&gt;&#x27;+esc(bounds.from)+&#x27; \u2014 &#x27;+esc(bounds.to)+&#x27; \u00b7 Albania local times&lt;\/p&gt;&lt;p&gt;&lt;strong&gt;&#x27;+items.length+&#x27; journey legs&lt;\/strong&gt; \u00b7 &#x27;+overlaps+&#x27; possible overlaps \u00b7 &#x27;+items.filter(r=&gt;r.qr_validated_at).length+&#x27; QR validated&lt;\/p&gt;&lt;p&gt;Booked leg value (excluding cancelled): &#x27;+cash(items.filter(r=&gt;bookingStatus(r)!==&#x27;cancelled&#x27;).reduce((sum,r)=&gt;sum+Number(r.agreed_price_eur||0),0))+&#x27;&lt;\/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Vehicle \/ driver&lt;\/th&gt;&lt;th&gt;Date \/ time&lt;\/th&gt;&lt;th&gt;Booking \/ journey&lt;\/th&gt;&lt;th&gt;Passengers&lt;\/th&gt;&lt;th&gt;Status&lt;\/th&gt;&lt;\/tr&gt;&lt;\/thead&gt;&lt;tbody&gt;&#x27;+items.map(r=&gt;&#x27;&lt;tr class=&quot;&#x27;+(rows.some(x=&gt;conflicts(r,x))?&#x27;overlap-row&#x27;:&#x27;&#x27;)+&#x27;&quot;&gt;&lt;td&gt;&#x27;+esc(r.vehicle_plate||&#x27;Unassigned&#x27;)+&#x27;&lt;br&gt;&#x27;+esc(r.driver_name||&#x27;Driver unassigned&#x27;)+(r.vehicle_source===&#x27;hired&#x27;?&#x27;&lt;br&gt;Hired&#x27;:&#x27;&#x27;)+&#x27;&lt;\/td&gt;&lt;td&gt;&#x27;+esc(r.service_date)+&#x27;&lt;br&gt;&#x27;+esc(String(r.pickup_time||r.service_time||&#x27;&#x27;).slice(0,5))+(r.end_at?&#x27;&lt;br&gt;Until &#x27;+esc(albaniaLocal(r.end_at).replace(&#x27;T&#x27;,&#x27; &#x27;)):&#x27;&#x27;)+&#x27;&lt;\/td&gt;&lt;td&gt;&#x27;+esc(r.reference)+&#x27; \u00b7 &#x27;+esc(r.leg_type)+&#x27;&lt;br&gt;&#x27;+esc(r.origin)+&#x27; \u2192 &#x27;+esc(r.destination)+&#x27;&lt;br&gt;&#x27;+esc(r.customer_name)+&#x27;&lt;\/td&gt;&lt;td&gt;&#x27;+esc(r.passenger_count)+&#x27;&lt;\/td&gt;&lt;td&gt;&#x27;+esc(bookingStatus(r))+&#x27;&lt;br&gt;&#x27;+esc(r.payment_status)+(r.qr_validated_at?&#x27;&lt;br&gt;\u2713 QR validated&#x27;:&#x27;&#x27;)+(rows.some(x=&gt;conflicts(r,x))?&#x27;&lt;br&gt;\u26a0 Possible overlap&#x27;:&#x27;&#x27;)+&#x27;&lt;\/td&gt;&lt;\/tr&gt;&#x27;).join(&#x27;&#x27;)+&#x27;&lt;\/tbody&gt;&lt;\/table&gt;&#x27;+(items.length?&#x27;&#x27;:&#x27;&lt;p&gt;No journeys match this period and filters.&lt;\/p&gt;&#x27;);\n $(&#x27;reportPreview&#x27;).innerHTML=body;return {items,bounds,body,text:reportText(items,bounds)};};\n for(const id of [&#x27;reportPeriod&#x27;,&#x27;reportDate&#x27;,&#x27;reportVehicle&#x27;])$(id).onchange=generate;\n $(&#x27;printReport&#x27;).onclick=()=&gt;{const report=generate();if(!report)return;const popup=window.open(&#x27;about:blank&#x27;,&#x27;_blank&#x27;);if(!popup){toast(&#x27;Allow pop-ups to print the report.&#x27;,true);return}popup.document.write(&#x27;&lt;!doctype html&gt;&lt;html&gt;&lt;head&gt;&lt;title&gt;AlbanianBus report &#x27;+report.bounds.from+&#x27;&lt;\/title&gt;&lt;style&gt;body{font:12px Arial;color:#291e3d;padding:20px}table{width:100%;border-collapse:collapse}td,th{border:1px solid #ddd;padding:8px;text-align:left;vertical-align:top;overflow-wrap:anywhere}thead{display:table-header-group}tr{break-inside:avoid}.overlap-row{background:#fff0d8}h2{color:#703da5}@page{size:A4 landscape;margin:12mm}&lt;\/style&gt;&lt;\/head&gt;&lt;body&gt;&#x27;+report.body+&#x27;&lt;\/body&gt;&lt;\/html&gt;&#x27;);popup.document.close();popup.focus();setTimeout(()=&gt;popup.print(),250);};\n $(&#x27;copyReport&#x27;).onclick=async()=&gt;{try{const r=generate();if(r){await navigator.clipboard.writeText(r.text);toast(&#x27;Report text copied&#x27;);}}catch{toast(&#x27;Use Print \/ Save PDF to share this report.&#x27;,true)}};\n $(&#x27;shareReport&#x27;).onclick=async()=&gt;{const r=generate();if(!r)return;if(navigator.share){try{await navigator.share({title:&#x27;AlbanianBus transfer report&#x27;,text:r.text});return}catch(e){if(e.name===&#x27;AbortError&#x27;)return;}}if(r.text.length&gt;6000){toast(&#x27;For a long report, use Print \/ Save PDF and attach the PDF in WhatsApp, or Copy report text.&#x27;,true);return}window.open(&#x27;https:\/\/wa.me\/?text=&#x27;+encodeURIComponent(r.text),&#x27;_blank&#x27;,&#x27;noopener,noreferrer&#x27;);};\n generate();openOverlay();\n}\n\nfunction printVoucher(r){const val=APP_URL+&quot;&amp;ref=&quot;+encodeURIComponent(r.reference);const wrap=document.createElement(&quot;div&quot;);wrap.innerHTML=&#x27;&lt;div style=&quot;font:16px Arial;color:#143450;padding:20px&quot;&gt;&lt;h1&gt;ALBANIAN BUS&lt;\/h1&gt;&lt;h2&gt;Private transfer voucher&lt;\/h2&gt;&lt;p&gt;&lt;b&gt;Reservation:&lt;\/b&gt; &#x27;+esc(r.reference)+&#x27;&lt;\/p&gt;&lt;p&gt;&lt;b&gt;Customer:&lt;\/b&gt; &#x27;+esc(r.customer_name)+&#x27; \u00b7 &#x27;+esc(r.passenger_count)+&#x27; passengers&lt;\/p&gt;&lt;p&gt;&lt;b&gt;Date:&lt;\/b&gt; &#x27;+esc(shortDate(r.service_date))+&#x27;&lt;\/p&gt;&lt;p&gt;&lt;b&gt;Route:&lt;\/b&gt; &#x27;+esc(r.origin)+&#x27; \u2192 &#x27;+esc(r.destination)+&#x27;&lt;\/p&gt;&lt;p&gt;&lt;b&gt;Pickup:&lt;\/b&gt; &#x27;+esc(r.pickup_location||&quot;To be confirmed&quot;)+&#x27;&lt;\/p&gt;&lt;p&gt;&lt;b&gt;Drop-off:&lt;\/b&gt; &#x27;+esc(r.dropoff_location||&quot;To be confirmed&quot;)+&#x27;&lt;\/p&gt;&lt;p&gt;&lt;b&gt;Pickup time:&lt;\/b&gt; &#x27;+esc(r.pickup_time||r.service_time||&quot;To be confirmed&quot;)+&#x27;&lt;\/p&gt;&lt;p&gt;&lt;b&gt;Flight:&lt;\/b&gt; &#x27;+esc(r.flight_number||&quot;\u2014&quot;)+&#x27;&lt;\/p&gt;&lt;p&gt;&lt;b&gt;Vehicle:&lt;\/b&gt; &#x27;+esc(r.vehicle_name||&quot;To be assigned&quot;)+&#x27; \u00b7 &#x27;+esc(r.vehicle_plate||&quot;&quot;)+&#x27;&lt;\/p&gt;&lt;p&gt;&lt;b&gt;Status:&lt;\/b&gt; &#x27;+esc(bookingStatus(r))+&#x27;&lt;\/p&gt;&lt;div id=&quot;qr&quot; style=&quot;margin-top:20px&quot;&gt;&lt;\/div&gt;&lt;p style=&quot;font-size:12px&quot;&gt;QR opens reservation in the secure admin calendar; staff sign-in required.&lt;\/p&gt;&lt;\/div&gt;&#x27;;const w=window.open(&quot;&quot;,&quot;_blank&quot;);if(!w){toast(&quot;Allow pop-ups to print voucher.&quot;,true);return}w.document.open();w.document.write(&quot;&lt;!doctype html&gt;&lt;html&gt;&lt;head&gt;&lt;title&gt;Transfer voucher &quot;+esc(r.reference)+&quot;&lt;\/title&gt;&lt;\/head&gt;&lt;body&gt;&quot;+wrap.innerHTML+&quot;&lt;\/body&gt;&lt;\/html&gt;&quot;);w.document.close();const s=w.document.createElement(&quot;script&quot;);s.src=&quot;https:\/\/cdn.jsdelivr.net\/npm\/qrcodejs@1.0.0\/qrcode.min.js&quot;;s.onload=()=&gt;{try{new w.QRCode(w.document.getElementById(&quot;qr&quot;),{text:val,width:148,height:148})}catch(_e){}setTimeout(()=&gt;w.print(),550)};w.document.head.appendChild(s)}\ndocument.addEventListener(&quot;click&quot;,e=&gt;{const el=e.target.closest(&quot;button&quot;);if(!el)return;if(el.dataset.day){selectedDate=el.dataset.day;const dt=new Date(selectedDate+&quot;T12:00:00&quot;);month=new Date(dt.getFullYear(),dt.getMonth(),1);paint()}if(el.dataset.record)openDetail(el.dataset.record);if(el.dataset.view){view=el.dataset.view;paint()}if(el.id===&quot;closeDialog&quot;||el.id===&quot;cancelForm&quot;)closeOverlay();if(el.id===&quot;editDispatch&quot;&amp;&amp;current)dispatchForm(current);if(el.id===&quot;editManual&quot;&amp;&amp;current)manualForm(current);if(el.id===&quot;shareBooking&quot;&amp;&amp;current)shareBooking(current);if(el.id===&quot;openDirectory&quot;)directoryDialog();if(el.id===&quot;recordCash&quot;&amp;&amp;current)recordCash(current);if(el.dataset.voidCash)voidCash(el.dataset.voidCash);if(el.id===&quot;openCashReport&quot;)cashReportsDialog();if(el.id===&quot;openReports&quot;)reportsDialog();if(el.id===&quot;showTicket&quot;&amp;&amp;current)showTicket(current);if(el.id===&quot;backToBooking&quot;&amp;&amp;current)openDetail(current.record_key);if(el.id===&quot;printBooking&quot;&amp;&amp;current)printVoucher(current)});\n$(&quot;prevMonth&quot;).onclick=()=&gt;{month=new Date(month.getFullYear(),month.getMonth()-1,1);selectedDate=iso(new Date(month.getFullYear(),month.getMonth(),1));paint()};\n$(&quot;nextMonth&quot;).onclick=()=&gt;{month=new Date(month.getFullYear(),month.getMonth()+1,1);selectedDate=iso(new Date(month.getFullYear(),month.getMonth(),1));paint()};\n$(&quot;todayBtn&quot;).onclick=()=&gt;{month=new Date();selectedDate=iso(new Date());paint()};\n$(&quot;search&quot;).oninput=paint;for(const id of [&#x27;bookingStatusFilter&#x27;,&#x27;paymentStatusFilter&#x27;,&#x27;dispatchStatusFilter&#x27;,&#x27;qrStatusFilter&#x27;])$(id).onchange=paint;$(&#x27;clearFilters&#x27;).onclick=()=&gt;{$(&#x27;search&#x27;).value=&#x27;&#x27;;for(const id of [&#x27;bookingStatusFilter&#x27;,&#x27;paymentStatusFilter&#x27;,&#x27;dispatchStatusFilter&#x27;,&#x27;qrStatusFilter&#x27;])$(id).value=&#x27;&#x27;;paint();};$(&quot;showTests&quot;).onchange=async(e)=&gt;{activeTests=e.target.checked;await load()};\n$(&quot;refresh&quot;).onclick=()=&gt;load();$(&quot;newBook&quot;).onclick=()=&gt;manualForm(null);$(&quot;mobileNew&quot;).onclick=()=&gt;manualForm(null);$(&quot;closeDialog&quot;).onclick=closeOverlay;$(&quot;overlay&quot;).onclick=e=&gt;{if(e.target===$(&quot;overlay&quot;))closeOverlay()};\n$(&quot;logout&quot;).onclick=async()=&gt;{await auth.auth.signOut();leave()};\n$(&quot;loginForm&quot;).onsubmit=async e=&gt;{e.preventDefault();if(!auth)return;const email=$(&quot;email&quot;).value.trim().toLowerCase(),password=$(&quot;password&quot;).value;const {error}=await auth.auth.signInWithPassword({email,password});if(error)alertLogin(error.message,true)};\n$(&quot;signup&quot;).onclick=async()=&gt;{if(!auth)return;const email=$(&quot;email&quot;).value.trim().toLowerCase(),password=$(&quot;password&quot;).value;if(!email||password.length&lt;8){alertLogin(&quot;Enter your email and a password with at least 8 characters.&quot;,true);return}const {error}=await auth.auth.signUp({email,password,options:{emailRedirectTo:APP_URL}});alertLogin(error?error.message:&quot;Account request submitted. Check your inbox to confirm your email, then sign in.&quot;,!!error)};\n$(&quot;magic&quot;).onclick=async()=&gt;{if(!auth)return;const email=$(&quot;email&quot;).value.trim().toLowerCase();if(!email){alertLogin(&quot;Enter your email address first.&quot;,true);return}const {error}=await auth.auth.signInWithOtp({email,options:{emailRedirectTo:APP_URL,shouldCreateUser:false}});alertLogin(error?error.message:&quot;Check your email for a sign-in link. If you do not have an account, use Create account first.&quot;,!!error)};\nsetInterval(()=&gt;{if(session&amp;&amp;!loading&amp;&amp;!$(&#x27;dashboard&#x27;).classList.contains(&#x27;hide&#x27;)&amp;&amp;document.visibilityState===&#x27;visible&#x27;&amp;&amp;$(&#x27;overlay&#x27;).classList.contains(&#x27;hide&#x27;))load();},45000);\nauthInit();\n})();\n&lt;\/script&gt;&lt;\/body&gt;&lt;\/html&gt;\"><\/iframe><style>html,body{margin:0!important;padding:0!important}.elementor-97876 .e-con,.elementor-97876 .e-con-inner,.elementor-97876 .elementor-widget-container{padding:0!important;max-width:100%!important;width:100%!important;min-width:0!important}#ab-staff-calendar{width:100%!important}<\/style>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-97876","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>AlbanianBus Transfers Staff Calendar - Albanian Bus<\/title>\n<meta name=\"robots\" content=\"noindex, follow\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"AlbanianBus Transfers Staff Calendar - Albanian Bus\" \/>\n<meta property=\"og:url\" content=\"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/\" \/>\n<meta property=\"og:site_name\" content=\"Albanian Bus\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-24T21:13:46+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/\",\"url\":\"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/\",\"name\":\"AlbanianBus Transfers Staff Calendar - Albanian Bus\",\"isPartOf\":{\"@id\":\"https:\/\/albanianbus.com\/wordpress\/#website\"},\"datePublished\":\"2026-10-24T19:36:54+00:00\",\"dateModified\":\"2026-10-24T21:13:46+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/albanianbus.com\/wordpress\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"AlbanianBus Transfers Staff Calendar\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/albanianbus.com\/wordpress\/#website\",\"url\":\"https:\/\/albanianbus.com\/wordpress\/\",\"name\":\"Bus Tirana to Ksamil\",\"description\":\"Bus Service in Albania\",\"publisher\":{\"@id\":\"https:\/\/albanianbus.com\/wordpress\/#organization\"},\"alternateName\":\"Bus Tirana to Saranda\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/albanianbus.com\/wordpress\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/albanianbus.com\/wordpress\/#organization\",\"name\":\"Albanianbus\",\"alternateName\":\"Albanian Riviera Bus\",\"url\":\"https:\/\/albanianbus.com\/wordpress\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/albanianbus.com\/wordpress\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/albanianbus.com\/wordpress\/wp-content\/uploads\/2022\/11\/cropped-ALBANIANBUS-tirana-saranda-1.png\",\"contentUrl\":\"https:\/\/albanianbus.com\/wordpress\/wp-content\/uploads\/2022\/11\/cropped-ALBANIANBUS-tirana-saranda-1.png\",\"width\":728,\"height\":543,\"caption\":\"Albanianbus\"},\"image\":{\"@id\":\"https:\/\/albanianbus.com\/wordpress\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"AlbanianBus Transfers Staff Calendar - Albanian Bus","robots":{"index":"noindex","follow":"follow"},"og_locale":"en_US","og_type":"article","og_title":"AlbanianBus Transfers Staff Calendar - Albanian Bus","og_url":"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/","og_site_name":"Albanian Bus","article_modified_time":"2026-10-24T21:13:46+00:00","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/","url":"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/","name":"AlbanianBus Transfers Staff Calendar - Albanian Bus","isPartOf":{"@id":"https:\/\/albanianbus.com\/wordpress\/#website"},"datePublished":"2026-10-24T19:36:54+00:00","dateModified":"2026-10-24T21:13:46+00:00","breadcrumb":{"@id":"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/albanianbus.com\/wordpress\/"},{"@type":"ListItem","position":2,"name":"AlbanianBus Transfers Staff Calendar"}]},{"@type":"WebSite","@id":"https:\/\/albanianbus.com\/wordpress\/#website","url":"https:\/\/albanianbus.com\/wordpress\/","name":"Bus Tirana to Ksamil","description":"Bus Service in Albania","publisher":{"@id":"https:\/\/albanianbus.com\/wordpress\/#organization"},"alternateName":"Bus Tirana to Saranda","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/albanianbus.com\/wordpress\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/albanianbus.com\/wordpress\/#organization","name":"Albanianbus","alternateName":"Albanian Riviera Bus","url":"https:\/\/albanianbus.com\/wordpress\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/albanianbus.com\/wordpress\/#\/schema\/logo\/image\/","url":"https:\/\/albanianbus.com\/wordpress\/wp-content\/uploads\/2022\/11\/cropped-ALBANIANBUS-tirana-saranda-1.png","contentUrl":"https:\/\/albanianbus.com\/wordpress\/wp-content\/uploads\/2022\/11\/cropped-ALBANIANBUS-tirana-saranda-1.png","width":728,"height":543,"caption":"Albanianbus"},"image":{"@id":"https:\/\/albanianbus.com\/wordpress\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages\/97876","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=97876"}],"version-history":[{"count":8,"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages\/97876\/revisions"}],"predecessor-version":[{"id":97891,"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages\/97876\/revisions\/97891"}],"wp:attachment":[{"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=97876"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}