{"version":3,"sources":["/var/www/html/acc-web/admin/src/components/functions/Top/TopIndex.vue","/var/www/html/acc-web/admin/src/components/functions/Admin/M0001User/M0001AdminUserFilter.vue","/var/www/html/acc-web/admin/src/components/functions/Admin/M0001User/M0001AdminUserList.vue","/var/www/html/acc-web/admin/src/components/functions/Admin/M0001User/M0001AdminUserSearch.vue","/var/www/html/acc-web/admin/src/components/functions/Admin/M0001User/M0001AdminUserEdit.vue","/var/www/html/acc-web/admin/src/components/functions/Admin/M0001User/M0001AdminUserIndex.vue","/var/www/html/acc-web/admin/src/components/functions/Admin/M0301ScanRecord/M0301ScanRecordFilter.vue","/var/www/html/acc-web/admin/src/components/functions/Admin/M0301ScanRecord/M0301ScanRecordList.vue","/var/www/html/acc-web/admin/src/components/functions/Admin/M0301ScanRecord/M0301ScanRecordUserDetails.vue","/var/www/html/acc-web/admin/src/components/functions/Admin/M0301ScanRecord/M0301ScanRecordSearch.vue","/var/www/html/acc-web/admin/src/components/functions/Admin/M0301ScanRecord/M0301ScanRecordIndex.vue"],"names":[],"mappings":"AAwEA,wBACA,WAAA,CACA,uBAAA,CAAA,oBAAA,CAAA,sBAAA,CACA,iBACA,CAEA,6BACA,WAAA,CACA,YACA,CAEA,mCACA,yEAAA,CAAA,iEACA,CCmIA,mCACA,UACA,CCxGA,4BACA,UACA,CC7CA,4BACA,UACA,CC8NA,0EACA,sCACA,CAEA,2CACA,WAAA,CACA,YACA,CCnIA,kDACA,WACA,CAEA,4BACA,UACA,CCEA,mCACA,UACA,CCtFA,mCACA,UACA,CCuBA,4BACA,UACA,CC5CA,4BACA,UACA,CCMA,kDACA,WACA,CAEA,4BACA,UACA","file":"1.9dd9c149a746ffa79f87.css","sourcesContent":["<template>\r\n  <v-container>\r\n    <v-row class=\"title text-h3 text-uppercase\">\r\n      {{ $t('title') }}\r\n    </v-row>\r\n    <v-row justify=\"center\">\r\n      <v-col\r\n        v-for=\"item in cards\"\r\n        :key=\"item.id\"\r\n        class=\"center-wrap\"\r\n        cols=\"12\"\r\n        md=\"4\"\r\n      >\r\n        <router-link\r\n          class=\"link-pointer router-div\"\r\n          :to=\"item.routerLink\"\r\n          tag=\"div\"\r\n        >\r\n          <v-card\r\n            class=\"ma-auto card-style\"\r\n            width=\"200\"\r\n            height=\"200\"\r\n          >\r\n            <v-row>\r\n              <v-icon\r\n                size=\"110\"\r\n                color=\"primary darken-2\"\r\n                class=\"ma-auto my-5\"\r\n              >\r\n                {{ item.icon }}\r\n              </v-icon>\r\n            </v-row>\r\n            <v-row justify=\"center\">\r\n              <v-col class=\"center-wrap\">\r\n                <div>{{ item.text }}</div>\r\n              </v-col>\r\n            </v-row>\r\n          </v-card>\r\n        </router-link>\r\n      </v-col>\r\n    </v-row>\r\n  </v-container>\r\n</template>\r\n\r\n<i18n src=\"./locales/en.json\"></i18n>\r\n<i18n src=\"./locales/zhHant.json\"></i18n>\r\n\r\n<script>\r\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\r\n\r\nexport default {\r\n  name: 'TopIndex',\r\n  mixins: [ErrorDisplay],\r\n  data: function () {\r\n    return {\r\n      cards: [\r\n        { id: 1, text: this.$t('sidebar.userManagement'), icon: 'fa-user', routerLink: 'User' },\r\n        { id: 2, text: this.$t('sidebar.scanRecord'), icon: 'fa-qrcode', routerLink: 'ScanRecord' }\r\n      ]\r\n    }\r\n  },\r\n  computed: {\r\n  },\r\n  mounted () {\r\n    this.$emit('pageName', this.$t('pageName'))\r\n  },\r\n  methods: {\r\n  }\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.title {\r\n  margin: 30px;\r\n  justify-content: center;\r\n  text-align: center;\r\n}\r\n\r\n.router-div {\r\n  width: 200px;\r\n  height: 200px\r\n}\r\n\r\n.card-style:hover {\r\n  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.3), 0 6px 20px 0 rgba(0, 0, 0, 0.2);\r\n}\r\n</style>\r\n","<template>\r\n  <div>\r\n    <v-card class=\"user-filter-card pa-5 elevation-3\">\r\n      <v-row>\r\n        <v-col\r\n          cols=\"12\"\r\n          sm=\"4\"\r\n        >\r\n          <v-text-field\r\n            id=\"searchIdNameTel\"\r\n            v-model=\"searchInfo.userInfo\"\r\n            :label=\"$t('search.userInfo')\"\r\n            :placeholder=\"$t('search.userInfoPlaceholder')\"\r\n            outlined\r\n          />\r\n        </v-col>\r\n\r\n        <v-col\r\n          cols=\"12\"\r\n          sm=\"4\"\r\n        >\r\n          <v-select\r\n            id=\"searchUserType\"\r\n            v-model=\"searchInfo.userType\"\r\n            :items=\"userTypeList\"\r\n            item-text=\"text\"\r\n            item-value=\"value\"\r\n            :label=\"$t('general.userType')\"\r\n            outlined\r\n            clearable\r\n          />\r\n        </v-col>\r\n\r\n        <v-col\r\n          cols=\"12\"\r\n          sm=\"4\"\r\n        >\r\n          <v-select\r\n            id=\"searchUserStatus\"\r\n            v-model=\"searchInfo.status\"\r\n            :items=\"statusList\"\r\n            item-text=\"text\"\r\n            item-value=\"value\"\r\n            :label=\"$t('general.status')\"\r\n            outlined\r\n            clearable\r\n          />\r\n        </v-col>\r\n\r\n        <v-col\r\n          cols=\"12\"\r\n          sm=\"4\"\r\n        >\r\n          <v-select\r\n            id=\"searchUserGender\"\r\n            v-model=\"searchInfo.gender\"\r\n            :items=\"genderList\"\r\n            item-text=\"text\"\r\n            item-value=\"value\"\r\n            :label=\"$t('general.gender')\"\r\n            outlined\r\n            clearable\r\n          />\r\n        </v-col>\r\n\r\n        <v-col\r\n          cols=\"12\"\r\n          sm=\"4\"\r\n        >\r\n          <v-dialog\r\n            ref=\"dateFromDialog\"\r\n            v-model=\"showDateFromPicker\"\r\n            :return-value.sync=\"searchInfo.joinDateFrom\"\r\n            persistent\r\n            width=\"320px\"\r\n          >\r\n            <template #activator=\"{ on, attrs }\">\r\n              <v-text-field\r\n                v-model=\"searchInfo.joinDateFrom\"\r\n                :label=\"$t('search.dateFrom')\"\r\n                readonly\r\n                outlined\r\n                clearable\r\n                v-bind=\"attrs\"\r\n                v-on=\"on\"\r\n              />\r\n            </template>\r\n            <v-date-picker\r\n              v-model=\"searchInfo.joinDateFrom\"\r\n              :locale=\"convertLocale(currentLocale, 'bcp47')\"\r\n              :max=\"searchInfo.joinDateEnd\"\r\n              scrollable\r\n              @input=\"setDate(searchInfo.joinDateFrom, 'dateFromDialog', showDateFromPicker)\"\r\n            />\r\n          </v-dialog>\r\n        </v-col>\r\n\r\n        <v-col\r\n          cols=\"12\"\r\n          sm=\"4\"\r\n        >\r\n          <v-dialog\r\n            ref=\"dateEndDialog\"\r\n            v-model=\"showDateEndPicker\"\r\n            :return-value.sync=\"searchInfo.joinDateEnd\"\r\n            persistent\r\n            width=\"320px\"\r\n          >\r\n            <template #activator=\"{ on, attrs }\">\r\n              <v-text-field\r\n                v-model=\"searchInfo.joinDateEnd\"\r\n                :label=\"$t('search.dateEnd')\"\r\n                readonly\r\n                outlined\r\n                clearable\r\n                v-bind=\"attrs\"\r\n                v-on=\"on\"\r\n              />\r\n            </template>\r\n            <v-date-picker\r\n              v-model=\"searchInfo.joinDateEnd\"\r\n              :locale=\"convertLocale(currentLocale, 'bcp47')\"\r\n              :min=\"searchInfo.joinDateFrom\"\r\n              scrollable\r\n              @input=\"setDate(searchInfo.joinDateEnd, 'dateEndDialog', showDateEndPicker)\"\r\n            />\r\n          </v-dialog>\r\n        </v-col>\r\n      </v-row>\r\n\r\n      <v-card-actions>\r\n        <v-btn\r\n          color=\"primary\"\r\n          @click=\"search()\"\r\n        >\r\n          {{ $t('common.search') }}\r\n        </v-btn>\r\n        <v-btn\r\n          color=\"accent darken-3\"\r\n          @click=\"clear()\"\r\n        >\r\n          {{ $t('common.clear') }}\r\n        </v-btn>\r\n        <v-btn\r\n          color=\"secondary\"\r\n          @click=\"add()\"\r\n        >\r\n          {{ $t('common.add', {item: null}) }}\r\n        </v-btn>\r\n      </v-card-actions>\r\n    </v-card>\r\n  </div>\r\n</template>\r\n\r\n<i18n src=\"./locales/en.json\"></i18n>\r\n<i18n src=\"./locales/zhHant.json\"></i18n>\r\n\r\n<script>\r\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\r\n\r\nexport default {\r\n  name: 'UserFilter',\r\n  mixins: [ErrorDisplay],\r\n  data: function () {\r\n    return {\r\n      searchInfo: {\r\n        userInfo: null,\r\n        userType: null,\r\n        status: null,\r\n        gender: null,\r\n        joinDateFrom: null,\r\n        joinDateEnd: null\r\n      },\r\n      userTypeList: [\r\n        { value: 'usr', text: this.$t('general.user') },\r\n        { value: 'adm', text: this.$t('general.admin') }\r\n      ],\r\n      statusList: [\r\n        { value: 0, text: this.$t('general.inactive') },\r\n        { value: 1, text: this.$t('general.active') },\r\n        { value: -1, text: this.$t('general.banned') }\r\n      ],\r\n      genderList: [\r\n        { value: 0, text: this.$t('general.male') },\r\n        { value: 1, text: this.$t('general.female') }\r\n      ],\r\n      showDateFromPicker: false,\r\n      showDateEndPicker: false\r\n    }\r\n  },\r\n  computed: {\r\n  },\r\n  mounted () {\r\n  },\r\n  methods: {\r\n    setDate (date, ref, modal) {\r\n      this.$refs[ref].save(date)\r\n      modal = false\r\n    },\r\n    search () {\r\n      this.$emit('search', this.searchInfo)\r\n    },\r\n    add () {\r\n      this.$emit('add')\r\n    },\r\n    clear () {\r\n      for (const key in this.searchInfo) {\r\n        this.searchInfo[key] = null\r\n      }\r\n      this.$emit('clear')\r\n    }\r\n  }\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n  .user-filter-card {\r\n    width: 100%\r\n  }\r\n</style>\r\n","<template>\r\n  <div>\r\n    <v-card class=\"user-list pa-5 elevation-3\">\r\n      <v-data-table\r\n        :headers=\"headers\"\r\n        :items=\"userList\"\r\n        :items-per-page=\"10\"\r\n        multi-sort\r\n      >\r\n        <template #[`item.user_type`]=\"{ item }\">\r\n          {{ formatUserType(item.user_type) }}\r\n        </template>\r\n\r\n        <template #[`item.gender`]=\"{ item }\">\r\n          {{ formatGender(item.gender) }}\r\n        </template>\r\n\r\n        <template #[`item.status`]=\"{ item }\">\r\n          {{ formatStatus(item.status) }}\r\n        </template>\r\n\r\n        <template #[`item.created_at`]=\"{ item }\">\r\n          {{ formatDate(item.created_at) }}\r\n        </template>\r\n\r\n        <template #[`item.actions`]=\"{ item }\">\r\n          <v-icon\r\n            class=\"mr-2\"\r\n            color=\"primary\"\r\n            :title=\"$t('common.edit', {item: null})\"\r\n            @click=\"detail(item)\"\r\n          >\r\n            mdi-pencil\r\n          </v-icon>\r\n          <v-icon\r\n            color=\"error\"\r\n            :title=\"$t('common.delete')\"\r\n            @click=\"del(item)\"\r\n          >\r\n            mdi-delete\r\n          </v-icon>\r\n        </template>\r\n      </v-data-table>\r\n    </v-card>\r\n  </div>\r\n</template>\r\n\r\n<i18n src=\"./locales/en.json\"></i18n>\r\n<i18n src=\"./locales/zhHant.json\"></i18n>\r\n\r\n<script>\r\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\r\nimport moment from 'moment'\r\n\r\nexport default {\r\n  name: 'UserList',\r\n  mixins: [ErrorDisplay],\r\n  props: {\r\n    userList: {\r\n      type: Array,\r\n      default: () => { return [] }\r\n    }\r\n  },\r\n  data: function () {\r\n    return {\r\n      headers: [\r\n        { text: this.$t('general.username'), value: 'login_id' },\r\n        { text: this.$t('general.name'), value: 'name' },\r\n        { text: this.$t('general.tel'), value: 'tel' },\r\n        { text: this.$t('general.userType'), value: 'user_type' },\r\n        { text: this.$t('general.status'), value: 'status' },\r\n        { text: this.$t('general.gender'), value: 'gender' },\r\n        { text: this.$t('general.joinDate'), value: 'created_at' },\r\n        { text: this.$t('common.actions'), value: 'actions' }\r\n      ]\r\n    }\r\n  },\r\n  computed: {\r\n  },\r\n  mounted () {\r\n  },\r\n  methods: {\r\n    formatUserType (userType) {\r\n      if (userType === 'usr') return this.$t('general.user')\r\n      if (userType === 'adm') return this.$t('general.admin')\r\n      return null\r\n    },\r\n    formatGender (gender) {\r\n      if (gender === 0) return this.$t('general.male')\r\n      if (gender === 1) return this.$t('general.female')\r\n      return null\r\n    },\r\n    formatStatus (status) {\r\n      if (status === 0) return this.$t('general.inactive')\r\n      if (status === 1) return this.$t('general.active')\r\n      if (status === -1) return this.$t('general.banned')\r\n      return null\r\n    },\r\n    formatDate (createdAt) {\r\n      moment.locale(this.convertLocale(this.currentLocale, 'bcp47'))\r\n      if (moment(createdAt).isValid()) return moment(createdAt).format('LLL')\r\n      return null\r\n    },\r\n    detail (item) {\r\n      this.$emit('detail', item)\r\n    },\r\n    del (item) {\r\n      this.$emit('del', item)\r\n    }\r\n  }\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.user-list {\r\n  width: 100%\r\n}\r\n</style>\r\n","<template>\r\n  <div class=\"max-width\">\r\n    <v-row class=\"my-4\">\r\n      <AdminUserFilter\r\n        class=\"max-width\"\r\n        @search=\"search($event)\"\r\n        @add=\"add($event)\"\r\n        @clear=\"clear($event)\"\r\n      />\r\n    </v-row>\r\n    <v-row class=\"my-4\">\r\n      <AdminUserList\r\n        class=\"max-width\"\r\n        :user-list=\"userList\"\r\n        @detail=\"detail($event)\"\r\n        @del=\"del($event)\"\r\n      />\r\n    </v-row>\r\n  </div>\r\n</template>\r\n\r\n<i18n src=\"./locales/en.json\"></i18n>\r\n<i18n src=\"./locales/zhHant.json\"></i18n>\r\n\r\n<script>\r\nimport AdminUserFilter from './M0001AdminUserFilter.vue'\r\nimport AdminUserList from './M0001AdminUserList.vue'\r\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\r\n\r\nexport default {\r\n  name: 'UserSearch',\r\n  components: {\r\n    AdminUserFilter,\r\n    AdminUserList\r\n  },\r\n  mixins: [ErrorDisplay],\r\n  props: {\r\n    userList: {\r\n      type: Array,\r\n      default: () => { return [] }\r\n    }\r\n  },\r\n  data: function () {\r\n    return {\r\n    }\r\n  },\r\n  computed: {\r\n  },\r\n  mounted () {\r\n  },\r\n  methods: {\r\n    search (event) {\r\n      this.$emit('search', event)\r\n    },\r\n    detail (event) {\r\n      this.$emit('detail', event)\r\n    },\r\n    add (event) {\r\n      this.$emit('add', event)\r\n    },\r\n    del (event) {\r\n      this.$emit('del', event)\r\n    },\r\n    clear (event) {\r\n      this.$emit('clear', event)\r\n    }\r\n  }\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.max-width {\r\n  width: 100%\r\n}\r\n</style>\r\n","<template>\r\n  <v-container>\r\n    <v-row justify=\"center\">\r\n      <v-img\r\n        v-if=\"userInfo.icon\"\r\n        class=\"user-profile\"\r\n        :src=\"userInfo.icon\"\r\n        max-width=\"200\"\r\n        max-height=\"200\"\r\n      />\r\n      <v-icon\r\n        v-else\r\n        class=\"user-profile-placeholder\"\r\n        size=\"100\"\r\n      >\r\n        fa-user\r\n      </v-icon>\r\n    </v-row>\r\n    <v-row>\r\n      <v-col\r\n        cols=\"12\"\r\n        sm=\"10\"\r\n      >\r\n        <v-text-field\r\n          id=\"editEmail\"\r\n          v-model=\"userInfo.login_id\"\r\n          :label=\"$t('edit.email')\"\r\n          :error=\"error.length ? (error.login_id.length && true) : false\"\r\n          :error-messages=\"error.login_id\"\r\n        />\r\n      </v-col>\r\n\r\n      <v-col\r\n        cols=\"12\"\r\n        sm=\"2\"\r\n      >\r\n        <v-select\r\n          id=\"editStatus\"\r\n          v-model=\"userInfo.status\"\r\n          :items=\"statusList\"\r\n          item-text=\"text\"\r\n          item-value=\"value\"\r\n          :label=\"$t('general.status')\"\r\n          :error=\"error.length ? (error.status.length && true) : false\"\r\n          :error-messages=\"error.status\"\r\n        />\r\n      </v-col>\r\n    </v-row>\r\n    <v-row>\r\n      <v-col\r\n        cols=\"12\"\r\n        sm=\"5\"\r\n      >\r\n        <v-text-field\r\n          id=\"editName\"\r\n          v-model=\"userInfo.name\"\r\n          :label=\"$t('general.name')\"\r\n          :error=\"error.length ? (error.name.length && true) : false\"\r\n          :error-messages=\"error.name\"\r\n        />\r\n      </v-col>\r\n\r\n      <v-col\r\n        cols=\"12\"\r\n        sm=\"5\"\r\n      >\r\n        <v-text-field\r\n          id=\"editTel\"\r\n          v-model=\"userInfo.tel\"\r\n          :label=\"$t('general.tel')\"\r\n          :error=\"error.length ? (error.tel.length && true) : false\"\r\n          :error-messages=\"error.tel\"\r\n        />\r\n      </v-col>\r\n\r\n      <v-col\r\n        cols=\"12\"\r\n        sm=\"2\"\r\n      >\r\n        <v-select\r\n          id=\"editUserType\"\r\n          v-model=\"userInfo.user_type\"\r\n          :items=\"userTypeList\"\r\n          item-text=\"text\"\r\n          item-value=\"value\"\r\n          :label=\"$t('general.userType')\"\r\n          :error=\"error.length ? (error.user_type.length && true) : false\"\r\n          :error-messages=\"error.user_type\"\r\n        />\r\n      </v-col>\r\n    </v-row>\r\n    <v-row>\r\n      <v-col\r\n        v-if=\"userInfo.id\"\r\n        cols=\"12\"\r\n        sm=\"5\"\r\n      >\r\n        <v-text-field\r\n          id=\"editJoinDate\"\r\n          v-model=\"userInfo.created_at\"\r\n          :label=\"$t('general.joinDate')\"\r\n          disabled\r\n          readonly\r\n        />\r\n      </v-col>\r\n\r\n      <v-col\r\n        v-if=\"!userInfo.id\"\r\n        cols=\"12\"\r\n        sm=\"5\"\r\n      >\r\n        <v-text-field\r\n          id=\"editPassword\"\r\n          v-model=\"userInfo.password\"\r\n          :label=\"$t('general.password')\"\r\n          :error=\"error.length ? (error.password.length && true) : false\"\r\n          :error-messages=\"error.password\"\r\n          type=\"password\"\r\n        />\r\n      </v-col>\r\n\r\n      <v-col\r\n        cols=\"12\"\r\n        sm=\"5\"\r\n      >\r\n        <v-dialog\r\n          ref=\"birthdayDialog\"\r\n          v-model=\"showBirthdayPicker\"\r\n          :return-value.sync=\"userInfo.birthday\"\r\n          persistent\r\n          width=\"320px\"\r\n        >\r\n          <template #activator=\"{ on, attrs }\">\r\n            <v-text-field\r\n              v-model=\"userInfo.birthday\"\r\n              :label=\"$t('general.birthday')\"\r\n              readonly\r\n              clearable\r\n              v-bind=\"attrs\"\r\n              v-on=\"on\"\r\n            />\r\n          </template>\r\n          <v-date-picker\r\n            v-model=\"userInfo.birthday\"\r\n            :locale=\"convertLocale(currentLocale, 'bcp47')\"\r\n            scrollable\r\n            @input=\"setDate(userInfo.birthday, 'birthdayDialog', showBirthdayPicker)\"\r\n          />\r\n        </v-dialog>\r\n      </v-col>\r\n\r\n      <v-col\r\n        cols=\"12\"\r\n        sm=\"2\"\r\n      >\r\n        <v-select\r\n          id=\"editGender\"\r\n          v-model=\"userInfo.gender\"\r\n          :items=\"genderList\"\r\n          item-text=\"text\"\r\n          item-value=\"value\"\r\n          :label=\"$t('general.gender')\"\r\n        />\r\n      </v-col>\r\n    </v-row>\r\n    <v-row>\r\n      <v-spacer />\r\n      <v-btn\r\n        class=\"ma-3\"\r\n        color=\"secondary\"\r\n        @click=\"back()\"\r\n      >\r\n        {{ $t('common.back') }}\r\n      </v-btn>\r\n      <v-btn\r\n        v-if=\"userInfo.id\"\r\n        class=\"ma-3\"\r\n        color=\"error\"\r\n        @click=\"del()\"\r\n      >\r\n        {{ $t('common.delete') }}\r\n      </v-btn>\r\n      <v-btn\r\n        class=\"ma-3\"\r\n        color=\"success\"\r\n        @click=\"edit()\"\r\n      >\r\n        {{ $t('common.save') }}\r\n      </v-btn>\r\n    </v-row>\r\n  </v-container>\r\n</template>\r\n\r\n<i18n src=\"./locales/en.json\"></i18n>\r\n<i18n src=\"./locales/zhHant.json\"></i18n>\r\n\r\n<script>\r\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\r\nimport SysUtils from '@/base/utils/SysUtils'\r\nimport moment from 'moment'\r\n\r\nexport default {\r\n  name: 'UserEdit',\r\n  mixins: [ErrorDisplay],\r\n  props: {\r\n    userDetails: {\r\n      type: Object,\r\n      default: () => { return {} }\r\n    },\r\n    validation: {\r\n      type: Object,\r\n      default: () => { return {} }\r\n    }\r\n  },\r\n  data: function () {\r\n    return {\r\n      userInfo: {},\r\n      error: {},\r\n      showBirthdayPicker: false,\r\n      userTypeList: [\r\n        { value: 'usr', text: this.$t('general.user') },\r\n        { value: 'adm', text: this.$t('general.admin') }\r\n      ],\r\n      statusList: [\r\n        { value: 0, text: this.$t('general.inactive') },\r\n        { value: 1, text: this.$t('general.active') },\r\n        { value: -1, text: this.$t('general.banned') }\r\n      ],\r\n      genderList: [\r\n        { value: 0, text: this.$t('general.male') },\r\n        { value: 1, text: this.$t('general.female') }\r\n      ]\r\n    }\r\n  },\r\n  watch: {\r\n    userDetails: {\r\n      deep: true,\r\n      handler (val) {\r\n        if (val) this.userInfo = JSON.parse(JSON.stringify(val))\r\n        this.userInfo.created_at = this.formatDate(this.userInfo.created_at)\r\n      }\r\n    }\r\n  },\r\n  mounted () {\r\n    this.init()\r\n  },\r\n  methods: {\r\n    init () {\r\n      this.userInfo = {\r\n        id: null,\r\n        login_id: null,\r\n        status: null,\r\n        name: null,\r\n        tel: null,\r\n        user_type: null,\r\n        created_at: null,\r\n        password: null,\r\n        birthday: null,\r\n        gender: null,\r\n        icon: null\r\n      }\r\n      this.error = {}\r\n    },\r\n    back () {\r\n      this.init()\r\n      this.$emit('back')\r\n    },\r\n    edit () {\r\n      this.error = {}\r\n      SysUtils.validate(this.userInfo, this.validation)\r\n        .then(validated => {\r\n          if (validated.valid) {\r\n            this.$emit('edit', JSON.parse(JSON.stringify(this.userInfo)))\r\n          } else {\r\n            this.error = validated.results\r\n          }\r\n        })\r\n    },\r\n    del () {\r\n      this.$emit('del', JSON.parse(JSON.stringify(this.userInfo)))\r\n    },\r\n    formatDate (createdAt) {\r\n      moment.locale(this.convertLocale(this.currentLocale, 'bcp47'))\r\n      if (moment(createdAt).isValid()) return moment(createdAt).format('LLL')\r\n      return null\r\n    },\r\n    setDate (date, ref, modal) {\r\n      this.$refs[ref].save(date)\r\n      modal = false\r\n    }\r\n  }\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.user-profile, .user-profile-placeholder{\r\n  border: 5px solid var(--v-primary-base);\r\n}\r\n\r\n.user-profile-placeholder{\r\n  width: 180px;\r\n  height: 180px;\r\n}\r\n</style>\r\n","<template>\r\n  <v-container>\r\n    <ScreenLoading :show=\"showLoading\" />\r\n    <v-row class=\"title text-h5 text-uppercase\">\r\n      <v-icon>fa-user</v-icon> &nbsp;\r\n      {{ editPage ? $t('index.titleEdit') : $t('index.titleSearch') }}\r\n    </v-row>\r\n    <v-row class=\"content max-width\">\r\n      <AdminUserSearch\r\n        v-show=\"!editPage\"\r\n        :user-list=\"userList\"\r\n        @search=\"search($event)\"\r\n        @add=\"add($event)\"\r\n        @detail=\"detail($event)\"\r\n        @del=\"del($event)\"\r\n        @clear=\"clear($event)\"\r\n      />\r\n      <AdminUserEdit\r\n        v-show=\"editPage\"\r\n        ref=\"userEdit\"\r\n        :user-details=\"userDetails\"\r\n        :validation=\"validations.edit\"\r\n        @edit=\"edit($event)\"\r\n        @del=\"del($event)\"\r\n        @back=\"back($event)\"\r\n      />\r\n    </v-row>\r\n    <Snackbar\r\n      v-model=\"showSnackbar\"\r\n      :text=\"snackbarText\"\r\n      :color=\"snackbarColor\"\r\n      top\r\n      right\r\n    />\r\n  </v-container>\r\n</template>\r\n\r\n<i18n src=\"./locales/en.json\"></i18n>\r\n<i18n src=\"./locales/zhHant.json\"></i18n>\r\n\r\n<script>\r\nimport AdminUserSearch from './M0001AdminUserSearch.vue'\r\nimport AdminUserEdit from './M0001AdminUserEdit.vue'\r\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\r\nimport DialogOptions from '@/components/functions/Common/mixins/DialogOptions'\r\nimport ScreenLoading from '@/base/components/atoms/AtScreenLoading'\r\nimport Snackbar from '@/components/functions/Common/plugins/Snackbar'\r\n\r\nexport default {\r\n  name: 'UserIndex',\r\n  components: {\r\n    AdminUserSearch,\r\n    AdminUserEdit,\r\n    ScreenLoading,\r\n    Snackbar\r\n  },\r\n  mixins: [ErrorDisplay, DialogOptions],\r\n  data: function () {\r\n    return {\r\n      showLoading: false,\r\n      showSnackbar: false,\r\n      snackbarText: '',\r\n      snackbarColor: 'success',\r\n      editPage: false,\r\n      searchCondCache: {}\r\n    }\r\n  },\r\n  computed: {\r\n    userList () {\r\n      return this.$store.state.M0001AdminUser.userList\r\n    },\r\n    userDetails () {\r\n      return this.$store.state.M0001AdminUser.userDetails\r\n    },\r\n    validations () {\r\n      return this.$store.state.M0001AdminUser.validations\r\n    }\r\n  },\r\n  mounted () {\r\n    this.$emit('pageName', this.$t('pageName'))\r\n    this.init()\r\n  },\r\n  methods: {\r\n    init () {\r\n      this.showLoading = true\r\n      this.$store.dispatch('M0001AdminUser/init', {})\r\n        .then(() => {\r\n          this.showLoading = false\r\n        }).catch((err) => {\r\n          this.showLoading = false\r\n          this.showError(err)\r\n        })\r\n    },\r\n    search (event) {\r\n      this.showLoading = true\r\n      this.$store.dispatch('M0001AdminUser/search', event)\r\n        .then(() => {\r\n          this.showLoading = false\r\n          this.searchCondCache = JSON.parse(JSON.stringify(event))\r\n        }).catch((err) => {\r\n          this.showLoading = false\r\n          this.showError(err)\r\n        })\r\n    },\r\n    add (event) {\r\n      this.editPage = true\r\n    },\r\n    detail (event) {\r\n      this.showLoading = true\r\n      this.$store.dispatch('M0001AdminUser/detail', { id: event.id })\r\n        .then(() => {\r\n          this.showLoading = false\r\n          this.editPage = true\r\n        }).catch((err) => {\r\n          this.showLoading = false\r\n          this.showError(err)\r\n        })\r\n    },\r\n    edit (event) {\r\n      this.showLoading = true\r\n      this.$store.dispatch('M0001AdminUser/edit', event)\r\n        .then(() => {\r\n          this.showLoading = false\r\n          this.editPage = false\r\n          this.$refs.userEdit.init()\r\n          this.search(this.searchCondCache)\r\n          this.snackbarText = (event.id ? this.$t('edit.editSuccess') : this.$t('edit.addSuccess'))\r\n          this.showSnackbar = true\r\n        }).catch((err) => {\r\n          console.log(err)\r\n          let showErr = true\r\n          this.showLoading = false\r\n          if (err.message === '0001') err.message = this.$t('error.duplicateId')\r\n          else showErr = false\r\n          this.showError(err, showErr)\r\n        })\r\n    },\r\n    del (event) {\r\n      const message = {\r\n        title: this.$t('common.delete'),\r\n        body: this.$t('common.deleteConfirm', { item: event.login_id })\r\n      }\r\n\r\n      this.$dialog.confirm(message, this.dialogOptions)\r\n        .then((dialog) => {\r\n          this.showLoading = true\r\n          this.$store.dispatch('M0001AdminUser/delete', { id: event.id })\r\n            .then(() => {\r\n              this.showLoading = false\r\n              this.editPage = false\r\n              this.$refs.userEdit.init()\r\n              this.search(this.searchCondCache)\r\n              this.snackbarText = this.$t('edit.deleteSuccess')\r\n              this.showSnackbar = true\r\n            }).catch((err) => {\r\n              this.showLoading = false\r\n              this.showError(err)\r\n            })\r\n        })\r\n    },\r\n    back (event) {\r\n      this.editPage = false\r\n    },\r\n    clear (event) {\r\n      this.$store.dispatch('M0001AdminUser/clear')\r\n    }\r\n  }\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.title, .content {\r\n  margin: 20px;\r\n}\r\n\r\n.max-width {\r\n  width: 100%\r\n}\r\n</style>\r\n","<template>\n  <div>\n    <v-card class=\"user-filter-card pa-5 elevation-3\">\n      <v-row>\n        <v-col\n          cols=\"12\"\n          sm=\"4\"\n        >\n          <v-text-field\n            id=\"searchUsername\"\n            v-model=\"searchInfo.username\"\n            :label=\"$t('search.username')\"\n            :placeholder=\"$t('search.usernamePlaceholder')\"\n            outlined\n          />\n        </v-col>\n\n        <v-col\n          cols=\"12\"\n          sm=\"4\"\n        >\n          <v-text-field\n            id=\"searchScanSn\"\n            v-model=\"searchInfo.scanSn\"\n            :label=\"$t('search.scanSn')\"\n            :placeholder=\"$t('search.scanSnPlaceholder')\"\n            outlined\n          />\n        </v-col>\n\n        <v-col\n          cols=\"12\"\n          sm=\"4\"\n        >\n          <v-select\n            id=\"searchScanType\"\n            v-model=\"searchInfo.scanType\"\n            :items=\"scanTypeList\"\n            item-text=\"text\"\n            item-value=\"value\"\n            :label=\"$t('general.scanType')\"\n            outlined\n            clearable\n          />\n        </v-col>\n\n        <v-col\n          cols=\"12\"\n          sm=\"4\"\n        >\n          <v-dialog\n            ref=\"dateFromDialog\"\n            v-model=\"showDateFromPicker\"\n            :return-value.sync=\"searchInfo.scanDateFrom\"\n            width=\"320px\"\n          >\n            <template #activator=\"{ on, attrs }\">\n              <v-text-field\n                v-model=\"searchInfo.scanDateFrom\"\n                :label=\"$t('search.dateFrom')\"\n                readonly\n                outlined\n                clearable\n                v-bind=\"attrs\"\n                v-on=\"on\"\n              />\n            </template>\n            <v-date-picker\n              v-model=\"searchInfo.scanDateFrom\"\n              :locale=\"convertLocale(currentLocale, 'bcp47')\"\n              :max=\"searchInfo.scanDateEnd\"\n              scrollable\n              @input=\"setDate(searchInfo.scanDateFrom, 'dateFromDialog', showDateFromPicker)\"\n            />\n          </v-dialog>\n        </v-col>\n\n        <v-col\n          cols=\"12\"\n          sm=\"4\"\n        >\n          <v-dialog\n            ref=\"dateEndDialog\"\n            v-model=\"showDateEndPicker\"\n            :return-value.sync=\"searchInfo.scanDateEnd\"\n            width=\"320px\"\n          >\n            <template #activator=\"{ on, attrs }\">\n              <v-text-field\n                v-model=\"searchInfo.scanDateEnd\"\n                :label=\"$t('search.dateEnd')\"\n                readonly\n                outlined\n                clearable\n                v-bind=\"attrs\"\n                v-on=\"on\"\n              />\n            </template>\n            <v-date-picker\n              v-model=\"searchInfo.scanDateEnd\"\n              :locale=\"convertLocale(currentLocale, 'bcp47')\"\n              :min=\"searchInfo.scanDateFrom\"\n              scrollable\n              @input=\"setDate(searchInfo.scanDateEnd, 'dateEndDialog', showDateEndPicker)\"\n            />\n          </v-dialog>\n        </v-col>\n      </v-row>\n\n      <v-card-actions>\n        <v-btn\n          color=\"primary\"\n          @click=\"search()\"\n        >\n          {{ $t('common.search') }}\n        </v-btn>\n        <v-btn\n          color=\"accent darken-3\"\n          @click=\"clear()\"\n        >\n          {{ $t('common.clear') }}\n        </v-btn>\n      </v-card-actions>\n    </v-card>\n  </div>\n</template>\n\n<i18n src=\"./locales/en.json\"></i18n>\n<i18n src=\"./locales/zhHant.json\"></i18n>\n\n<script>\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\n\nexport default {\n  name: 'ScanRecordFilter',\n  mixins: [ErrorDisplay],\n  data: function () {\n    return {\n      searchInfo: {\n        username: null,\n        scanSn: null,\n        scanType: null,\n        scanDateFrom: null,\n        scanDateEnd: null\n      },\n      scanTypeList: [\n        { value: 'product', text: this.$t('general.product') },\n        { value: 'certificate', text: this.$t('general.certificate') }\n      ],\n      showDateFromPicker: false,\n      showDateEndPicker: false\n    }\n  },\n  computed: {\n  },\n  mounted () {\n  },\n  methods: {\n    setDate (date, ref, modal) {\n      this.$refs[ref].save(date)\n      modal = false\n    },\n    search () {\n      this.$emit('search', this.searchInfo)\n    },\n    add () {\n      this.$emit('add')\n    },\n    clear () {\n      for (const key in this.searchInfo) {\n        this.searchInfo[key] = null\n      }\n      this.$emit('clear')\n    }\n  }\n}\n</script>\n\n<style scoped>\n  .user-filter-card {\n    width: 100%\n  }\n</style>\n","<template>\n  <div>\n    <v-card class=\"scan-record-list pa-5 elevation-3\">\n      <v-data-table\n        :headers=\"headers\"\n        :items=\"scanRecordList\"\n        :items-per-page=\"10\"\n        multi-sort\n      >\n        <template #[`item.login_id`]=\"{ item }\">\n          <div\n            style=\"cursor:pointer\"\n            :title=\"$t('general.detail', {item: null})\"\n            @click=\"detail(item)\"\n          >\n            <v-icon\n              class=\"mr-2\"\n              color=\"primary\"\n            >\n              mdi-account-details\n            </v-icon>\n            {{ item.login_id }}\n          </div>\n        </template>\n        <template #[`item.scan_type`]=\"{ item }\">\n          <v-chip\n            v-if=\"item.scan_type\"\n            :color=\"getColor(item.scan_type)\"\n            dark\n          >\n            {{ formatScanType(item.scan_type) }}\n          </v-chip>\n        </template>\n        <template #[`item.created_at`]=\"{ item }\">\n          {{ formatDate(item.created_at) }}\n        </template>\n      </v-data-table>\n    </v-card>\n  </div>\n</template>\n\n<i18n src=\"./locales/en.json\"></i18n>\n<i18n src=\"./locales/zhHant.json\"></i18n>\n\n<script>\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\nimport moment from 'moment'\n\nexport default {\n  name: 'ScanRecordList',\n  mixins: [ErrorDisplay],\n  props: {\n    scanRecordList: {\n      type: Array,\n      default: () => { return [] }\n    }\n  },\n  data: function () {\n    return {\n      headers: [\n        { text: this.$t('general.username'), value: 'login_id' },\n        { text: this.$t('general.scanSn'), value: 'scan_sn' },\n        { text: this.$t('general.scanType'), value: 'scan_type' },\n        { text: this.$t('general.scanDate'), value: 'created_at' }\n      ]\n    }\n  },\n  computed: {\n  },\n  mounted () {\n  },\n  methods: {\n    formatScanType (scanType) {\n      if (scanType === 'product') return this.$t('general.product')\n      if (scanType === 'certificate') return this.$t('general.certificate')\n      return null\n    },\n    getColor (scanType) {\n      if (scanType === 'product') return 'green'\n      if (scanType === 'certificate') return 'blue'\n      return null\n    },\n    formatDate (createdAt) {\n      moment.locale(this.convertLocale(this.currentLocale, 'bcp47'))\n      if (moment(createdAt).isValid()) return moment(createdAt).format('LLL')\n      return null\n    },\n    detail (item) {\n      this.$emit('detail', item)\n    }\n  }\n}\n</script>\n\n<style scoped>\n.scan-record-list {\n  width: 100%\n}\n</style>\n","<template>\n  <div>\n    <v-card>\n      <v-card-title>\n        <span class=\"text-h5\">Info details</span>\n      </v-card-title>\n      <v-card-text>\n        <v-container>\n          <v-card>\n            <v-row justify=\"center\">\n              <v-img\n                v-if=\"row.icon\"\n                class=\"user-profile\"\n                :src=\"row.icon\"\n                max-width=\"200\"\n                max-height=\"200\"\n              />\n              <v-icon\n                v-else\n                class=\"user-profile-placeholder\"\n                size=\"100\"\n              >\n                fa-user\n              </v-icon>\n            </v-row>\n            <v-card-title class=\"subheading font-weight-bold\">\n              {{ row.login_id }}\n            </v-card-title>\n\n            <v-divider />\n\n            <v-list dense>\n              <v-list-item\n                v-for=\"header in headers\"\n                :key=\"header.id\"\n              >\n                <v-list-item-content>{{ header.text }}</v-list-item-content>\n                <v-list-item-content class=\"align-end\">\n                  <div v-if=\"header.value == 'user_type'\">\n                    {{ formatUserType(row[header.value]) }}\n                  </div>\n                  <div v-else-if=\"header.value == 'gender'\">\n                    {{ formatGender(row[header.value]) }}\n                  </div>\n                  <div v-else-if=\"header.value == 'status'\">\n                    {{ formatStatus(row[header.value]) }}\n                  </div>\n                  <div v-else>\n                    {{ row[header.value] }}\n                  </div>\n                </v-list-item-content>\n              </v-list-item>\n            </v-list>\n          </v-card>\n        </v-container>\n      </v-card-text>\n    </v-card>\n  </div>\n</template>\n\n<i18n src=\"./locales/en.json\"></i18n>\n<i18n src=\"./locales/zhHant.json\"></i18n>\n\n<script>\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\nimport moment from 'moment'\n\nexport default {\n  name: 'ScanRecordUserDetails',\n  components: {},\n  mixins: [ErrorDisplay],\n  props: {\n    row: {\n      type: Object,\n      default: () => {\n        return {}\n      }\n    }\n  },\n  data: function () {\n    return {\n      headers: [\n        { text: this.$t('general.name'), value: 'name' },\n        { text: this.$t('general.tel'), value: 'tel' },\n        { text: this.$t('general.userType'), value: 'user_type' },\n        { text: this.$t('general.status'), value: 'status' },\n        { text: this.$t('general.gender'), value: 'gender' },\n        { text: this.$t('general.joinDate'), value: 'joined_at' }\n      ]\n    }\n  },\n  computed: {},\n  mounted () {},\n  methods: {\n    formatUserType (userType) {\n      if (userType === 'usr') return this.$t('general.user')\n      if (userType === 'adm') return this.$t('general.admin')\n      return null\n    },\n    formatGender (gender) {\n      if (gender === 0) return this.$t('general.male')\n      if (gender === 1) return this.$t('general.female')\n      return null\n    },\n    formatStatus (status) {\n      if (status === 0) return this.$t('general.inactive')\n      if (status === 1) return this.$t('general.active')\n      if (status === -1) return this.$t('general.banned')\n      return null\n    },\n    formatDate (createdAt) {\n      moment.locale(this.convertLocale(this.currentLocale, 'bcp47'))\n      if (moment(createdAt).isValid()) return moment(createdAt).format('LLL')\n      return null\n    }\n  }\n}\n</script>\n\n<style scoped>\n.max-width {\n  width: 100%;\n}\n</style>\n","<template>\n  <div class=\"max-width\">\n    <v-row class=\"my-4\">\n      <ScanRecordFilter\n        class=\"max-width\"\n        @search=\"search($event)\"\n        @clear=\"clear($event)\"\n      />\n    </v-row>\n    <v-row class=\"my-4\">\n      <ScanRecordList\n        class=\"max-width\"\n        :scan-record-list=\"scanRecordList\"\n        @detail=\"detail\"\n      />\n    </v-row>\n    <v-row justify=\"center\">\n      <v-dialog\n        v-model=\"dialog\"\n        max-width=\"600px\"\n      >\n        <ScanRecordUserDetails\n          :row=\"row\"\n        />\n      </v-dialog>\n    </v-row>\n  </div>\n</template>\n\n<i18n src=\"./locales/en.json\"></i18n>\n<i18n src=\"./locales/zhHant.json\"></i18n>\n\n<script>\nimport ScanRecordFilter from './M0301ScanRecordFilter.vue'\nimport ScanRecordList from './M0301ScanRecordList.vue'\nimport ScanRecordUserDetails from './M0301ScanRecordUserDetails.vue'\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\n\nexport default {\n  name: 'ScanRecordSearch',\n  components: {\n    ScanRecordFilter,\n    ScanRecordList,\n    ScanRecordUserDetails\n  },\n  mixins: [ErrorDisplay],\n  props: {\n    scanRecordList: {\n      type: Array,\n      default: () => { return [] }\n    }\n  },\n  data: function () {\n    return {\n      dialog: false,\n      row: {}\n    }\n  },\n  computed: {\n  },\n  mounted () {\n  },\n  methods: {\n    search (event) {\n      this.$emit('search', event)\n    },\n    detail (event) {\n      this.dialog = true\n      this.row = event\n    },\n    clear (event) {\n      this.$emit('clear', event)\n    }\n  }\n}\n</script>\n\n<style scoped>\n.max-width {\n  width: 100%\n}\n</style>\n","<template>\n  <v-container>\n    <ScreenLoading :show=\"showLoading\" />\n    <v-row class=\"title text-h5 text-uppercase\">\n      <v-icon>fa-qrcode</v-icon> &nbsp;\n      {{ editPage ? $t('index.titleEdit') : $t('index.titleSearch') }}\n    </v-row>\n    <v-row class=\"content max-width\">\n      <ScanRecordSearch\n        v-show=\"!editPage\"\n        :scan-record-list=\"scanRecordList\"\n        @search=\"search($event)\"\n        @add=\"add($event)\"\n        @detail=\"detail($event)\"\n        @del=\"del($event)\"\n        @clear=\"clear($event)\"\n      />\n    </v-row>\n  </v-container>\n</template>\n\n<i18n src=\"./locales/en.json\"></i18n>\n<i18n src=\"./locales/zhHant.json\"></i18n>\n\n<script>\nimport ScanRecordSearch from './M0301ScanRecordSearch.vue'\nimport ErrorDisplay from '@/components/functions/Common/mixins/ErrorDisplay'\nimport ScreenLoading from '@/base/components/atoms/AtScreenLoading'\n\nexport default {\n  name: 'ScanRecordIndex',\n  components: {\n    ScanRecordSearch,\n    ScreenLoading\n  },\n  mixins: [ErrorDisplay],\n  data: function () {\n    return {\n      showLoading: false,\n      editPage: false\n    }\n  },\n  computed: {\n    scanRecordList () {\n      return this.$store.state.M0301ScanRecord.scanRecordList\n    }\n  },\n  mounted () {\n    this.$emit('pageName', this.$t('pageName'))\n  },\n  methods: {\n    search (event) {\n      this.showLoading = true\n      this.$store.dispatch('M0301ScanRecord/search', event)\n        .then(() => {\n          this.showLoading = false\n        }).catch((err) => {\n          this.showLoading = false\n          this.showError(err)\n        })\n    },\n    add (event) {\n\n    },\n    detail (event) {\n      this.showLoading = true\n      this.$store.dispatch('M0001AdminUser/detail', { id: event.id })\n        .then(() => {\n          this.showLoading = false\n          this.editPage = true\n        }).catch((err) => {\n          this.showLoading = false\n          this.showError(err)\n        })\n    },\n    del (event) {\n\n    },\n    clear (event) {\n      this.$store.dispatch('M0301ScanRecord/clear')\n    }\n  }\n}\n</script>\n\n<style scoped>\n.title, .content {\n  margin: 20px;\n}\n\n.max-width {\n  width: 100%\n}\n</style>\n"]}