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/PartnershipTable/PartnershipTable.vue
<template>
  <div class="height-set" id="partnership-table">
    <div class="spinner-main">
      <Loader :loading="widgetLoading"> </Loader>
    </div>
    <template v-if="!widgetLoading && tableData.length">
      <div class="card height-set">
        <div class="card-body">
          <h4 class="card-title">Partnership Table</h4>
          <div class="row mt-4">
            <!-- Search Bar Widget-->
            <div class="col-sm-12 col-md-2">
              <div id="tickets-table_filter" class="dataTables_filter">
                <label class="d-inline-flex align-items-center">
                  Search:
                  <b-form-input
                    v-model="filter"
                    type="search"
                    placeholder="Search..."
                    class="form-control form-control-sm ms-2"
                  ></b-form-input>
                </label>
              </div>
            </div>
            <!-- Page Limit Widget-->
            <div class="col-sm-12 col-md-2">
              <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="perPage"
                    size="sm"
                    :options="pageOptions"
                  ></b-form-select
                  >&nbsp;entries
                </label>
              </div>
            </div>
            <!-- Add New Partnership Button-->
            <div class="col-sm-12 col-md-8 text-md-end text-sm-start">
              <button
                type="button"
                class="btn btn-primary waves-effect waves-light btn-addNewPartnerShip"
                @click="addPartnershipModalShow = true"
              >
                Add New Partnership
              </button>
            </div>
          </div>
          <!-- Partnership List -->
          <div class="table-responsive mb-0">
            <b-table
              class="datatables"
              :items="tableData"
              :fields="fields"
              responsive="sm"
              :per-page="perPage"
              :current-page="currentPage"
              :sort-by.sync="sortBy"
              :sort-desc.sync="sortDesc"
              :filter="filter"
              :filter-included-fields="filterOn"
              @filtered="onFiltered"
              :bordered="true"
              thead-class="table-light"
            >
              <template #cell(action)="data">
                <button
                  type="button"
                  class="btn btn-light waves-effect"
                  @click="selectPartner(data.item)"
                >
                  View
                </button>
              </template>
            </b-table>
          </div>
          <div class="row">
            <div class="col">
              <div class="dataTables_paginate paging_simple_numbers float-end">
                <ul class="pagination pagination-rounded mb-0">
                  <!-- pagination -->
                  <b-pagination
                    v-model="currentPage"
                    :total-rows="rows"
                    :per-page="perPage"
                  ></b-pagination>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- View Partnership Details Modalss  -->
      <b-modal
        v-model="modalShow"
        id="workflow-modal"
        dialog-class="modal-dialog-slideout"
        :hide-footer="true"
        content-class="rounded-0"
      >
        <template #modal-header="{ close }">
          <button type="button" class="btn btn-primary" @click="close()">
            <i class="bx bx-left-arrow-alt font-size-16 align-middle me-2"></i>
            Back
          </button>
        </template>
        <partnership-details
          v-if="selectedPartner"
          :selectedPartner="selectedPartner"
          :billingTypes="billingTypes"
          :businessTypes="businessTypes"
          :partnerTypes="partnerTypes"
          :roles="roles"
          @accountClosed="unselectPartner"
        ></partnership-details
      ></b-modal>
      <!-- Add Partnership Modal  -->
      <b-modal
        v-model="addPartnershipModalShow"
        dialog-class="modal-dialog-slideout"
        title-class="font-18"
        size="xl"
        content-class="rounded-0"
        footer-class="text-end"
        :hide-footer="true"
        id="workflow-modal"
      >
        <template #modal-header="{ close }">
          <button type="button" class="btn btn-primary" @click="close()">
            <i class="bx bx-left-arrow-alt font-size-16 align-middle me-2"></i>
            Close
          </button>
        </template>
        <div class="row justify-content-center">
          <div class="col-xl-10">
            <div class="card">
              <div class="card-body">
                <h4 class="card-title">Add New Partnership</h4>

                <b-form @submit.prevent="modalformSubmit">
                  <div class="row">
                    <div class="col-md-6 text-center">
                      <div class="mt-4 mt-md-0 mb-1">
                        <div
                          class="profile-avatar border-radius-0 avatar-lg"
                          v-if="!avatar"
                        >
                          {{ avatarName }}
                        </div>
                        <template v-else>
                          <p class="text-muted">Partnership Large Logo</p>
                          <img
                            class="avatar-lg w-auto"
                            alt="200x200"
                            :src="renderImageUrl"
                            data-holder-rendered="true"
                          />
                        </template>
                      </div>
                      <b-button variant="link" class="image-change-button pt-0"
                        ><input
                          class="form-control"
                          type="file"
                          @change="onChangeAvatar"
                        /><span
                          >{{ !avatar ? "Upload Large Logo" : "Change" }}
                        </span></b-button
                      >
                      <span v-if="avatar"> | </span>
                      <b-button
                        variant="link"
                        class="image-change-button pt-0"
                        v-if="avatar"
                        @click="avatar = null"
                      >
                        <span>Remove</span>
                      </b-button>
                      <p>
                        <em class="image-size-specify-tag">Optimal size: Height >70px</em>
                      </p>
                    </div>
                    <div class="col-md-6 text-center">
                      <div class="mt-4 mt-md-0 mb-1">
                        <div
                          class="profile-avatar avatar-lg border-radius-0"
                          v-if="!avatarSmall"
                        >
                          {{ avatarName }}
                        </div>
                        <template v-else>
                          <p class="text-muted">Partnership Small Logo</p>
                          <img
                            class="avatar-lg"
                            alt="200x200"
                            :src="renderImageUrlSmall"
                            data-holder-rendered="true"
                          />
                        </template>
                      </div>
                      <b-button variant="link" class="image-change-button pt-0"
                        ><input
                          class="form-control"
                          type="file"
                          @change="onChangeAvatarSmall"
                        /><span
                          >{{ !avatarSmall ? "Upload Small Logo" : "Change" }}
                        </span></b-button
                      >
                      <span v-if="avatarSmall"> | </span>
                      <b-button
                        variant="link"
                        class="image-change-button pt-0"
                        v-if="avatarSmall"
                        @click="avatarSmall = null"
                      >
                        <span>Remove</span>
                      </b-button>
                      <p>
                        <em class="image-size-specify-tag"
                          >Optimal size: >70px X >70px</em
                        >
                      </p>
                    </div>
                    <div class="col-md-12">
                      <b-form-group
                        class="mb-3"
                        label="Partnership name"
                        label-for="formrow-partnershipname-input"
                      >
                        <b-form-input
                          id="formrow-partnershipname-input"
                          type="text"
                          placeholder="Partnership name"
                          v-model="form.partnershipName"
                          name="partnershipName"
                          :class="{
                            'is-invalid': submitted && $v.form.partnershipName.$error,
                          }"
                        ></b-form-input>
                        <div
                          v-if="submitted && $v.form.partnershipName.$error"
                          class="invalid-feedback"
                        >
                          <span v-if="!$v.form.partnershipName.required"
                            >This value is required.</span
                          >
                        </div>
                      </b-form-group>
                    </div>
                  </div>

                  <div class="row">
                    <div class="col-md-4 mb-3">
                      <label>Current Default Billing</label>
                      <multiselect
                        v-model="form.defaultBilling"
                        :options="billingTypes"
                        :class="{
                          'is-invalid': submitted && $v.form.defaultBilling.$error,
                        }"
                        placeholder="Select billing type"
                        label="label"
                      ></multiselect>
                      <div
                        v-if="submitted && $v.form.defaultBilling.$error"
                        class="invalid-feedback"
                      >
                        <span v-if="!$v.form.defaultBilling.required"
                          >This value is required.</span
                        >
                      </div>
                    </div>
                    <div class="col-md-4 mb-3">
                      <label>Business Type</label>
                      <multiselect
                        v-model="form.businessType"
                        :options="businessTypes"
                        :class="{
                          'is-invalid': submitted && $v.form.businessType.$error,
                        }"
                        placeholder="Business Type"
                        label="label"
                      ></multiselect>

                      <div
                        v-if="submitted && $v.form.businessType.$error"
                        class="invalid-feedback"
                      >
                        <span v-if="!$v.form.businessType.required"
                          >This value is required.</span
                        >
                      </div>
                    </div>
                    <div class="col-md-4 mb-3">
                      <label>Partner Type</label>
                      <multiselect
                        v-model="form.partnerType"
                        :options="partnerTypes"
                        :class="{
                          'is-invalid': submitted && $v.form.partnerType.$error,
                        }"
                        placeholder="Partner Type"
                        label="label"
                      ></multiselect>

                      <div
                        v-if="submitted && $v.form.partnerType.$error"
                        class="invalid-feedback"
                      >
                        <span v-if="!$v.form.partnerType.required"
                          >This value is required.</span
                        >
                      </div>
                    </div>
                  </div>
                  <div class="row">
                    <div class="col-md-6">
                      <b-form-group
                        class="mb-3"
                        label="Partner Domain"
                        label-for="formrow-partnerurl-input"
                      >
                        <b-form-input
                          id="formrow-partnerurl-input"
                          type="text"
                          placeholder="Partner Url"
                          v-model="form.partnerUrl"
                          name="partnerUrl"
                          :class="{
                            'is-invalid': submitted && $v.form.partnerUrl.$error,
                          }"
                        >
                        </b-form-input>

                        <div
                          v-if="submitted && $v.form.partnerUrl.$error"
                          class="invalid-feedback"
                        >
                          <span v-if="!$v.form.partnerUrl.required"
                            >This value is required.</span
                          >
                          <span v-else-if="!$v.form.partnerUrl.domainValidator">{{
                            formvalidationMessages.domainvalidatorMessage
                          }}</span>
                        </div>
                      </b-form-group>
                    </div>
                    <div class="col-md-6">
                      <!-- <photoshop-picker v-model="sidebarColor" /> -->
                      <b-form-group class="mb-3" label="Select Primary Color">
                        <b-input-group>
                          <template #prepend>
                            <!-- <v-input-colorpicker
                              v-model="form.sidebarColor"
                              :style="{ backgroundColor: form.sidebarColor }"
                            /> -->
                          </template>
                          <b-form-input
                            id="formrow-colorpicker-input"
                            type="text"
                            placeholder="Select Primary Color"
                            v-model="form.sidebarColor"
                            name="colorpicker"
                          ></b-form-input>
                        </b-input-group>
                      </b-form-group>
                    </div>
                    <div class="col-md-6">
                      <b-form-group
                        class="mb-3"
                        label="Default System Email"
                        label-for="formrow-systememail-input"
                      >
                        <b-form-input
                          id="formrow-systememail-input"
                          type="text"
                          placeholder="Default system email"
                          v-model="form.systemEmail"
                          name="systemEmail"
                          :class="{
                            'is-invalid': submitted && $v.form.systemEmail.$error,
                          }"
                        ></b-form-input>
                        <div
                          v-if="submitted && $v.form.systemEmail.$error"
                          class="invalid-feedback"
                        >
                          <span v-if="!$v.form.systemEmail.required"
                            >This value is required.</span
                          >
                          <span v-else-if="!$v.form.partnerUrl.email"
                            >Please provide a valid email.</span
                          >
                        </div>
                      </b-form-group>
                    </div>
                    <div class="col-md-6">
                      <b-form-group
                        class="mb-3"
                        label="Invite Partner User Email"
                        label-for="formrow-systememail-input"
                      >
                        <b-form-input
                          id="formrow-partneruseremail-input"
                          type="text"
                          placeholder="Invite partner user email"
                          v-model="form.partneruseremail"
                          name="partneruseremail"
                          :class="{
                            'is-invalid': submitted && $v.form.partneruseremail.$error,
                          }"
                        ></b-form-input>
                        <div
                          v-if="submitted && $v.form.partneruseremail.$error"
                          class="invalid-feedback"
                        >
                          <span v-if="!$v.form.partneruseremail.required"
                            >This value is required.</span
                          >
                          <span v-else-if="!$v.form.partneruseremail.email"
                            >Please provide a valid email.</span
                          >
                        </div>
                      </b-form-group>
                    </div>
                    <div class="col-md-6">
                      <div class="form-check form-switch mb-3 form-switch-lg">
                        <input
                          class="form-check-input"
                          type="checkbox"
                          id="restrictLoginAccess"
                          v-model="form.expandedMenu"
                        />
                        <label class="form-check-label" for="restrictLoginAccess"
                          >Display expanded menu as default</label
                        >
                      </div>
                    </div>
                  </div>
                  <div>
                    <b-button variant="light" @click="closeModalAddPartnership">
                      Cancel</b-button
                    >
                    <b-button variant="primary" type="submit" @click="modalSubmitClicked">
                      <i
                        class="bx bx-loader bx-spin font-size-16 align-middle me-2"
                        v-if="addPartnershipLoading"
                      ></i>
                      Confirm
                    </b-button>
                  </div>
                </b-form>
              </div>
            </div>
          </div>
        </div>
      </b-modal>
    </template>
  </div>
