Last active
October 3, 2024 16:15
-
-
Save arpeggio068/beaf56502b872870d41ef571ab4f25e8 to your computer and use it in GitHub Desktop.
Booking Reservation CRUD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //code.gs | |
| const spreadsheetId = 'Your Google Sheet ID'; | |
| const ss = SpreadsheetApp.openById(spreadsheetId); | |
| function doGet(e){ | |
| return HtmlService.createTemplateFromFile("main").evaluate() | |
| .setTitle("Admin Booking") | |
| .addMetaTag('viewport', 'width=device-width, initial-scale=1') | |
| .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL); | |
| } | |
| function loadPartialHTML_(partial) { | |
| const htmlServ =HtmlService.createTemplateFromFile(partial); | |
| return htmlServ.evaluate().getContent(); | |
| } | |
| function loadAddVisitView(){ | |
| return loadPartialHTML_("addRecord"); | |
| } | |
| function loadSearchView(){ | |
| return loadPartialHTML_("search"); | |
| } | |
| function loadEditVisitView(){ | |
| return loadPartialHTML_("editRecord"); | |
| } | |
| function loadSetHolidaysView(){ | |
| return loadPartialHTML_("setHolidays"); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| ///////////// Login Func ///////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| function search2(searchtext){//For Login | |
| const loginSheetID = spreadsheetId //user data | |
| const range = SpreadsheetApp.openById(loginSheetID).getSheetByName("user").getDataRange(); | |
| const data = range.getValues() | |
| const firstElement = data.shift() //skip first row | |
| let ar = []; | |
| data.forEach(function(f) { | |
| if (~[f[0]].indexOf(searchtext)) { | |
| ar.push([ f[0],f[1] ]); | |
| } | |
| }) | |
| //Logger.log(data); | |
| return ar; | |
| }; | |
| function processForm2(formObject){//For Login | |
| let concat = formObject.searchtext3; | |
| let result = ""; | |
| if(concat){ | |
| result = search2(concat); | |
| } | |
| return result; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| ///////////// End Login Func ///////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| ///////////// Search Record Func ///////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| function getDataForSearch(){ | |
| const ws = ss.getSheetByName("data"); | |
| const data = ws.getRange(2, 1, ws.getLastRow()-1,7).getValues(); | |
| data.sort(function(a,b){ //sort by date | |
| if(a[0] != ""){ | |
| let moddate1 = a[4].split("/")[2]+"/"+a[4].split("/")[1]+"/"+a[4].split("/")[0] | |
| let moddate2 = b[4].split("/")[2]+"/"+b[4].split("/")[1]+"/"+b[4].split("/")[0] | |
| let c = new Date(moddate1); | |
| let d = new Date(moddate2); | |
| return c-d; | |
| } | |
| }); | |
| return data; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| ///////////// End Search Record Func ///////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| ///////////// Edit & Delete Record Func ///////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| function getCustomerById(id){ | |
| const ws = ss.getSheetByName("data"); | |
| const dataIDs = ws.getRange(2, 1, ws.getLastRow()-1,1).getValues().map(r => r[0].toString().toLowerCase()); | |
| const posIndex = dataIDs.indexOf(id.toString().toLowerCase()); | |
| const rowNumber = posIndex === -1 ? 0 : posIndex+2; | |
| const customerInfo = ws.getRange(rowNumber, 1,1 ,7).getValues()[0]; | |
| //Logger.log(customerInfo[0]) | |
| return { | |
| dataID:customerInfo[0], | |
| custID:customerInfo[1], | |
| name:customerInfo[2], | |
| tel:customerInfo[3], | |
| date:customerInfo[4], | |
| time:customerInfo[5] | |
| } | |
| } | |
| function editCustomerById(id,customerInfo){ | |
| const ws = ss.getSheetByName("data"); | |
| const dataIDs = ws.getRange(2, 1, ws.getLastRow()-1,1).getValues().map(r => r[0].toString().toLowerCase()); | |
| const posIndex = dataIDs.indexOf(id.toString().toLowerCase()); | |
| const rowNumber = posIndex === -1 ? 0 : posIndex+2; | |
| let fullQ = getFullQ(customerInfo.date) | |
| let oldDate = ws.getRange(rowNumber,5).getValue(); | |
| let oldTime = ws.getRange(rowNumber,6).getValue(); | |
| if(customerInfo.date == oldDate && customerInfo.time == oldTime){ | |
| ws.getRange(rowNumber,2,1,7).setValues([[ | |
| customerInfo.custID, | |
| customerInfo.name, | |
| customerInfo.tel, | |
| "'"+customerInfo.date, | |
| "'"+customerInfo.time, | |
| customerInfo.admin, | |
| new Date() | |
| ]]); | |
| return "success"; | |
| } | |
| else if(!fullQ.includes(customerInfo.time)){ | |
| ws.getRange(rowNumber,2,1,7).setValues([[ | |
| customerInfo.custID, | |
| customerInfo.name, | |
| customerInfo.tel, | |
| "'"+customerInfo.date, | |
| "'"+customerInfo.time, | |
| customerInfo.admin, | |
| new Date() | |
| ]]); | |
| return "success"; | |
| } | |
| else{ | |
| return "fail"; | |
| } | |
| } | |
| function deleteById(id){ | |
| const ws = ss.getSheetByName("data"); | |
| const custIDs = ws.getRange(2, 1, ws.getLastRow()-1,1).getValues().map(r => r[0].toString().toLowerCase()); | |
| const posIndex = custIDs.indexOf(id.toString().toLowerCase()); | |
| const rowNumber = posIndex === -1 ? 0 : posIndex+2; | |
| ws.deleteRow(rowNumber); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| ///////////// End Edit & Delete Record Func ///////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| ///////////// Add Record Func ///////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| function getCalendar(){ //get disable days and full booked days | |
| const ws = ss.getSheetByName("data"); | |
| const data = ws.getRange(2,1,ws.getLastRow()-1,7).getValues(); | |
| let disableDays = [] | |
| data.forEach(function(a){ | |
| if(a[1] == "holiday"){ | |
| let moddate = a[4].split("/")[2]+"/"+a[4].split("/")[1]+"/"+a[4].split("/")[0] | |
| disableDays.push( | |
| new Date(moddate).setHours(0,0,0,0) | |
| ) | |
| } | |
| }) | |
| let countQ = []; | |
| data.forEach(function(b){ | |
| if(b[1] != "holiday"){ | |
| countQ.push([ | |
| b[4], //date | |
| countIF(data,4,b[4]) | |
| ]) | |
| } | |
| }) | |
| countQ.forEach(function(c){ | |
| if(c[1] >= 4){ //max 4 person for 1 day, 9:00 = 2 person, 10:00 = 2 person | |
| let fullqdate = c[0].split("/")[2]+"/"+c[0].split("/")[1]+"/"+c[0].split("/")[0] | |
| disableDays.push( | |
| new Date(fullqdate).setHours(0,0,0,0) | |
| ) | |
| } | |
| }) | |
| let uniqueDays = []; | |
| disableDays.forEach(function(d){ | |
| if(uniqueDays.indexOf(d) === -1){ | |
| uniqueDays.push(d); | |
| } | |
| }); | |
| let curUniqueDays = []; | |
| let currentDate = new Date() | |
| let currentDate2 = new Date(currentDate).setHours(0,0,0,0) | |
| uniqueDays.forEach(function(e){ | |
| if(new Date(e) >= currentDate2){ | |
| curUniqueDays.push(e) | |
| } | |
| }) | |
| //Logger.log(uniqueDays); | |
| return curUniqueDays; | |
| } | |
| function getFullQ(userdate){ //get full Q time | |
| //userdate = "22/4/2022" | |
| const ws = ss.getSheetByName("data"); | |
| const data = ws.getRange(2,1,ws.getLastRow()-1,7).getValues(); | |
| let countQ = []; | |
| let fullQ = []; | |
| data.forEach(function(a){ | |
| if(a[4] == userdate && a[1] != "holiday"){ | |
| countQ.push([ | |
| a[5], //time | |
| countIFS2(data,4,a[4],5,a[5]) | |
| ]) | |
| } | |
| }) | |
| countQ.forEach(function(b){ | |
| if(b[1] >= 2){ //max 2 person per time, 9:00 = 2 person, 10:00 = 2 person | |
| fullQ.push(b[0]) | |
| } | |
| }) | |
| let uniqueFullQ = []; | |
| fullQ.forEach(function(d){ | |
| if(uniqueFullQ.indexOf(d) === -1){ | |
| uniqueFullQ.push(d); | |
| } | |
| }); | |
| //Logger.log(uniqueFullQ); | |
| return uniqueFullQ; | |
| } | |
| function addNewRow(rowData) { | |
| const ws = ss.getSheetByName("data"); | |
| const newID = uniqueId(); | |
| let fullQ = getFullQ(rowData.date) | |
| if(!fullQ.includes(rowData.time)){ | |
| ws.appendRow([newID(), | |
| rowData.custID, | |
| rowData.name, | |
| rowData.tel, | |
| "'"+rowData.date, | |
| "'"+rowData.time, | |
| rowData.admin, | |
| new Date() | |
| ]); | |
| return "success"; | |
| } | |
| else{ | |
| return "fail"; | |
| } | |
| } | |
| function searchNameByCustomerId(formObject){ | |
| const ws = ss.getSheetByName("data").getDataRange(); | |
| const data = ws.getValues(); | |
| const firstElement = data.shift() | |
| let ar = []; | |
| data.forEach(function(f) { | |
| if (f[1] == formObject.custID) { | |
| ar.push(f[2]); | |
| } | |
| }); | |
| let uniqueNames = []; | |
| ar.forEach(function(d){ | |
| if(uniqueNames.indexOf(d) === -1){ | |
| uniqueNames.push(d); | |
| } | |
| }); | |
| //Logger.log(data); | |
| return uniqueNames; | |
| } | |
| function notNameByCustomerId(){ //for name autocomplete | |
| const ws = ss.getSheetByName("data").getDataRange(); | |
| const data = ws.getValues(); | |
| const firstElement = data.shift() | |
| let ar = []; | |
| data.forEach(function(f) { | |
| if (f[1] == "ex_ttmd"){ | |
| ar.push(f[2]); | |
| } | |
| }); | |
| let uniqueNames = []; | |
| ar.forEach(function(d){ | |
| if(uniqueNames.indexOf(d) === -1){ | |
| uniqueNames.push(d); | |
| } | |
| }); | |
| //Logger.log(uniqueNames); | |
| return uniqueNames; | |
| } | |
| function getCustomerTels(){ //for tel autocomplete | |
| const data = ss.getSheetByName("data").getDataRange().getValues(); | |
| let ar = []; | |
| data.forEach(function(f) { | |
| if (f[3] !== "tel"){ // "tel" = column name | |
| ar.push(f[3]); | |
| } | |
| }); | |
| let uniqueTels = []; | |
| ar.forEach(function(d){ | |
| if(uniqueTels.indexOf(d) === -1){ | |
| uniqueTels.push(d); | |
| } | |
| }); | |
| //Logger.log(uniqueTels); | |
| return uniqueTels; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| ///////////// End Add Record Func ///////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| ///////////// Set Holidays Func ///////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| function addNewHolidayRow(rowData) { | |
| const ws = ss.getSheetByName("data"); | |
| const newID = uniqueId(); | |
| ws.appendRow([newID(), | |
| rowData.custID, | |
| rowData.name, | |
| rowData.tel, | |
| "'"+rowData.date, | |
| "'"+rowData.time, | |
| rowData.admin, | |
| new Date() | |
| ]); | |
| return true; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| ///////////// End Set Holidays Func ///////// | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| //code.gs | |
| //utility.gs | |
| //////// count function////////////////// | |
| function countIF(array,index1,condition1){ //count for 1 condition | |
| var countVal = 0; | |
| array.forEach(function(e){ | |
| if(e[index1] == condition1){ | |
| countVal ++ | |
| } | |
| }); | |
| return countVal | |
| } | |
| function countIFS2(array,index1,condition1,index2,condition2){ //count for 2 condition | |
| var countVal = 0; | |
| array.forEach(function(e){ | |
| if(e[index1] == condition1 && e[index2] == condition2){ | |
| countVal ++ | |
| } | |
| }); | |
| return countVal | |
| } | |
| ////////end count function////////////////// | |
| function uniqueId(){ | |
| const firstItem = { | |
| value: "0" | |
| }; | |
| /*length can be increased for lists with more items.*/ | |
| let counter = "123456789".split('') | |
| .reduce((acc, curValue, curIndex, arr) => { | |
| const curObj = {}; | |
| curObj.value = curValue; | |
| curObj.prev = acc; | |
| return curObj; | |
| }, firstItem); | |
| firstItem.prev = counter; | |
| return function () { | |
| let now = Date.now(); | |
| if (typeof performance === "object" && typeof performance.now === "function") { | |
| now = performance.now().toString().replace('.', ''); | |
| } | |
| counter = counter.prev; | |
| return `${now}${Math.random().toString(16).substr(2)}${counter.value}`; | |
| } | |
| } | |
| //utility.gs | |
| <!-- main.html --> | |
| <!doctype html> | |
| <html lang="en"> | |
| <head> | |
| <!-- Required meta tags --> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | |
| <!-- Bootstrap CSS --> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous"> | |
| <style> | |
| h1,h2,h3,h4,h5,h6 {text-align: center;} | |
| .nav-link{ | |
| cursor:pointer; | |
| .form-elegant .font-small { | |
| font-size: 0.8rem; } | |
| .form-elegant .z-depth-1a { | |
| -webkit-box-shadow: 0 2px 5px 0 rgba(55, 161, 255, 0.26), 0 4px 12px 0 rgba(121, 155, 254, 0.25); | |
| box-shadow: 0 2px 5px 0 rgba(55, 161, 255, 0.26), 0 4px 12px 0 rgba(121, 155, 254, 0.25); } | |
| .form-elegant .z-depth-1-half, | |
| .form-elegant .btn:hover { | |
| -webkit-box-shadow: 0 5px 11px 0 rgba(85, 182, 255, 0.28), 0 4px 15px 0 rgba(36, 133, 255, 0.15); | |
| box-shadow: 0 5px 11px 0 rgba(85, 182, 255, 0.28), 0 4px 15px 0 rgba(36, 133, 255, 0.15); } | |
| } | |
| /*#loading { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| z-index: 10000; | |
| width: 100vw; | |
| height: 100vh; | |
| background-color: rgba(255,255,255,0.9); | |
| }*/ | |
| .nav { | |
| background-color: #F8F054 !important; | |
| } | |
| *{ | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font: 16px Arial; | |
| } | |
| .own-set{ | |
| padding: 10px; | |
| width: 500px; | |
| } | |
| div.ui-datepicker, .ui-datepicker input{ | |
| font-size:110%; | |
| background: #FCF5F4; | |
| //border: 1px solid #FCFCE3; | |
| //color: #FCFCE3; | |
| } | |
| a.ui-state-default{ | |
| background-color: #F7FCFB ; | |
| } | |
| label.required::before { | |
| content: '*'; | |
| margin-right: 4px; | |
| color: red; | |
| } | |
| #divMenuUraianKerja{ | |
| border: 1px solid rgba(0,0,0,0.2); | |
| padding: 20px; | |
| /* margin-left:10px; | |
| margin-right:10px; | |
| margin-top: 15px; */ | |
| border-radius: 10px; | |
| margin: auto; | |
| background-color: #F9F8DA; | |
| font-family: 'Prompt'; | |
| } | |
| #divMenuUraianKerja2{ | |
| border: 1px solid rgba(0,0,0,0.2); | |
| padding: 20px; | |
| /* margin-left:10px; | |
| margin-right:10px; | |
| margin-top: 15px; */ | |
| border-radius: 10px; | |
| margin: auto; | |
| background-color:#F7FCFA ; | |
| font-family: 'Prompt'; | |
| } | |
| p{ | |
| font-size: 0.8em; | |
| } | |
| #app{ | |
| border: 1px solid rgba(0,0,0,0.2); | |
| padding: 10px; | |
| /* margin-left:10px; | |
| margin-right:10px; | |
| margin-top: 15px; */ | |
| border-radius: 13px; | |
| margin: auto; | |
| background-color:#FCFCF9; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <center><h5 style="color:#ACA710"; >Admin Booking</h5></center> | |
| <div id="formlogin" > | |
| <center> <form> | |
| <label for="searchtext3" id="pass-label" style = "font-size:15px;color:black">Password</label> | |
| <input type="password" class="form-control col-sm-3" id="searchtext3" name="searchtext3" placeholder="Password"> | |
| <input type="hidden" id="recent-user"> | |
| <input type="hidden" id="search-hn"> | |
| <input type="hidden" id="main_hn"> | |
| <input type="hidden" id="temp_hn"> | |
| <input type="hidden" id="temp_name"> | |
| <br> <button type="button" id="login" class="btn btn-primary mb-2" onclick="handleFormSubmit2()">Login</button><p> | |
| <span id="resp-spinnerA" class="spinner-border spinner-grow-sm text-danger d-none" role="status" aria-hidden="true"></span> | |
| </form></center> | |
| </div> | |
| <div id= "userform"> | |
| <div id = "maincontainer" class="container invisible"> | |
| <nav id="navigation"> | |
| <ul class="nav nav-tabs main-nav"> | |
| <li class="nav-item"> | |
| <div class="nav-link" id="search-link" >Search/Edit</div> | |
| </li> | |
| <li class="nav-item"> | |
| <div class="nav-link active" id="addrec-link" >Add Reccord</div> | |
| </li> | |
| <li class="nav-item"> | |
| <div class="nav-link" id="setHoliday-link" >Set Holiday</div> | |
| </li> | |
| </ul> | |
| </nav> | |
| <!-- <div id = "form_waiting" style="font-size:20px;color:red;"></div> --> | |
| <div id="loading" class="d-flex justify-content-center align-items-center invisible" style="color:#F0530A;"> | |
| <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> | |
| Please wait... | |
| </div> | |
| <div id="app"></div> | |
| <!-- Content here --> | |
| </div><!-- Close container --> | |
| </div> <!-- Close userform --> | |
| <!-- Optional JavaScript --> | |
| <!-- jQuery first, then Popper.js, then Bootstrap JS --> | |
| <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script> | |
| <script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s" crossorigin="anonymous"></script> | |
| <!--Autocomplete & Calendar JQuery--> | |
| <link rel="stylesheet" href="//code.jquery.com/ui/1.13.0/themes/base/jquery-ui.css"> | |
| <link rel="stylesheet" href="/resources/demos/style.css"> | |
| <script src="https://code.jquery.com/jquery-3.6.0.js"></script> | |
| <script src="https://code.jquery.com/ui/1.13.0/jquery-ui.js"></script> | |
| <!--Autocomplete & Calendar JQuery--> | |
| <script> | |
| var data; | |
| var disabledDaysArray = []; | |
| var gCustID ="", gName = "", gTel = "", userName = ""; | |
| //----------------------------------------------------------------------------------// | |
| //------- Set Calendar/AutoComplete Function -------------// | |
| //----------------------------------------------------------------------------------// | |
| function populateDates(disabledDays){ | |
| var currentDate = new Date(); | |
| var results = []; | |
| for(var i=0; i<disabledDays.length; i++ ){ | |
| results += new Date(disabledDays[i]).toDateString(); | |
| } | |
| $(function(){ | |
| $("#datepicker" ).datepicker({ | |
| minDate: currentDate, | |
| maxDate: +45, | |
| dateFormat: "d/m/yy", | |
| // dayNamesMin: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส"], | |
| // monthNames: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", | |
| // "ธันวาคม"], | |
| // monthNamesShort: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."], | |
| navigationAsDateFormat: true, | |
| beforeShowDay: function(date){ if(results.indexOf(date.toDateString())>-1 | |
| // || date.getDay() === 0 | |
| // || date.getDay() === 6 | |
| ) | |
| {return [false];}else{return [true];} | |
| } | |
| }); | |
| }); | |
| disabledDays.forEach(function(r){ | |
| let date = new Date(r).getDate(); | |
| let month = new Date(r).getMonth() +1; | |
| let year = new Date(r).getFullYear(); | |
| let strDate = date+"/"+month+"/"+year | |
| disabledDaysArray.push(strDate) | |
| }) | |
| waitingEnd(); | |
| } | |
| function populateHolidays(disabledDays){ | |
| var currentDate = new Date(); | |
| var results = []; | |
| for(var i=0; i<disabledDays.length; i++ ){ | |
| results += new Date(disabledDays[i]).toDateString(); | |
| } | |
| $(function(){ | |
| $("#datepicker" ).datepicker({ | |
| changeMonth: 'true', | |
| changeYear: 'true', | |
| minDate: currentDate, | |
| maxDate: +366, | |
| dateFormat: "d/m/yy", | |
| // dayNamesMin: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส"], | |
| // monthNames: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", | |
| // "ธันวาคม"], | |
| // monthNamesShort: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."], | |
| navigationAsDateFormat: true, | |
| beforeShowDay: function(date){ if(results.indexOf(date.toDateString())>-1 | |
| // || date.getDay() === 0 | |
| // || date.getDay() === 6 | |
| ) | |
| {return [false];}else{return [true];} | |
| } | |
| }); | |
| }); | |
| disabledDays.forEach(function(r){ | |
| let date = new Date(r).getDate(); | |
| let month = new Date(r).getMonth() +1; | |
| let year = new Date(r).getFullYear(); | |
| let strDate = date+"/"+month+"/"+year | |
| disabledDaysArray.push(strDate) | |
| }) | |
| waitingEnd(); | |
| } | |
| function populateVisitDates(){ | |
| var currentDate = new Date(); | |
| $(function(){ | |
| $("#datechoose" ).datepicker({ | |
| changeMonth: 'true', | |
| changeYear: 'true', | |
| minDate: currentDate, | |
| maxDate: +366, | |
| dateFormat: "d/m/yy", | |
| // dayNamesMin: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส"], | |
| // monthNames: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", | |
| // "ธันวาคม"], | |
| // monthNamesShort: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."], | |
| navigationAsDateFormat: true | |
| // beforeShowDay: function (date){ if( date.getDay() === 0 || date.getDay() === 6) | |
| // {return [false];}else{return [true];} | |
| // } | |
| }); | |
| }); | |
| //loadingEnd(); | |
| } | |
| function populatePtNames(names){ | |
| $(function(){ | |
| var availableTags2 = names; | |
| $("#name").autocomplete({ | |
| source: availableTags2 | |
| }); | |
| }); | |
| } | |
| function populatePtTels(tels){ | |
| $(function() { | |
| var availableTags2 = tels; | |
| $("#tel").autocomplete({ | |
| source: availableTags2 | |
| }); | |
| }); | |
| } | |
| //----------------------------------------------------------------------------------// | |
| //------- End Set Calendar/AutoComplete Function -------------// | |
| //----------------------------------------------------------------------------------// | |
| //------------------------------------------------------------------------------// | |
| //--------------------------- Load Page View Function -------------------------// | |
| //------------------------------------------------------------------------------// | |
| function loadView(options){ | |
| var id = typeof options.id === "undefined" ? "app": options.id; | |
| var cb = typeof options.callback === "undefined" ? function(){}: options.callback; | |
| waitingStart(); | |
| google.script.run.withSuccessHandler(function(html){ | |
| document.getElementById(id).innerHTML = html; | |
| waitingEnd(); //loadingEnd(); | |
| typeof options.params === "undefined" ? cb():cb(options.params); | |
| })[options.func](); | |
| } | |
| function loadSearchView(){ | |
| loadView({func:"loadSearchView",callback:setDataForSearch}); | |
| } | |
| function loadAddVisitView(){ | |
| loadView({func:"loadAddVisitView",callback:setAddVisitView}); | |
| } | |
| function loadAddViewOnFail(){ | |
| loadView({func:"loadAddVisitView",callback:setAddViewOnFail}); | |
| } | |
| function loadSetHolidaysView(){ | |
| loadView({func:"loadSetHolidaysView",callback:setSendVisitView}); | |
| } | |
| function setAddVisitView(){ | |
| //loadingStart(); | |
| waitingStart(); | |
| letGoTrim(); | |
| google.script.run.withSuccessHandler(populatePtTels).getCustomerTels(); | |
| google.script.run.withSuccessHandler(populateDates).getCalendar(); | |
| } | |
| function setAddViewOnFail(){ | |
| waitingStart(); | |
| letGoTrim(); | |
| google.script.run.withSuccessHandler(populatePtTels).getCustomerTels(); | |
| google.script.run.withSuccessHandler(populateDates).getCalendar(); | |
| document.getElementById("custID").value = gCustID; | |
| document.getElementById("name").value = gName; | |
| document.getElementById("tel").value = gTel; | |
| } | |
| function setEditVisitView(){ | |
| letGoTrim(); | |
| google.script.run.withSuccessHandler(populatePtTels).getCustomerTels(); | |
| google.script.run.withSuccessHandler(populateDates).getCalendar(); | |
| } | |
| function setSendVisitView(){ | |
| waitingStart(); | |
| populateVisitDates(); | |
| google.script.run.withSuccessHandler(populateHolidays).getCalendar(); | |
| } | |
| //------------------------------------------------------------------------------// | |
| //--------------------------- End Load Page View Function ----------------------// | |
| //------------------------------------------------------------------------------// | |
| //------------------------------------------------------------------------------// | |
| //-------------------------- Waiting Function ------------------------// | |
| //------------------------------------------------------------------------------// | |
| function waitingStart(){ | |
| document.getElementById("loading").classList.remove("invisible"); | |
| document.getElementById('app').style.display='none'; | |
| } | |
| function waitingEnd(){ | |
| document.getElementById("loading").classList.add("invisible"); | |
| document.getElementById('app').style.display='block'; | |
| } | |
| //------------------------------------------------------------------------------// | |
| //-------------------------- End Waiting Function ------------------------// | |
| //------------------------------------------------------------------------------// | |
| //------------------------------------------------------------------------------// | |
| //---------------------- Click Input Change Event Function ---------------------// | |
| //------------------------------------------------------------------------------// | |
| function activeTabChange(e){ | |
| var navLinkS= document.querySelectorAll(".main-nav .nav-link"); | |
| navLinkS.forEach(function(linkEl){ | |
| linkEl.classList.remove("active"); | |
| }); | |
| e.target.classList.add("active"); | |
| } | |
| function navClickEventHandler(e){ | |
| if(e.target.matches(".nav-link")){ | |
| activeTabChange(e); | |
| } | |
| } | |
| function inputEventHandler(e){ | |
| if(e.target.matches("#searchInput")){ | |
| search(); | |
| } | |
| } | |
| function displayConfirmationDelete(e){ | |
| if( e.target.dataset.buttonState ==="delete"){ | |
| e.target.previousElementSibling.classList.remove("d-none"); | |
| e.target.textContent= "cancel"; | |
| e.target.dataset.buttonState = "cancel"; | |
| }else{ | |
| e.target.previousElementSibling.classList.add("d-none"); | |
| e.target.textContent= "delete"; | |
| e.target.dataset.buttonState = "delete"; | |
| } | |
| } | |
| function clickEventHandler(e){ | |
| if(e.target.matches(".before-delete-button")){ | |
| displayConfirmationDelete(e); | |
| } | |
| if(e.target.matches(".delete-button")){ | |
| deleteCustomer(e); | |
| } | |
| if(e.target.matches(".edit-button")){ | |
| loadView({func:"loadEditVisitView", callback:afterEditViewLoads, params:{custID:e.target.dataset.customerId} }); | |
| } | |
| if(e.target.matches("#save-changes")){ | |
| editCustomer(); | |
| } | |
| if(e.target.matches("#cancel-changes")){ | |
| loadSearchView(); | |
| } | |
| }//End Func Click Event | |
| //------------------------------------------------------------------------------// | |
| //---------------------- End Click/Input/Change Event Function -----------------// | |
| //------------------------------------------------------------------------------// | |
| //----------------------------------------------------------------------------------// | |
| //------- Login Function -------------// | |
| //----------------------------------------------------------------------------------// | |
| function handleFormSubmit2(){ // for login | |
| let formObject = {}; | |
| formObject.searchtext3 = document.getElementById('searchtext3').value; | |
| if(document.getElementById('searchtext3').value == "" ){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Please fill your information completely.' | |
| }) | |
| }else{ | |
| document.getElementById('resp-spinnerA').classList.remove("d-none"); | |
| document.getElementById('login').style.display = "none"; | |
| google.script.run.withSuccessHandler(showUserForm).processForm2(formObject); | |
| }; | |
| }; | |
| function showUserForm(dataArray) { | |
| document.getElementById('resp-spinnerA').classList.add("d-none"); | |
| if(dataArray && dataArray !== undefined && dataArray.length != 0){ | |
| userName = dataArray[0][1]; | |
| document.getElementById("pass-label").innerHTML = "Admin "+dataArray[0][1]; | |
| document.getElementById("pass-label").style = "font-size:17px;color:#ACA710"; | |
| document.getElementById('login').style.display = "none"; | |
| document.getElementById("searchtext3").style.display = "none"; | |
| document.getElementById("maincontainer").classList.remove("invisible"); | |
| }else{ | |
| document.getElementById("pass-label").innerHTML = "Invalid Password"; | |
| document.getElementById("pass-label").style = "font-size:15px;color:red"; | |
| document.getElementById('login').style.display = "block"; | |
| setTimeout(function(){ | |
| document.getElementById("pass-label").innerHTML = "Password"; | |
| document.getElementById("pass-label").style = "font-size:15px;color:black"; | |
| },3000); | |
| } | |
| } | |
| //----------------------------------------------------------------------------------// | |
| //------- End Login Function -------------// | |
| //----------------------------------------------------------------------------------// | |
| //------------------------------------------------------------------------------// | |
| //-------------------------- Search Function -------------------------// | |
| //------------------------------------------------------------------------------// | |
| function setDataForSearch(){ | |
| waitingStart(); | |
| google.script.run.withSuccessHandler(function(dataReturned){ | |
| data = dataReturned.slice(); | |
| waitingEnd(); | |
| }).getDataForSearch(); | |
| } | |
| function search(){ | |
| let searchInput = document.getElementById("searchInput").value.toString().toLowerCase().trim(); | |
| let searchWords = searchInput.split(/\s+/); | |
| let searchColumns =[1,2]; | |
| let resultsArray = searchInput === "" ? [] :data.filter(function(r){ | |
| return searchWords.every(function(word){ | |
| return searchColumns.some(function(colIndex){ | |
| return r[colIndex].toString().toLowerCase().indexOf(word) !== -1 | |
| }); | |
| }); | |
| }); | |
| let searchResultBox = document.getElementById("searchResults"); | |
| let templateBox = document.getElementById("rowTemplate"); | |
| let template = templateBox.content; | |
| searchResultBox.innerHTML=""; | |
| resultsArray.forEach(function(r){ | |
| let tr = template.cloneNode(true); | |
| let custIDColumn = tr.querySelector(".custID"); | |
| let nameColumn = tr.querySelector(".name"); | |
| let dateColumn = tr.querySelector(".date"); | |
| let timeColumn = tr.querySelector(".time"); | |
| let deleteButton = tr.querySelector(".delete-button"); | |
| let editButton = tr.querySelector(".edit-button"); | |
| //custIDColumn.textContent= r[0]; | |
| deleteButton.dataset.customerId = r[0]; | |
| editButton.dataset.customerId = r[0]; | |
| custIDColumn.textContent= r[1]; | |
| nameColumn.textContent= r[2]; | |
| dateColumn.textContent= r[4]; | |
| timeColumn.textContent= r[5]; | |
| searchResultBox.appendChild(tr); | |
| }); | |
| }//end func search | |
| //------------------------------------------------------------------------------// | |
| //-------------------------- End Search Function -------------------------// | |
| //------------------------------------------------------------------------------// | |
| //------------------------------------------------------------------------------// | |
| //-------------------- Utility/Check Value/Check Format Function --------// | |
| //------------------------------------------------------------------------------// | |
| function trim_text(el) { | |
| el.value = el.value. | |
| replace(/(^\s*)|(\s*$)/gi, ""). // removes leading and trailing spaces | |
| replace(/[ ]{2,}/gi, " "). // replaces multiple spaces with one space | |
| replace(/\n +/, "\n"); // Removes spaces after newlines | |
| return; | |
| } | |
| function letGoTrim(){ | |
| $(function(){ | |
| $("textarea").change(function(){ | |
| trim_text(this); | |
| }); | |
| $("input").change(function(){ | |
| trim_text(this); | |
| }); | |
| }); | |
| } | |
| function validate(){ | |
| let fieldsToValidate = document.querySelectorAll("#userform input,#userform textarea,#userform select"); | |
| Array.prototype.forEach.call(fieldsToValidate,function(el){ | |
| if(el.checkValidity()){ | |
| el.classList.remove("is-invalid"); | |
| }else{ | |
| el.classList.add("is-invalid"); | |
| } | |
| }); | |
| return Array.prototype.every.call(fieldsToValidate,function(el){ | |
| return el.checkValidity(); | |
| }); | |
| } | |
| function checkLeapYears(input){ | |
| year = parseInt(input); | |
| if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)){ | |
| return true; | |
| }else{ | |
| return false; | |
| } | |
| } | |
| function isInt(n){ | |
| return n != "" && !isNaN(n) && Math.round(n) == n; | |
| } | |
| function isFloat(n){ | |
| return n != "" && !isNaN(n) && Math.round(n) != n; | |
| } | |
| function addDayToCurrentDate(days){ | |
| let currentDate = new Date(); | |
| return new Date(currentDate.setDate(currentDate.getDate() + days)).setHours(0,0,0,0); | |
| } | |
| function checkDateFormat(){//Protect user type the date by themselves on addRecord page | |
| let chooseDate = document.getElementById('datepicker').value; | |
| let dayFormat = chooseDate.split('/'); | |
| let date = dayFormat[0]; | |
| let month = dayFormat[1]; | |
| let year = dayFormat[2]; | |
| let thisYear = new Date().getFullYear(); | |
| let numberDaysBefore = new Date(addDayToCurrentDate(1)); | |
| let fourtyfiveDaysBefore = new Date(addDayToCurrentDate(45)); | |
| let userDate = new Date(dayFormat[2], dayFormat[1] - 1, dayFormat[0]); | |
| let time = document.getElementById('time').value.trim(); | |
| if(dayFormat.length != 3 || isFloat(date) || isFloat(month) || isFloat(year) ){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if((Number(date) < 10 && date.length > 1) || (Number(month) < 10 && month.length > 1) || (year.length != 4)){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if(disabledDaysArray.includes(chooseDate)){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if(date <1 || date > 31 || month < 1 || month > 12 || year > thisYear+1){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if(checkLeapYears(year) === true && month == 2 && date > 29 || month == 4 && date == 31 || | |
| checkLeapYears(year) === false && month == 2 && date > 28 || month == 6 && date == 31 || | |
| month == 9 && date == 31 || month == 11 && date == 31){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if(userDate < numberDaysBefore || userDate > fourtyfiveDaysBefore){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Must be booked at least 1 day in advance!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| /*else if(userDate.getDay() == 0 || userDate.getDay() == 6){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'งดนัดวันเสาร์ อาทิตย์!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| }*/ | |
| else if(time.length == 0){ | |
| document.getElementById("display_error").innerHTML = "Please select a time!"; | |
| document.getElementById("display_error").style = "color:red"; | |
| setTimeout(function(){ | |
| document.getElementById("display_error").innerHTML = ""; | |
| //document.getElementById("display_error").style = "color:green"; | |
| },5000); | |
| return false; | |
| } | |
| else{ | |
| return true; | |
| } | |
| }//End Func checkDateFormat | |
| function checkDateFormatEdit(){//Protect user type the date by themselves on editRecord page | |
| let chooseDate = document.getElementById('datepicker').value; | |
| let dayFormat = chooseDate.split('/'); | |
| let date = dayFormat[0]; | |
| let month = dayFormat[1]; | |
| let year = dayFormat[2]; | |
| let thisYear = new Date().getFullYear(); | |
| let numberDaysBefore = new Date(addDayToCurrentDate(1)); | |
| let fourtyfiveDaysBefore = new Date(addDayToCurrentDate(45)); | |
| let userDate = new Date(dayFormat[2], dayFormat[1] - 1, dayFormat[0]); | |
| let time = document.getElementById('time').value.trim(); | |
| if(dayFormat.length != 3 || isFloat(date) || isFloat(month) || isFloat(year) ){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if((Number(date) < 10 && date.length > 1) || (Number(month) < 10 && month.length > 1) || (year.length != 4)){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if(date <1 || date > 31 || month < 1 || month > 12 || year > thisYear+1){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if(checkLeapYears(year) === true && month == 2 && date > 29 || month == 4 && date == 31 || | |
| checkLeapYears(year) === false && month == 2 && date > 28 || month == 6 && date == 31 || | |
| month == 9 && date == 31 || month == 11 && date == 31){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if(userDate < numberDaysBefore || userDate > fourtyfiveDaysBefore){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Must be booked at least 1 day in advance!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| /*else if(userDate.getDay() == 0 || userDate.getDay() == 6){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'งดนัดวันเสาร์ อาทิตย์!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| }*/ | |
| else if(time.length == 0){ | |
| document.getElementById("display_error").innerHTML = "Please select a time!"; | |
| document.getElementById("display_error").style = "color:red"; | |
| setTimeout(function(){ | |
| document.getElementById("display_error").innerHTML = ""; | |
| //document.getElementById("display_error").style = "color:green"; | |
| },5000); | |
| return false; | |
| } | |
| else{ | |
| return true; | |
| } | |
| }//End Func checkDateFormat | |
| function checkDateFormatHoliday(){//Protect user type the date by themselves on setHolidays page | |
| let chooseDate = document.getElementById('datechoose').value; | |
| let dayFormat = chooseDate.split('/'); | |
| let date = dayFormat[0]; | |
| let month = dayFormat[1]; | |
| let year = dayFormat[2]; | |
| let thisYear = new Date().getFullYear(); | |
| let userDate = new Date(dayFormat[2], dayFormat[1] - 1, dayFormat[0]); | |
| if(dayFormat.length != 3 || isFloat(date) || isFloat(month) || isFloat(year) ){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if((Number(date) < 10 && date.length > 1) || (Number(month) < 10 && month.length > 1) || (year.length != 4)){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if(disabledDaysArray.includes(chooseDate)){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'This holiday is already set!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if(date <1 || date > 31 || month < 1 || month > 12 || year > thisYear+1){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| else if(checkLeapYears(year) === true && month == 2 && date > 29 || month == 4 && date == 31 || | |
| checkLeapYears(year) === false && month == 2 && date > 28 || month == 6 && date == 31 || | |
| month == 9 && date == 31 || month == 11 && date == 31){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Incorrected date format, please select from the calendar only!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| } | |
| /*else if(userDate.getDay() == 0 || userDate.getDay() == 6){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'วันหยุดวันเสาร์ อาทิตย์ ถูกตั้งค่าไว้แล้ว!' | |
| }) | |
| $("#datepicker").val(""); | |
| return false; | |
| }*/ | |
| else{ | |
| return true; | |
| } | |
| }//End Func checkDateFormat Holiday | |
| function checkPersonal(){ | |
| let custID = document.getElementById("custID").value.trim(); | |
| let name = document.getElementById("name").value.trim(); | |
| let tel = document.getElementById("tel").value.trim(); | |
| if(name.length == 0 || tel.length == 0 || custID.length == 0){ | |
| return false; | |
| } | |
| else{ | |
| return true; | |
| } | |
| } | |
| function resetTimeOption(){ | |
| let optionHTML = '<option disabled selected value="">Select Time</option>'; | |
| optionHTML += '<option value="9:00">9:00</option>'; | |
| optionHTML += '<option value="10:00">10:00</option>'; | |
| // optionHTML += '<option value="11:00">11:00</option>'; | |
| // optionHTML += '<option value="13:00">13:00</option>'; | |
| // optionHTML += '<option value="14:00">14:00</option>'; | |
| // optionHTML += '<option value="15:00">15:00</option>'; | |
| // optionHTML += '<option value="16:00">16:00</option>'; | |
| // optionHTML += '<option value="17:00">17:00</option>'; | |
| // optionHTML += '<option value="18:00">18:00</option>'; | |
| // optionHTML += '<option value="19:00">19:00</option>'; | |
| document.getElementById('time').innerHTML = optionHTML; | |
| } | |
| //------------------------------------------------------------------------------// | |
| //-------------------- End Utility/Check Value/Check Format Function ------// | |
| //------------------------------------------------------------------------------// | |
| //------------------------------------------------------------------------------// | |
| //-------------------------- Add Reccord Function -------------------------// | |
| //------------------------------------------------------------------------------// | |
| function sendCustIDforAutocomplete() { | |
| var formObject = {}; | |
| formObject.custID = document.getElementById('custID').value; | |
| if(formObject.custID !=""){ | |
| document.getElementById('save-btn').disabled = true; | |
| document.getElementById('name').disabled = true; | |
| document.getElementById("search_name").innerHTML = "searching name..."; | |
| document.getElementById("search_name").style = "color:red"; | |
| //document.getElementById("search_name").style.fontSize = "initial"; | |
| google.script.run.withSuccessHandler(populatePtNamesID).searchNameByCustomerId(formObject); | |
| } | |
| }; | |
| function populatePtNamesID(names){ | |
| if(names && names !== undefined && names.length != 0){ //alert(names[0]); | |
| $( function(){ | |
| var availableTags2 = names; | |
| $("#name").autocomplete({ | |
| source: availableTags2 | |
| }); | |
| }); | |
| document.getElementById('name').value = names[names.length-1]; | |
| } | |
| else{ | |
| google.script.run.withSuccessHandler(populatePtNames).notNameByCustomerId(); | |
| document.getElementById('name').value = ""; | |
| } | |
| document.getElementById("search_name").innerHTML = "Please check the correctness of name and customerID"; | |
| document.getElementById("search_name").style = "color:blue"; | |
| document.getElementById('name').disabled = false; | |
| document.getElementById('save-btn').disabled = false; | |
| } | |
| function setTimeSelector(timeArray){ | |
| if(timeArray && timeArray !== undefined && timeArray.length != 0){ | |
| for(var i=0; i<timeArray.length; i++){ | |
| const foundOption = [...document.querySelectorAll(".select-time option")] | |
| .find(o => timeArray.includes(o.value)); //dataArray | |
| if(foundOption){ | |
| foundOption.remove(); | |
| } | |
| } | |
| } | |
| else{ | |
| resetTimeOption(); | |
| } | |
| document.getElementById("display_error").innerHTML = "Please select a time!"; | |
| document.getElementById("display_error").style = "color:green"; | |
| setTimeout(function(){ | |
| document.getElementById("display_error").innerHTML = ""; | |
| },3000); | |
| document.getElementById("save-btn").disabled = false; | |
| document.getElementById("time").disabled = false; | |
| } | |
| function afterDatepickerChange(){ //for time select | |
| resetTimeOption(); | |
| document.getElementById("save-btn").disabled = true; | |
| document.getElementById("time").disabled = true; | |
| let telpattern = document.getElementById('tel').checkValidity(); | |
| let userdate = document.getElementById('datepicker').value; | |
| if(checkPersonal() == false){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Please completed personal information before select a date!' | |
| }) | |
| document.getElementById('datepicker').value = ""; | |
| } | |
| else if(telpattern == false){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Invalid phone number format!' | |
| //showConfirmButton: false | |
| //timer: 20000 | |
| }) | |
| document.getElementById('datepicker').value = ""; | |
| } | |
| else{ | |
| document.getElementById("display_error").innerHTML = "Searching time..."; | |
| document.getElementById("display_error").style = "color:green"; | |
| google.script.run.withSuccessHandler(setTimeSelector).getFullQ(userdate); | |
| }; | |
| } | |
| function afterButtonClick(){ | |
| if(checkDateFormat()){ | |
| if(validate()){ | |
| document.getElementById("save-btn").disabled = true; | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'warning', | |
| title: 'Add record', | |
| text: "Please wait...", | |
| showConfirmButton: true | |
| //timer: 20000 | |
| }) | |
| document.getElementById("display_error").innerHTML = "Add record..."; | |
| document.getElementById("display_error").style = "color:green"; | |
| waitingStart(); | |
| let custID = document.getElementById("custID"); | |
| let name = document.getElementById("name"); | |
| let tel = document.getElementById("tel"); | |
| let date = document.getElementById("datepicker"); | |
| let time = document.getElementById("time"); | |
| gCustID = custID.value; | |
| gName = name.value; | |
| gTel = tel.value; | |
| let rowData = { | |
| custID:custID.value, | |
| name:name.value, | |
| tel:tel.value, | |
| date:date.value, | |
| time:time.value, | |
| admin:userName | |
| }; | |
| google.script.run.withSuccessHandler(function(return_string){ | |
| if(return_string == "success"){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'success', | |
| html: '<div style = "font-size:20px;color:green;">Success, please capture the screen</div>'+ | |
| '<div style="font-size:17px;color:black;">'+"Name "+rowData.name+" Date "+rowData.date | |
| +" Time "+rowData.time+'</div>', | |
| //showConfirmButton: true, | |
| timer: 100000 | |
| }) | |
| loadAddVisitView(); | |
| document.getElementById("display_error").innerHTML = "Success!"; | |
| document.getElementById("display_error").style = "color:green"; | |
| setTimeout(function(){ | |
| document.getElementById("display_error").innerHTML = ""; | |
| },10000); | |
| } | |
| else{ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| html: '<div style = "font-size:20px;color:red;">Fully booked, please select new time</div>' | |
| //timer: 10000 | |
| }) | |
| loadAddViewOnFail(); | |
| document.getElementById("display_error").innerHTML = "Fully booked, please select new time!"; | |
| document.getElementById("display_error").style = "color:red"; | |
| setTimeout(function(){ | |
| document.getElementById("display_error").innerHTML = ""; | |
| },10000); | |
| } | |
| document.getElementById("save-btn").disabled = false; | |
| }).addNewRow(rowData); | |
| }else{ | |
| document.getElementById("display_error").innerHTML = "Please completed all required information!"; | |
| document.getElementById("display_error").style = "color:red"; | |
| setTimeout(function(){ | |
| document.getElementById("display_error").innerHTML = ""; | |
| //document.getElementById("display_error").style = "color:green"; | |
| },5000); | |
| $('#errorNotification').toast('show'); | |
| } | |
| } | |
| } | |
| //------------------------------------------------------------------------------// | |
| //-------------------------- End Add Reccord Function -------------------------// | |
| //------------------------------------------------------------------------------// | |
| //------------------------------------------------------------------------------// | |
| //-------------------------- Edit & Delete Function -------------------------// | |
| //------------------------------------------------------------------------------// | |
| function afterEditViewLoads(params){ | |
| waitingStart(); | |
| document.getElementById("customer-id").value = params.custID; | |
| google.script.run.withSuccessHandler(function(customerInfo){ | |
| document.getElementById("custID").value = customerInfo.custID; | |
| document.getElementById("name").value = customerInfo.name; | |
| document.getElementById("tel").value = customerInfo.tel; | |
| document.getElementById("datepicker").value = customerInfo.date; | |
| document.getElementById("time").innerHTML = "<option>"+customerInfo.time+"</option>"; | |
| setEditVisitView(); | |
| }).getCustomerById(params.custID); | |
| } | |
| function setTimeSelectorForEdit(timeArray){ | |
| if(timeArray && timeArray !== undefined && timeArray.length != 0){ | |
| for(var i=0; i<timeArray.length; i++){ | |
| const foundOption = [...document.querySelectorAll(".select-time option")] | |
| .find(o => timeArray.includes(o.value)); //dataArray | |
| if(foundOption){ | |
| foundOption.remove(); | |
| } | |
| } | |
| } | |
| else{ | |
| resetTimeOption(); | |
| } | |
| document.getElementById("display_error").innerHTML = "Please select a time!"; | |
| document.getElementById("display_error").style = "color:green"; | |
| setTimeout(function(){ | |
| document.getElementById("display_error").innerHTML = ""; | |
| },3000); | |
| document.getElementById("save-changes").disabled = false; | |
| document.getElementById("time").disabled = false; | |
| } | |
| function afterDatepickerChangeEdit() { //for time select | |
| resetTimeOption(); | |
| document.getElementById("save-changes").disabled = true; | |
| document.getElementById("time").disabled = true; | |
| let telpattern = document.getElementById('tel').checkValidity(); | |
| let userdate = document.getElementById('datepicker').value; | |
| //formObject.searchtext2 = document.getElementById('searchtext2').value; | |
| if(checkPersonal() == false){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Please completed personal information before select a date!!' | |
| }) | |
| document.getElementById('datepicker').value = ""; | |
| } | |
| else if(telpattern == false){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: 'Invalid phone number format!' | |
| //showConfirmButton: false | |
| //timer: 20000 | |
| }) | |
| document.getElementById('datepicker').value = ""; | |
| } | |
| else{ | |
| document.getElementById("display_error").innerHTML = "Searching time......"; | |
| document.getElementById("display_error").style = "color:green"; | |
| google.script.run.withSuccessHandler(setTimeSelectorForEdit).getFullQ(userdate); | |
| }; | |
| } | |
| function editCustomer(){ | |
| if(checkDateFormatEdit()){ | |
| if(validate()){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'warning', | |
| title: "Edit", | |
| text: "Please wait..." , | |
| showConfirmButton: true | |
| }) | |
| let customerInfo ={}; | |
| customerInfo.custID = document.getElementById("custID").value; | |
| customerInfo.name = document.getElementById("name").value; | |
| customerInfo.tel = document.getElementById("tel").value; | |
| customerInfo.date = document.getElementById("datepicker").value; | |
| customerInfo.time = document.getElementById("time").value; | |
| customerInfo.admin = userName; | |
| let id = document.getElementById("customer-id").value; | |
| google.script.run.withSuccessHandler(function(return_string){ | |
| if(return_string == "success"){ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'success', | |
| title: "Edit success !!!", | |
| text: "Customer "+customerInfo.name+"\nDate "+customerInfo.date+ "\nTime "+customerInfo.time, | |
| showConfirmButton: true | |
| }) | |
| loadSearchView(); | |
| } | |
| else{ | |
| Swal.fire({ | |
| position: 'center', | |
| icon: 'error', | |
| title: "Fully booked!!!", | |
| text: "Please select new time", | |
| showConfirmButton: true | |
| }) | |
| loadSearchView(); | |
| } | |
| }).editCustomerById(id,customerInfo); | |
| } | |
| } | |
| } | |
| function deleteCustomer(e){ | |
| let custID = e.target.dataset.customerId; | |
| waitingStart(); | |
| google.script.run.withSuccessHandler(function(){ | |
| e.target.closest(".result-box").remove(); | |
| let ids= data.map(function(r){return r[0].toString().toLowerCase() }); | |
| let index= ids.indexOf(custID.toString().toLowerCase()); | |
| data.splice(index,1); | |
| waitingEnd(); | |
| }).deleteById(custID); | |
| } | |
| //------------------------------------------------------------------------------// | |
| //-------------------------- End Edit & Delete Function ----------------------// | |
| //------------------------------------------------------------------------------// | |
| //------------------------------------------------------------------------------// | |
| //-------------------------- Send Holidays Function -------------------------// | |
| //------------------------------------------------------------------------------// | |
| function saveHoliday(){ | |
| if(checkDateFormatHoliday()){ | |
| if(validate()){ | |
| document.getElementById("save_visit_btn").disabled = true; | |
| document.getElementById("display_error").innerHTML = "Add record..."; | |
| document.getElementById("display_error").style = "color:green"; | |
| //loadingStart(); | |
| //var insit = document.getElementById("insit"); | |
| //var dentist = "holiday"; | |
| let custID = "holiday"; | |
| let name = "admin"; | |
| let tel = "000-0000000"; | |
| let date = document.getElementById("datechoose"); | |
| let time = "0:00"; | |
| var rowData = {custID:custID, | |
| name:name, | |
| tel:tel, | |
| date:date.value, | |
| time:time, | |
| admin:userName | |
| }; | |
| google.script.run.withSuccessHandler(function(){ | |
| afterSendVisitSubmit(); | |
| }).addNewHolidayRow(rowData); | |
| }else{ | |
| document.getElementById("display_error").innerHTML = "The required information is required."; | |
| document.getElementById("display_error").style = "color:red"; | |
| setTimeout(function(){ | |
| document.getElementById("display_error").innerHTML = ""; | |
| //document.getElementById("display_error").style = "color:green"; | |
| },3000); | |
| $('#errorNotification').toast('show'); | |
| } | |
| } | |
| } | |
| function afterSendVisitSubmit(e){ | |
| loadSetHolidaysView(); | |
| document.getElementById("display_error").innerHTML = "Success, please check the calendar!"; | |
| document.getElementById("display_error").style = "color:green"; | |
| setTimeout(function(){ | |
| document.getElementById("display_error").innerHTML = ""; | |
| //document.getElementById("display_error").style = "color:green"; | |
| },15000); | |
| document.getElementById("save_visit_btn").disabled = false; | |
| } | |
| //------------------------------------------------------------------------------// | |
| //-------------------------- End Send Holidays Function -----------------------// | |
| //------------------------------------------------------------------------------// | |
| document.getElementById("app").addEventListener("input",inputEventHandler); | |
| document.getElementById("app").addEventListener("click",clickEventHandler); | |
| document.getElementById("navigation").addEventListener("click",navClickEventHandler); | |
| document.getElementById("search-link").addEventListener("click",loadSearchView); | |
| document.getElementById("addrec-link").addEventListener("click",loadAddVisitView); | |
| document.getElementById("setHoliday-link").addEventListener("click",loadSetHolidaysView); | |
| document.addEventListener("DOMContentLoaded",loadAddVisitView); | |
| </script> | |
| </body> | |
| </html> | |
| <!-------------------------------------------------------------------------------------------> | |
| <!-- main.html --> | |
| <!-- addRecord.html --> | |
| <div id = "userform" class = "container"> | |
| <h4>Add Record</h4> | |
| <div class="z-depth-4" style="max-width: 800px;margin: 20px auto;"id="divMenuUraianKerja"> | |
| <h6>Information part</h6> | |
| <div class="ui-widget"> | |
| <input type="number" id="custID" name="custID" class="form-control" placeholder="Customer ID" onchange="sendCustIDforAutocomplete()" required> | |
| <div class = "invalid-feedback">required</div> | |
| </div><br> | |
| <div class="ui-widget"> | |
| <input type="text" id="name" name="name" class="form-control" placeholder="Name" required> | |
| <div class = "invalid-feedback">required</div> | |
| <p style="color:blue;" id = "search_name">Please check the correctness of name and customerID</p> | |
| </div> | |
| <div class="ui-widget"> | |
| <input type="text" id="tel" name="tel" class="form-control" placeholder="Tel" pattern="[0][0-9]{2}-[0-9]{7}"required> | |
| <div id = "telpattern" class = "invalid-feedback">Incorrect tel format</div> | |
| <p style="font-size:13px;color:blue;">Tel e.g. 088-9995555</p> | |
| </div> | |
| </div><!--divMenuUraianKerja --> | |
| <div class="z-depth-4" style="max-width: 800px;margin: 20px auto;"id="divMenuUraianKerja"> | |
| <h6>Booking part</h6> | |
| <div > | |
| <input type="text" id="datepicker" class="form-control" placeholder="Date" onchange="afterDatepickerChange()"required> | |
| <div class = "invalid-feedback">required</div> | |
| </div> | |
| <br><div class="ui-widget" id="create"> | |
| <span class="value"> | |
| <select id ="time" name="time-choose" class="form-control select-time" required> | |
| </select> | |
| <div class = "invalid-feedback">required</div> | |
| </span> | |
| </div> | |
| <div id = "display_error"></div> | |
| <br><button id = "save-btn" type="button" class="btn btn-primary mb-2" onclick="afterButtonClick()">Booking</button> | |
| </div><!--divMenuUraianKerja --> | |
| </div><!-- Container --> | |
| <!-- addRecord.html --> | |
| <!-- editRecord.html --> | |
| <div id = "userform" class = "container"> | |
| <h4>Edit Record</h4> | |
| <div class="z-depth-4" style="max-width: 800px;margin: 20px auto;"id="divMenuUraianKerja2"> | |
| <h6>Information part</h6> | |
| <input type="hidden" disabled id="customer-id" > | |
| <div class="ui-widget"> | |
| <input type="number" id="custID" name="custID" class="form-control" placeholder="Customer ID" required> | |
| <div class = "invalid-feedback">required</div> | |
| </div><br> | |
| <div class="ui-widget"> | |
| <input type="text" id="name" name="name" class="form-control" placeholder="Name" required> | |
| <div class = "invalid-feedback">required</div> | |
| <p style="color:blue;" id = "search_name">Please check the correctness of name and customerID</p> | |
| </div> | |
| <div class="ui-widget"> | |
| <input type="text" id="tel" name="tel" class="form-control" placeholder="Tel" pattern="[0][0-9]{2}-[0-9]{7}"required> | |
| <div id = "telpattern" class = "invalid-feedback">tel format incorrect</div> | |
| <p style="font-size:13px;color:blue;">tel e.g. 088-9995555</p> | |
| </div> | |
| </div><!--divMenuUraianKerja --> | |
| <div style="max-width: 800px;margin: 20px auto;"id="divMenuUraianKerja2"> | |
| <h6>Booking part</h6> | |
| <div > | |
| <input type="text" id="datepicker" class="form-control" placeholder="Date" onchange="afterDatepickerChangeEdit()"required> | |
| <div class = "invalid-feedback">required</div> | |
| </div> | |
| <br><div class="ui-widget" id="create"> | |
| <span > | |
| <select id ="time" name="time-choose" class="form-control select-time" required> | |
| </select> | |
| <div class = "invalid-feedback">required</div> | |
| </span> | |
| </div> | |
| <div id = "display_error"></div> | |
| <br> | |
| <button type="button" class="btn btn-primary" id ="save-changes">Edit</button> | |
| <button class="btn btn-primary" id="cancel-changes" style="background-color: #FF6347;">Cancel</button> | |
| </div><!--divMenuUraianKerja --> | |
| </div><!-- Container --> | |
| <!-- editRecord.html --> | |
| <!-- search.html --> | |
| <br><h6 style="color:blue;">Search by CustomerID or Name</h6> | |
| <div class="form-group"> | |
| <input type="text" class="form-control" id="searchInput" placeholder="CustomerID or Name"> | |
| <table class="table table-hover"> | |
| <thead> | |
| <tr> | |
| <th scope="col">CustomerID</th> | |
| <th scope="col">Name</th> | |
| <th scope="col">Date</th> | |
| <th scope="col">Time</th> | |
| <th scope="col"></th> | |
| </tr> | |
| </thead> | |
| <tbody id ="searchResults"></tbody> | |
| </table> | |
| <template id="rowTemplate"> | |
| <tr class = "result-box"> | |
| <td class ="custID" scope="row"></td> | |
| <td class ="name"></td> | |
| <td class ="date"></td> | |
| <td class ="time"></td> | |
| <td><button type="button" class="btn btn-outline-dark edit-button" style="background-color:#2196f3;color:white">edit | |
| </button></td> | |
| <td> | |
| <div class="btn-group" role="group" > | |
| <button type="button" class= "btn btn-warning delete-button d-none" style="color:white">confirm</button> | |
| <button type="button" class="btn btn-outline-dark before-delete-button" style="background-color:#FF6347;color:white" | |
| data-button-state = "delete">delete</button> | |
| </div> | |
| </td> | |
| </tr> | |
| </template> | |
| </div> | |
| <!-------------------------------------------------------------------------------------------> | |
| <!-- search.html --> | |
| <!-- setHolidays.html --> | |
| <div id = "userform" > | |
| <center> | |
| <h5 id = "chose">Add Holidays</h5> | |
| <div class="z-depth-4" style="max-width: 800px;margin: 20px auto;"id="divMenuUraianKerja"> | |
| <div class="col-sm-5"> | |
| <br><div > | |
| Calendar <div id="datepicker"></div> | |
| <p style="font-size:13px;color:red;">Check the calendar every time after add a holiday</p> | |
| </div> | |
| <br><br><br><br><br><br><br><br><br><br><br><br> | |
| <div> | |
| <input type="text" id="datechoose" class="form-control" placeholder="Select a holiday" required> | |
| <div class = "invalid-feedback">required</div> | |
| </div> | |
| </div> | |
| <div id = "display_error"></div> | |
| <br><button id = "save_visit_btn" type="button" class="btn btn-primary mb-2" onclick="saveHoliday()">Add</button> | |
| </div><!--divMenuUraianKerja --> | |
| </center> | |
| </div><!-- Container --> | |
| <!-- setHolidays.html --> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment