
{"id":97960,"date":"2026-10-25T23:52:08","date_gmt":"2026-10-25T22:52:08","guid":{"rendered":"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/"},"modified":"2026-10-26T01:10:25","modified_gmt":"2026-10-26T00:10:25","slug":"albanianbus-tour-management","status":"publish","type":"page","link":"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/","title":{"rendered":"AlbanianBus Tour Management"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"97960\" class=\"elementor elementor-97960\">\n\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-ab901001 e-con-full e-con\" data-id=\"ab901001\" data-element_type=\"container\" data-settings=\"{&quot;content_width&quot;:&quot;full&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ab901002 elementor-widget elementor-widget-html\" data-id=\"ab901002\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<iframe id=\"ab-tour-management\" title=\"AlbanianBus Tour Management\" style=\"display:block;width:100%;height:1000px;border:0\" srcdoc=\"&lt;!doctype html&gt;&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&quot;&gt;&lt;meta name=&quot;robots&quot; content=&quot;noindex,nofollow&quot;&gt;&lt;title&gt;AlbanianBus Tour Management&lt;\/title&gt;&lt;script src=&quot;https:\/\/cdn.jsdelivr.net\/npm\/@supabase\/supabase-js@2.95.0\/dist\/umd\/supabase.js&quot;&gt;&lt;\/script&gt;&lt;style&gt;\n*{box-sizing:border-box}body{margin:0;background:#f5f2fa;color:#30213e;font:15px\/1.5 system-ui,sans-serif}main{max-width:1180px;padding:24px 16px 60px;margin:auto}h1{font-size:28px;margin:0}h2{font-size:21px;margin:0 0 16px}h3{font-size:17px}.brand{color:#703da5;font-weight:800;font-size:12px;letter-spacing:.08em}.row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.between{justify-content:space-between}.card{background:white;padding:22px;border:1px solid #e0d5e9;border-radius:16px;margin-top:16px;min-width:0}.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.triple{grid-template-columns:repeat(3,minmax(0,1fr))}label{display:grid;gap:6px;font-size:13px;font-weight:650;margin-bottom:12px}input,select,textarea,button{font:inherit;max-width:100%;min-width:0;border-radius:9px;padding:10px;border:1px solid #cdbbdf}input,select,textarea{width:100%;background:white;color:inherit}button{background:#703da5;border-color:#703da5;color:white;font-weight:650;cursor:pointer;min-height:42px}.outline{background:white;color:#703da5}.small{font-size:13px;color:#70637b}.badge{padding:4px 9px;border-radius:20px;background:#f1e8fa;font-size:12px}.warning{background:#fff1d8;color:#76531c;padding:10px;border-radius:9px}.tick{display:flex;align-items:center;gap:7px}.tick input{width:17px;height:17px;accent-color:#703da5}.tabs{margin-top:20px}.tabs button[aria-selected=true]{background:#49256e}.days{display:flex;gap:12px;flex-wrap:wrap}.tabs button{flex:1}#message{position:sticky;top:0;z-index:4;background:#efe5fa;border-radius:9px;padding:12px}#message:empty{display:none}.error{color:#9a2936}.booking{padding:13px 0;border-top:1px solid #eee;overflow-wrap:anywhere}.departure{border-left:4px solid #703da5}dialog{border:0;border-radius:16px;width:min(95vw,700px);max-height:90vh;overflow:auto;padding:22px}dialog::backdrop{background:#23132c88}pre{white-space:pre-wrap;font:inherit;overflow-wrap:anywhere}a{color:#703da5}[hidden]{display:none!important}@media(max-width:650px){main{padding:16px 10px}.grid{grid-template-columns:1fr}.triple{grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.card{padding:16px}.row&gt;*{max-width:100%}.toolbar label{flex:1 1 130px}h1{font-size:24px}.actions button{flex:1;font-size:12px;padding:9px}.tabs{gap:6px}.tabs button{font-size:13px;padding:9px}}@media print{body{background:white}#login,.tabs,.toolbar,button,#settings,#guides,#message,.hide-print{display:none!important}.card{break-inside:avoid}main{max-width:none;padding:0}dialog{display:none}}\n&lt;\/style&gt;&lt;\/head&gt;&lt;body&gt;&lt;main&gt;&lt;header class=&quot;row between&quot;&gt;&lt;div&gt;&lt;div class=&quot;brand&quot;&gt;ALBANIANBUS \u00b7 STAFF&lt;\/div&gt;&lt;h1&gt;Tours: settings &amp; calendar&lt;\/h1&gt;&lt;\/div&gt;&lt;button id=&quot;logout&quot; class=&quot;outline&quot; hidden&gt;Sign out&lt;\/button&gt;&lt;\/header&gt;&lt;p class=&quot;small&quot;&gt;Manage direct tour bookings. Tour checkout remains in test mode. Bokun bookings are not imported here.&lt;\/p&gt;&lt;div id=&quot;message&quot; role=&quot;status&quot; aria-live=&quot;polite&quot;&gt;&lt;\/div&gt;\n&lt;section id=&quot;login&quot; class=&quot;card&quot;&gt;&lt;h2&gt;Staff sign-in&lt;\/h2&gt;&lt;p class=&quot;small&quot;&gt;Use your existing AlbanianBus staff calendar account. Only authorised staff can access booking details.&lt;\/p&gt;&lt;form id=&quot;loginForm&quot;&gt;&lt;label&gt;Email&lt;input id=&quot;email&quot; type=&quot;email&quot; autocomplete=&quot;username&quot; required&gt;&lt;\/label&gt;&lt;label&gt;Password&lt;input id=&quot;password&quot; type=&quot;password&quot; autocomplete=&quot;current-password&quot; required&gt;&lt;\/label&gt;&lt;button&gt;Sign in&lt;\/button&gt;&lt;\/form&gt;&lt;p class=&quot;small&quot;&gt;&lt;a href=&quot;https:\/\/albanianbus.com\/wordpress\/index.php\/transfers-staff-calendar\/&quot; target=&quot;_blank&quot;&gt;Open the transfer staff calendar to create an account or use its email sign-in option.&lt;\/a&gt;&lt;\/p&gt;&lt;\/section&gt;\n&lt;div id=&quot;app&quot; hidden&gt;&lt;nav class=&quot;row tabs&quot;&gt;&lt;button data-tab=&quot;calendar&quot; aria-selected=&quot;true&quot;&gt;\ud83d\udcc5 Calendar&lt;\/button&gt;&lt;button data-tab=&quot;settings&quot; aria-selected=&quot;false&quot;&gt;\u2699 Tour settings&lt;\/button&gt;&lt;button data-tab=&quot;guides&quot; aria-selected=&quot;false&quot;&gt;\ud83e\uddd1\u200d\ud83c\udfeb Guides&lt;\/button&gt;&lt;\/nav&gt;\n&lt;section id=&quot;calendar&quot;&gt;&lt;div class=&quot;card&quot;&gt;&lt;div class=&quot;row toolbar&quot;&gt;&lt;label&gt;From&lt;input id=&quot;from&quot; type=&quot;date&quot;&gt;&lt;\/label&gt;&lt;label&gt;To&lt;input id=&quot;to&quot; type=&quot;date&quot;&gt;&lt;\/label&gt;&lt;label&gt;Tour&lt;select id=&quot;filterTour&quot;&gt;&lt;option value=&quot;&quot;&gt;All tours&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;button id=&quot;refresh&quot;&gt;Refresh&lt;\/button&gt;&lt;button id=&quot;planDeparture&quot; class=&quot;outline&quot;&gt;Plan a departure&lt;\/button&gt;&lt;\/div&gt;&lt;div class=&quot;row hide-print&quot; style=&quot;margin-bottom:12px&quot;&gt;&lt;button class=&quot;outline&quot; id=&quot;showToday&quot;&gt;Today&lt;\/button&gt;&lt;button class=&quot;outline&quot; id=&quot;showWeek&quot;&gt;This week&lt;\/button&gt;&lt;button class=&quot;outline&quot; id=&quot;showMonth&quot;&gt;This month&lt;\/button&gt;&lt;\/div&gt;&lt;div class=&quot;row&quot;&gt;&lt;label class=&quot;tick&quot;&gt;&lt;input type=&quot;checkbox&quot; id=&quot;includeTests&quot; checked&gt;Show test bookings&lt;\/label&gt;&lt;label class=&quot;tick&quot;&gt;&lt;input type=&quot;checkbox&quot; id=&quot;includePending&quot;&gt;Include unpaid bookings&lt;\/label&gt;&lt;button id=&quot;print&quot; class=&quot;outline&quot;&gt;Print&lt;\/button&gt;&lt;\/div&gt;&lt;p class=&quot;small&quot;&gt;Grouped by tour and day. Unpaid bookings are shown separately and excluded from confirmed passenger totals. Capacity warnings never block bookings.&lt;\/p&gt;&lt;\/div&gt;&lt;div id=&quot;departureList&quot;&gt;&lt;\/div&gt;&lt;\/section&gt;\n&lt;section id=&quot;settings&quot; hidden&gt;&lt;div class=&quot;card&quot;&gt;&lt;label&gt;Choose tour&lt;select id=&quot;tourSelect&quot;&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;p id=&quot;configuredNote&quot; class=&quot;small&quot;&gt;&lt;\/p&gt;&lt;form id=&quot;settingsForm&quot;&gt;&lt;label class=&quot;tick&quot;&gt;&lt;input id=&quot;enabled&quot; type=&quot;checkbox&quot;&gt;Open this test widget for bookings&lt;\/label&gt;&lt;p class=&quot;warning&quot;&gt;This controls the native test widget only. It does not publish a tour, replace Bokun, or enable real payments.&lt;\/p&gt;&lt;label&gt;Shared per-person rate&lt;select id=&quot;rateCode&quot; required&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;div class=&quot;grid triple&quot;&gt;&lt;label&gt;Adult price \u00b7 EUR&lt;input id=&quot;adultPrice&quot; type=&quot;number&quot; min=&quot;.01&quot; step=&quot;.01&quot; required&gt;&lt;\/label&gt;&lt;label&gt;Child price \u00b7 EUR&lt;input id=&quot;childPrice&quot; type=&quot;number&quot; min=&quot;.01&quot; step=&quot;.01&quot; required&gt;&lt;\/label&gt;&lt;label&gt;Infant price \u00b7 EUR&lt;input id=&quot;infantPrice&quot; type=&quot;number&quot; min=&quot;0&quot; step=&quot;.01&quot; required&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;div class=&quot;grid&quot;&gt;&lt;label&gt;Infant maximum age&lt;input id=&quot;infantAge&quot; type=&quot;number&quot; min=&quot;0&quot; max=&quot;17&quot; required&gt;&lt;\/label&gt;&lt;label&gt;Child maximum age&lt;input id=&quot;childAge&quot; type=&quot;number&quot; min=&quot;1&quot; max=&quot;99&quot; required&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;p class=&quot;small&quot;&gt;Age bands remain continuous. For example: infant 0\u20132, child 3\u201312, adult 13+.&lt;\/p&gt;&lt;h3&gt;Pickup cities &amp; times \u00b7 Albania local time&lt;\/h3&gt;&lt;div id=&quot;pickupFields&quot;&gt;&lt;\/div&gt;&lt;h3&gt;Available audio-guide languages&lt;\/h3&gt;&lt;div id=&quot;audioLanguages&quot; class=&quot;days&quot;&gt;&lt;\/div&gt;&lt;p class=&quot;small&quot;&gt;Enable only languages with a prepared audio guide for this tour. These are separate from the live guide\u2019s spoken languages.&lt;\/p&gt;&lt;h3&gt;Operating season (optional)&lt;\/h3&gt;&lt;div class=&quot;grid&quot;&gt;&lt;label&gt;First operating date&lt;input id=&quot;availableFrom&quot; type=&quot;date&quot;&gt;&lt;\/label&gt;&lt;label&gt;Last operating date&lt;input id=&quot;availableUntil&quot; type=&quot;date&quot;&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;h3&gt;Operating days&lt;\/h3&gt;&lt;div id=&quot;weekdays&quot; class=&quot;days&quot;&gt;&lt;\/div&gt;&lt;label&gt;Closed dates \u00b7 one date per line (YYYY-MM-DD)&lt;textarea id=&quot;closedDates&quot; rows=&quot;4&quot; placeholder=&quot;2026-12-25&quot;&gt;&lt;\/textarea&gt;&lt;\/label&gt;&lt;label&gt;Advisory passengers per departure (optional)&lt;input id=&quot;capacity&quot; type=&quot;number&quot; min=&quot;1&quot; max=&quot;1000&quot;&gt;&lt;\/label&gt;&lt;p class=&quot;small&quot;&gt;An advisory capacity warns staff; customers can still book. For now a booking can contain 1\u201355 travellers.&lt;\/p&gt;&lt;button id=&quot;saveSettings&quot; type=&quot;submit&quot;&gt;Save tour settings&lt;\/button&gt; &lt;a id=&quot;preview&quot; target=&quot;_blank&quot; hidden&gt;Open test widget \u2197&lt;\/a&gt;&lt;\/form&gt;&lt;\/div&gt;&lt;\/section&gt;\n&lt;section id=&quot;guides&quot; hidden&gt;&lt;div class=&quot;card&quot;&gt;&lt;div class=&quot;row between&quot;&gt;&lt;h2&gt;Guide pool &amp; profiles&lt;\/h2&gt;&lt;button type=&quot;button&quot; id=&quot;newGuide&quot; class=&quot;outline&quot;&gt;\uff0b New profile&lt;\/button&gt;&lt;\/div&gt;&lt;p class=&quot;small&quot;&gt;Review website applications, approve guides for assignments and maintain private profiles. The number of languages is calculated from the languages selected. Profiles and staff notes are not public.&lt;\/p&gt;&lt;p&gt;&lt;a id=&quot;registrationLink&quot; href=&quot;https:\/\/albanianbus.com\/wordpress\/index.php\/become-an-albanianbus-tour-guide\/&quot; target=&quot;_blank&quot;&gt;Open guide registration \u2197&lt;\/a&gt;&lt;\/p&gt;&lt;div class=&quot;grid&quot;&gt;&lt;label&gt;Status&lt;select id=&quot;guideStatusFilter&quot;&gt;&lt;option value=&quot;&quot;&gt;All profiles&lt;\/option&gt;&lt;option value=&quot;pending&quot;&gt;Pending applications&lt;\/option&gt;&lt;option value=&quot;approved&quot;&gt;Approved pool&lt;\/option&gt;&lt;option value=&quot;inactive&quot;&gt;Inactive&lt;\/option&gt;&lt;option value=&quot;declined&quot;&gt;Declined&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;label&gt;Search name, city, language or speciality&lt;input id=&quot;guideSearch&quot; type=&quot;search&quot;&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;div id=&quot;guideList&quot;&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;div class=&quot;card&quot;&gt;&lt;h2 id=&quot;guideFormTitle&quot;&gt;New guide profile&lt;\/h2&gt;&lt;form id=&quot;guideForm&quot;&gt;&lt;div class=&quot;grid&quot;&gt;&lt;label&gt;Full name&lt;input id=&quot;guideName&quot; maxlength=&quot;160&quot; required&gt;&lt;\/label&gt;&lt;label&gt;Phone \/ WhatsApp&lt;input id=&quot;guidePhone&quot; type=&quot;tel&quot; maxlength=&quot;80&quot;&gt;&lt;\/label&gt;&lt;label&gt;Email&lt;input id=&quot;guideEmail&quot; type=&quot;email&quot; maxlength=&quot;200&quot;&gt;&lt;\/label&gt;&lt;label&gt;Base city&lt;input id=&quot;guideCity&quot; maxlength=&quot;120&quot;&gt;&lt;\/label&gt;&lt;label&gt;Profile status&lt;select id=&quot;guideStatus&quot;&gt;&lt;option value=&quot;approved&quot;&gt;Approved&lt;\/option&gt;&lt;option value=&quot;pending&quot;&gt;Pending review&lt;\/option&gt;&lt;option value=&quot;inactive&quot;&gt;Inactive&lt;\/option&gt;&lt;option value=&quot;declined&quot;&gt;Declined&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;label&gt;Years of experience&lt;input id=&quot;guideYears&quot; type=&quot;number&quot; min=&quot;0&quot; max=&quot;80&quot;&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;h3&gt;Spoken languages&lt;\/h3&gt;&lt;div id=&quot;guideLanguages&quot; class=&quot;days&quot;&gt;&lt;\/div&gt;&lt;label&gt;Other languages \u00b7 comma separated&lt;input id=&quot;guideOtherLanguages&quot; maxlength=&quot;500&quot;&gt;&lt;\/label&gt;&lt;div class=&quot;grid&quot;&gt;&lt;label&gt;Regions covered \u00b7 comma separated&lt;input id=&quot;guideRegions&quot; maxlength=&quot;1000&quot;&gt;&lt;\/label&gt;&lt;label&gt;Specialities \u00b7 comma separated&lt;input id=&quot;guideSpecialties&quot; maxlength=&quot;1000&quot; placeholder=&quot;Culture, hiking, rafting, history&quot;&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;label&gt;Biography \/ introduction&lt;textarea id=&quot;guideBio&quot; maxlength=&quot;3000&quot; rows=&quot;4&quot;&gt;&lt;\/textarea&gt;&lt;\/label&gt;&lt;label&gt;Qualifications \/ certificates (declared; verify separately)&lt;textarea id=&quot;guideCertifications&quot; maxlength=&quot;1500&quot;&gt;&lt;\/textarea&gt;&lt;\/label&gt;&lt;label&gt;Website or professional profile \u00b7 HTTPS&lt;input id=&quot;guideUrl&quot; type=&quot;url&quot; maxlength=&quot;500&quot;&gt;&lt;\/label&gt;&lt;label&gt;Availability \/ work preferences&lt;textarea id=&quot;guideAvailability&quot; maxlength=&quot;1000&quot;&gt;&lt;\/textarea&gt;&lt;\/label&gt;&lt;label&gt;Private staff notes&lt;textarea id=&quot;guideStaffNotes&quot; maxlength=&quot;4000&quot; rows=&quot;4&quot; placeholder=&quot;Interview notes, strengths, references, feedback&quot;&gt;&lt;\/textarea&gt;&lt;\/label&gt;&lt;p id=&quot;guideConsent&quot; class=&quot;small&quot;&gt;&lt;\/p&gt;&lt;button id=&quot;saveGuide&quot;&gt;Save profile&lt;\/button&gt;&lt;\/form&gt;&lt;\/div&gt;&lt;\/section&gt;&lt;\/div&gt;\n&lt;dialog id=&quot;assignment&quot;&gt;&lt;form id=&quot;assignmentForm&quot;&gt;&lt;h2 id=&quot;assignmentTitle&quot;&gt;Departure assignment&lt;\/h2&gt;&lt;label&gt;Vehicle&lt;select id=&quot;vehicleSelect&quot;&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;div class=&quot;grid&quot;&gt;&lt;label&gt;Vehicle name&lt;input id=&quot;vehicleName&quot; maxlength=&quot;160&quot;&gt;&lt;\/label&gt;&lt;label&gt;Plate&lt;input id=&quot;vehiclePlate&quot; maxlength=&quot;50&quot;&gt;&lt;\/label&gt;&lt;label&gt;Passenger capacity&lt;input id=&quot;vehicleCapacity&quot; type=&quot;number&quot; min=&quot;1&quot; max=&quot;1000&quot;&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;label&gt;Tour guide&lt;select id=&quot;guideSelect&quot;&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;div class=&quot;grid&quot;&gt;&lt;label&gt;Guide name&lt;input id=&quot;assignedGuideName&quot; maxlength=&quot;160&quot;&gt;&lt;\/label&gt;&lt;label&gt;Guide phone&lt;input id=&quot;assignedGuidePhone&quot; type=&quot;tel&quot; maxlength=&quot;80&quot;&gt;&lt;\/label&gt;&lt;label&gt;Vehicle busy from&lt;input id=&quot;startTime&quot; type=&quot;time&quot;&gt;&lt;\/label&gt;&lt;label&gt;Vehicle busy until&lt;input id=&quot;endTime&quot; type=&quot;time&quot;&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;p class=&quot;small&quot;&gt;Enter the full same-day vehicle duty to improve overlap warnings. Without both times, same-day reuse is flagged as possible overlap.&lt;\/p&gt;&lt;label&gt;Notes&lt;textarea id=&quot;notes&quot; maxlength=&quot;1500&quot;&gt;&lt;\/textarea&gt;&lt;\/label&gt;&lt;div class=&quot;row actions&quot;&gt;&lt;button type=&quot;submit&quot;&gt;Save assignment&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;closeAssignment&quot; class=&quot;outline&quot;&gt;Close&lt;\/button&gt;&lt;\/div&gt;&lt;\/form&gt;&lt;\/dialog&gt;\n&lt;dialog id=&quot;share&quot;&gt;&lt;h2&gt;Passenger list \u00b7 WhatsApp&lt;\/h2&gt;&lt;p class=&quot;small&quot;&gt;The list includes customer phone numbers and accommodation locations. Review it before sharing with your assigned guide or driver.&lt;\/p&gt;&lt;pre id=&quot;shareText&quot;&gt;&lt;\/pre&gt;&lt;div class=&quot;row actions&quot;&gt;&lt;button id=&quot;sendWhatsapp&quot;&gt;Open WhatsApp&lt;\/button&gt;&lt;button id=&quot;copyList&quot; class=&quot;outline&quot;&gt;Copy list&lt;\/button&gt;&lt;button id=&quot;closeShare&quot; class=&quot;outline&quot;&gt;Close&lt;\/button&gt;&lt;\/div&gt;&lt;\/dialog&gt;\n&lt;\/main&gt;&lt;script&gt;\n(()=&gt;{\nconst $=id=&gt;document.getElementById(id),BASE=&#039;https:\/\/eyhphryauiihzmnmcqlk.supabase.co\/functions\/v1\/tour-management&#039;,auth=window.supabase.createClient(&#039;https:\/\/eyhphryauiihzmnmcqlk.supabase.co&#039;,&#039;sb_publishable_NFysUe4qKtg420wU0PbVRw_Appl5waV&#039;,{auth:{detectSessionInUrl:false,persistSession:true,autoRefreshToken:true}});\nlet session=null,data=null,calendarData=null,groups=[],selectedGroup=null,selectedSettings=null,shareText=&#039;&#039;,editingGuide=null;\nconst esc=s=&gt;String(s??&#039;&#039;).replace(\/[&amp;&lt;&gt;&quot;&#039;]\/g,c=&gt;({&#039;&amp;&#039;:&#039;&amp;amp;&#039;,&#039;&lt;&#039;:&#039;&amp;lt;&#039;,&#039;&gt;&#039;:&#039;&amp;gt;&#039;,&#039;&quot;&#039;:&#039;&amp;quot;&#039;,&quot;&#039;&quot;:&#039;&amp;#39;&#039;}[c]));\nconst money=n=&gt;new Intl.NumberFormat(&#039;en-IE&#039;,{style:&#039;currency&#039;,currency:&#039;EUR&#039;}).format(n\/100);\nfunction msg(s,bad=false){$(&#039;message&#039;).textContent=s;$(&#039;message&#039;).className=bad?&#039;error&#039;:&#039;&#039;;}\nasync function api(action,body,query=&#039;&#039;){const r=await fetch(BASE+&#039;?api=&#039;+action+query,{method:body?&#039;POST&#039;:&#039;GET&#039;,headers:{Authorization:&#039;Bearer &#039;+session.access_token,&#039;Content-Type&#039;:&#039;application\/json&#039;},body:body?JSON.stringify(body):undefined});const j=await r.json();if(!r.ok)throw Error(j.error||&#039;Please try again&#039;);return j;}\nasync function run(fn){try{await fn();}catch(e){msg(e.message,true);}}\nfunction tourName(id){return data.tours.find(t=&gt;t.id===id)?.tour_name||&#039;Tour &#039;+id;}\nconst cities=[&#039;Tirana&#039;,&#039;Durres&#039;,&#039;Golem&#039;,&#039;Shkoder&#039;],days=[&#039;Sun&#039;,&#039;Mon&#039;,&#039;Tue&#039;,&#039;Wed&#039;,&#039;Thu&#039;,&#039;Fri&#039;,&#039;Sat&#039;];\n$(&#039;weekdays&#039;).innerHTML=days.map((d,i)=&gt;&#039;&lt;label class=&quot;tick&quot;&gt;&lt;input type=&quot;checkbox&quot; name=&quot;day&quot; value=&quot;&#039;+i+&#039;&quot;&gt;&#039;+d+&#039;&lt;\/label&gt;&#039;).join(&#039;&#039;);\n$(&#039;pickupFields&#039;).innerHTML=cities.map(c=&gt;&#039;&lt;div class=&quot;grid&quot;&gt;&lt;label class=&quot;tick&quot;&gt;&lt;input type=&quot;checkbox&quot; id=&quot;pickup-&#039;+c+&#039;&quot;&gt;&#039;+(c===&#039;Durres&#039;?&#039;Durr\u00ebs&#039;:c)+&#039;&lt;\/label&gt;&lt;label&gt;Pickup time&lt;input type=&quot;time&quot; id=&quot;time-&#039;+c+&#039;&quot;&gt;&lt;\/label&gt;&lt;\/div&gt;&#039;).join(&#039;&#039;);\ndocument.querySelectorAll(&#039;[data-tab]&#039;).forEach(b=&gt;b.onclick=()=&gt;{for(const el of document.querySelectorAll(&#039;[data-tab]&#039;))el.setAttribute(&#039;aria-selected&#039;,String(el===b));for(const id of [&#039;calendar&#039;,&#039;settings&#039;,&#039;guides&#039;])$(id).hidden=id!==b.dataset.tab;});\nasync function loadConfig(){data=await api(&#039;config&#039;);$(&#039;tourSelect&#039;).innerHTML=data.tours.map(t=&gt;&#039;&lt;option value=&quot;&#039;+t.id+&#039;&quot;&gt;&#039;+esc(t.tour_name)+&#039;&lt;\/option&gt;&#039;).join(&#039;&#039;);$(&#039;filterTour&#039;).innerHTML=&#039;&lt;option value=&quot;&quot;&gt;All tours&lt;\/option&gt;&#039;+$(&#039;tourSelect&#039;).innerHTML;renderGuides();renderSettings();}\nconst spokenOptions=[&quot;Albanian&quot;,&quot;English&quot;,&quot;German&quot;,&quot;Spanish&quot;,&quot;Italian&quot;,&quot;French&quot;,&quot;Polish&quot;,&quot;Hebrew&quot;,&quot;Greek&quot;,&quot;Turkish&quot;,&quot;Arabic&quot;,&quot;Dutch&quot;,&quot;Portuguese&quot;,&quot;Russian&quot;],splitList=s=&gt;s.split(&#039;,&#039;).map(x=&gt;x.trim()).filter(Boolean);\n$(&#039;guideLanguages&#039;).innerHTML=spokenOptions.map(l=&gt;&#039;&lt;label class=&quot;tick&quot;&gt;&lt;input type=&quot;checkbox&quot; name=&quot;spokenLanguage&quot; value=&quot;&#039;+esc(l)+&#039;&quot;&gt;&#039;+esc(l)+&#039;&lt;\/label&gt;&#039;).join(&#039;&#039;);\nfunction renderGuides(){const search=$(&#039;guideSearch&#039;).value.trim().toLowerCase(),status=$(&#039;guideStatusFilter&#039;).value,items=data.guides.filter(g=&gt;(!status||g.status===status)&amp;&amp;(!search||[g.name,g.base_city,...g.languages,...g.specialties].join(&#039; &#039;).toLowerCase().includes(search)));\n$(&#039;guideList&#039;).innerHTML=items.length?items.map(g=&gt;&#039;&lt;div class=&quot;booking&quot;&gt;&lt;div class=&quot;row between&quot;&gt;&lt;strong&gt;\ud83e\uddd1\u200d\ud83c\udfeb &#039;+esc(g.name)+&#039;&lt;\/strong&gt;&lt;span class=&quot;badge&quot;&gt;&#039;+esc(g.status)+&#039; \u00b7 &#039;+g.language_count+&#039; languages&lt;\/span&gt;&lt;\/div&gt;&lt;p&gt;\ud83d\udccd &#039;+esc(g.base_city||&#039;Base not entered&#039;)+&#039;&lt;br&gt;\ud83d\udde3 &#039;+esc(g.languages.join(&#039;, &#039;)||&#039;Languages not entered&#039;)+&#039;&lt;br&gt;\ud83d\udcde &#039;+esc(g.phone||&#039;&#039;)+&#039;&lt;br&gt;\u2709 &#039;+esc(g.email||&#039;&#039;)+&#039;&lt;\/p&gt;&lt;p class=&quot;small&quot;&gt;&#039;+esc(g.specialties.join(&#039;, &#039;))+&#039; \u00b7 &#039;+esc(g.regions.join(&#039;, &#039;))+&#039;&lt;\/p&gt;&lt;button type=&quot;button&quot; class=&quot;outline&quot; data-edit-guide=&quot;&#039;+g.id+&#039;&quot;&gt;View \/ edit profile&lt;\/button&gt;&lt;\/div&gt;&#039;).join(&#039;&#039;):&#039;&lt;p class=&quot;small&quot;&gt;No matching guide profiles.&lt;\/p&gt;&#039;;\ndocument.querySelectorAll(&#039;[data-edit-guide]&#039;).forEach(b=&gt;b.onclick=()=&gt;editGuide(data.guides.find(g=&gt;g.id===b.dataset.editGuide)));}\nfunction editGuide(g){editingGuide=g||null;$(&#039;guideForm&#039;).reset();$(&#039;guideFormTitle&#039;).textContent=g?&#039;Profile: &#039;+g.name:&#039;New guide profile&#039;;const fields={guideName:&#039;name&#039;,guidePhone:&#039;phone&#039;,guideEmail:&#039;email&#039;,guideCity:&#039;base_city&#039;,guideStatus:&#039;status&#039;,guideYears:&#039;experience_years&#039;,guideBio:&#039;bio&#039;,guideCertifications:&#039;certifications&#039;,guideUrl:&#039;profile_url&#039;,guideAvailability:&#039;availability_notes&#039;,guideStaffNotes:&#039;staff_notes&#039;};\nfor(const[id,key]of Object.entries(fields))$(id).value=g?.[key]??(key===&#039;status&#039;?&#039;approved&#039;:&#039;&#039;);\ndocument.querySelectorAll(&#039;[name=spokenLanguage]&#039;).forEach(el=&gt;el.checked=!!g?.languages.includes(el.value));$(&#039;guideOtherLanguages&#039;).value=(g?.languages||[]).filter(l=&gt;!spokenOptions.includes(l)).join(&#039;, &#039;);$(&#039;guideRegions&#039;).value=(g?.regions||[]).join(&#039;, &#039;);$(&#039;guideSpecialties&#039;).value=(g?.specialties||[]).join(&#039;, &#039;);$(&#039;guideConsent&#039;).textContent=g?(g.registration_source===&#039;website&#039;?&#039;Website application. &#039;:&#039;Staff-entered profile. &#039;)+(g.contact_consent?&#039;Contact consent recorded.&#039;:&#039;No website contact consent recorded.&#039;):&#039;New staff-entered profile.&#039;;$(&#039;saveGuide&#039;).disabled=data?.role===&#039;viewer&#039;;if(g)$(&#039;guideFormTitle&#039;).scrollIntoView({behavior:&#039;smooth&#039;,block:&#039;start&#039;});}\n$(&#039;newGuide&#039;).onclick=()=&gt;editGuide(null);$(&#039;guideStatusFilter&#039;).onchange=renderGuides;$(&#039;guideSearch&#039;).oninput=renderGuides;\nfunction renderSettings(){const id=Number($(&#039;tourSelect&#039;).value),s=data.settings.find(s=&gt;s.tour_id===id);selectedSettings=s||null;$(&#039;audioLanguages&#039;).innerHTML=Object.entries(data.audio_language_options).map(([code,label])=&gt;&#039;&lt;label class=&quot;tick&quot;&gt;&lt;input type=&quot;checkbox&quot; name=&quot;audioOption&quot; value=&quot;&#039;+code+&#039;&quot; &#039;+((s?.audio_languages||[]).includes(code)?&#039;checked&#039;:&#039;&#039;)+&#039;&gt;&#039;+esc(label)+&#039;&lt;\/label&gt;&#039;).join(&#039;&#039;);$(&#039;configuredNote&#039;).textContent=s?&#039;Configured \u00b7 TEST MODE \u00b7 changes apply to new bookings.&#039;:&#039;Not configured. Enter verified prices and pickup times before enabling.&#039;;\n$(&#039;enabled&#039;).checked=!!s?.enabled;\nconst rates=data.rates.filter(r=&gt;r.tour_id===id&amp;&amp;r.priced_per_person&amp;&amp;r.service_mode!==&#039;Private&#039;);$(&#039;rateCode&#039;).innerHTML=&#039;&lt;option value=&quot;&quot;&gt;Choose a shared rate&lt;\/option&gt;&#039;+rates.map(r=&gt;&#039;&lt;option value=&quot;&#039;+r.id+&#039;&quot;&gt;&#039;+esc(r.rate_title||r.rate_code||&#039;Shared rate&#039;)+&#039;&lt;\/option&gt;&#039;).join(&#039;&#039;);$(&#039;rateCode&#039;).value=String(s?.rate_id||rates.find(r=&gt;s?.rate_code&amp;&amp;r.rate_code===s.rate_code)?.id||(rates.length===1?rates[0].id:&#039;&#039;));\nfor(const key of [&#039;adult&#039;,&#039;child&#039;,&#039;infant&#039;]){$(key+&#039;Price&#039;).value=s?((s.ticket_categories.find(c=&gt;c.key===key)?.price_cents??0)\/100):&#039;&#039;;}\n$(&#039;infantAge&#039;).value=s?s.ticket_categories.find(c=&gt;c.key===&#039;infant&#039;).max_age:2;$(&#039;childAge&#039;).value=s?s.ticket_categories.find(c=&gt;c.key===&#039;child&#039;).max_age:12;\nfor(const city of cities){$(&#039;pickup-&#039;+city).checked=!!s?.pickup_times[city];$(&#039;time-&#039;+city).value=s?.pickup_times[city]||&#039;&#039;;}\ndocument.querySelectorAll(&#039;[name=day]&#039;).forEach(el=&gt;el.checked=(s?.operating_days||[0,1,2,3,4,5,6]).includes(Number(el.value)));\n$(&#039;closedDates&#039;).value=(s?.closed_dates||[]).join(&#039;\\n&#039;);$(&#039;capacity&#039;).value=s?.advisory_capacity||&#039;&#039;;$(&#039;availableFrom&#039;).value=s?.available_from||&#039;&#039;;$(&#039;availableUntil&#039;).value=s?.available_until||&#039;&#039;;$(&#039;preview&#039;).hidden=!s?.enabled;$(&#039;preview&#039;).href=&#039;https:\/\/albanianbus.com\/wordpress\/index.php\/berat-booking-test\/?tour_id=&#039;+id;\n$(&#039;saveSettings&#039;).disabled=data.role===&#039;viewer&#039;;}\n$(&#039;tourSelect&#039;).onchange=renderSettings;\n$(&#039;settingsForm&#039;).onsubmit=e=&gt;{e.preventDefault();run(async()=&gt;{const infant=Number($(&#039;infantAge&#039;).value),child=Number($(&#039;childAge&#039;).value),id=Number($(&#039;tourSelect&#039;).value),pickups={};for(const city of cities)if($(&#039;pickup-&#039;+city).checked)pickups[city]=$(&#039;time-&#039;+city).value;\nconst categories=[{key:&#039;adult&#039;,min_age:child+1,max_age:null},{key:&#039;child&#039;,min_age:infant+1,max_age:child},{key:&#039;infant&#039;,min_age:0,max_age:infant}].map(c=&gt;({...c,price_cents:Math.round(Number($(c.key+&#039;Price&#039;).value)*100)}));\nawait api(&#039;settings&#039;,{tour_id:id,enabled:$(&#039;enabled&#039;).checked,expected_updated_at:selectedSettings?.updated_at||null,rate_id:$(&#039;rateCode&#039;).value?Number($(&#039;rateCode&#039;).value):null,ticket_categories:categories,audio_languages:[...document.querySelectorAll(&#039;[name=audioOption]:checked&#039;)].map(el=&gt;el.value),pickup_times:pickups,operating_days:[...document.querySelectorAll(&#039;[name=day]:checked&#039;)].map(el=&gt;Number(el.value)),available_from:$(&#039;availableFrom&#039;).value||null,available_until:$(&#039;availableUntil&#039;).value||null,closed_dates:$(&#039;closedDates&#039;).value.split(\/[\\s,]+\/).filter(Boolean),advisory_capacity:$(&#039;capacity&#039;).value?Number($(&#039;capacity&#039;).value):null});\nawait loadConfig();$(&#039;tourSelect&#039;).value=id;renderSettings();msg(&#039;Tour settings saved. Existing booking prices and pickup times are unchanged.&#039;);});};\n$(&#039;guideForm&#039;).onsubmit=e=&gt;{e.preventDefault();run(async()=&gt;{const payload={id:editingGuide?.id||null,expected_updated_at:editingGuide?.updated_at||null,name:$(&#039;guideName&#039;).value,phone:$(&#039;guidePhone&#039;).value,email:$(&#039;guideEmail&#039;).value,base_city:$(&#039;guideCity&#039;).value,status:$(&#039;guideStatus&#039;).value,experience_years:$(&#039;guideYears&#039;).value,languages:[...document.querySelectorAll(&#039;[name=spokenLanguage]:checked&#039;)].map(el=&gt;el.value).concat(splitList($(&#039;guideOtherLanguages&#039;).value)),regions:splitList($(&#039;guideRegions&#039;).value),specialties:splitList($(&#039;guideSpecialties&#039;).value),bio:$(&#039;guideBio&#039;).value,certifications:$(&#039;guideCertifications&#039;).value,profile_url:$(&#039;guideUrl&#039;).value,availability_notes:$(&#039;guideAvailability&#039;).value,staff_notes:$(&#039;guideStaffNotes&#039;).value};await api(&#039;guide&#039;,payload);data=await api(&#039;config&#039;);renderGuides();editGuide(null);msg(&#039;Guide profile saved. Only approved guides appear in the assignment list.&#039;);});};\nfunction groupKey(x){return [x.tour_id,x.service_date,x.test_mode].join(&#039;|&#039;);}\nfunction prepareGroups(){const map=new Map();for(const a of calendarData.assignments)map.set(groupKey(a),{...a,planned:true,bookings:[]});for(const b of calendarData.bookings){const k=groupKey(b);if(!map.has(k))map.set(k,{tour_id:b.tour_id,service_date:b.service_date,test_mode:b.test_mode,bookings:[]});map.get(k).bookings.push(b);}groups=[...map.values()].sort((a,b)=&gt;a.service_date.localeCompare(b.service_date)||tourName(a.tour_id).localeCompare(tourName(b.tour_id)));}\nfunction overlap(a,b){if(a===b||!a.vehicle_plate||!b.vehicle_plate||a.test_mode!==b.test_mode||a.service_date!==b.service_date||a.vehicle_plate.replace(\/\\s\/g,&#039;&#039;).toUpperCase()!==b.vehicle_plate.replace(\/\\s\/g,&#039;&#039;).toUpperCase())return false;return !a.start_time||!a.end_time||!b.start_time||!b.end_time||a.start_time&lt;b.end_time&amp;&amp;b.start_time&lt;a.end_time;}\nfunction visibleBookings(g){return g.bookings.filter(b=&gt;b.status===&#039;paid_test&#039;||$(&#039;includePending&#039;).checked&amp;&amp;b.status===&#039;pending_payment&#039;);}\nfunction renderCalendar(){if(!calendarData)return;const filtered=groups.filter(g=&gt;(!g.test_mode||$(&#039;includeTests&#039;).checked)&amp;&amp;(!$(&#039;filterTour&#039;).value||g.tour_id===Number($(&#039;filterTour&#039;).value))&amp;&amp;(visibleBookings(g).length||g.planned));$(&#039;departureList&#039;).innerHTML=filtered.length?filtered.map(g=&gt;{const i=groups.indexOf(g),bookings=visibleBookings(g),pax=g.bookings.filter(b=&gt;b.status===&#039;paid_test&#039;).reduce((n,b)=&gt;n+b.passengers,0),pending=g.bookings.filter(b=&gt;b.status===&#039;pending_payment&#039;).reduce((n,b)=&gt;n+b.passengers,0),capacity=g.vehicle_capacity||data.settings.find(s=&gt;s.tour_id===g.tour_id)?.advisory_capacity;return &#039;&lt;article class=&quot;card departure&quot;&gt;&lt;div class=&quot;row between&quot;&gt;&lt;span class=&quot;badge&quot;&gt;&#039;+esc(g.service_date)+(g.test_mode?&#039; \u00b7 TEST&#039;:&#039;&#039;)+&#039;&lt;\/span&gt;&lt;span&gt;&#039;+pax+&#039; confirmed travellers&#039;+(pending?&#039; \u00b7 &#039;+pending+&#039; awaiting payment&#039;:&#039;&#039;)+&#039;&lt;\/span&gt;&lt;\/div&gt;&lt;h3&gt;&#039;+esc(tourName(g.tour_id))+&#039;&lt;\/h3&gt;&lt;p&gt;\ud83d\ude90 &#039;+esc(g.vehicle_name||&#039;Vehicle unassigned&#039;)+&#039; &#039;+esc(g.vehicle_plate||&#039;&#039;)+&#039;&lt;br&gt;\ud83e\uddd1\u200d\ud83c\udfeb &#039;+esc(g.guide_name||&#039;Guide unassigned&#039;)+(g.guide_phone?&#039; \u00b7 &#039;+esc(g.guide_phone):&#039;&#039;)+&#039;&lt;\/p&gt;&#039;+(capacity&amp;&amp;pax&gt;capacity?&#039;&lt;p class=&quot;warning&quot;&gt;\u26a0 Confirmed passengers exceed capacity (&#039;+capacity+&#039;). Arrange extra transport.&lt;\/p&gt;&#039;:&#039;&#039;)+(groups.some(b=&gt;overlap(g,b))?&#039;&lt;p class=&quot;warning&quot;&gt;\u26a0 Vehicle used by another tour on this date. Check duty times.&lt;\/p&gt;&#039;:&#039;&#039;)+&#039;&lt;div class=&quot;row actions&quot;&gt;&lt;button data-assign=&quot;&#039;+i+&#039;&quot;&gt;Assign vehicle &amp; guide&lt;\/button&gt;&lt;button class=&quot;outline&quot; data-share=&quot;&#039;+i+&#039;&quot;&gt;WhatsApp list&lt;\/button&gt;&lt;\/div&gt;&#039;+bookings.map(b=&gt;&#039;&lt;div class=&quot;booking&quot;&gt;&lt;strong&gt;&#039;+esc(b.customer_name)+&#039;&lt;\/strong&gt; \u00b7 &#039;+b.passengers+&#039; travellers &lt;span class=&quot;badge&quot;&gt;&#039;+(b.status===&#039;paid_test&#039;?&#039;Test payment recorded&#039;:&#039;Unpaid&#039;)+&#039;&lt;\/span&gt;&lt;br&gt;&#039;+esc(b.reference)+&#039;&lt;br&gt;\ud83d\udd52 &#039;+esc(b.pickup_city)+&#039; &#039;+esc(b.pickup_time.slice(0,5))+&#039; \u00b7 Adults &#039;+b.adults+&#039; \/ Children &#039;+b.children+&#039; \/ Infants &#039;+b.infants+(b.audio_language?&#039; \u00b7 Audio: &#039;+esc(data.audio_language_options[b.audio_language]||b.audio_language):&#039;&#039;)+&#039;&lt;br&gt;\ud83d\udcde &#039;+esc(b.customer_phone)+&#039;&lt;br&gt;\ud83d\udccd &#039;+esc(b.hotel_name)+&#039; \u00b7 &#039;+esc(b.hotel_address||&#039;&#039;)+(b.latitude!=null?&#039; &lt;a target=&quot;_blank&quot; rel=&quot;noopener&quot; href=&quot;https:\/\/www.google.com\/maps?q=&#039;+b.latitude+&#039;,&#039;+b.longitude+&#039;&quot;&gt;Map \u2197&lt;\/a&gt;&#039;:&#039;&#039;)+&#039;&lt;\/div&gt;&#039;).join(&#039;&#039;)+&#039;&lt;\/article&gt;&#039;;}).join(&#039;&#039;):&#039;&lt;div class=&quot;card&quot;&gt;No matching direct bookings. Change dates or include unpaid test bookings to see your tests.&lt;\/div&gt;&#039;;\ndocument.querySelectorAll(&#039;[data-assign]&#039;).forEach(b=&gt;b.onclick=()=&gt;openAssignment(groups[Number(b.dataset.assign)]));document.querySelectorAll(&#039;[data-share]&#039;).forEach(b=&gt;b.onclick=()=&gt;openShare(groups[Number(b.dataset.share)]));}\nasync function loadCalendar(){calendarData=await api(&#039;calendar&#039;,null,&#039;&amp;from=&#039;+$(&#039;from&#039;).value+&#039;&amp;to=&#039;+$(&#039;to&#039;).value);prepareGroups();renderCalendar();}\nfunction openAssignment(g){selectedGroup=g;$(&#039;assignmentTitle&#039;).textContent=tourName(g.tour_id)+&#039; \u00b7 &#039;+g.service_date;$(&#039;vehicleSelect&#039;).innerHTML=&#039;&lt;option value=&quot;&quot;&gt;Type another vehicle&lt;\/option&gt;&#039;+data.vehicles.map(v=&gt;&#039;&lt;option value=&quot;&#039;+v.id+&#039;&quot;&gt;&#039;+esc(v.name)+&#039; &#039;+esc(v.plate||&#039;&#039;)+&#039;&lt;\/option&gt;&#039;).join(&#039;&#039;);$(&#039;guideSelect&#039;).innerHTML=&#039;&lt;option value=&quot;&quot;&gt;Type another guide&lt;\/option&gt;&#039;+data.guides.filter(v=&gt;v.status===&#039;approved&#039;&amp;&amp;v.active).map(v=&gt;&#039;&lt;option value=&quot;&#039;+v.id+&#039;&quot;&gt;&#039;+esc(v.name)+&#039;&lt;\/option&gt;&#039;).join(&#039;&#039;);$(&#039;vehicleSelect&#039;).value=g.vehicle_id||&#039;&#039;;$(&#039;guideSelect&#039;).value=g.guide_id||&#039;&#039;;for(const [id,key]of Object.entries({vehicleName:&#039;vehicle_name&#039;,vehiclePlate:&#039;vehicle_plate&#039;,vehicleCapacity:&#039;vehicle_capacity&#039;,assignedGuideName:&#039;guide_name&#039;,assignedGuidePhone:&#039;guide_phone&#039;,notes:&#039;notes&#039;}))$(id).value=g[key]||&#039;&#039;;$(&#039;startTime&#039;).value=g.start_time?.slice(0,5)||&#039;&#039;;$(&#039;endTime&#039;).value=g.end_time?.slice(0,5)||&#039;&#039;;$(&#039;assignment&#039;).showModal();}\n$(&#039;vehicleSelect&#039;).onchange=()=&gt;{const v=data.vehicles.find(x=&gt;x.id===$(&#039;vehicleSelect&#039;).value);if(v){$(&#039;vehicleName&#039;).value=v.name;$(&#039;vehiclePlate&#039;).value=v.plate||&#039;&#039;;$(&#039;vehicleCapacity&#039;).value=v.capacity||&#039;&#039;;}};\n$(&#039;guideSelect&#039;).onchange=()=&gt;{const v=data.guides.find(x=&gt;x.id===$(&#039;guideSelect&#039;).value);if(v){$(&#039;assignedGuideName&#039;).value=v.name;$(&#039;assignedGuidePhone&#039;).value=v.phone||&#039;&#039;;}};\n$(&#039;assignmentForm&#039;).onsubmit=e=&gt;{e.preventDefault();run(async()=&gt;{await api(&#039;assignment&#039;,{tour_id:selectedGroup.tour_id,service_date:selectedGroup.service_date,test_mode:selectedGroup.test_mode,vehicle_id:$(&#039;vehicleSelect&#039;).value||null,vehicle_name:$(&#039;vehicleName&#039;).value,vehicle_plate:$(&#039;vehiclePlate&#039;).value,vehicle_capacity:$(&#039;vehicleCapacity&#039;).value,guide_id:$(&#039;guideSelect&#039;).value||null,guide_name:$(&#039;assignedGuideName&#039;).value,guide_phone:$(&#039;assignedGuidePhone&#039;).value,start_time:$(&#039;startTime&#039;).value,end_time:$(&#039;endTime&#039;).value,notes:$(&#039;notes&#039;).value});$(&#039;assignment&#039;).close();await loadCalendar();msg(&#039;Departure assignment saved.&#039;);});};\nfunction openShare(g){const bs=visibleBookings(g).sort((a,b)=&gt;a.pickup_time.localeCompare(b.pickup_time)||a.pickup_city.localeCompare(b.pickup_city));shareText=(g.test_mode?&#039;\ud83e\uddea VET\u00cbM TEST \u2014 JO REZERVIME REALE\\n\\n&#039;:&#039;&#039;)+&#039;\ud83d\ude8c ALBANIANBUS \u2014 LISTA E TURIT\\n\ud83d\uddd3 &#039;+g.service_date+&#039;\\n\ud83c\udfde &#039;+tourName(g.tour_id)+&#039;\\n\\n\ud83d\ude90 Mjeti: &#039;+(g.vehicle_name||&#039;Pa caktuar&#039;)+&#039;\\n\ud83d\udd22 Targa: &#039;+(g.vehicle_plate||&#039;Pa caktuar&#039;)+&#039;\\n\ud83e\uddd1\u200d\ud83c\udfeb Guida: &#039;+(g.guide_name||&#039;Pa caktuar&#039;)+&#039;\\n\ud83d\udcde &#039;+(g.guide_phone||&#039;&#039;)+&#039;\\n\\n&#039;+bs.map((b,i)=&gt;(i+1)+&#039;. \ud83d\udc64 &#039;+b.customer_name+&#039;\\n\ud83c\udfab &#039;+b.reference+&#039; \u00b7 &#039;+(b.status===&#039;paid_test&#039;?&#039;Pages\u00eb test e regjistruar&#039;:&#039;\u26a0 PA PAGUAR&#039;)+&#039;\\n\ud83d\udc65 &#039;+b.passengers+&#039; pasagjer\u00eb \u00b7 &#039;+b.adults+&#039; t\u00eb rritur \/ &#039;+b.children+&#039; f\u00ebmij\u00eb \/ &#039;+b.infants+&#039; foshnja\\n\ud83c\udfa7 Audio: &#039;+(data.audio_language_options[b.audio_language]||b.audio_language||&#039;Pa zgjedhur&#039;)+&#039;\\n\ud83d\udd52 &#039;+b.pickup_city+&#039; &#039;+b.pickup_time.slice(0,5)+&#039;\\n\ud83d\udcde &#039;+b.customer_phone+&#039;\\n\ud83d\udccd &#039;+b.hotel_name+&#039; \u00b7 &#039;+(b.hotel_address||&#039;&#039;)+(b.latitude!=null?&#039;\\n\ud83d\uddfa https:\/\/www.google.com\/maps?q=&#039;+b.latitude+&#039;,&#039;+b.longitude:&#039;&#039;)).join(&#039;\\n\\n&#039;)+(g.notes?&#039;\\n\\n\ud83d\udcdd &#039;+g.notes:&#039;&#039;);$(&#039;shareText&#039;).textContent=shareText;$(&#039;share&#039;).showModal();}\n$(&#039;sendWhatsapp&#039;).onclick=()=&gt;window.open(&#039;https:\/\/wa.me\/?text=&#039;+encodeURIComponent(shareText),&#039;_blank&#039;,&#039;noopener&#039;);\n$(&#039;copyList&#039;).onclick=()=&gt;run(async()=&gt;{await navigator.clipboard.writeText(shareText);msg(&#039;Passenger list copied.&#039;);});\n$(&#039;closeShare&#039;).onclick=()=&gt;$(&#039;share&#039;).close();$(&#039;closeAssignment&#039;).onclick=()=&gt;$(&#039;assignment&#039;).close();\n$(&#039;planDeparture&#039;).onclick=()=&gt;{const id=Number($(&#039;filterTour&#039;).value);if(!id){msg(&#039;Choose a tour in the filter first, then click Plan a departure.&#039;,true);return;}const date=$(&#039;from&#039;).value;if(!date){msg(&#039;Choose a departure date in From.&#039;,true);return;}openAssignment({tour_id:id,service_date:date,test_mode:true,bookings:[]});};\nfunction setRange(mode){const t=new Intl.DateTimeFormat(&#039;en-CA&#039;,{timeZone:&#039;Europe\/Tirane&#039;}).format(new Date()),d=new Date(t+&#039;T12:00:00Z&#039;);let from=t,to=t;if(mode===&#039;week&#039;){const monday=new Date(d);monday.setUTCDate(d.getUTCDate()-((d.getUTCDay()+6)%7));from=monday.toISOString().slice(0,10);monday.setUTCDate(monday.getUTCDate()+6);to=monday.toISOString().slice(0,10);}if(mode===&#039;month&#039;){from=t.slice(0,7)+&#039;-01&#039;;to=new Date(Date.UTC(d.getUTCFullYear(),d.getUTCMonth()+1,0,12)).toISOString().slice(0,10);}$(&#039;from&#039;).value=from;$(&#039;to&#039;).value=to;run(loadCalendar);}\n$(&#039;showToday&#039;).onclick=()=&gt;setRange(&#039;day&#039;);$(&#039;showWeek&#039;).onclick=()=&gt;setRange(&#039;week&#039;);$(&#039;showMonth&#039;).onclick=()=&gt;setRange(&#039;month&#039;);\n$(&#039;refresh&#039;).onclick=()=&gt;run(loadCalendar);$(&#039;print&#039;).onclick=()=&gt;window.print();for(const id of [&#039;includeTests&#039;,&#039;includePending&#039;,&#039;filterTour&#039;])$(id).onchange=renderCalendar;\n$(&#039;loginForm&#039;).onsubmit=e=&gt;{e.preventDefault();run(async()=&gt;{const out=await auth.auth.signInWithPassword({email:$(&#039;email&#039;).value.trim(),password:$(&#039;password&#039;).value});if(out.error)throw out.error;$(&#039;password&#039;).value=&#039;&#039;;});};\n$(&#039;logout&#039;).onclick=()=&gt;run(async()=&gt;{await auth.auth.signOut();});\nasync function enter(s){session=s;$(&#039;login&#039;).hidden=!!s;$(&#039;app&#039;).hidden=!s;$(&#039;logout&#039;).hidden=!s;if(!s){data=null;calendarData=null;groups=[];$(&#039;departureList&#039;).innerHTML=&#039;&#039;;return;}await run(async()=&gt;{await loadConfig();await loadCalendar();msg(&#039;Staff access verified. Tour checkout is still in test mode.&#039;);});}\nconst today=new Intl.DateTimeFormat(&#039;en-CA&#039;,{timeZone:&#039;Europe\/Tirane&#039;}).format(new Date());$(&#039;from&#039;).value=today;$(&#039;to&#039;).value=new Date(Date.parse(today+&#039;T12:00:00Z&#039;)+30*86400000).toISOString().slice(0,10);\nauth.auth.onAuthStateChange((_event,s)=&gt;{setTimeout(()=&gt;enter(s),0);});auth.auth.getSession().then(out=&gt;enter(out.data.session));\nnew ResizeObserver(()=&gt;{try{const f=parent.document.getElementById(&#039;ab-tour-management&#039;);if(f)f.style.height=Math.max(850,document.body.scrollHeight+30)+&#039;px&#039;;}catch{}}).observe(document.body);\n})();\n&lt;\/script&gt;&lt;\/body&gt;&lt;\/html&gt;\"><\/iframe>\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-97960","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 Tour Management - 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 Tour Management - Albanian Bus\" \/>\n<meta property=\"og:url\" content=\"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/\" \/>\n<meta property=\"og:site_name\" content=\"Albanian Bus\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-26T00:10:25+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\/albanianbus-tour-management\/\",\"url\":\"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/\",\"name\":\"AlbanianBus Tour Management - Albanian Bus\",\"isPartOf\":{\"@id\":\"https:\/\/albanianbus.com\/wordpress\/#website\"},\"datePublished\":\"2026-10-25T22:52:08+00:00\",\"dateModified\":\"2026-10-26T00:10:25+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/albanianbus.com\/wordpress\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"AlbanianBus Tour Management\"}]},{\"@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 Tour Management - Albanian Bus","robots":{"index":"noindex","follow":"follow"},"og_locale":"en_US","og_type":"article","og_title":"AlbanianBus Tour Management - Albanian Bus","og_url":"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/","og_site_name":"Albanian Bus","article_modified_time":"2026-10-26T00:10:25+00:00","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/","url":"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/","name":"AlbanianBus Tour Management - Albanian Bus","isPartOf":{"@id":"https:\/\/albanianbus.com\/wordpress\/#website"},"datePublished":"2026-10-25T22:52:08+00:00","dateModified":"2026-10-26T00:10:25+00:00","breadcrumb":{"@id":"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/albanianbus.com\/wordpress\/index.php\/albanianbus-tour-management\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/albanianbus.com\/wordpress\/"},{"@type":"ListItem","position":2,"name":"AlbanianBus Tour Management"}]},{"@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\/97960","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=97960"}],"version-history":[{"count":6,"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages\/97960\/revisions"}],"predecessor-version":[{"id":97972,"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages\/97960\/revisions\/97972"}],"wp:attachment":[{"href":"https:\/\/albanianbus.com\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=97960"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}