</template>

<script>
import PartnershipService from "../../service/partnershipService";
import MainService from "../../service/mainService";
import Loader from "../../components/Loader/loader.vue";
import PartnershipDetails from "./PartnershipDetails.vue";
import { toastConfig } from "../../utils/util";
import { required, email, url } from "vuelidate/lib/validators";
import Multiselect from "vue-multiselect";
import * as _ from "lodash";
import InputColorPicker from "vue-native-color-picker";

import {
  BFormInput,
  BFormSelect,
  BTable,
  BPagination,
  BModal,
  BButton,
  BFormGroup,
  BInputGroup,
  BForm,
} from "bootstrap-vue-next";

import {
  formvalidation,
  formvalidationMessages,
  isFileWithinLimit,
} from "../../utils/util";

const { domainValidator } = formvalidation;

export default {
  components: {
    Loader,
    PartnershipDetails,
    Multiselect,
    InputColorPicker,
    BFormInput,
    BFormSelect,
    BTable,
    BPagination,
    BModal,
    BButton,
    BFormGroup,
    // VInputColorpicker,
    BInputGroup,
    BForm,
  },
  data() {
    return {
      formvalidationMessages,
      partnershipListLoading: false,
      addPartnershipModalShow: false,
      billingTypesLoading: false,
      businessTypesLoading: false,
      partnerTypesLoading: false,
      addPartnershipLoading: false,
      roleLoading: false,
      billingTypes: [],
      businessTypes: [],
      partnerTypes: [],
      roles: [],
      selectedPartner: null,
      modalShow: false,
      headVariant: "light",

      tableData: [],
      totalRows: 1,
      currentPage: 1,
      perPage: 5,
      pageOptions: [5, 10, 25, 50, 100],
      filter: null,
      filterOn: [],
      sortBy: "partnershipName",
      sortDesc: false,
      fields: [
        {
          key: "partnershipName",
          sortable: true,
        },
        {
          key: "created_on",
          sortable: true,
        },
        {
          key: "updated_on",
          sortable: true,
        },
        "action",
      ],
      avatar: null,
      avatarSmall: null,
      form: {
        partnershipName: "",
        defaultBilling: null,
        businessType: null,
        partnerType: null,
        partnerUrl: "",
        systemEmail: "",
        partneruseremail: "",
        sidebarColor: "#2a3042",
        expandedMenu: false,
      },
      submitted: false,
    };
  },
  validations: {
    form: {
      partnershipName: { required },
      defaultBilling: { required },
      businessType: { required },
      partnerType: { required },
      partnerUrl: { required, domainValidator },
      systemEmail: { required, email },
      partneruseremail: { required, email },
    },
  },
  mounted() {
    this.getPartnerships();
    this.getBillingTypes();
    this.getBusinessTypes();
    this.getRoles();
    this.getPartnerTypes();
  },
  computed: {
    /**
     * Total no. of records
     */
    rows() {
      return this.tableData.length;
    },
    /**
     * Total no. of records
     */
    widgetLoading() {
      return (
        this.partnershipListLoading ||
        this.billingTypesLoading ||
        this.roleLoading ||
        this.partnerTypesLoading ||
        this.businessTypesLoading
      );
    },
    avatarName() {
      if (!this.form.partnershipName) {
        return "";
      }
      return this.form.partnershipName.charAt(0).toUpperCase();
    },
    renderImageUrl() {
      if (this.avatar == null) {
        return null;
      }
      const image =
        typeof this.avatar === "object" ? URL.createObjectURL(this.avatar) : this.avatar;
      return image;
    },
    renderImageUrlSmall() {
      if (this.avatarSmall == null) {
        return null;
      }
      const image =
        typeof this.avatarSmall === "object"
          ? URL.createObjectURL(this.avatarSmall)
          : this.avatarSmall;
      return image;
    },
  },

  methods: {
    modalSubmitClicked(e) {
      e.preventDefault();
      this.modalformSubmit();
    },
    closeModalAddPartnership() {
      this.addPartnershipModalShow = false;
      this.v$.form.$reset();
    },
    /**
     * Search the table data with search input
     */
    onFiltered(filteredItems) {
      // Trigger pagination to update the number of buttons/pages due to filtering
      this.totalRows = filteredItems.length;
      this.currentPage = 1;
    },
    modalformSubmit() {
      this.submitted = true;
      this.v$?.$touch();
      if (this.v$?.$invalid) {
        return;
      }
      const formData = new FormData();
      formData.append("data", JSON.stringify(this.form));
      if (this.avatar !== null && typeof this.avatar === "object") {
        formData.append("file", this.avatar);
      }
      if (this.avatarSmall !== null && typeof this.avatarSmall === "object") {
        formData.append("filesmall", this.avatarSmall);
      }
      this.addPartnership(formData);
    },
    onChangeAvatar(e) {
      const { files } = e.target;
      if (files && files[0]) {
        const tempFiles = [...files];
        if (
          tempFiles[0].type.includes("image") &&
          isFileWithinLimit(files[0].size / 1024 / 1024, 5)
        ) {
          let reader = new FileReader();
          reader.readAsDataURL(tempFiles[0]);
          reader.onload = (evt) => {
            let img = new Image();
            img.onload = () => {
              if (img.height < 70) {
                this.$toast.open(
                  toastConfig.toastError("The image should have a minmum height of 70px.")
                );
              } else {
                this.avatar = tempFiles[0];
              }
            };
            img.src = evt.target.result;
          };
        } else {
          this.$toast.open(
            toastConfig.toastError(
              "The file should be an image and should be less than 5MB"
            )
          );
        }
      }
      e.target.value = "";
    },
    onChangeAvatarSmall(e) {
      const { files } = e.target;
      if (files && files[0]) {
        const tempFiles = [...files];
        if (
          tempFiles[0].type.includes("image") &&
          isFileWithinLimit(tempFiles[0].size / 1024 / 1024, 5)
        ) {
          let reader = new FileReader();
          reader.readAsDataURL(tempFiles[0]);
          reader.onload = (evt) => {
            let img = new Image();
            img.onload = () => {
              if (img.height < 70 || img.width < 70) {
                this.$toast.open(
                  toastConfig.toastError(
                    "The image should have a minmum height and width of 70px."
                  )
                );
              } else if (img.height !== img.width) {
                this.$toast.open(
                  toastConfig.toastError("The height and width of image should be same.")
                );
              } else {
                this.avatarSmall = tempFiles[0];
              }
            };
            img.src = evt.target.result;
          };
        } else {
          this.$emit(
            "toast",
            toastConfig.toastError(
              "The file should be an image and should be less than 5MB"
            )
          );
        }
      }
      e.target.value = "";
    },
    resetForm() {
      this.form = {
        partnershipName: "",
        defaultBilling: null,
        businessType: null,
        partnerType: null,
        partnerUrl: "",
        systemEmail: "",
        partneruseremail: "",
        sidebarColor: "#2a3042",
      };
      this.avatar = null;
      this.avatarSmall = null;
    },
    /**
     * Get all partnerships
     */
    getPartnerships() {
      this.partnershipListLoading = true;
      PartnershipService.getPartnerships()
        .then(({ data: { success, message, data } }) => {
          if (success) {
            // console.log(success, message, data);
            // this.$toast.open(toastConfig.toastSuccess(message));
            this.partnershipListLoading = false;
            this.tableData = data;
          } else {
            this.$toast.open(toastConfig.toastError(message));
            this.partnershipListLoading = false;
          }
        })
        .catch((e) => {
          this.partnershipListLoading = false;
          this.$toast.open(
            toastConfig.toastError(
              "Something went wrong while fetching partnership list!"
            )
          );
          console.log("error", e);
        });
    },
    getBillingTypes() {
      this.billingTypesLoading = true;
      PartnershipService.getPartnershipBillingTypes()
        .then(({ data: { success, message, data } }) => {
          if (success) {
            // console.log(success, message, data);
            // this.$toast.open(toastConfig.toastSuccess(message));
            this.billingTypesLoading = false;
            this.billingTypes = data;
          } else {
            this.$toast.open(toastConfig.toastError(message));
            this.billingTypesLoading = false;
          }
        })
        .catch((e) => {
          this.billingTypesLoading = false;
          this.$toast.open(
            toastConfig.toastError("Something went wrong while fetching billing types!")
          );
          console.log("error", e);
        });
    },
    getBusinessTypes() {
      this.businessTypesLoading = true;
      PartnershipService.getPartnershipBusinessTypes()
        .then(({ data: { success, message, data } }) => {
          if (success) {
            // console.log(success, message, data);
            // this.$toast.open(toastConfig.toastSuccess(message));
            this.businessTypesLoading = false;
            this.businessTypes = data;
          } else {
            this.$toast.open(toastConfig.toastError(message));
            this.businessTypesLoading = false;
          }
        })
        .catch((e) => {
          this.businessTypesLoading = false;
          this.$toast.open(
            toastConfig.toastError("Something went wrong while fetching business types!")
          );
          console.log("error", e);
        });
    },
    getRoles() {
      this.roleLoading = true;
      MainService.getAppRoles()
        .then(({ data: { success, message, data } }) => {
          if (success) {
            this.roleLoading = false;
            this.roles = data;
          } else {
            this.$toast.open(toastConfig.toastError(message));
            this.roleLoading = false;
          }
        })
        .catch((e) => {
          this.roleLoading = false;
          console.log("error", e);
          this.$toast.open(
            toastConfig.toastError("Something went wrong while fetching app roles!")
          );
        });
    },
    getPartnerTypes() {
      this.partnerTypesLoading = true;
      PartnershipService.getPartnershipTypes()
        .then(({ data: { success, message, data } }) => {
          if (success) {
            this.partnerTypesLoading = false;
            this.partnerTypes = data;
          } else {
            this.$toast.open(toastConfig.toastError(message));
            this.partnerTypesLoading = false;
          }
        })
        .catch((e) => {
          this.partnerTypesLoading = false;
          console.log("error", e);
          this.$toast.open(
            toastConfig.toastError("Something went wrong while fetching partner types!")
          );
        });
    },
    addPartnership(postData) {
      this.addPartnershipLoading = true;
      PartnershipService.addPartnership(postData)
        .then(({ data: { success, message } }) => {
          if (success) {
            this.$toast.open(toastConfig.toastSuccess(message));
            this.addPartnershipLoading = false;
            this.closeModalAddPartnership();
            this.resetForm();
            this.getPartnerships();
          } else {
            this.$toast.open(toastConfig.toastError(message));
            this.addPartnershipLoading = false;
          }
        })
        .catch((e) => {
          this.addPartnershipLoading = false;
          console.log("error", e);
          this.$toast.open(
            toastConfig.toastError("Something went wrong while trying to add partnership")
          );
        });
    },
    /**
     * Select a partner when clicking view button
     */
    selectPartner(partnerData) {
      this.selectedPartner = partnerData.sid;
      this.modalShow = true;
    },
    unselectPartner() {
      this.selectedPartner = null;
      this.modalShow = false;
      this.getPartnerships();
    },
  },
  //directives: { "v-input-colorpicker": InputColorPicker },
  watch: {
    /**
     * Watch modal triggering variable
     */
    modalShow(flag) {
      if (!flag) {
        this.selectedPartner = null;
      }
    },
  },
};
</script>