Ver Fonte

کامیت موقت

hgh há 1 ano atrás
pai
commit
c37c3f3409

+ 1 - 1
src/components/EntityIndexGridItem.vue

@@ -40,7 +40,7 @@ export default {
 <style scoped lang="scss">
 .EntityIndexGridItem {
   width: 100%;
-  margin-bottom: 8px;
+
   .table-column {
     margin-bottom: 16px;
     .label {

+ 20 - 27
src/components/Widgets/Classroom/ClassroomList/ClassroomList.vue

@@ -21,6 +21,12 @@
                 :show-expand-button="false"
                 :show-reload-button="false"
                 :show-search-button="false">
+    <template #before-form-builder>
+      <filters :unitCategories="unitCategories"
+               :units="units"
+               @onUnitCategoriesFilterChanged="onUnitCategoriesFilterChanged"
+               @onUnitsFilterChanged="onUnitsFilterChanged" />
+    </template>
     <template #entity-index-table-cell="{inputData}">
       <template v-if="inputData.col.name === 'number'">
         {{ inputData.rowNumber }}
@@ -49,22 +55,19 @@
 </template>
 
 <script>
-import { shallowRef } from 'vue'
 import { EntityIndex } from 'quasar-crud'
 import Enums from 'src/assets/Enums/Enums.js'
 import { Invoice } from 'src/models/Invoice.js'
 import ShamsiDate from 'src/assets/ShamsiDate.js'
 import { APIGateway } from 'src/api/APIGateway.js'
 import { FormBuilderAssist } from 'quasar-form-builder'
-import BtnControl from 'src/components/Control/btn.vue'
 import { Registration } from 'src/models/Registration.js'
 import { mixinAuth, mixinWidget } from 'src/mixin/Mixins.js'
 import UserClassroomCard from 'src/components/Widgets/Classroom/UserClassroomCard/UserClassroomCard.vue'
 import Breadcrumbs from 'src/components/Widgets/Breadcrumbs/Breadcrumbs.vue'
 import { TranscriptSheet } from 'src/models/TranscriptSheet'
 import FormBuilderBarCode from 'src/components/FormBuilderCustumComponents/FormBuilderBarCode.vue'
-
-const BtnControlComp = shallowRef(BtnControl)
+import Filters from './filters.vue'
 
 export default {
   name: 'UserPanel.Profile.AllClassrooms',
@@ -72,36 +75,19 @@ export default {
     FormBuilderBarCode,
     EntityIndex,
     Breadcrumbs,
-    UserClassroomCard
+    UserClassroomCard,
+    Filters
   },
   mixins: [mixinAuth, mixinWidget],
   data () {
     return {
       mounted: false,
+      unitCategories: [],
+      units: [],
       national_code: null,
       inputs: [
-        {
-          type: 'select',
-          name: 'category',
-          options: [],
-          value: null,
-          label: 'گروه آموزشی',
-          placeholder: ' ',
-          col: 'col-md-2 col-12'
-        },
-        {
-          type: 'select',
-          name: 'unit',
-          responseKey: 'unit',
-          options: [],
-          value: null,
-          label: 'درس',
-          placeholder: ' ',
-          col: 'col-md-2 col-12'
-        },
         { type: 'hidden', name: 'classroom__unit__category__type', value: 'TRAINING' },
-        { type: 'hidden', name: 'owner', value: null },
-        { type: BtnControlComp, name: 'btn', responseKey: 'btn', label: 'جستجو', placeholder: ' ', atClick: () => {}, col: 'col-md-2 col-12' }
+        { type: 'hidden', name: 'owner', value: null }
       ],
       api: APIGateway.registration.APIAdresses.base,
       table: {
@@ -204,7 +190,8 @@ export default {
       return 'UserPanel.Profile.ClassroomInfo'
     },
     selectedCategoryId () {
-      return this.getInputValue('category')
+      // return this.getInputValue('category')
+      return 1 // TODO:
     }
   },
   watch: {
@@ -221,6 +208,10 @@ export default {
     this.mounted = true
   },
   methods: {
+    onUnitCategoriesFilterChanged () {
+    },
+    onUnitsFilterChanged () {
+    },
     setClassroomTypeOfInputs () {
       FormBuilderAssist.setAttributeByName(this.inputs, 'classroom__unit__category__type', 'value', this.localOptions.classroomType)
 
@@ -303,6 +294,7 @@ export default {
               label: item.title
             }
           }))
+          this.unitCategories = categories.list
         })
         .catch(() => {})
     },
@@ -313,6 +305,7 @@ export default {
       })
         .then(unitList => {
           this.loadSelectOptions('unit', this.getSelectOptions(unitList.list.list, 'id', 'title'))
+          this.units = unitList.list
         })
         .catch(() => {
         })

+ 221 - 0
src/components/Widgets/Classroom/ClassroomList/filters.vue

@@ -0,0 +1,221 @@
+<template>
+  <div class="filters">
+    <div class="main-filters">
+      <div class="unitCategories">
+        <q-btn v-if="unitCategories?.list?.length > 0"
+               flat
+               class="filter-btn unitCategory filter-btn__selected">
+          <div class="filter-btn-title">
+            همه
+          </div>
+        </q-btn>
+        <q-btn v-for="(unitCategory, unitCategoryIndex) in unitCategories.list"
+               :key="unitCategoryIndex"
+               flat
+               :to="{name: showCategoryRouteName, params: {category_id: unitCategory.id}}"
+               class="filter-btn unitCategory">
+          <div class="filter-btn-title">
+            {{ unitCategory.title }}
+          </div>
+        </q-btn>
+      </div>
+      <div class="unitCategories">
+        <q-btn v-if="units?.list?.length > 0"
+               flat
+               class="filter-btn unitCategory filter-btn__selected">
+          <div class="filter-btn-title">
+            همه
+          </div>
+        </q-btn>
+        <q-btn v-for="(unit, unitIndex) in units.list"
+               :key="unitIndex"
+               flat
+               :to="{name: showCategoryRouteName, params: {category_id: unit.id}}"
+               class="filter-btn unitCategory">
+          <div class="filter-btn-title">
+            {{ unit.title }}
+          </div>
+        </q-btn>
+      </div>
+      <div class="content-type-filters" />
+    </div>
+    <div class="sub-filters">
+      <q-expansion-item v-model="subFilterExpanded"
+                        :header-style="'display: none;'">
+        <q-card class="sub-filters-card">
+          <div class="media-types">
+            <q-btn v-for="(mediaType, mediaTypeIndex) in mediaTypes"
+                   :key="mediaTypeIndex"
+                   flat
+                   class="filter-btn unitCategory"
+                   :class="{'filter-btn__selected': selectedMediaType === mediaType.value}"
+                   @click="filterMediaType(mediaType.value)">
+              <div class="filter-btn-title">
+                {{ mediaType.label }}
+              </div>
+            </q-btn>
+          </div>
+          <div class="search-input">
+            <q-input v-model="searchText"
+                     debounce="500">
+              <template #prepend>
+                <q-icon name="search" />
+              </template>
+            </q-input>
+          </div>
+        </q-card>
+      </q-expansion-item>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Media } from 'src/models/Media.js'
+import { UnitCategory, UnitCategoryList } from 'src/models/UnitCategory'
+import { UnitList } from 'src/models/Unit'
+
+export default {
+  name: 'UnitCategoryItem',
+  props: {
+    unitCategories: {
+      type: UnitCategoryList,
+      default: new UnitCategoryList()
+    },
+    units: {
+      type: UnitList,
+      default: new UnitList()
+    },
+    unitCategory: {
+      type: UnitCategory,
+      default: new UnitCategory()
+    },
+    showCategoryRouteName: {
+      type: String,
+      default: 'Public.UnitCategory.Show'
+    },
+    listType: {
+      type: String,
+      default: 'category_parent_parent'
+    }
+  },
+  emits: ['filter'],
+  data () {
+    return {
+      media: new Media(),
+      searchText: null,
+      selectedMediaType: null,
+      subFilterExpanded: false
+    }
+  },
+  computed: {
+    mediaTypes () {
+      return [{
+        label: 'همه',
+        value: null
+      }].concat(this.media.typeEnums)
+    },
+    screenGtMd () {
+      if (typeof window === 'undefined') {
+        return true
+      }
+      return this.$q.screen.gt.md
+    }
+  },
+  watch: {
+    searchText () {
+      this.emitFilters()
+    },
+    screenGtMd: {
+      handler (newValue) {
+        if (!newValue) {
+          this.$nextTick(() => {
+            this.subFilterExpanded = true
+          })
+        }
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    filterMediaType (mediaType) {
+      this.selectedMediaType = mediaType
+      this.emitFilters()
+    },
+    emitFilters () {
+      this.$emit('filter', this.getFilterObject())
+    },
+    getFilterObject () {
+      return {
+        medias__type: this.selectedMediaType,
+        search: this.searchText
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.filters {
+  .main-filters {
+    display: flex;
+    flex-direction: column;
+    gap: 8px;
+    flex-wrap: wrap;
+    justify-content: space-between;
+
+    .unitCategories {
+      display: flex;
+      gap: 8px;
+      flex-wrap: nowrap;
+      overflow-y: auto;
+      justify-content: flex-start;
+      scrollbar-width: none; // فایرفاکس
+      -ms-overflow-style: none; // IE و Edge قدیمی
+    }
+    .content-type-filters {
+
+    }
+  }
+  .sub-filters {
+    .sub-filters-card {
+      display: flex;
+      gap: 8px;
+      flex-wrap: wrap;
+      align-items: center;
+      justify-content: space-between;
+      padding-top: 12px;
+      .media-types {
+        display: flex;
+        gap: 8px;
+        flex-wrap: wrap;
+        justify-content: flex-start;
+        height: 42.63px;
+      }
+    }
+  }
+  .filter-btn {
+    border: 1px solid #000000;
+    border-radius: 20px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    background: #FFFFFF;
+    height: 43px;
+    padding: 0 8px;
+    white-space: nowrap;
+    .filter-btn-title {
+      font-size: 14px;
+      color: #212121;
+    }
+    &.filter-btn__selected {
+      background: #444444;
+      .filter-btn-title {
+        color: white;
+      }
+    }
+  }
+}
+.unitCategories::-webkit-scrollbar {
+  display: none;               // کروم و سافاری
+}
+</style>