shop.js 55.9 KB
Newer Older
Administrator committed
1 2 3 4
var main_content = $('#main-content'),
    shop_section = $('section.shop'),
    orders_section = $('section.orders'),
    main_waiting_zone = $('#main-waiting-zone'),
5 6 7
    loading_img = $('#rotating_loader').clone()
        .removeAttr('id')
        .addClass('rotating_loader'),
Administrator committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
    product_template = $('#templates .product'),
    cart_elt_template = $('#templates .cart-elt'),
    categ_menu_template = $('#templates .category-menu'),
    alim_categ = $('#alim_categ'),
    non_alim_categ = $('#non_alim_categ'),
    cart = $('#cart'),
    cart_total = $('.cart-total'),
    valid_wrapper = $('#valid-wrapper'),
    valid_cart = $('#valid-cart'),
    skw = $('#search-input'),
    bday_sel = $('select[name="bday"]'),
    bday_change_sel = $('select[name="bday-change"]'),
    current_order_bdate = $('#current_order_bdate'),
    my_orders_wrap = $('#my-orders-sumup'),
    cart_destroy_msg = $('#templates .destroy-cart-msg'),
    modify_best_date_msg = $('#templates .modify-best-date-msg'),
    current_action = null,
    slots_pack_nb = $('[name="bhour"] option').length - 1,
    dragSrcEl = null,
    forbidden_slots = [],
    closing_dates = [],
29
    my_sent_orders = [],
Administrator committed
30 31
    right_column = $('#right-column'),
    visit_mode = false,
32
    timer = null;
Administrator committed
33 34 35 36 37 38 39


/** --- UTILS --- **/
//$('.time-given-for-validation')

// Sort products div according to selected sort type
function sort_product_divs(divs_to_sort, sort_type) {
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
    let compare_price_uom = function (a, b) {
        // For products by unit : get uom price
        // For products by kg : get unit price (which is price of kg, we need to do this because some of them don't have a uom price)
        let a_price_uom = $(a).find("span.uom_price")
            .text() == 'Unité(s)' ? parseFloat($(a).find("span.uom_price")
                .text()) : parseFloat($(a).find("span.price")
                .text());
        let b_price_uom = $(b).find("span.uom_price")
            .text() == 'Unité(s)' ? parseFloat($(b).find("span.uom_price")
                .text()) : parseFloat($(b).find("span.price")
                .text());

        return a_price_uom > b_price_uom ? 1 : -1;
    };

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
    var sorted_products = divs_to_sort.sort(function (a, b) {
        switch (sort_type) {
        case 'name_asc':
            return ($(a).find(".name")
                .text() > $(b).find(".name")
                .text()) ? 1 : -1;
        case 'name_desc':
            return ($(a).find(".name")
                .text() < $(b).find(".name")
                .text()) ? 1 : -1;
        case 'price_unit_asc':
            return parseFloat($(a).find("span.price")
                .text()) > parseFloat($(b).find("span.price")
                .text()) ? 1 : -1;
        case 'price_unit_desc':
            return parseFloat($(a).find("span.price")
                .text()) < parseFloat($(b).find("span.price")
                .text()) ? 1 : -1;
        case 'price_uom_asc':
74
            return compare_price_uom(a, b);
75
        case 'price_uom_desc':
76
            return compare_price_uom(b, a);
77 78 79 80 81 82
        default:
            return $(a).find(".name")
                .text() > $(b).find(".name")
                .text();
        }
    });
Administrator committed
83

84
    return sorted_products;
Administrator committed
85 86 87 88
}

function djLogError(e) {
    try {
89 90
        $.post('/shop/log_error', {error: JSON.stringify(e)});
    } catch (e) {
91
        console.log(e);
Administrator committed
92 93 94 95
    }
}

