class Mission { constructor(args = null) { this.args = args; this.config = { products: { tv: { dn: 'Smart TV\'s', bp: 100, gpd: 10 }, ha: { dn: 'Home Appliances', bp: 150, gpd: 12 }, as: { dn: 'Audio Systems', bp: 100, gpd: 50 }, lp: { dn: 'Laptops', bp: 150, gpd: 100 }, sp: { dn: 'SmartPhones', bp: 150, gpd: 20 } } } this.create(); this.spinner = ``; self.onnetrestoreEvents = self.onnetrestoreEvents ?? []; this.cpdet = {} } init(c) { try { this.config = { ...this.config, ...c } } catch { console.log('Invalid initialization object'); } this.start(); } sharePdct() { Client.share({ title: mss.pdct?.pname ?? currPdct.dn, text: `@${CALC.parseMoney(currPdct.bp, true)}/-`, url: `${AC.env}${location.pathname.slice(1)}?venture=[0]` }); sessionStorage.exportImage = mss.pdct?.imgs[0] ?? ''; } create() { let x = `

`; $('body').addClass('d-flex flex-column h-100').append(x); } #checkStockSize(dot) { let eop = new Date(), cpd = Date.now(), tdiff; eop.setFullYear(eop.getFullYear() + 1); eop.setMonth(0); eop.setDate(1); tdiff = eop.getTime() - cpd; let estss = Math.ceil(tdiff / (1000 * 60 * 60 * 24)) * dot; $('#estss').text(estss); return estss; } start() { self.currPdct = this.config.products[this.config.cp]; let view = `

${currPdct.dn}

Countdown:
Bid price: Ksh ${currPdct.bp}
-
${currPdct.gpd} units available

Latest Bids

Be the first to place your bid here
`; $('main').html(view).find('.hedex').children() $('header.masta').find('#ct').text(currPdct.dn); this.checkDrawTime('#timetodraw,.timetodraw'); this.#fetchProduct(); this.#checkStockSize(currPdct.gpd); this.syncBids(); } #fetchProduct() { $.ajax({ url: 'promotions/res/.incs/pdts/', data: { fetch: this.config.cp }, dataType: 'json', success: pdct => { this.#parseProduct(pdct) }, error: err => { if (isNetError(err)) return; showToast(err.statusText); } }) } #parseProduct(pdct) { mss.pdct = pdct; $('#pdctName').text(pdct.pname); $('#pdctMprice').text(pdct.price).closest('.card').on('click', function () { mss.viewPdct(pdct); }); $('#pdctImg')[0].src = (pdct.imgs[0]); mss.cpdet = pdct; } viewPdct(pdct) { let m = `

${pdct.pname}


Remaining: ${this.#checkStockSize(currPdct.gpd)}units
Today's offer: ${currPdct.gpd} units
`; Action.confirm({ title: "Product Details", html: m, positive: "Place Bid", negative: "Back" }).then(res => { if (res) return mss.bid('#bidder'); }) } async #createAccRef(amount) { try { return new Promise((resolve, reject) => { let r; try { r = Operator.getSP().venture; } catch (e) { e } if (Number(r) < 0) resolve(r); $.post('promotions/.inc/api/createTxnRef', { uid: localStorage.user, amount: amount, strict: false }).then(res => resolve(res)).fail(err => reject(err.statusText)) }).catch(err => showToast(err.message ?? err)) } catch (error) { console.log(error.message); } } #createTimestamp() { let x = new Date(); x.setMinutes(x.getMinutes() - x.getTimezoneOffset()); return x.toJSON().replace(/[^0-9]/g, '').slice(0, -3); } async bid(t) { if (mss.lock) return ActionCentre('*Please confirm the previous transaction to proceed on another bid', 15000, 'Error'); let pdct = this.config.products[this.config.cp]; await this.getPhoneNumber().then(async pn => { let Timestamp = this.#createTimestamp(), Amount = pdct.bp, AccountReference; localStorage.setItem('user', pn); await this.#createAccRef(pdct.bp).then(acref => { if (!acref) return showToast('Unable to create Account Reference'); if (isNaN(acref)) return showToast('Invalid Account reference: ' + acref); AccountReference = acref; }); if (!AccountReference) return; Swal.fire({ html: `
A payment request has been sent to your phone number, please complete the payment to place your bid.
` }).then(confirmed => { if (!confirmed) return; const pmReq = { AccountReference: AccountReference, Amount: Amount, TransactionDesc: pdct.dn, PhoneNumber: pn, Timestamp: Timestamp } Trigger.reqDeposit(pmReq).then(async res => { if (res && res.status == 200) { mss.lock = true; mss.submitBid(AccountReference); let bidData = { ref: JSON.stringify({ FirstName: localStorage.getItem('user'), MSISDN: pn }), etime: Timestamp, id: AccountReference }; mss.parseonSyncBids([bidData], true); setTimeout(() => { mss.lock = false; showToast('Bid placed successfully ✅'); }, 5000); } else { showToast(res?.message ?? 'Payment request failed, please try again later'); } }).catch(err => { mss.lock = false; if (isNetError(err)) { showToast('Network error: Please check your internet connection'); return; } showToast(err.message ?? err); }); }) }) } checkDrawTime(plc) { function time() { let ctime = new Date(), ctimeOffsetBalancer = ctime.getTimezoneOffset() / 60 + 3; ctime.setHours(ctime.getHours() + ctimeOffsetBalancer) let dtime = new Date(ctime); dtime.setDate(dtime.getDate() + 1); dtime.setHours(0); dtime.setMinutes(0); dtime.setSeconds(0); let dtt = dtime.getTime(), ctt = ctime.getTime(), diffTime = dtt - ctt, hoursin = Math.floor(diffTime / (1000 * 60 * 60)), minutesin = Math.floor((diffTime % (1000 * 60 * 60)) / (1000 * 60)), secsin = Math.floor((diffTime % (1000 * 60)) / 1000); return `${hoursin}H: ${minutesin}M: ${secsin}S`; } if (document.querySelector(plc)) return setInterval(() => { $(plc).html(time()); }, 1000); return time(); } submitBid(bid) { try { $.ajax({ url: 'promotions/res/.incs/stream/', type: 'POST', data: { bid: bid }, success: res => { try { if (res && !isNaN(res)) return showToast('Entered to draw successfully ✅'); throw JSON.parse(res); } catch { showToast(res); } }, error: err => { if (isNetError(err)) return setTimeout(() => mss.submitBid(bid), 5000) } }) } catch (error) { console.log(error.message ?? error) } } parseonSyncBids(bids, instate = false) { try { if (!bids.length) return; let bidView = ``; if (instate) bidView += ``; $('#hedexArea').html(bidView); } else { $('#hedex').append(bidView); } $('#khamara')[0].scrollIntoView(); } catch (error) { console.log(error.message); } } syncBids() { try { if (!mss.bidStream) mss.bidStream = setInterval(mss.syncBids, 10000); if (!document.hasFocus()) return console.log('Stream paused'); if (mss.passcode && mss.passcode != 1) return; const url = `promotions/res/.incs/stream/`; $.ajax({ url: url, type: 'POST', data: { x: mss.config.cp, pass: mss.pass ?? '' }, beforeSend: e => { mss.passcode = performance.now(); }, complete: e => { mss.passcode = 1; }, dataType: 'json', success: data => { return mss.parseonSyncBids(data, mss.pass ? false : true); }, error: err => { mss.passcode = 1; if (isNetError(err)) return self.onnetrestoreEvents[0] = () => { mss.syncBids(); } } }); } catch (error) { console.log(error); } } } self.mss = new Mission();