HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: //home/arjun/projects/buyercall/buyercall/assets/vue/widgets/contactManagement/components/List.vue
<template>
  <div class="spinner-main">
    <growing-loader :isMini="true" v-if="loading"></growing-loader>
  </div>
  <div class="card height-set">
    <div class="card-body">
      <div class="d-flex justify-content-between align-items-center">
        <h4 class="card-title">Leads List</h4>
        <button
          type="button"
          class="btn btn-primary waves-effect waves-light btn-addNewPartnerShip"
          @click="addNewLeads()"
        >
          Add New Lead
        </button>
      </div>
      <div class="row" style="margin-top: -1.5rem !important">
        <div class="row mt-4">
          <template v-if="tableData.length == 0 || tableData.length">
            <div class="col-sm-12 col-md-2" style="width: 350px">
              <div id="tickets-table_filter" class="dataTables_filter">
                <label class="d-inline-flex align-items-center w-100">
                  <b-form-input
                    v-model="filter"
                    type="search"
                    placeholder="Search for..."
                    class="form-control form-control-sm ms-2"
                    style="height: 40px"
                  ></b-form-input>
                </label>
              </div>
            </div>

            <div class="col-sm-12 col-md-2" style="width: fit-content">
              <datepicker
                v-model="pickedFrom"
                class="form-control form-control-sm"
                :format="DatePickerFormat"
                style="height: 38px"
              />
            </div>

            <div class="col-sm-12 col-md-2" style="width: fit-content">
              <datepicker
                v-model="pickedTo"
                class="form-control form-control-sm"
                :format="DatePickerFormat"
                style="height: 38px"
              />
            </div>

            <div class="col-sm-12 col-md-2" style="width: fit-content">
              <button
                type="button"
                class="btn btn-light waves-effect waves-light btn-addNewPartnerShip btn-width text-muted"
                @click="downloadCSVItem()"
              >
                Download CSV
              </button>
            </div>

            <div class="col-sm-12 col-md-2" style="width: fit-content">
              <input
                ref="fileInput"
                type="file"
                @change="handleFileUpload"
                class="btn btn-light waves-effect waves-light btn-addNewPartnerShip btn-width"
                style="display: none"
              />
              <button
                @click="triggerFileInput"
                class="btn btn-light waves-effect waves-light btn-addNewPartnerShip btn-width text-muted"
              >
                Import Leads
              </button>
              <!-- <ul>
                <li v-for="(row, index) in csvData" :key="index">{{ row }}</li>
              </ul> -->
            </div>
            <div class="col-sm-12 col-md-2" style="width: fit-content">
              <button
                type="button"
                class="btn btn-light waves-effect waves-light btn-addNewPartnerShip btn-width text-muted"
                v-bind:class="{ 'btn-soft-secondary': isFilterActive }"
                v-bind:style="{
                  'background-color': isFilterActive ? '#74788d' : '',
                }"
                @click="additionalFilters()"
              >
                <Icon
                  :icon="isFilterActive ? 'mdi:filter-outline' : 'mdi:filter-outline'"
                  :color="isFilterActive ? '#ffffff' : ''"
                  style="margin-right: 5px"
                />
                <span :style="{ color: isFilterActive ? '#ffffff' : '' }">Filters</span>
              </button>
            </div>

            <div class="col-sm-12 col-md-2" style="width: fit-content">
              <button
                type="button"
                class="btn btn-light waves-effect waves-light btn-addNewPartnerShip btn-width text-muted"
                @click="resetFilters()"
              >
                Reset Filters
              </button>
            </div>
          </template>
        </div>
      </div>
      <div class="table-responsive mb-0">
        <b-table
          class="datatables"
          :items="filteredItems"
          :fields="fields"
          responsive="sm"
          :per-page="tablelength"
          :sort-by.sync="sortBy"
          :sort-desc.sync="sortDesc"
          :bordered="true"
          thead-class="table-white"
          :hover="true"
          :striped="false"
          :busy="loading"
          :show-empty="true"
          sticky-header="false"
        >
          <template #table-busy>
            <growing-loader></growing-loader>
          </template>
          <template #cell(0)="data">
            <span style="font-weight: 600">
              {{ (currentPage - 1) * perPage + data.index + 1 }}
            </span>
          </template>
          <template #cell(1)="data">
            <div style="display: flex; flex-direction: column">
              <span>{{ data.item["1"] + " " + data.item["10"] }}</span>
            </div>
          </template>
          <template #cell(2)="data">
            <div style="display: flex; flex-direction: column">
              <span>{{ data.item["2"] }}</span>
            </div>
          </template>
          <template #cell(3)="data">
            <div style="display: flex; flex-direction: column">
              <span>{{ data.item["3"] }}</span>
            </div>
          </template>

          <template #cell(4)="data">
            <div>
              <span class="sourcetype" v-if="data.item['4'] === 'import '">Import</span>
              <span class="sourcetypecredit" v-if="data.item['4'] === ''">Credit</span>
            </div>
          </template>

          <template #cell(is_active)="data">
            <span class="badge bg-info" v-if="data.item.isActive">YES</span>
            <span class="badge bg-danger" v-else>NO</span>
          </template>
          <template #cell(status)="data">
            <span class="badge bg-success" v-if="data.item.status === 1">Ready</span>
            <span class="badge bg-warning" v-if="data.item.status === 0">Warning</span>
          </template>

          <template #cell(action)="data">
            <div class="btn-group">
              <button
                type="button"
                class="btn btn-light waves-effect"
                data-bs-toggle="dropdown"
                aria-haspopup="true"
                aria-expanded="false"
              >
                Action
              </button>
              <div class="dropdown-menu dropdown-menu-right">
                <button class="dropdown-item" @click="quickEdit(data.item)">Edit</button>
              </div>
            </div>
          </template>
        </b-table>
      </div>
      <div class="row">
        <div class="col d-flex justify-content-between align-items-center">
          <div id="tickets-table_length" class="dataTables_length">
            <label class="d-inline-flex align-items-center">
              Show&nbsp;
              <b-form-select
                class="form-select form-select-sm"
                v-model="tablelength"
                size="sm"
                :options="pageOptions"
                style="height: 40px"
                @change="handleAssignedAgentChange"
              ></b-form-select
              >&nbsp;
            </label>
          </div>

          <div class="dataTables_paginate paging_simple_numbers float-end">
            <ul class="pagination pagination-rounded mb-0">
              <b-pagination
                v-model="currentPage"
                :total-rows="rows"
                :per-page="perPage"
                @update:modelValue="fetchData"
              ></b-pagination>
            </ul>
          </div>
        </div>
      </div>
      <leads-popup
        v-if="showConfirmDelete"
        @fileupload="showFileInput"
        @downloadcsv="sampleTemplateDownload"
        @cancel="cancel"
      ></leads-popup>
    </div>
  </div>
