PageSourceSearch

https://kagoafrica.com/transporter/assets/js/register.js?version=3.0.9.1

js kagoafrica.com collected 2026-09-24 14:16:13 UTC 17,624 bytes, 592 lines download raw bytes

1class PageState {
2  constructor() {
3    this.companyInformation = {};
4    this.personalInformation = {};
5    this.documents = {};
6    this.activeTab = "company-info";
7    this.routes = [];
8    this.securityQuestions = {
9      1: "What is your favorite color?",
10      3: "What is your pet's name?",
11      4: "What was the name of your math teacher?",
12      5: "What was your childhood nickname?",
13      6: "What is the name of your favorite childhood friend?",
14    };
15    this.selectedSecurityQuestions = {};
16    this.maxFileSizeInMB = 2;
17    this.totalMaxFileSizeInMB = 12;
18    this.mergedDocument = false;
19  }
20
21  setActiveTab(tabId) {
22    this.activeTab = tabId;
23    this.switchTabs(tabId);
24  }
25
26  switchTabs(tabId) {
27    // Disable All Tabs
28    document.querySelectorAll(".nav-link").forEach((navLink) => {
29      navLink.classList.remove("active");
30      navLink.classList.add("disabled");
31    });
32
33    document.querySelectorAll(".tab-pane").forEach((tab) => {
34      tab.classList.remove("active");
35    });
36
37    if (tabId == "company-info") {
38      $("#company-info").addClass("active");
39      $("#company-info-tab-btn").addClass("active");
40      $("#company-info-tab-btn").removeClass("disabled");
41    } else if (tabId == "personal-info") {
42      $("#personal-info").addClass("active");
43      $("#personal-info-tab-btn").addClass("active");
44      $("#personal-info-tab-btn").removeClass("disabled");
45    } else if (tabId == "documents") {
46      $("#documents").addClass("active");
47      $("#documents-tab-btn").addClass("active");
48      $("#documents-tab-btn").removeClass("disabled");
49    }
50  }
51
52  setRoutes(data) {
53    this.routes = data;
54    routeSelectize.clearOptions();
55    data.forEach((route) => {
56      routeSelectize.addOption({ value: route, text: route });
57    });
58  }
59
60  setSecurityQuestions(data) {
61    this.selectedSecurityQuestions = data;
62    this.renderSecurityQuestions();
63  }
64
65  renderSecurityQuestions() {
66    let htmlString = "";
67    $(".security-questions-table tbody").html(htmlString);
68    for (const [questionId, questionObj] of Object.entries(
69      this.selectedSecurityQuestions
70    )) {
71      htmlString += `
72        <tr data-row-id="${questionId}">
73          <td>${questionObj.question}</td>
74          <td class='q-answer'>****</td>
75          <td>
76            <button class="btn btn-sm bg-light text-dark me-2 view-btn show" data-question-id="${questionId}">show</button>
77            <button class="btn btn-sm bg-light text-dark remove-btn" data-question-id="${questionId}">remove</button>
78          </td>
79        </tr>
80        `;
81    }
82    $(".security-questions-table tbody").html(htmlString);
83  }
84}
85
86const pageState = new PageState();
87
88// Initialize selectize
89const routeSelectize = $("#routes").selectize({
90  plugins: ["remove_button"],
91})[0].selectize;
92
93const questionSelectize = $("#question").selectize()[0].selectize;
94
95// Initialize Mobile Input
96let mobileItiInstance = window.intlTelInput(document.getElementById("mobile"), {
97  // any initialisation options go here
98  initialCountry: "TZ",
99  formatOnDisplay: true,
100  utilsScript: true,
101  separateDialCode: true,
102  preferredCountries: ["KE", "UG", "TZ"],
103});
104
105// Initialize dropzone
106const mergedDropzone = new Dropzone("div.dropzone", {
107    url: "/upload-endpoint.php", // Your backend PHP upload endpoint
108    autoProcessQueue: false,
109    paramName: "merged_document", // Field name sent to the server
110    maxFilesize: 5, // Maximum file size in MB
111    maxFiles: 1, // Only accept 1 single merged file
112    acceptedFiles: ".pdf,application/pdf",
113    addRemoveLinks: true,
114    dictDefaultMessage: "<strong>Have a single PDF document?</strong><br>Drop file here or click to upload",
115    
116    init: function () {
117      this.on("addedfile", function (file) {
118        // Enforce single file constraint: replace old file if new one is added
119        if (this.files.length > 1) {
120          this.removeFile(this.files[0]);
121        }
122
123        // Auto-assign the single file ID to all 6 hidden document inputs
124        document.querySelectorAll(".individual-doc-input").forEach((input) => {
125          // console.log(input);
126          // input.files = this.files[0];
127          input.setAttribute("disabled", true);
128          input.setAttribute("readonly", true);
129          console.log("Input Disabled");
130        });
131
132        pageState.mergedDocument = file;
133        document.getElementById("individual-document-block").style.display = "flex";
134      });
135
136      this.on("success", function (file, response) {
137        // Parse server response (e.g., uploaded file ID)
138        const fileData = typeof response === "string" ? JSON.parse(response) : response;
139        
140        // Auto-assign the single file ID to all 6 hidden document inputs
141        document.querySelectorAll(".individual-doc-input").forEach((input) => {
142          console.log(input);
143          input.value = fileData.file_id;
144          input.setAttribute("disabled", true);
145        });
146      });
147
148      this.on("removedfile", function () {
149        // Reset individual references if user removes the merged PDF
150        document.querySelectorAll(".individual-doc-input").forEach((input) => {
151          input.removeAttribute("readonly");
152          input.removeAttribute("disabled");
153        });
154
155        document.getElementById("individual-document-block").style.display = "none";
156      });
157    }
158  });
159
160// Get Routes
161getData(
162  {
163    appType: "getLocation",
164  },
165  (auth = false)
166).then((res) => {
167  if (res.status == "failed") {
168  } else {
169    pageState.setRoutes(Object.keys(res));
170  }
171});
172
173// Handle Tab Validation
174$(".nav-link").on("click", (e) => e.preventDefault());
175$(".next-btn").on("click", (e) => {
176  let currentTab = e.target.dataset.currentTab;
177  let nextTab = e.target.dataset.nextTab;
178
179  let isValid = validateActiveTab();
180  if (!isValid) return;
181
182  // if (nextTab == "documents") {
183  //   if ($("#company_type").val() == "Limited Company") {
184  //     $(".limited-company-docs").removeClass("d-none");
185  //     $(".sole-prop-docs").addClass("d-none");
186  //   } else if ($("#company_type").val() == "Sole Proprietership") {
187  //     $(".limited-company-docs").addClass("d-none");
188  //     $(".sole-prop-docs").removeClass("d-none");
189  //   }
190  // }
191
192  // Switch Tabs
193  pageState.setActiveTab(nextTab);
194});
195
196$(".back-btn").on("click", (e) => {
197  let currentTab = e.target.dataset.currentTab;
198  let nextTab = e.target.dataset.nextTab;
199
200  // Switch Tabs
201  pageState.setActiveTab(nextTab);
202});
203
204function validateActiveTab() {
205  if (pageState.activeTab == "company-info") {
206    let isValid = validateCompanyInfo();
207    return isValid;
208  } else if (pageState.activeTab == "personal-info") {
209    let isValid = validatePersonalInfo();
210    return isValid;
211  } else if (pageState.activeTab == "documents") {
212    let isValid = validateDocuments();
213    return isValid;
214  }
215}
216
217function resetCompanyInfoErrors() {
218  $(".error.companyName").addClass("d-none");
219  $(".error.tinNo").addClass("d-none");
220  $(".error.address").addClass("d-none");
221  $(".error.businessType").addClass("d-none");
222  $(".error.no").addClass("d-none");
223  $(".error.routes").addClass("d-none");
224  $(".error.company_type").addClass("d-none");
225}
226
227function validateCompanyInfo() {
228  let isValid = true;
229
230  let companyName = $("#companyName").val();
231  let tinNumber = $("#tinNo").val();
232  let address = $("#address").val();
233  let specialization = $("#businessType").val();
234  let companyType = $("#company_type").val();
235  let noOfTrucks = $("#no").val();
236  let preferredCountries = routeSelectize.getValue();
237
238  resetCompanyInfoErrors();
239
240  if (!companyName) {
241    $(".error.companyName").removeClass("d-none");
242    isValid = false;
243  }
244
245  if (!tinNumber) {
246    $(".error.tinNo").removeClass("d-none");
247    isValid = false;
248  }
249
250  if (!address) {
251    $(".error.address").removeClass("d-none");
252    isValid = false;
253  }
254
255  if (!specialization) {
256    $(".error.businessType").removeClass("d-none");
257    isValid = false;
258  }
259
260  if (!noOfTrucks) {
261    $(".error.no").removeClass("d-none");
262    isValid = false;
263  }
264
265  if (preferredCountries.length < 1) {
266    $(".error.routes").removeClass("d-none");
267    isValid = false;
268  }
269
270  if (!companyType) {
271    $(".error.company_type").removeClass("d-none");
272    isValid = false;
273  }
274
275  return isValid;
276}
277
278function resetPersonalInfoErrors() {
279  $(".error.firstName").addClass("d-none");
280  $(".error.lastName").addClass("d-none");
281  $(".error.position").addClass("d-none");
282  $(".error.email").addClass("d-none");
283  $(".error.mobile").addClass("d-none");
284  $(".error.questions").addClass("d-none");
285}
286
287function validatePersonalInfo() {
288  let isValid = true;
289
290  let firstName = $("#firstName").val();
291  let lastName = $("#lastName").val();
292  let position = $("#position").val();
293  let email = $("#email").val();
294
295  resetPersonalInfoErrors();
296
297  if (!firstName) {
298    $(".error.firstName").removeClass("d-none");
299    isValid = false;
300  }
301
302  if (!lastName) {
303    $(".error.lastName").removeClass("d-none");
304    isValid = false;
305  }
306
307  if (!position) {
308    $(".error.position").removeClass("d-none");
309    isValid = false;
310  }
311
312  if (!email) {
313    $(".error.email").removeClass("d-none");
314    isValid = false;
315  }
316
317  if (!mobileItiInstance.isValidNumber()) {
318    $(".error.mobile").removeClass("d-none");
319    isValid = false;
320  }
321
322  if (Object.keys(pageState.selectedSecurityQuestions).length < 3) {
323    $(".error.questions").removeClass("d-none");
324    isValid = false;
325  }
326
327  return isValid;
328}
329
330// Handle Security Questions
331$("#add-sec-btn").on("click", (e) => {
332  let question = questionSelectize.getValue();
333  let answer = $("#answer").val();
334
335  if (!question || !answer) {
336    return;
337  }
338
339  if (pageState.selectedSecurityQuestions[question]) {
340    return;
341  }
342
343  pageState.selectedSecurityQuestions[question] = {
344    question: pageState.securityQuestions[question],
345    answer: answer,
346  };
347
348  questionSelectize.setValue("");
349  $("#answer").val("");
350
351  pageState.setSecurityQuestions(pageState.selectedSecurityQuestions);
352});
353
354$(".security-questions-table tbody").on("click", ".view-btn", (e) => {
355  const questionId = e.target.dataset.questionId;
356  const action = e.target.classList.contains("show") ? "show" : "hide";
357  if (action == "show") {
358    $(`tr[data-row-id="${questionId}"]`)
359      .find(".q-answer")
360      .html(pageState.selectedSecurityQuestions[questionId].answer);
361    e.target.classList.replace("show", "hide");
362    e.target.textContent = "hide";
363  } else {
364    $(`tr[data-row-id="${questionId}"]`).find(".q-answer").html("****");
365    e.target.classList.replace("hide", "show");
366    e.target.textContent = "show";
367  }
368});
369
370$(".security-questions-table tbody").on("click", ".remove-btn", (e) => {
371  const questionId = e.target.dataset.questionId;
372  delete pageState.selectedSecurityQuestions[questionId];
373  pageState.setSecurityQuestions(pageState.selectedSecurityQuestions);
374});
375
376function resetDocumentsError() {
377  $(".error.crt").addClass("d-none");
378  $(".error.memo").addClass("d-none");
379  $(".error.tax").addClass("d-none");
380  $(".error.tin").addClass("d-none");
381  $(".error.businessLicense").addClass("d-none");
382  $(".error.insuaranceNote").addClass("d-none");
383  $(".error.terms").addClass("d-none");
384  $(".error.acquisitionChannel").addClass("d-none");
385}
386
387function validateDocuments() {
388  let isValid = true;
389
390  resetDocumentsError();
391
392  // if ($("#company_type").val() == "Limited Company") {
393    let crt = $("#crt").prop("files")[0];
394    let brela = $("#memo").prop("files")[0];
395    let tax = $("#tax").prop("files")[0];
396
397    if (!crt) {
398      $(".error.crt").removeClass("d-none");
399      isValid = false;
400    }
401
402    if (!brela) {
403      $(".error.memo").removeClass("d-none");
404      isValid = false;
405    }
406
407    if (!tax) {
408      $(".error.tax").removeClass("d-none");
409      isValid = false;
410    }
411
412    if (crt && crt.size / (1024 * 1024) > pageState.maxFileSizeInMB) {
413      $('.error.crt').text('The file upload cannot exceed 5MB');
414      $('.error.crt').removeClass('d-none');
415      isValid = false;
416    }
417
418    if (brela && brela.size / (1024 * 1024) > pageState.maxFileSizeInMB) {
419      $('.error.memo').text('The file upload cannot exceed 5MB');
420      $('.error.memo').removeClass('d-none');
421      isValid = false;
422    }
423
424    if (tax && tax.size / (1024 * 1024) > pageState.maxFileSizeInMB) {
425      $('.error.tax').text('The file upload cannot exceed 5MB');
426      $('.error.tax').removeClass('d-none');
427      isValid = false;
428    }
429  // } 
430  
431  // else if ($("#company_type").val() == "Sole Proprietership") {
432    let tin = $("#tin").prop("files")[0];
433    let businessLicense = $("#businessLicense").prop("files")[0];
434    let insuaranceNote = $("#insuaranceNote").prop("files")[0];
435
436    if (!tin) {
437      $(".error.tin").removeClass("d-none");
438      isValid = false;
439    }
440
441    if (!businessLicense) {
442      $(".error.businessLicense").removeClass("d-none");
443      isValid = false;
444    }
445
446    if (!insuaranceNote) {
447      $(".error.insuaranceNote").removeClass("d-none");
448      isValid = false;
449    }
450
451    if (tin && tin.size / (1024 * 1024) > pageState.maxFileSizeInMB) {
452      $('.error.tin').text('The file upload cannot exceed 5MB');
453      $('.error.tin').removeClass('d-none');
454      isValid = false;
455    }
456
457    if (businessLicense && businessLicense.size / (1024 * 1024) > pageState.maxFileSizeInMB) {
458      $('.error.businessLicense').text('The file upload cannot exceed 5MB');
459      $('.error.businessLicense').removeClass('d-none');
460      isValid = false;
461    }
462
463    if (insuaranceNote && insuaranceNote.size / (1024 * 1024) > pageState.maxFileSizeInMB) {
464      $('.error.insuaranceNote').text('The file upload cannot exceed 5MB');
465      $('.error.insuaranceNote').removeClass('d-none');
466      isValid = false;
467    }
468  // }
469
470  if (!$("#terms").is(":checked")) {
471    $(".error.terms").removeClass("d-none");
472    isValid = false;
473  }
474
475  if (!$("#acquisitionChannel").val()) {
476    $(".error.acquisitionChannel").removeClass("d-none");
477    isValid = false;
478  } 
479
480  return isValid;
481}
482
483// Handle Submit
484$("#submit-btn").on("click", (e) => {
485  let isValid =
486    validateCompanyInfo() && validatePersonalInfo();
487
488  if (!pageState.mergedDocument && !validateDocuments()) {
489    return;
490  }
491
492  $(".error.terms").addClass("d-none");
493  $(".error.acquisitionChannel").addClass("d-none");
494  if (!$("#terms").is(":checked")) {
495    $(".error.terms").removeClass("d-none");
496    isValid = false;
497  }
498
499  if (!$("#acquisitionChannel").val()) {
500    $(".error.acquisitionChannel").removeClass("d-none");
501    isValid = false;
502  }
503
504  if (!isValid) return;
505
506  let loader = document.createElement("div");
507  loader.classList.add("spinner", "spinner-grow", "spinner-grow-sm", "ms-2");
508  e.target.append(loader);
509  e.target.setAttribute("disabled", true);
510
511  // Get Data
512  const data = {
513    appType: "signUp",
514    firstName: $("#firstName").val(),
515    lastName: $("#lastName").val(),
516    position: $("#position").val(),
517    email: $("#email").val(),
518    mobile: mobileItiInstance.getNumber(),
519    security: JSON.stringify(pageState.selectedSecurityQuestions),
520    companyName: $("#companyName").val(),
521    tinNo: $("#tinNo").val(),
522    address: $("#address").val(),
523    companyType: $("#company_type").val(),
524    businessType: $("#businessType").val(),
525    no: $("#no").val(),
526    selected_routes: JSON.stringify(routeSelectize.getValue()),
527    acquisitionChannel: $("#acquisitionChannel").val()
528  };
529
530  let totalFileSizeInBytes = 0;
531  if (!pageState.mergedDocument) {
532    data.crt = $("#crt").prop("files")[0];
533    data.memo = $("#memo").prop("files")[0];
534    data.tax = $("#tax").prop("files")[0];
535    totalFileSizeInBytes = (data.crt.size + data.memo.size + data.tax.size);
536    data.tin = $("#tin").prop("files")[0];
537    data.businessLicense = $("#businessLicense").prop("files")[0];
538    data.insuaranceNote = $("#insuaranceNote").prop("files")[0];
539    totalFileSizeInBytes = (data.tin.size + data.businessLicense.size + data.insuaranceNote.size);
540    const totalFileSizeInMB = (totalFileSizeInBytes / (1024 * 1024)).toFixed(2);
541    if (totalFileSizeInMB > pageState.totalMaxFileSizeInMB) {
542      swal("Warning", "The total file size of the 3 attached documents exceed the limit of 15MB (5MB per file)", "warning");
543      return;
544    }
545  }
546
547  else {
548    data.singleDocumentUpload = true;
549    data.mergedDocument = pageState.mergedDocument;
550  }
551
552  // Post Data
553  postData(data, (json = false), (auth = false))
554    .then((res) => {
555      console.log(res);
556      if (res.status == "failed") {
557        swal("Failed registration", res.message, "warning");
558      } else {
559        swal(
560          "Success",
561          "This application will undergo review and you will receive an email",
562          "success"
563        );
564
565        // Clear form after submission
566        $("input, select, textarea").val("");
567        routeSelectize.clear();
568        questionSelectize.clear();
569        mobileItiInstance.setNumber("");
570        pageState.setSecurityQuestions({});
571        mergedDropzone.removeAllFiles(true);
572        $("#terms").prop("checked", false);
573        document.querySelectorAll(".individual-doc-input").forEach((input) => {
574          input.value = "";
575          input.removeAttribute("readonly");
576          input.removeAttribute("disabled");
577        });
578        resetCompanyInfoErrors();
579        resetPersonalInfoErrors();
580        resetDocumentsError();
581        pageState.setActiveTab("company-info");
582        document.getElementById("individual-document-block").style.display = "none";
583      }
584    })
585    .catch(error => {
586      swal("Error", error.message, "error");
587    })
588    .finally(() => {
589      loader.remove();
590      e.target.removeAttribute("disabled");
591    });
592});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.