var french_date_and_time = function(dstring) {
96 97 98 99
    if (shop_mode == 'delivery') {
        return dstring;
    }

100
    var formatted = dstring.trim().replace(/-/g, "/"); // replace for Safari
Administrator committed
101
    //expected = YYYY-MM-DD HH:MM[:00]
102

Administrator committed
103
    try {
104 105 106 107 108 109
        const options = {weekday: 'short', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric'};

        dt = new Date(formatted);
        formatted = dt.toLocaleString('fr-FR', options);
    } catch (e) {
        //no matter
Administrator committed
110
    }
111 112 113

    return formatted;
};
Administrator committed
114 115 116
/* ----------- */

var adjustCartHeight = function() {
117 118 119 120
    var max_height = window.innerHeight - 250 - 50;

    $('#cart-wrapper').css({'max-height': max_height + 'px'});
};
Administrator committed
121 122

var adjustSizes = function() {
123 124
    adjustCartHeight();
};
Administrator committed
125 126

var resetProgressBar = function() {
127 128 129 130
    $('#header_step_one').removeClass('step_one_active');
    $('#header_step_two').removeClass('step_two_active');
    $('#header_step_three').removeClass('step_three_active');
};
Administrator committed
131 132

function handleDragStart(e) {
133 134
    // Target (this) element is the source node.
    dragSrcEl = this;
Administrator committed
135

136 137
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/html', this.outerHTML);
Administrator committed
138

139
    this.classList.add('dragElem');
Administrator committed
140 141
}
function handleDragOver(e) {
142 143 144 145
    if (e.preventDefault) {
        e.preventDefault(); // Necessary. Allows us to drop.
    }
    this.classList.add('over');
Administrator committed
146

147
    e.dataTransfer.dropEffect = 'move'; // See the section on the DataTransfer object.
Administrator committed
148

149
    return false;
Administrator committed
150 151 152
}

function handleDragLeave(e) {
153
    this.classList.remove('over'); // this / e.target is previous target element.
Administrator committed
154 155 156
}

function handleDrop(e) {
157 158 159 160 161 162 163
    // this/e.target is current target element.
    if (e.stopPropagation) {
        e.stopPropagation(); // Stops some browsers from redirecting.
    }
    var receiver = $(this);

    if (receiver.prop('draggable') == true) {
Administrator committed
164
    // Don't do anything if dropping the same column we're dragging.
165 166 167 168 169 170 171 172 173 174 175 176 177 178
        if (dragSrcEl != this) {
            var droped = $(e.dataTransfer.getData('text/html'));
            var nb = parseInt(receiver.find('td.nb').text(), 10) + parseInt(droped.find('td.nb').text(), 10);
            var amount = parseFloat(receiver.find('td.amount').text()) + parseFloat(droped.find('td.amount').text());

            receiver.find('td.nb').text(nb);
            receiver.find('td.amount').text(amount.toFixed(2));
            receiver.attr('data-addid', droped.data('id'));
            this.parentNode.removeChild(dragSrcEl);
            sendFusionCartProposition(receiver.data('id'), droped.data('id'), receiver.find('.bdate').text());
        }
        this.classList.remove('over');
    } else {
        console.log('Pas le droit');
Administrator committed
179 180 181 182
    }



183
    return false;
Administrator committed
184 185 186
}

function handleDragEnd(e) {
187 188
    // this/e.target is the source node.
    this.classList.remove('over');
Administrator committed
189 190 191 192

}

function addDnDHandlers(elem) {
193 194 195 196 197
    elem.addEventListener('dragstart', handleDragStart, false);
    elem.addEventListener('dragover', handleDragOver, false);
    elem.addEventListener('dragleave', handleDragLeave, false);
    elem.addEventListener('drop', handleDrop, false);
    elem.addEventListener('dragend', handleDragEnd, false);
Administrator committed
198 199 200 201

}

var releaseTimeSlotOfCurrentOrder = function() {
202 203
    var c_id = order._id;

Administrator committed
204 205
    try {
        post_form(
206 207 208 209 210 211 212 213
            '/shop/delete_cart',
            {cart_id: c_id},
            function(err, result) {
                storeOrderForMigration();
                displayMsg("Le temps pour valider le panier s'est écoulé; le créneau a été libéré.<br/>Le contenu du panier a été sauvegardé, et vous devez maintenant réinitialiser une commande.");
                reset_home();
            }
        );
Administrator committed
214
    } catch (error) {
215
        djLogError({ctx: "release timeslot", msg:error});
Administrator committed
216
    }
217
};
Administrator committed
218 219 220
var countdown_timer = function() {
    try {
        if (typeof order.timer_end_date != "undefined") {
221 222 223
            const difference = +new Date(order.timer_end_date) - +new Date();

            let remaining = "Temps écoulé";
Administrator committed
224 225

            if (difference > 0) {
226
                const parts = {
Administrator committed
227 228 229
                    h: Math.floor((difference / (1000 * 60 * 60)) % 24),
                    mn: Math.floor((difference / 1000 / 60) % 60),
                    s: Math.floor((difference / 1000) % 60)
230
                };
Administrator committed
231

232
                remaining = Object.keys(parts)
Administrator committed
233
                    .map(part => {
234 235 236 237
                        val = parts[part];
                        if ((part == 'mn' || part == 's') && val < 10) val = '0' + val;

                        return `${val} ${part}`;
Administrator committed
238 239 240 241
                    })
                    .join(" ");

            } else {
242
                releaseTimeSlotOfCurrentOrder();
Administrator committed
243
            }
244
            document.getElementById("countdown").innerHTML = remaining;
Administrator committed
245 246 247
        } else {
            //order has been stored for migration or has been stored before countdown implementation
            if (typeof order.best_date != "undefined") {
248 249 250
                const difference = +new Date(order.best_date.replace(/-/g, "/")) - +new Date();

                if (difference/1000/3600 < 24) releaseTimeSlotOfCurrentOrder();
Administrator committed
251 252 253
            }
        }
    } catch (error) {
254
        djLogError({ctx: "countdown timer", msg:error});
Administrator committed
255
    }
256
};
Administrator committed
257 258

var launch_countdown_timer = function() {
259 260 261 262
    countdown_timer();
    if (timer) clearTimeout(timer);
    timer = setInterval(countdown_timer, 1000);
};
Administrator committed
263 264

var getMaxTimeBeforeValidation = function() {
265 266
    var max_time = 1;

Administrator committed
267
    try {
268 269 270 271
        const selected_day = $('.overlay-content [name="bday"]').val()
            .replace(/-/g, "/"); // replace for Safari
        const selected_hour = $('.overlay-content [name="bhour"]').val();

Administrator committed
272
        if (selected_hour.length > 0) {
273 274 275 276
            const difference = +new Date(selected_day + ' ' + selected_hour) - +new Date(); // unit = ms
            const h_before_pickup = difference/1000/3600;
            const delta = h_before_pickup - min_delay;

Administrator committed
277
            if (delta >= (hours_for_validation - 0.5)) {
278 279 280
                max_time = hours_for_validation;
            } else if (delta > 0.3) {
                max_time = delta;
Administrator committed
281
            } else {
282
                max_time = 0.3;
Administrator committed
283 284
            }
        } else {
285
            max_time = -1;
Administrator committed
286 287 288
        }

    } catch (error) {
289
        djLogError({ctx: "get maxtime bf valid", msg:error});
Administrator committed
290
    }
291 292 293

    return max_time;
};
Administrator committed
294 295

var adaptTimeGivenForValidationMsg = function() {
296 297
    var max_time_before_validation = getMaxTimeBeforeValidation();

Administrator committed
298
    if (!isNaN(max_time_before_validation) && max_time_before_validation > -1) {
299 300 301 302
        const h = Math.floor(max_time_before_validation % 24);
        var mn = Math.floor((max_time_before_validation - h) * 60);

        if (mn < 10) mn = '0' + mn;
Administrator committed
303

304 305
        $('.overlay-content .time-given-for-validation').text(h + ' h '+ mn + ' mn');
        $('.overlay-content .tv-msg').show();
Administrator committed
306
    } else {
307
        $('.overlay-content .tv-msg').hide();
Administrator committed
308
    }
309
};
Administrator committed
310 311 312

/** return javascript setted dates for time computation **/
var getStartTimeAndEndTimeForShortDay = function(short_day) {
313 314
    var periods = [];

Administrator committed
315 316
    try {
        for (i in opening[short_day]) {
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
            var [
                sh,
                sm
            ] = opening[short_day][i]['start'].split(':');
            var [
                eh,
                em
            ] = opening[short_day][i]['end'].split(':');
            var s = new Date();
            var e = new Date();

            s.setHours(sh);
            s.setMinutes(sm);
            e.setHours(eh);
            e.setMinutes(em);
            periods.push({start:s, end: e});
Administrator committed
333 334
        }
    } catch (error) {
335
        djLogError({ctx: "getStartTimeAndEndTimeForShortDay", msg:error});
Administrator committed
336
    }
337 338 339

    return periods;
};
Administrator committed
340
var getSlotsNumberForShorDay = function(short_day) {
341 342
    var slots_pack_nb = 0;

Administrator committed
343
    try {
344 345
        var periods = getStartTimeAndEndTimeForShortDay(short_day);

Administrator committed
346
        for (i in periods) {
347
            slots_pack_nb += (periods[i].end - periods[i].start)/1000/60/slot_size;
Administrator committed
348 349
        }
    } catch (error) {
350
        djLogError({ctx: "getSlotsNumberForShorDay", msg:error});
Administrator committed
351
    }
352 353 354

    return slots_pack_nb;
};
Administrator committed
355 356

var generateHourOptions = function() {
357 358 359 360 361
    var selected_day = $('.overlay-content [name^="bday"]').val();
    var hours_sel = $('.overlay-content [name^="bhour"]');
    var options = [{val: '', text: '---> Heure'}];
    var short_day = new Intl.DateTimeFormat('fr-FR', {weekday: 'short'}).format(new Date(selected_day));
    var periods = getStartTimeAndEndTimeForShortDay(short_day);
Administrator committed
362

363
    hours_sel.find('option').remove();
Administrator committed
364 365

    for (i in periods) {
366 367 368 369 370
        var start = periods[i].start;
        var end = periods[i].start;
        var d = periods[i].start;
        var nb_slots = (periods[i].end - periods[i].start)/1000/60/slot_size;

Administrator committed
371
        for (var j=0; j < nb_slots; j++) {
372 373 374 375 376 377 378 379 380 381 382
            if (j > 0) d = new Date(d.setMinutes(d.getMinutes() + slot_size));
            var h = d.getHours();
            var m = d.getMinutes();

            if (h < 10) h = '0' + h;
            if (m < 10) m = '0' + m;
            var hm = h + ':' + m;
            var slot = (selected_day + ' ' + hm).replace(/-/g, "/"); // replace for Safari
            var addit = true;
            const difference = (+new Date(slot) - +new Date())/1000/3600;

Administrator committed
383
            if (difference < 0 || (difference > 0 && min_delay > 0 && difference < min_delay)) {
384
                addit = false;
Administrator committed
385
            }
386 387 388 389
            forbidden_slots.forEach(function(s) {
                if (slot == s.replace(/-/g, "/")) addit = false;
            });
            if (addit == true) options.push({val: hm, text: hm});
Administrator committed
390 391 392
        }

    }
393 394 395 396 397
    $.each(options, function(i, e) {
        hours_sel.append($('<option>').val(e.val)
            .text(e.text));
    });
};
Administrator committed
398
var filterHourOptions = function() {
399 400
    var selected_day = $('.overlay-content [name^="bday"]').val();

Administrator committed
401
    if (typeof opening != "undefined" && (typeof opening_start_date == "undefined" || new Date(selected_day) >= opening_start_date)) {
402
        generateHourOptions();
Administrator committed
403
    } else { // for compatibility
404 405 406 407
        $('.overlay-content [name^="bhour"]').html($('#cart_creation_form [name^="bhour"]').html());
        var options = $('.overlay-content [name^="bhour"] option');

        options.each(function(i, o) {
Administrator committed
408
            try {
409
                $(o).show();
Administrator committed
410
                if ($(o).val().length > 1) {
411 412 413
                    var slot = (selected_day + ' ' + $(o).val()).replace(/-/g, "/"); // replace for Safari
                    const difference = +new Date(slot) - +new Date();

Administrator committed
414
                    if (difference/1000/3600 < min_delay) {
415
                        $(o).hide();
Administrator committed
416
                    } else {
417 418 419
                        forbidden_slots.forEach(function(s) {
                            if (slot == s.replace(/-/g, "/")) $(o).hide();
                        });
Administrator committed
420
                    }
421
                    $(o).prop('selected', false);
Administrator committed
422
                } else {
423
                    $(o).prop('selected', true); // if day has been changed
Administrator committed
424 425
                }
            } catch (error) {
426
                djLogError({ctx: "filter hours options", msg:error});
Administrator committed
427
            }
428
        });
Administrator committed
429
    }
430
    $('.overlay-content .tv-msg').hide();
Administrator committed
431

432
};
Administrator committed
433 434

var is_possible_day = function(date, short_day) {
435 436 437
    var answer = true;

    var dsfn = 0; // day slots forbidden number
Administrator committed
438

439 440 441 442 443
    $.each(forbidden_slots, function(i, e) {
        var dh = e.split(' ');

        if (dh.length == 2 && dh[0] == date) dsfn += 1;
    });
Administrator committed
444 445 446 447
    if (typeof opening != "undefined") {

        if (typeof opening[short_day] != "undefined") {
            // compute slots_pack_nb value
448
            slots_pack_nb = getSlotsNumberForShorDay(short_day);
Administrator committed
449 450 451


        } else {
452
            answer = false;
Administrator committed
453 454
        }
    }
455
    if (dsfn == slots_pack_nb) answer = false;
Administrator committed
456

457 458
    return answer;
};
Administrator committed
459 460

var fillBDayOptions = function(select) {
461 462 463 464 465 466 467 468 469 470 471 472
    select.find('option').remove();
    select.append($('<option>').attr("value", "")
        .text("---> Jour"));
    date_options = {weekday:'long', day: 'numeric', month: 'long'};
    var opening_days = [
        'mar.',
        'mer.',
        'jeu.',
        'ven.',
        'sam.'
    ]; // default for previous code compat.

Administrator committed
473
    if (typeof opening != "undefined") {
474
        opening_days = Object.keys(opening);
Administrator committed
475
    }
476 477 478
    var start = new Date();
    var d = new Date();

Administrator committed
479
    for (var i=0; i<10; i++) {
480 481 482 483 484 485 486 487 488 489 490 491 492
        if (i > 0) d = new Date(d.setDate(d.getDate() + 1));

        if (!closing_dates.includes(d.toISOString().slice(0, 10))) {
            short_day = new Intl.DateTimeFormat('fr-FR', {weekday: 'short'}).format(d);
            if (opening_days.indexOf(short_day) > -1) {
                var date_text = d.toLocaleDateString('fr-FR', date_options);
                var date = d.toISOString().slice(0, 10);
                // Adding it only if slots are left

                if (is_possible_day(date, short_day))
                    select.append($('<option>').attr("value", date)
                        .text(date_text));
            }
Administrator committed
493 494
        }
    }
495
};
Administrator committed
496 497 498


var getStoredOrder = function() {
499 500
    var stored = null;

Administrator committed
501
    try {
502
        stored = JSON.parse(localStorage.getItem(current_order_name));
503
    } catch (e) {
Administrator committed
504 505
        //WARNING : In this case, make sure the user haven't got any order initialized
        //TODO : make a request to retrieve it
506
        alert("Votre navigateur ne permet pas de mémoriser durablement les paniers (localStorage)");
Administrator committed
507
    }
508 509 510

    return stored;
};
Administrator committed
511 512

var getStoredOrderForMigration = function() {
513 514
    var stored = null;

Administrator committed
515
    try {
516
        stored = JSON.parse(localStorage.getItem(saved_order_name));
517 518
    } catch (e) {
        djLogError({ctx: "get stored for mig", msg:e});
Administrator committed
519
    }
520 521 522

    return stored;
};
Administrator committed
523 524
var storeOrderForMigration = function() {
    try {
525 526 527 528 529 530
        var to_save = order;

        delete to_save._id;
        delete to_save._rev;
        delete to_save.timer_end_date;
        delete to_save.best_date;
531
        localStorage.setItem(saved_order_name, JSON.stringify(to_save));
532 533 534 535
        order = to_save;
        storeOrder();
    } catch (e) {
        djLogError({ctx: "store for mig", msg:e});
Administrator committed
536
    }
537
};
Administrator committed
538 539
var storeOrder = function() {
    try {
540
        localStorage.setItem(current_order_name, JSON.stringify(order));
541 542
    } catch (e) {
        djLogError({ctx: "store order", msg:e});
Administrator committed
543
    }
544
};
Administrator committed
545 546

var getStoredCatElts = function() {
547 548
    var stored = null;

Administrator committed
549 550
    try {
        stored = JSON.parse(localStorage.getItem('catElts'));
551
    } catch (e) {
Administrator committed
552 553
        //no matter
    }
554 555 556

    return stored;
};
Administrator committed
557 558 559

var storeCatElts = function() {
    try {
560 561 562
        localStorage.setItem("catElts", JSON.stringify(category_elts));
    } catch (e) {
        djLogError({ctx: "store cat elts", msg:e});
Administrator committed
563
    }
564
};
Administrator committed
565
var putLoadingImgOn = function(target) {
566 567
    target.append(loading_img);
};
Administrator committed
568
var removeLoadingImg = function() {
569 570
    $('.rotating_loader').remove();
};
Administrator committed
571 572

var putAlimCategData = function() {
573 574 575 576 577 578 579 580 581 582 583 584
    [
        'epicerie',
        'liquide',
        'produits_frais',
        'surgeles'
    ].forEach(function(k) {
        var div = categ_menu_template.clone().attr('data-id', categories[k].id);

        div.find('.dropbtn').text(categories[k].label);
        alim_categ.append(div);
    });
};
Administrator committed
585 586

var putNonAlimCategData = function() {
587 588 589 590 591 592 593 594 595 596 597
    [
        'bazar',
        'droguerie',
        'parfumerie'
    ].forEach(function(k) {
        var div = categ_menu_template.clone().attr('data-id', categories[k].id);

        div.find('.dropbtn').text(categories[k].label);
        non_alim_categ.append(div);
    });
};
Administrator committed
598 599 600 601 602

var pass2step2 = function() {
    try {
        if (order.products.length > 0 && order.state == "init") {
            // a cart in process has been stored, render it
603
            renderStoredCart();
Administrator committed
604
        }
605 606
    } catch (e) {
        djLogError({ctx: "pass2step2", msg:e});
Administrator committed
607
    }
608 609 610 611
    main_waiting_zone.hide();
    $('h1').show();
    var recup = order.best_date || 'non défini';

612 613
    if (shop_mode == 'shop')
        current_order_bdate.html("Récupération : <strong>" + french_date_and_time(recup) + "</strong>");
Administrator committed
614
    if (visit_mode == true) {
615 616 617
        $('.product .choice').hide();
        right_column.hide();
        $('.arrow-block').css('visibility', 'hidden');
Administrator committed
618 619

    } else {
620 621 622
        $('.product .choice').show();
        right_column.show();
        $('.arrow-block').css('visibility', 'visible');
Administrator committed
623 624

    }
625 626 627
    orders_section.hide();
    main_content.show();
    shop_section.show();
Administrator committed
628

629 630
    $('#header_step_one').addClass('step_one_active');
};
Administrator committed
631 632 633 634

var updateCartTotal = function(products_nb, total) {

    if (products_nb == 0) {
635 636 637 638 639
        valid_wrapper.hide();
        cart.find('.msg').show();
        cart_total.find('span').text('');
    } else {
        cart_total.find('span').text('Total : ' + total.toFixed(2) + ' € TTC');
Administrator committed
640
    }
641
};
Administrator committed
642 643

var addProductToOrder = function(pdt, max_qty, callback) {
644
    answer = {product: pdt};
Administrator committed
645 646

    // Insert or update pdt data
647 648 649 650 651
    var p_index = null;

    $.each(order.products, function(i, e) {
        if (e.id == pdt.id) p_index = i;
    });
Administrator committed
652
    if (p_index !== null) {
653 654 655
        var p = order.products[p_index];
        var qty = p.qty + pdt.qty;

Administrator committed
656
        if (pdt.unit != "U") {
657
            qty = parseFloat(p.qty) + parseFloat(pdt.qty);
Administrator committed
658
        }
659 660
        var total = parseFloat(p.total) + parseFloat(pdt.total);

Administrator committed
661
        if (qty > max_qty) {
662
            answer.warning = "max_qty";
Administrator committed
663
        }
664 665 666 667
        order.products[p_index].qty = qty;
        order.products[p_index].total = parseFloat(total).toFixed(2);
        answer.product = order.products[p_index];
        answer.refresh = true;
Administrator committed
668
    } else {
669
        order.products.push(pdt);
Administrator committed
670 671
    }

672 673 674 675 676
    order.total += parseFloat(pdt.total);
    updateCartTotal(order.products.length, order.total);
    storeOrder();
    callback(answer);
};
Administrator committed
677 678

var removeProductFromCart = function() {
679 680
    var cart_elt = $(this).closest('.cart-elt');
    var pid = cart_elt.data('pid');
Administrator committed
681
    //console.log('On va supprimer le produit ' + pid)
682 683 684
    var p_index = null;

    $.each(order.products, function(i, e) {
Administrator committed
685
        if (e.id == pid) {
686 687
            p_index = i;
            order.total -= parseFloat(e.total);
Administrator committed
688
        }
689
    });
Administrator committed
690
    if (p_index !== null) {
691 692 693 694
        order.products.splice(p_index, 1);
        updateCartTotal(order.products.length, order.total);
        cart_elt.remove();
        storeOrder();
Administrator committed
695
    }
696
};
Administrator committed
697
var renderProductInCart = function(elt_div, pdt) {
698 699 700 701 702 703 704
    elt_div.find('.name').text(pdt.name);
    elt_div.find('.qty').text(pdt.qty);
    elt_div.find('.price').text(pdt.price);
    elt_div.find('.total').text(pdt.total);
    cart.prepend(elt_div);
    elt_div.find('img').click(removeProductFromCart);
};
Administrator committed
705 706

var addProductToCart = function() {
707 708 709
    var p_div = $(this).closest('.product');
    var qty = p_div.find('input[name="qty"]').val();
    var available_qty = parseFloat(p_div.find('.available_qty').text());
Administrator committed
710

711 712 713
    cart.find('.msg').hide();
    valid_cart.show();
    valid_wrapper.show();
Administrator committed
714 715 716 717
    try {
        if (order.state == "init") {

            if (qty > 0) {
718 719 720
                var msg = "";
                var too_much = "Vous avez pris plus de produit que le stock indicatif.\nVous n'aurez peut-être pas toute la quantité.";

721
                if (parseFloat(qty) > available_qty && stock_warning == true) {
722
                    msg = too_much;
Administrator committed
723
                }
724 725 726
                var u = p_div.find('.unit').text()
                    .substring(0, 1);

Administrator committed
727
                if (u == "U") {
728
                    qty = parseInt(qty, 10);
Administrator committed
729
                } else {
730
                    qty = parseFloat(qty).toFixed(3);
Administrator committed
731 732 733
                }

                var pdt = {id: p_div.data('pid'),
734 735 736 737 738 739 740 741 742 743
                    name: p_div.find('.name').text(),
                    qty : qty,
                    price : parseFloat(p_div.find('span.price').text()).toFixed(2),
                    unit: u
                };

                pdt.total = pdt.qty * pdt.price;
                pdt.total = parseFloat(pdt.total).toFixed(2);

                addProductToOrder(pdt, available_qty, function(answer) {
Administrator committed
744 745 746
                    // console.log('réponse')
                    // console.log(answer)
                    if (typeof answer.error === "undefined") {
747 748
                        var cart_elt_div = null;

Administrator committed
749
                        if (answer.refresh) {
750
                            cart_elt_div = cart.find('[data-pid="'+pdt.id+'"]');
Administrator committed
751
                        } else {
752
                            cart_elt_div = cart_elt_template.clone().attr('data-pid', pdt.id);
Administrator committed
753 754
                        }
                        if (cart_elt_div && cart_elt_div.length > 0) {
755
                            renderProductInCart(cart_elt_div, answer.product);
Administrator committed
756
                        } else {
757
                            djLogError("Problème insertion de l'article dans le panier");
Administrator committed
758 759 760
                        }
                    }
                    if (typeof answer.warning !== "undefined") {
761
                        if (answer.warning == "max_qty" && stock_warning == true)
762
                            msg = too_much;
Administrator committed
763
                    }
764
                });
Administrator committed
765 766

                if (msg.length > 0) {
767
                    alert(msg);
Administrator committed
768 769
                }
            }
770 771
        } else if (order.state == "validating") {
            alert("Le panier est en cours d'envoi. Impossible d'ajouter un article.");
Administrator committed
772
        }
773 774
    } catch (e) {
        djLogError({ctx: "add product to cart", msg:e});
Administrator committed
775 776
    }

777
};
Administrator committed
778 779

var isChoosenSlotValid = function(slot) {
780 781 782
    var answer = true;
    var cause = '';

783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
    // For delivery, no slot validation: return true
    if (shop_mode == 'shop') {
        forbidden_slots.forEach(function(e) {
            if (slot == e) {
                answer = false; cause = 'full';
            }
        });
        //Does it respect min delay ?
        var now = new Date();
        var min_date = new Date();
        var slot_date = new Date(slot.replace(/-/g, "/")); // replace for Safari

        min_date = new Date(min_date.setHours(now.getHours() + min_delay));
        if (slot_date - min_date < 0) {
            answer = false; cause = 'delay';
798 799 800 801 802
        }
    }

    return {res: answer, reason: cause};
};
Administrator committed
803 804

var showForbiddenSlots = function() {
805 806 807
    if (forbidden_slots.length > 0) {
        var fb_slots = $('.mconfirm .forbidden-slots');
        var ul = fb_slots.find('ul');
Administrator committed
808

809 810 811 812 813 814 815 816 817 818
        ul.empty();
        forbidden_slots.forEach(function(e) {
            var li = $('<li>').text(e);

            ul.append(li);
        });
        fb_slots.show();
    }

};
Administrator committed
819
var closeForbiddenList = function() {
820 821 822 823
    var fb_slots = $('.mconfirm .forbidden-slots');

    fb_slots.hide();
};
Administrator committed
824 825 826


var initCart = function () {
827 828 829 830 831 832 833
    current_action = 'init_cart';
    var bd = $('.mconfirm select[name="bday"]').val();
    var bh = $('.mconfirm select[name="bhour"]').val();
    var no_accept_msg = $('.mconfirm .no-accept-reason');
    var allowed_slot = isChoosenSlotValid(bd + ' '+ bh);

    no_accept_msg.hide();
Administrator committed
834 835

    if (allowed_slot.res == false || bd.length == 0 || bh.length == 0) {
836 837 838 839 840
        var day_zone = $('.mconfirm span.ask-day');
        var delay_msg = $('.mconfirm span.delay24h');

        day_zone.css({'border': 'none', 'background-color': 'white'});
        delay_msg.css({'background-color': 'white', 'padding': '0'});
Administrator committed
841

842 843
        if (allowed_slot.res == false && allowed_slot.reason == 'full') showForbiddenSlots();
        if (allowed_slot.reason == 'delay') delay_msg.css({'padding': '2px', 'background-color': 'black'});
Administrator committed
844

845 846 847
        no_accept_msg.show();
        setTimeout(function() {
            modal.css("width", "100%"); //modal div is closed after callback has been triggered
Administrator committed
848
            if (allowed_slot == true && (bd.length == 0 || bh.length == 0))
849 850
                day_zone.css({'border':'1px solid red', 'background-color':'#fcbbf4'});
        }, 500);
Administrator committed
851 852 853 854


    } else {
        if (is_time_to('init_cart', 15000)) { // prevent double click or browser hic up bug
855 856
            order.state = 'init';
            order.best_date = bd + " " + bh;
Administrator committed
857

858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886
            make_user_wait('Enregistrement des informations de réservation...');
            post_form(
                '/shop/cart_init', {order: JSON.stringify(order)},
                function(err, result) {
                    if (!err) {
                        main_content.show();
                        if (typeof result.res.cart != "undefined" && result.res.cart.length == 2) {
                            var storedOrderFM = getStoredOrderForMigration();

                            if (storedOrderFM) {
                                order.products = storedOrderFM.products;
                                order.total = storedOrderFM.total;
                                localStorage.removeItem('saved_order');
                            }
                            order._id = result.res.cart[0];
                            if (hours_for_validation > 0) {
                                var limit = new Date();
                                const time_to_add = getMaxTimeBeforeValidation();
                                const h_to_add = Math.floor(time_to_add % 24);
                                const mn_to_add = Math.floor((time_to_add - h_to_add) * 60);

                                limit.setHours(limit.getHours() + h_to_add);
                                limit.setMinutes(limit.getMinutes() + mn_to_add);
                                order.timer_end_date = limit;
                                launch_countdown_timer();
                            }

                            storeOrder();
                            pass2step2();
Administrator committed
887 888 889


                        } else {
890 891 892 893 894 895 896 897 898 899
                            order.state = 'error_on_submit';
                            message = "Problème d'enregistrement";
                            if (typeof result.res.ts_respect != "undefined") {
                                if (result.res.ts_respect == false)
                                    message += "\nLe créneau horaire choisi n'est pas correct.";
                            } else {
                                message += "\nSi cela persiste, merci de nous contacter.";
                            }
                            alert(message);
                            djLogError({ctx: "cart init ajax response 1", msg:result});
Administrator committed
900

901 902 903 904
                        }
                    } else {
                        djLogError({ctx: "cart init ajax response 2", msg:err});
                    }
Administrator committed
905 906 907 908
                }
            );
        }
    }
909
};
Administrator committed
910 911 912 913 914



var validCart = function() {

915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949
    valid_cart.hide();
    valid_wrapper.append(loading_img);
    $('#header_step_two').addClass('step_two_active');
    order.state = 'validating';
    order.accept_substitution = $('.mconfirm input[name="accept_substitution"]').prop('checked');
    order.comment = $('textarea[name="cart_comment"]').val();
    post_form(
        '/shop/cart', {order: JSON.stringify(order)},
        function(err, result) {
            if (!err) {
                try {
                    if (typeof result.res.cart != "undefined" && result.res.cart != null) {
                        if (typeof result.res.cart._rev != "undefined") {
                            clearCart();
                            $('#header_step_three').addClass('step_three_active');
                            reset_home();
                            main_waiting_zone.find('h2').text('Merci pour votre commande !');
                            main_waiting_zone.find('li.survey').css('display', 'block');
                            display_msg_box("Un email vient d'être envoyé avec des informations supplémentaires et le récapitulatif (il peut être dans les spams).");
                        } else {
                            result.browser_error = "Pas de ._rev pour la commande !";
                            djLogError({ctx: "Valid cart 1", msg:result});
                        }
                    } else {
                        storeOrderForMigration();
                        var msg = "Le pré-enregistrement de la commande, avec la date, n'a pas pu être retrouvé.\n";

                        msg += "Les produits du panier ont été sauvegardés.\n";
                        alert(msg);
                        reset_home();
                        djLogError({ctx: "Valid cart 2", msg:result});
                    }
                    valid_wrapper.find('.rotating_loader').remove();
                } catch (e) {
                    djLogError({ctx: "Valid cart 3", msg:result, msg2:e});
Administrator committed
950
                }
951 952 953 954
            } else {
                djLogError({ctx: "Valid cart 4", msg:err});
            }
        }
Administrator committed
955
    );
956
};
Administrator committed
957 958

var clearCart = function() {
959
    order = { products: [], total: 0.00, type: shop_mode};
960 961 962 963 964
    storeOrder();
    cart.find('.cart-elt').remove();
    updateCartTotal(0, 0);
    valid_wrapper.find('.rotating_loader').remove();
};
Administrator committed
965 966

var renderStoredCart = function() {
967 968 969 970 971 972 973 974 975 976 977 978
    cart.find('.cart-elt').remove();
    cart.find('.msg').hide();
    valid_wrapper.show();
    $.each(order.products, function(i, e) {
        var cart_elt_div = cart_elt_template.clone().attr('data-pid', e.id);

        renderProductInCart(cart_elt_div, e);

    });
    if (order.products.length > 0) valid_cart.show();
    updateCartTotal(order.products.length, order.total);
};
Administrator committed
979 980 981


var appendProductsToGrid = function (grid, pdts, sort = true) {
982 983 984 985 986 987 988 989 990
    var product_divs = [];

    $.each(pdts, function (i, pdt) {
        var p_div = product_template.clone().attr('data-pid', pdt.id);
        var qty = p_div.find('input[name="qty"]');

        p_div.find('.name').text(pdt.name);
        if (pdt.image_small != false)
            p_div.find('img').attr('src', 'data:image/jpeg;base64,' + pdt.image_small);
Administrator committed
991
        //p_div.find('img').remove()
992 993
        p_div.find('span.price').text(pdt.list_price);
        p_div.find('.unit').text(pdt.uom_id[1]);
Administrator committed
994
        if (pdt.price_weight_net != "") {
995
            p_div.find('span.uom_price').text(pdt.price_weight_net + ' €');
Administrator committed
996
        } else if (pdt.price_volume != "") {
997
            p_div.find('span.uom_price').text(pdt.price_volume + ' €');
Administrator committed
998
        } else if (pdt.price_weight_net == "" && pdt.price_volume == "" && pdt.uom_id[0] == 1) {
999
            p_div.find('span.uom_price').text('non renseigné');
Administrator committed
1000 1001
        }
        if (pdt.uom_id[0] == 1) {
1002
            p_div.find('div.uom_price').show();
Administrator committed
1003
        }
1004 1005
        p_div.find('.available_qty').text(pdt.qty_available);
        p_div.find('.incoming_qty').text(pdt.incoming_qty);
Administrator committed
1006 1007

        if (pdt.uom_id[1].indexOf('U') == 0) {
1008
            qty.attr('oninput', "this.value=this.value.replace(/[^0-9]/g,'');");
Administrator committed
1009
        } else {
1010
            qty.attr('min', 0).attr('step', 0.1);
Administrator committed
1011
        }
1012
        qty.val(1);
Administrator committed
1013

1014 1015
        product_divs.push(p_div);
    });
Administrator committed
1016 1017

    if (product_divs.length > 0) {
1018
        if (sort) {
Administrator committed
1019
        // Sort by selected sort type and display
1020 1021 1022
            var sort_type = grid.parent().find('select.products_sort option:selected')
                .val();
            var sorted_products = sort_product_divs(product_divs, sort_type);
Administrator committed
1023

1024 1025 1026 1027
            grid.html(sorted_products);
        } else {
            grid.html(product_divs);
        }
Administrator committed
1028

1029 1030
        grid.parent().find('div.products_sort_container')
            .show();
Administrator committed
1031
    }
1032
};
Administrator committed
1033 1034

var loadAllAvailableBoughtProducts = function() {
1035 1036 1037 1038
    var msg_cont = $('#content1_msg');

    putLoadingImgOn(content1);
    msg_cont.html($('#loading_bought_products_msg').html());
Administrator committed
1039
    try {
1040 1041 1042 1043 1044 1045
        $.ajax({
            url :'/shop/get_all_available_bought_products',
            dataType: 'json'
        })
            .done(function(rData) {
                removeLoadingImg();
Administrator committed
1046 1047 1048

                //console.log(rData)
                if (rData.res && rData.res.data && rData.res.data.pdts && rData.res.data.pdts.length > 0) {
1049 1050 1051 1052
                    msg_cont.remove();
                    var grid = content1.find('section');

                    appendProductsToGrid(grid, rData.res.data.pdts, false);
Administrator committed
1053
                } else {
1054
                    msg_cont.html('Aucun produit trouvé');
Administrator committed
1055
                }
1056
            });
Administrator committed
1057

1058 1059
    } catch (e) {
        alert('Impossible de récupérer les produits que vous avez déjà achetés');
Administrator committed
1060
    }
1061
};
Administrator committed
1062

1063 1064 1065 1066 1067 1068 1069
var shouldCategoryBeShown = function (cat_id) {
    let answer = true;

    if (excluded_cat.indexOf(cat_id) > -1) {
        answer = false;
    }
    if (typeof cat_nb_pdts != "undefined") {
1070 1071
        let list = cat_nb_pdts.list;
        let cat_ids = Object.keys(list).map(x => parseInt(x, 10));
1072
        //cat_ids is now an array of category ids which have product
1073

1074 1075 1076 1077 1078
        if (cat_ids.indexOf(cat_id) < 0) {
            // cat_id is corresponding to a category which have no product
            answer = false;
        }
    }
1079

1080
    return answer;
1081
};
Administrator committed
1082
var appendChildrenCatToMenu = function (catdiv, children) {
1083 1084 1085
    var ul = catdiv.find('ul');

    $.each(children, function(i, e) {
1086
        if (shouldCategoryBeShown(e.id)) {
1087
            var li = $('<li>').addClass("nav-item");
1088 1089 1090 1091 1092 1093 1094 1095 1096

            // Remove TVA in cat name
            let name = e.name;

            name = name.replaceAll(' TVA 20%', '');
            name = name.replaceAll(' TVA 5,5%', '');
            name = name.replaceAll(' 20%', '');
            name = name.replaceAll(' 5,5%', '');

1097
            var span = $('<span>').attr('data-id', e.id)
1098
                .text(name);
1099 1100 1101

            li.append(span);
            ul.append(li);
Administrator committed
1102 1103
        }

1104 1105
    });
};
Administrator committed
1106 1107

var getCategChildren = function() {
1108 1109 1110 1111
    var clicked = $(this);
    var cat_id = clicked.data('id');
    var li_nb = clicked.find('li').length;

Administrator committed
1112 1113 1114
    if (typeof category_elts[cat_id] == "undefined") {
        try {
            $.ajax({
1115 1116 1117
                url : '/shop/get_cat_children',
                data: {id: cat_id},
                dataType: 'json'
Administrator committed
1118
            })
1119 1120 1121 1122 1123 1124 1125
                .done(function(rData) {
                    if (typeof rData.res.data != "undefined" && rData.res.data.length > 0) {
                        category_elts[cat_id] = rData.res.data;
                        storeCatElts();
                        appendChildrenCatToMenu(clicked, category_elts[cat_id]);
                    }
                });
Administrator committed
1126

1127
        } catch (e) {
Administrator committed
1128 1129 1130
            //alert('Impossible de récupérer les catégories')
        }
    } else if (li_nb == 0) {
1131
        appendChildrenCatToMenu(clicked, category_elts[cat_id]);
Administrator committed
1132
    }
1133
};
Administrator committed
1134 1135

var getCategProducts = function() {
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
    var clicked = $(this);
    var cat_id = clicked.data('id');
    var tab = clicked.closest('li.tab');
    var msg_cont = tab.find('.msg');
    var content = tab.find('.content');
    var grid = content.find('section');
    var msg = $('#loading_categ_products_msg').clone()
        .removeAttr('id');

    grid.empty();
    putLoadingImgOn(content);
    var menu_ul = tab.find('ul');

    menu_ul.hide(); /** needed to make visitor known retrival is in process **/
    msg.find('span').text(clicked.text());
    msg_cont.html(msg);
Administrator committed
1152
    try {
1153 1154 1155 1156 1157 1158
        $.ajax({
            url :'/shop/get_categ_products',
            data: {id: cat_id},
            dataType: 'json'
        })
            .done(function(rData) {
Administrator committed
1159 1160
                if (typeof rData.res.data != "undefined" && typeof rData.res.data.pdts != "undefined") {
                    //console.log(rData)
1161
                    appendProductsToGrid(grid, rData.res.data.pdts);
Administrator committed
1162 1163 1164
                } else {
                    // ? what to do
                }
1165 1166 1167 1168
                removeLoadingImg();
                msg_cont.empty();
                menu_ul.removeAttr('style'); /** Needed to enable dropdown menu again **/
            });
Administrator committed
1169

1170 1171
    } catch (e) {
        alert('Impossible de récupérer les articles de cette catégorie');
Administrator committed
1172
    }
1173
};
Administrator committed
1174

1175
var initPromotionTabs = function() {
Administrator committed
1176
    if (promoted_pdts.length > 0) {
1177 1178 1179 1180
        $('.tab.promote').css('display', 'block');
        appendProductsToGrid($('#tab-content0').find('section'), promoted_pdts);
        $('input[name="tabs"]').removeAttr('checked');
        $('#tab0').prop('checked', true);
Administrator committed
1181 1182
    }
    if (discounted_pdts.length > 0) {
1183 1184
        $('.tab.discount').css('display', 'block');
        appendProductsToGrid($('#tab-content-1').find('section'), discounted_pdts);
Administrator committed
1185
    }
1186
};
Administrator committed
1187 1188

var search_product = function() {
1189 1190
    var kw = skw.val().trim();

Administrator committed
1191 1192
    if (kw.length > 0) {
        if (is_time_to('search_product', 1000)) { // prevent double click or browser hic up bug
1193 1194 1195 1196 1197 1198
            var grid = content4.find('section');
            var msg_cont = content4.find('.msg');

            grid.empty();
            putLoadingImgOn(content4);
            msg_cont.show();
Administrator committed
1199
            try {
1200 1201 1202 1203 1204 1205
                $.ajax({
                    url :'/shop/search_product',
                    data: {kw: kw},
                    dataType: 'json'
                })
                    .done(function(rData) {
Administrator committed
1206 1207
                        if (typeof rData.res.data != "undefined" && typeof rData.res.data.pdts != "undefined") {
                            //console.log(rData)
1208
                            appendProductsToGrid(grid, rData.res.data.pdts);
Administrator committed
1209 1210 1211
                        } else {
                            // ? what to do
                        }
1212 1213 1214
                        removeLoadingImg();
                        msg_cont.hide();
                    });
Administrator committed
1215

1216 1217
            } catch (e) {
                alert('Impossible de récupérer les articles de cette catégorie');
Administrator committed
1218 1219 1220 1221
            }
        }
    }

1222 1223
    return false; //prevent page reload
};
Administrator committed
1224 1225

var displaySentOrders = function() {
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242
    var waiting_msg = orders_section.find('.waiting_msg');

    $('.arrow-block').css('visibility', 'hidden');
    $('h1').hide();

    shop_section.hide();

    main_content.show();
    orders_section.show();
    make_user_wait('Recherche de commandes envoyées....');
    my_orders_wrap.hide();
    var no_action_available_msg = orders_section.find('.no-action-available-msg');

    no_action_available_msg.hide();
    var tbody = orders_section.find('tbody');

    tbody.empty();
Administrator committed
1243
    try {
1244 1245 1246 1247 1248
        $.ajax({
            url :'/shop/my_orders',
            dataType: 'json'
        })
            .done(function(rData) {
Administrator committed
1249 1250
                if (typeof rData.res.error != "undefined") {
                    if (rData.res.error == "Authentification non valide") {
1251
                        window.location.href = '/';
Administrator committed
1252
                    } else {
1253 1254
                        alert("Impossible de récupérer les données.");
                        djLogError({ctx: "get orders", msg:rData});
Administrator committed
1255
                    }
1256
                } else if (typeof rData.res.data.orders != "undefined") {
Administrator committed
1257
                    if (rData.res.data.orders.length > 0) {
1258
                        my_sent_orders = rData.res.data.orders;
1259 1260 1261 1262 1263
                        var eye = '<i class="fas fa-eye fl"></i>';
                        var delete_icon = '<i class="fas fa-trash fr"></i>';
                        var edit = '<i class="fas fa-edit"></i>';
                        var show_no_action_available_msg = false;

1264
                        $.each(my_sent_orders, function(i, o) {
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277
                            var bdate_content = "<span>" + o.best_date + "</span>";

                            if (o.state == "init" || o.state == "validating") bdate_content += " " + edit;
                            var actions_content = "";

                            if (o.state != "validating") show_no_action_available_msg = true;
                            if (o.submitted_time) ctime = parseInt(o.submitted_time*1000, 10);
                            else ctime = parseInt(o.init_time*1000, 10);

                            var date = format_date_to_sortable_string(new Date(ctime));
                            var tr = $('<tr>').attr('data-id', o._id)
                                .attr('data-rev', o._rev);

Administrator committed
1278
                            if (o.state == "validating" || o.state == "init") {
1279 1280
                                actions_content = delete_icon;
                                tr.prop('draggable', true);
Administrator committed
1281
                            }
1282 1283 1284 1285 1286 1287 1288 1289
                            var td1 = $('<td>').addClass('date create')
                                .text(date);
                            var td2 = $('<td>').addClass('date bdate')
                                .html(bdate_content);
                            var td3 = $('<td>').addClass('nb')
                                .text(o.products.length);
                            var td4 = $('<td>').addClass('amount')
                                .text(parseFloat(o.total).toFixed(2));
1290 1291

                            actions_content = eye + ' ' + actions_content;
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
                            var td5 = $('<td>').addClass('actions')
                                .html(actions_content);

                            tr.append(td1);
                            tr.append(td2);
                            tr.append(td3);
                            tr.append(td4);
                            tr.append(td5);
                            tbody.append(tr);
                            addDnDHandlers(tr.get(0));
                        });
                        if (show_no_action_available_msg == true) no_action_available_msg.show();

                        my_orders_wrap.show();
Administrator committed
1306
                    } else {
1307 1308
                        waiting_msg.show();
                        waiting_msg.html('<h3 style="text-align:center;">Aucune commande en cours.</h3>');
Administrator committed
1309
                    }
1310
                    main_waiting_zone.hide();
Administrator committed
1311
                }
1312
            });
Administrator committed
1313

1314 1315
    } catch (e) {
        alert('Impossible de récupérer les commandes en cours');
Administrator committed
1316
    }
1317
};
Administrator committed
1318 1319 1320 1321

/** Couchdb stored cart action **/
//change date methods will be useless when cart modifications will be possible since cart process validation is already done
var validBDayChange = function(cart_id) {
1322 1323 1324
    var bd = $('.mconfirm select[name="bday-change"]').val();
    var bh = $('.mconfirm select[name="bhour-change"]').val();
    var allowed_slot = isChoosenSlotValid(bd + ' '+ bh);
Administrator committed
1325 1326

    if (allowed_slot.res == false || bd.length == 0 || bh.length == 0) {
1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
        var day_zone = $('.mconfirm span.ask-day');
        var delay_msg = $('.mconfirm span.delay24h');

        day_zone.css({'border': 'none', 'background-color': 'white'});
        delay_msg.css({'background-color': 'white', 'padding': '0'});

        if (allowed_slot.res == false && allowed_slot.reason == 'full') showForbiddenSlots();
        if (allowed_slot.reason == 'delay') delay_msg.css({'padding': '2px', 'background-color': 'black'});
        setTimeout(function() {
            modal.css("width", "100%"); //modal div is closed after callback has been triggered
Administrator committed
1337
            if (allowed_slot == true && (bd.length == 0 || bh.length == 0))
1338 1339
                day_zone.css({'border':'1px solid red', 'background-color':'#fcbbf4'});
        }, 500);
Administrator committed
1340 1341 1342 1343


    } else {
        if (is_time_to('change_date', 15000)) { // prevent double click or browser hic up bug
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370
            var waiting_msg = $('<p>').append(loading_img);

            waiting_msg.append("<br/>Traitement de la demande de changement de date en cours....");
            setTimeout(function() {
                displayMsg(waiting_msg);
            }, 200); // delay needed because of closeModal called by confirm click
            post_form(
                '/shop/cart/' + cart_id + '/change_date',
                {new_date: bd + " " + bh},
                function(err, result) {
                    if (typeof result.res.changed != "undefined" && typeof result.res.changed[0] != "undefined" && result.res.changed[0].length == 3) {
                        alert("Nouvelle date enregistrée !");
                        displaySentOrders();
                    } else {

                        message = "Problème d'enregistrement";
                        if (typeof result.res.ts_respect != "undefined") {
                            if (result.res.ts_respect == false)
                                message += "\nLe créneau horaire choisi n'est pas correct.";
                        } else {
                            message += "\nSi cela persiste, merci de nous contacter.";
                        }
                        alert(message);
                    }
                    closeModal();
                }
            );
Administrator committed
1371 1372
        }
    }
1373
};
Administrator committed
1374
var changeBestDate = function() {
1375
    var clicked = $(this);
Administrator committed
1376 1377
    var clicked_tr = clicked.closest('tr'),
        id = clicked_tr.data('id'),
1378 1379 1380
        msg = modify_best_date_msg;

    msg.find('.current-bdate').text(clicked_tr.find('.bdate span').text());
Administrator committed
1381
    //copy hours from cart validation and slots constraints div to this msg content
1382
    var cart_vform = $('#cart_creation_form');
Administrator committed
1383

1384 1385
    msg.find('select[name="bhour-change"]').html(cart_vform.find('select[name="bhour"]').html());
    msg.find('.slots-constraints').html(cart_vform.find('.slots-constraints').html());
1386 1387
    if (shop_mode == 'shop')
        fillBDayOptions(bday_change_sel);
1388 1389 1390 1391 1392 1393

    updateUnavailableSlots(function() {
        openModal(msg.html(), function() {
            validBDayChange(id);
        }, 'Enregistrer');
    });
Administrator committed
1394

1395 1396

};
Administrator committed
1397

1398 1399 1400 1401 1402 1403 1404
var showSentCart = function() {
    let clicked = $(this),
        clicked_tr = clicked.closest('tr'),
        id = clicked_tr.data('id'),
        content = $('<div>'),
        table = $('<table>');
    let header = $('<tr><th>Article</th><th>Qté</th><th>Prix Total (T.T.C)</th></tr>');
1405 1406
    let bottom_msg = $('<p>').html("<em>Contenu non modifiable.</em>");

1407
    table.append(header);
1408
    $.each(my_sent_orders, function(i, e) {
1409
        if (e._id == id) {
1410
            $.each(e.products, function (j, p) {
1411 1412 1413
                let tr = $('<tr>'),
                    name = $('<td>').text(p.name),
                    qty = $('<td>').text(p.qty),
1414
                    total = $('<td>').text(p.total);
1415 1416 1417 1418 1419

                tr.append(name);
                tr.append(qty);
                tr.append(total);
                table.append(tr);
1420
            });
1421
        }
1422
    });
1423 1424 1425 1426

    content.append(table);
    content.append(bottom_msg);
    displayMsg(content.html());
1427
};
1428

Administrator committed
1429
var destroySentCart = function() {
1430
    var clicked = $(this);
Administrator committed
1431 1432
    var clicked_tr = clicked.closest('tr'),
        id = clicked_tr.data('id'),
1433
        msg = cart_destroy_msg.clone();
Administrator committed
1434

1435 1436
    msg.find('.date').text(clicked_tr.find('.create').text());
    msg.find('.bdate').text(clicked_tr.find('.bdate span').text());
Administrator committed
1437
    openModal(
1438 1439
        msg.html(),
        function() {
Administrator committed
1440
        // Confirm button callback
1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
            var waiting_msg = $('<p>').append(loading_img);

            waiting_msg.append("<br/>Traitement de la demande de suppression en cours....");
            setTimeout(function() {
                displayMsg(waiting_msg);
            }, 200); // delay needed because of closeModal called by confirm click
            post_form(
                '/shop/delete_cart',
                {cart_id: id},
                function(err, result) {
Administrator committed
1451 1452
                    if (!err) {
                        if (typeof result.res !== "undefined" && typeof result.res.del_action !== "undefined") {
1453
                            clicked_tr.remove();
Administrator committed
1454
                            // remove from browser stored data if it was the current one
1455 1456
                            if (order._id == id) clearCart();
                            alert("Commande détruite");
Administrator committed
1457
                        } else {
1458
                            djLogError({ctx: "destroy", msg: result});
Administrator committed
1459 1460 1461
                        }

                    } else {
1462
                        djLogError({ctx: "destroy", msg:err});
Administrator committed
1463
                    }
1464 1465 1466 1467 1468 1469
                    closeModal();
                }
            );
        },
        'Détruire'
    );
Administrator committed
1470

1471
};
Administrator committed
1472 1473

var sendFusionCartProposition = function(main_id, addid, date) {
1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486
    openModal(
        'Enregistrer la fusion des 2 commandes<br/>Récupération le '+ french_date_and_time(date),
        function() {
            var waiting_msg = $('<p>').append(loading_img);

            waiting_msg.append("<br/>Traitement de la demande de fusion en cours....");
            setTimeout(function() {
                displayMsg(waiting_msg);
            }, 200); // delay needed because of closeModal called by confirm click
            post_form(
                '/shop/fusion_carts',
                {id: main_id, add_id: addid},
                function(err, result) {
Administrator committed
1487 1488 1489
                    if (!err) {
                        try {
                            if (typeof result.res !== "undefined" && typeof result.res.del_action !== "undefined") {
1490
                                alert("Commandes fusionnées");
Administrator committed
1491 1492

                            } else {
1493
                                djLogError({ctx: "fusion", msg: result});
Administrator committed
1494
                            }
1495 1496
                        } catch (e1) {
                            djLogError({ctx: "fusion", msg: e1});
Administrator committed
1497 1498 1499
                        }

                    } else {
1500
                        djLogError({ctx: "fusion", msg:err});
Administrator committed
1501
                    }
1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512
                    closeModal();
                }
            );
        },
        'Envoyer',
        true,
        true,
        displaySentOrders // callback if canceled

    );
};
Administrator committed
1513 1514 1515 1516

// Get full slots and closing dates
var updateUnavailableSlots = function(callback) {
    try {
1517 1518 1519 1520 1521 1522
        $.ajax({
            url :'/shop/full_slots',
            dataType: 'json'
        })
            .done(function(rData) {
                forbidden_slots = [];
Administrator committed
1523
                if (typeof rData.res.full_slots != "undefined" && rData.res.full_slots.length > 0) {
1524
                    forbidden_slots = rData.res.full_slots;
Administrator committed
1525 1526
                }

1527
                closing_dates = [];
Administrator committed
1528
                if (typeof rData.res.closing_dates != "undefined" && rData.res.closing_dates.length > 0) {
1529
                    closing_dates = rData.res.closing_dates;
Administrator committed
1530 1531
                }

1532 1533
                callback();
            });
Administrator committed
1534

1535 1536
    } catch (e) {
        djLogError({ctx: "update unavailable slots", msg:e});
Administrator committed
1537
    }
1538
};
Administrator committed
1539 1540

var launch_init_form = function() {
1541 1542 1543
    make_user_wait('Préparation du formulaire...');
    current_action = 'init_form';
    updateUnavailableSlots(function() {
1544 1545
        if (shop_mode == 'shop')
            fillBDayOptions(bday_sel);
1546 1547 1548
        openModal($('#cart_creation_form').html(), initCart, 'Commencer la commande');
    });
};
Administrator committed
1549 1550

var ask_user_for_action = function(msg) {
1551 1552 1553 1554
    main_waiting_zone.show();
    main_waiting_zone.find('.msg').html(msg);
    main_waiting_zone.find('.loader').hide();
};
Administrator committed
1555 1556

var make_user_wait = function(msg) {
1557 1558 1559 1560
    main_waiting_zone.show();
    main_waiting_zone.find('.msg').html(msg);
    main_waiting_zone.find('.loader').show();
};
Administrator committed
1561 1562 1563 1564

var init_shop = function() {
    if (typeof order._id == "undefined") {
        if (order.products.length > 0) {
1565
            storeOrderForMigration();
Administrator committed
1566
        }
1567
        ask_user_for_action($('#templates .after-login-msg').html());
Administrator committed
1568 1569

    } else {
1570 1571
        launch_countdown_timer();
        pass2step2();
Administrator committed
1572 1573 1574
    }


1575
};
Administrator committed
1576 1577

var reset_home = function() {
1578 1579 1580 1581 1582 1583 1584 1585
    window.scrollTo(0, 0);
    $('.arrow-block').css('visibility', 'visible');
    main_content.hide();
    main_waiting_zone.show();
    orders_section.hide();
    orders_section.find('tbody').empty();
    init_shop();
};
Administrator committed
1586 1587

var justVisit = function() {
1588 1589 1590
    visit_mode = true;
    pass2step2();
};
Administrator committed
1591

1592 1593 1594
var current_order_name = shop_mode == 'shop' ? 'currentShopOrder' : 'currentDeliveryOrder';
var saved_order_name = shop_mode == 'shop' ? 'saved_shop_order' : 'saved_delivery_order';
var order = getStoredOrder() || { products: [], total: 0.00, type: shop_mode};
1595 1596 1597
var content1 = $('#tab-content1');
var content4 = $('#tab-content4');
var category_elts = getStoredCatElts() || {};
Administrator committed
1598 1599

/** init first render **/
1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
adjustCartHeight();
putAlimCategData();
putNonAlimCategData();
initPromotionTabs();
init_shop();

//cart_validation_form
valid_cart.click(function() {
    if (is_time_to('valid_cart', 1000)) { // prevent double click or browser hic up bug
        openModal($('#cart_validation_form').html(), validCart, 'Valider la commande');
        $('.mconfirm .pickup_date span').text(french_date_and_time(order.best_date));
Administrator committed
1611
    }
1612
});
Administrator committed
1613 1614


1615
$('#get_my_bought_products').click(loadAllAvailableBoughtProducts);
1616

1617 1618 1619 1620 1621 1622
$(document).on('change', '[name="bhour"]', adaptTimeGivenForValidationMsg);
$(document).on('click', '#alim_categ > div, #non_alim_categ > div', getCategChildren);
$(document).on('click', '#alim_categ ul li span, #non_alim_categ ul li span', getCategProducts);
$(document).on('click', '.product button', addProductToCart);
$(document).on('click', '.forbidden-slots .fs-close', closeForbiddenList);
$(document).on('click', 'td.date .fa-edit', changeBestDate);
1623
$(document).on('click', 'td.actions .fa-eye', showSentCart);
1624
$(document).on('click', 'td.actions .fa-trash', destroySentCart);
Administrator committed
1625

1626 1627 1628
if (shop_mode == 'shop')
    $(document).on('change', '[name^="bday"]', filterHourOptions);

1629 1630 1631 1632
$(document).on(
    'click', '.new-order',
    function() {
        visit_mode = false;
Administrator committed
1633
        if (typeof order._id == "undefined") {
1634 1635
            reset_home();
            clearCart();
Administrator committed
1636
            resetProgressBar();
1637 1638
            main_content.hide();
            launch_init_form();
Administrator committed
1639
        } else {
1640 1641
            djLogError({msg: "Une commande est déjà en cours", order:order});
            pass2step2();
Administrator committed
1642
        }
1643 1644
    }
);
Administrator committed
1645

1646 1647
$(document).on('click', '.my-orders', displaySentOrders);
$(document).on('click', '.visit', justVisit);
Administrator committed
1648

1649 1650 1651 1652 1653
$('#deconnect').click(function() {
    $.ajax("/website/deconnect").done(function() {
        window.location.reload();
    });
});
Administrator committed
1654

1655 1656 1657 1658
$('#go_to_top').click(function() {
    window.scrollTo(0, 0);
});
$('.back-to-home').click(reset_home);
Administrator committed
1659 1660 1661

/* Listener on product sorting selector */
$("select.products_sort").change(function () {
1662 1663 1664 1665 1666
    var clicked = $(this);
    var tab = clicked.closest('li.tab');
    var content = tab.find('.content');
    var grid = content.find('section');
    var products = grid.find('div.product');
Administrator committed
1667

1668 1669
    var sort_type = clicked.children("option:selected").val();
    var sorted_products = sort_product_divs(products, sort_type);
Administrator committed
1670

1671 1672
    grid.html(sorted_products);
});
Administrator committed
1673

1674 1675 1676
window.onresize = adjustSizes;
$(document).on("closemodal", function() {
    if (current_action == "init_form") reset_home();
Administrator committed
1677

1678
});