</template>

<script>
import { listTableConfig } from "../constants";
import GrowingLoader from "../../../components/GrowingLoader.vue";
import { BTable, BFormInput, BFormSelect, BPagination } from "bootstrap-vue-next";
import Datepicker from "vue3-datepicker";

import { Icon } from "@iconify/vue";
import LeadsPopup from "./LeadsPopup.vue";

import Papa from "papaparse";

import _ from "lodash";
export default {
  emits: [
    "onAddButtonClicked",
    "onDelete",
    "onAddFiltersClicked",
    "onErrorMethod",
    "reset",
    "onEditContact",
    "uploadcsv",
    "datefilter",
    "page-changed",
    "page-show",
  ],
  props: {
    leadsData: {
      type: Array,
      required: true,
      default: () => [],
    },
    leadInfo: {
      type: Object,
      required: true,
    },
    loading: {
      type: Boolean,
      required: true,
    },
    isFilterActive: {
      type: Boolean,
      required: true,
    },
    fromdate: {
      type: Date,
      required: true,
    },
    todate: {
      type: Date,
      required: true,
    },
    currentPages: {
      type: Number,
      required: true,
    },
    totalpage: {
      type: Number,
      required: true,
    },
  },
  data() {
    return {
      tableData: [],
      tablelength: 10,
      currentPage: 1,
      tablestart: 0,
      dataSingObjectArray: [],
      sampleTemplateData: listTableConfig.sampleTemplate,
      sampleTemplaeHeading: listTableConfig.sampleTemplateHeading,
      csvkeys: listTableConfig.CSV_KEYS,
      csvHeading: listTableConfig.downloadAllCSV,
      SEARCH_KEYS: listTableConfig.SEARCH_KEYS,
      filter: null,
      showConfirmDelete: false,
      fromDate: "",
      // pickedFrom: new Date("2010-01-01"),
      // pickedTo: new Date(),

      pickedFrom: null,
      pickedTo: null,
      DatePickerFormat: "dd/MM/yyyy",
      disabledDates: {
        to: new Date(Date.now() - 8640000),
      },
      csvData: [],
      ...listTableConfig,
    };
  },
  computed: {
    rows() {
      // return this.leadInfo.recordsTotal;
      return Math.ceil((this.leadInfo.recordsTotal / this.tablelength) * 10);
    },

    filteredItems() {
      // Perform case-insensitive search based on the search query
      const query = this.filter ? this.filter.toLowerCase() : "";

      if (query) {
        return this.tableData.filter((item) => {
          return this.SEARCH_KEYS.some((key) =>
            (item[key]?.toString()?.toLowerCase() || "").includes(query)
          );
        });
      } else {
        return this.tableData;
      }
    },
  },
  methods: {
    handleAssignedAgentChange(e) {
      this.tablelength = e;
      this.tablestart = 0;
      this.selectedDateFrom();
      this.$emit("page-show", e);
    },
    fetchData(e) {
      this.currentPage = e; // Update currentPage with the new page number
      this.tablestart = (this.currentPage - 1) * this.tablelength; // Calculate tablestart based on currentPage
      this.$emit("page-changed", e);
      this.selectedDateFrom();
    },

    selectedDateFrom() {
      let filters = {
        df: this.formatDates(this.pickedFrom),
        dt: this.formatDates(this.pickedTo),
        stf: "0",
        stp: "0",
        sts: "0",
        sis: "0",
        sas: "0",
        sais: "0",
        length: this.tablelength,
        start: this.tablestart,
        aa: null,
        ps: null,
        ms: null,
        mks: null,
        fs: null,
        cs: null,
        cbs: null,
        order: [
          {
            dir: "desc",
            column: "5",
          },
        ],
      };

      let selecteddate = {
        from: this.pickedFrom,
        to: this.pickedTo,
      };
      this.$emit("datefilter", filters, selecteddate);
    },

    formatDates(selecteddate) {
      const dateObject = new Date(selecteddate);
      const day = ("0" + dateObject.getDate()).slice(-2);
      const month = ("0" + (dateObject.getMonth() + 1)).slice(-2);
      const year = dateObject.getFullYear();

      this.formattedDate = `${month}${day}${year}`;

      return this.formattedDate;
    },
    resetFilters() {
      this.currentPage = 1;
      this.$emit("reset");
    },
    triggerFileInput(event) {
      this.showConfirmDelete = true;
    },

    showFileInput() {
      this.showConfirmDelete = false;
      this.$refs.fileInput.click();
    },
    sampleTemplateDownload() {
      this.showConfirmDelete = false;

      const csvContent =
        "data:text/csv;charset=utf-8," +
        this.sampleTemplaeHeading.join(",") +
        "\n" +
        this.sampleTemplateData
          .map((item) => this.sampleTemplaeHeading.map((key) => item[key]).join(","))
          .join("\n");

      // Create a data URI for the CSV content
      const encodedUri = encodeURI(csvContent);

      // Create a link element and trigger a download
      const link = document.createElement("a");
      link.setAttribute("href", encodedUri);
      link.setAttribute("download", "SampleLeadsTemplate.csv");
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    },
    handleFileUpload(event) {
      const file = event.target.files[0];

      // Perform a simple validation based on the file extension
      if (!file || !file.name.toLowerCase().endsWith(".csv")) {
        this.error = "Please select a valid CSV file.";
        this.$emit("onErrorMethod", "Please select a valid CSV file.");
        return "";
      }

      // Clear any previous error messages
      this.error = null;
      // Parse the CSV file
      Papa.parse(file, {
        complete: (result) => {
          // Apply transformations to the parsed data
          this.csvData = result.data
            .filter((item) => Object.keys(item).length > 1)
            .map((item) => ({
              ...item,
              zip: item.zip.toString(), // Convert zip to a string
            }));

          this.$emit("uploadcsv", this.csvData);
        },
        header: true, // set to true if your CSV file has a header row
        dynamicTyping: true,
      });
    },
    quickEdit(item) {
      this.$emit("onEditContact", item["11"]);
    },
    downloadCSVItem(item) {
      let csvContent = "";

      const dataArray = item ? [item] : this.tableData;

      if (dataArray.length > 0) {
        csvContent =
          "data:text/csv;charset=utf-8," +
          this.csvHeading.join(",") +
          "\n" +
          dataArray
            .map((item) =>
              this.CSV_KEYS.map((key) => item[key] || "") // Handle undefined values
                .join(",")
            )
            .join("\n");

        // Create a data URI for the CSV content
        const encodedUri = encodeURI(csvContent);

        // Create a link element and trigger a download
        const link = document.createElement("a");
        link.setAttribute("href", encodedUri);
        link.setAttribute("download", "leads.csv");
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }
    },

    addNewLeads() {
      this.$emit("onAddButtonClicked");
    },
    additionalFilters() {
      this.$emit("onAddFiltersClicked");
    },
    cancel() {
      this.showConfirmDelete = false;
    },
  },
  components: {
    GrowingLoader,
    BTable,
    BFormInput,
    BFormSelect,
    BPagination,
    Datepicker,
    Icon,
    LeadsPopup,
  },
  watch: {
    leadsData: {
      immediate: true,
      handler(newVal) {
        if (newVal) {
          this.tableData = newVal;
        }
      },
    },
    isFilterActive: {
      immediate: true,
      handler(newVal) {},
    },
    pickedFrom(newValue, oldValue) {
      if (newValue !== oldValue) {
        if (oldValue) {
          this.selectedDateFrom();
          this.currentPage = 1;
        }
      }
    },
    pickedTo(newValue, oldValue) {
      if (newValue !== oldValue) {
        if (oldValue) {
          this.selectedDateFrom();
          this.currentPage = 1;
        }
      }
    },

    fromdate: {
      immediate: true,
      handler(newVal) {
        this.pickedFrom = newVal;
      },
    },
    todate: {
      immediate: true,
      handler(newVal) {
        this.pickedTo = newVal;
      },
    },
    currentPages: {
      immediate: true,
      handler(newVal) {
        if (newVal !== this.currentPage) {
          this.currentPage = newVal;
        }
      },
    },
    totalpage: {
      immediate: true,
      handler(newVal) {
        if (newVal !== this.currentPage) {
          this.tablelength = newVal;
        }
      },
    },
  },
};
</script>