Browse Source

fixed #184

ali 3 năm trước cách đây
mục cha
commit
bcbc02227e

+ 1 - 1
package.json

@@ -52,7 +52,7 @@
     "process": "^0.11.10",
     "quasar": "^2.12.0",
     "quasar-app-extension-q-page-builder": "^0.1.63",
-    "quasar-crud": "^0.3.53",
+    "quasar-crud": "^0.3.55",
     "quasar-form-builder": "^0.1.110",
     "quasar-template-builder": "^1.0.23",
     "quasar-ui-q-page-builder": "^0.1.63",

+ 8 - 0
src/api/APIGateway.js

@@ -3,6 +3,7 @@ import AuthAPI from 'src/api/models/Auth.js'
 import UserAPI from 'src/api/models/User.js'
 import PostAPI from 'src/api/models/Post.js'
 import UnitAPI from 'src/api/models/Unit.js'
+import TeamAPI from 'src/api/models/Team.js'
 import MediaAPI from 'src/api/models/Media.js'
 import TicketAPI from 'src/api/models/Ticket.js'
 import WalletAPI from 'src/api/models/Wallet.js'
@@ -24,6 +25,9 @@ import TicketCategoryAPI from 'src/api/models/TicketCategory.js'
 import SessionTemplateAPI from 'src/api/models/SessionTemplate.js'
 import ContentCategoryAPI from 'src/api/models/ContentCategory.js'
 import InstalmentOfferAPI from 'src/api/models/InstalmentOffer.js'
+import ClassroomGraderAPI from 'src/api/models/ClassroomGraders.js'
+import ClassroomLeadersAPI from 'src/api/models/ClassroomLeaders.js'
+import TeamRegistrationsAPI from 'src/api/models/TeamRegistrations.js'
 import ClassroomRegistrationAPI from 'src/api/models/ClassroomRegistration.js'
 import ProjectAttendanceSheetsAPI from 'src/api/models/ProjectAttendanceSheets.js'
 import SessionAttendanceSheetsAPI from 'src/api/models/SessionAttendanceSheets.js'
@@ -35,6 +39,7 @@ export const APIGateway = {
   user: new UserAPI(),
   unit: new UnitAPI(),
   post: new PostAPI(),
+  team: new TeamAPI(),
   media: new MediaAPI(),
   ticket: new TicketAPI(),
   wallet: new WalletAPI(),
@@ -56,6 +61,9 @@ export const APIGateway = {
   sessionTemplate: new SessionTemplateAPI(),
   contentCategory: new ContentCategoryAPI(),
   instalmentOffer: new InstalmentOfferAPI(),
+  classroomGrader: new ClassroomGraderAPI(),
+  classroomLeaders: new ClassroomLeadersAPI(),
+  teamRegistrations: new TeamRegistrationsAPI(),
   classroomRegistration: new ClassroomRegistrationAPI(),
   projectAttendanceSheets: new ProjectAttendanceSheetsAPI(),
   sessionAttendanceSheets: new SessionAttendanceSheetsAPI()

+ 18 - 0
src/api/models/Classroom.js

@@ -11,6 +11,7 @@ export default class ClassroomAPI extends APIRepository {
       byId: (id) => '/lma/classrooms/' + id,
       enroll: (id) => '/lma/classrooms/' + id + '/enroll',
       drop: (id) => '/lma/classrooms/' + id + '/drop',
+      leaders: (id) => '/lma/classrooms/' + id + '/leaders',
       members: '/lma/registrations',
       activitySheet: '/lma/registrations/activity_sheet',
       enrollByAdmin: (classroomId, userId) => '/lma/classrooms/' + classroomId + '/enrolll?user_id=' + userId,
@@ -97,6 +98,23 @@ export default class ClassroomAPI extends APIRepository {
     })
   }
 
+  appendLeaders (data) {
+    return this.sendRequest({
+      apiMethod: 'put',
+      api: this.api,
+      request: this.APIAdresses.leaders(data.classroomId),
+      data: {
+        leaders: data.leaders // array of numbers
+      },
+      resolveCallback: (response) => {
+        return new Classroom(response.data)
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+
   dropByAdmin (classroomId, userId) {
     return this.sendRequest({
       apiMethod: 'put',

+ 16 - 0
src/api/models/ClassroomGraders.js

@@ -0,0 +1,16 @@
+import { appApi } from 'src/boot/axios.js'
+import APIRepository from '../classes/APIRepository.js'
+
+export default class ClassroomGraderAPI extends APIRepository {
+  constructor() {
+    super('classroom_graders', appApi, '/lma/classroom_graders')
+    this.APIAdresses = {
+      base: '/lma/classroom_graders',
+      byId: (id) => '/lma/classroom_graders/' + id
+    }
+    this.CacheList = {
+      base: this.name + this.APIAdresses.base,
+      byId: (id) => this.name + this.APIAdresses.byId(id)
+    }
+  }
+}

+ 16 - 0
src/api/models/ClassroomLeaders.js

@@ -0,0 +1,16 @@
+import { appApi } from 'src/boot/axios.js'
+import APIRepository from '../classes/APIRepository.js'
+
+export default class ClassroomLeaderAPI extends APIRepository {
+  constructor() {
+    super('classroom_leaders', appApi, '/lma/classroom_leaders')
+    this.APIAdresses = {
+      base: '/lma/classroom_leaders',
+      byId: (id) => '/lma/classroom_leaders/' + id
+    }
+    this.CacheList = {
+      base: this.name + this.APIAdresses.base,
+      byId: (id) => this.name + this.APIAdresses.byId(id)
+    }
+  }
+}

+ 34 - 0
src/api/models/Team.js

@@ -0,0 +1,34 @@
+import { appApi } from 'src/boot/axios.js'
+import APIRepository from '../classes/APIRepository.js'
+
+export default class TeamAPI extends APIRepository {
+  constructor() {
+    super('teams', appApi, '/lma/teams')
+    this.APIAdresses = {
+      base: '/lma/teams',
+      byId: (id) => '/lma/teams/' + id,
+      registrations: (id) => '/lma/teams/' + id + '/registrations'
+    }
+    this.CacheList = {
+      base: this.name + this.APIAdresses.base,
+      byId: (id) => this.name + this.APIAdresses.byId(id)
+    }
+  }
+
+  appendRegistrations (data) {
+    return this.sendRequest({
+      apiMethod: 'put',
+      api: this.api,
+      request: this.APIAdresses.registrations(data.teamId),
+      data: {
+        registrations: data.registrations // array of numbers
+      },
+      resolveCallback: (response) => {
+        return response.data
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+}

+ 14 - 0
src/api/models/TeamRegistrations.js

@@ -0,0 +1,14 @@
+import { appApi } from 'src/boot/axios.js'
+import APIRepository from '../classes/APIRepository.js'
+
+export default class TeamAPI extends APIRepository {
+  constructor() {
+    super('teams', appApi, '/lma/teams')
+    this.APIAdresses = {
+      base: '/lma/team_registrations'
+    }
+    this.CacheList = {
+      base: this.name + this.APIAdresses.base
+    }
+  }
+}

+ 214 - 0
src/components/Widgets/Team/AdminTeamCreate/AdminTeamCreate.vue

@@ -0,0 +1,214 @@
+<template>
+  <div class="AdminTeamCreate"
+       :style="localOptions.style">
+    <div class="flex justify-end">
+      <q-btn flat
+             color="grey"
+             @click="$router.go(-1)">
+        بازگشت
+        >
+      </q-btn>
+    </div>
+    <entity-create v-if="mounted"
+                   ref="entityCreate"
+                   v-model:value="inputs"
+                   title="ایجاد گروه"
+                   :api="api"
+                   :entity-id-key="entityIdKey"
+                   :entity-param-key="entityParamKey"
+                   :show-route-name="showRouteName"
+                   :show-close-button="false"
+                   :show-edit-button="false"
+                   :show-expand-button="false"
+                   :show-save-button="false"
+                   :show-reload-button="false" />
+  </div>
+</template>
+
+<script>
+import { shallowRef } from 'vue'
+import { EntityCreate } from 'quasar-crud'
+import { mixinWidget } from 'src/mixin/Mixins.js'
+import { APIGateway } from 'src/api/APIGateway.js'
+import BtnControl from 'src/components/Control/btn.vue'
+import { FormBuilderAssist } from 'quasar-form-builder'
+import FormBuilderInputEditor from 'src/components/FormBuilderCustumComponents/FormBuilderInputEditor.vue'
+
+const BtnControlComp = shallowRef(BtnControl)
+const FormBuilderInputEditorComp = shallowRef(FormBuilderInputEditor)
+
+export default {
+  name: 'AdminTeamCreate',
+  components: { EntityCreate },
+  mixins: [mixinWidget],
+  data () {
+    const classroomId = this.$route.params.classroom_id
+    return {
+      mounted: false,
+      entityLoading: false,
+      api: APIGateway.team.APIAdresses.base,
+      entityIdKey: 'id',
+      entityParamKey: 'id',
+      showRouteName: 'Admin.Classroom.Team.Show',
+      inputs: [
+        { type: 'input', name: 'title', responseKey: 'title', label: 'عنوان گروه', placeholder: ' ', col: 'col-md-3 col-12' },
+        { type: 'input', name: 'capacity', responseKey: 'capacity', label: 'ظرفیت', placeholder: ' ', col: 'col-md-3 col-12' },
+        {
+          type: 'entity',
+          name: 'leader',
+          selectionMode: 'single',
+          popUpButtonConfig: {
+            label: 'انتخاب سرگروه',
+            outline: true,
+            buttonColor: 'deep-purple',
+            buttonTextColor: 'white',
+            buttonBadgeColor: 'pink'
+          },
+          dialogConfirmButtonConfig: {
+            label: 'تایید',
+            buttonColor: 'deep-purple',
+            buttonTextColor: 'white',
+            buttonBadgeColor: 'pink'
+          },
+
+          apiAddress: APIGateway.classroomLeaders.APIAdresses.base,
+          tableTitle: 'لیست کل سرگروه ها',
+          showTableItemsRouteName: 'Admin.BlockManagement.Show',
+          tableKeys: {
+            data: 'results',
+            total: 'count',
+            currentPage: 'current',
+            perPage: 'per_page',
+            pageKey: 'page'
+          },
+          table: {
+            columns: [
+              {
+                name: 'number',
+                required: true,
+                label: 'شماره',
+                align: 'left',
+                field: () => ''
+              },
+              {
+                name: 'id',
+                required: true,
+                label: 'شناسه',
+                align: 'left',
+                field: row => row.leader_info.id
+              },
+              {
+                name: 'title',
+                required: true,
+                label: 'جنسیت',
+                align: 'left',
+                field: row => (row.leader_info.gender === 1) ? 'مذکر' : ((row.leader_info.gender === 2) ? 'مونث' : '-')
+              },
+              {
+                name: 'creation_time',
+                required: true,
+                label: 'نام و نام خانوادگی',
+                align: 'left',
+                field: row => row.leader_info.firstname + ' ' + row.leader_info.lastname
+              },
+              {
+                name: 'creation_time',
+                required: true,
+                label: 'کدملی',
+                align: 'left',
+                field: row => row.leader_info.national_code
+              },
+              {
+                name: 'creation_time',
+                required: true,
+                label: 'شماره تلفن',
+                align: 'left',
+                field: row => row.leader_info.mobile_number
+              },
+              {
+                name: 'creation_time',
+                required: true,
+                label: 'دانشگاه',
+                align: 'left',
+                field: row => row.leader_info.last_academy_name
+              },
+              {
+                name: 'creation_time',
+                required: true,
+                label: 'شهر',
+                align: 'left',
+                field: row => row.leader_info.living_city
+              },
+              {
+                name: 'actions',
+                required: true,
+                label: 'عملیات',
+                align: 'left',
+                field: ''
+              }
+            ]
+          },
+          inputs: [
+            { type: 'hidden', name: 'classroom', value: classroomId }
+          ],
+          itemIndicatorKey: row => row.leader_info.firstname + ' ' + row.leader_info.lastname,
+          // itemIndicatorKey: 'firstname',
+          itemIdentifyKey: 'id',
+          indexConfig: {
+            itemIdentifyKey: 'id'
+          },
+
+          value: null,
+          selected: null,
+          col: 'col-md-3 col-12'
+        },
+        { type: FormBuilderInputEditorComp, name: 'description', responseKey: 'description', label: 'توضیحات', col: 'col-12' },
+        { type: 'hidden', name: 'classroom', value: classroomId },
+        { type: BtnControlComp, name: 'btn', responseKey: 'btn', label: 'ایجاد گروه', placeholder: ' ', atClick: () => {}, col: 'col-md-6' }
+      ]
+    }
+  },
+  mounted() {
+    this.setActionBtn()
+    this.mounted = true
+  },
+  methods: {
+    setActionBtn () {
+      FormBuilderAssist.setAttributeByName(this.inputs, 'btn', 'atClick', this.create)
+    },
+    create() {
+      this.entityLoading = true
+      this.$refs.entityCreate.createEntity(false)
+        .then((response) => {
+          this.entityLoading = false
+          this.$router.push({ name: 'Admin.Classroom.Team.Show', params: { classroom_id: this.$route.params.classroom_id, team_id: response.data.id } })
+        })
+        .catch(() => {
+          this.entityLoading = false
+        })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.AdminTeamCreate {
+  .title {
+    font-style: normal;
+    font-weight: 700;
+    font-size: 24px;
+    line-height: 140%;
+    color: #424242;
+    margin-bottom: 27px;
+    position: relative;
+    .back-action {
+      position: absolute;
+      right: 0;
+      top: 0;
+    }
+  }
+  :deep(.form) {
+    padding: 24px;
+  }
+}
+</style>

+ 21 - 0
src/components/Widgets/Team/AdminTeamCreate/OptionPanel.vue

@@ -0,0 +1,21 @@
+<template>
+  <option-panel-tabs v-model:options="localOptions">
+    <template #main-tab>
+      ...
+    </template>
+  </option-panel-tabs>
+</template>
+
+<script>
+import { defineComponent } from 'vue'
+import { mixinOptionPanel } from 'quasar-ui-q-page-builder'
+import OptionPanelTabs from 'quasar-ui-q-page-builder/src/components/OptionPanelComponents/OptionPanelTabs.vue'
+
+export default defineComponent({
+  name: 'OptionPanel',
+  components: {
+    OptionPanelTabs
+  },
+  mixins: [mixinOptionPanel]
+})
+</script>

+ 431 - 0
src/components/Widgets/Team/AdminTeamShow/AdminTeamShow.vue

@@ -0,0 +1,431 @@
+<template>
+  <div class="AdminTeamShow"
+       :style="localOptions.style">
+    <div class="flex justify-end">
+      <q-btn flat
+             color="grey"
+             @click="$router.go(-1)">
+        بازگشت
+        >
+      </q-btn>
+    </div>
+    <entity-edit v-if="mounted"
+                 ref="entityEdit"
+                 v-model:value="inputs"
+                 title="اطلاعات گروه"
+                 :api="api"
+                 :entity-id-key="entityIdKey"
+                 :entity-param-key="entityParamKey"
+                 :show-close-button="false"
+                 :show-edit-button="false"
+                 :show-expand-button="false"
+                 :show-save-button="false"
+                 :show-reload-button="false"
+                 :redirect-after-edit="false"
+                 :after-load-input-data="afterLoadInputData" />
+
+    <q-separator class="q-my-lg" />
+
+    <entity-index v-if="mounted"
+                  ref="teamRegistrationList"
+                  v-model:value="teamRegistrationListInputs"
+                  title="لیست اعضای گروه"
+                  :api="teamRegistrationListApi"
+                  :table="teamRegistrationListTable"
+                  :table-keys="teamRegistrationListTableKeys"
+                  :show-search-button="false"
+                  :show-reload-button="false"
+                  :show-expand-button="false">
+      <template #toolbar>
+        <form-builder ref="formBuilder"
+                      v-model:value="addTeamRegistrationInputs"
+                      :loading="addNewTeamRegistrationLoading" />
+      </template>
+      <template v-slot:entity-index-table-cell="{inputData, showConfirmRemoveDialog}">
+        <template v-if="inputData.col.name === 'number'">
+          {{ inputData.rowNumber }}
+        </template>
+        <template v-else-if="inputData.col.name === 'actions'">
+          <div class="action-column-entity-index">
+            <delete-btn @click="showConfirmRemoveDialog(inputData.props.row, 'id', getRemoveMessage(inputData.props.row))" />
+          </div>
+        </template>
+        <template v-else>
+          {{ inputData.col.value }}
+        </template>
+      </template>
+    </entity-index>
+  </div>
+</template>
+
+<script>
+import { shallowRef } from 'vue'
+import { EntityEdit, EntityIndex } from 'quasar-crud'
+import { mixinWidget } from 'src/mixin/Mixins.js'
+import { APIGateway } from 'src/api/APIGateway.js'
+import BtnControl from 'src/components/Control/btn.vue'
+import { FormBuilder, inputMixin, FormBuilderAssist } from 'quasar-form-builder'
+import EntityInput from 'quasar-crud/src/components/Entity/Attachment/EntityInput.vue'
+import DeleteBtn from 'src/components/Control/DeleteBtn.vue'
+import FormBuilderInputEditor from 'src/components/FormBuilderCustumComponents/FormBuilderInputEditor.vue'
+
+const BtnControlComp = shallowRef(BtnControl)
+const EntityInputComp = shallowRef(EntityInput)
+const FormBuilderInputEditorComp = shallowRef(FormBuilderInputEditor)
+
+export default {
+  name: 'AdminTeamShow',
+  components: {
+    DeleteBtn,
+    EntityEdit,
+    EntityIndex,
+    FormBuilder
+  },
+  mixins: [mixinWidget, inputMixin],
+  data () {
+    const teamId = this.$route.params.team_id
+    const classroomId = this.$route.params.classroom_id
+    return {
+      mounted: false,
+      entityLoading: true,
+      api: APIGateway.team.APIAdresses.byId(teamId),
+      entityIdKey: 'id',
+      entityParamKey: 'id',
+      inputs: [
+        { type: 'input', name: 'title', responseKey: 'title', label: 'عنوان گروه', placeholder: ' ', col: 'col-md-3 col-12' },
+        { type: 'input', name: 'capacity', responseKey: 'capacity', label: 'ظرفیت', placeholder: ' ', col: 'col-md-3 col-12' },
+        { type: 'separator', name: 'space', label: 'مشخصات سرگروه', className: 'custom-separator', col: 'col-12' },
+        { type: 'input', name: 'leader_info.firstname', responseKey: 'leader_info.firstname', label: 'نام سرگروه', placeholder: ' ', ignoreValue: true, col: 'col-md-3 col-12' },
+        { type: 'input', name: 'leader_info.lastname', responseKey: 'leader_info.lastname', label: 'نام خانوادگی سرگروه', placeholder: ' ', ignoreValue: true, col: 'col-md-3 col-12' },
+        { type: 'separator', name: 'space', size: '0', col: 'col-12' },
+        {
+          type: 'entity',
+          name: 'leader',
+          responseKey: 'leader_info',
+          selectionMode: 'single',
+          popUpButtonConfig: {
+            label: 'انتخاب سرگروه',
+            outline: true,
+            buttonColor: 'deep-purple',
+            buttonTextColor: 'white',
+            buttonBadgeColor: 'pink'
+          },
+          dialogConfirmButtonConfig: {
+            label: 'تایید',
+            buttonColor: 'deep-purple',
+            buttonTextColor: 'white',
+            buttonBadgeColor: 'pink'
+          },
+
+          apiAddress: APIGateway.classroomLeaders.APIAdresses.base,
+          tableTitle: 'لیست کل سرگروه ها',
+          showTableItemsRouteName: 'Admin.BlockManagement.Show',
+          tableKeys: {
+            data: 'results',
+            total: 'count',
+            currentPage: 'current',
+            perPage: 'per_page',
+            pageKey: 'page'
+          },
+          table: {
+            columns: [
+              {
+                name: 'leader',
+                required: true,
+                label: 'شناسه',
+                align: 'left',
+                field: row => row.leader
+              },
+              {
+                name: 'leader_info.gender',
+                required: true,
+                label: 'جنسیت',
+                align: 'left',
+                field: row => (row.leader_info.gender === 1) ? 'مذکر' : ((row.leader_info.gender === 2) ? 'مونث' : '-')
+              },
+              {
+                name: 'leader_info.full_name',
+                required: true,
+                label: 'نام و نام خانوادگی',
+                align: 'left',
+                field: row => row.leader_info.firstname + ' ' + row.leader_info.lastname
+              },
+              {
+                name: 'leader_info.national_code',
+                required: true,
+                label: 'کدملی',
+                align: 'left',
+                field: row => row.leader_info.national_code
+              },
+              {
+                name: 'leader_info.mobile_number',
+                required: true,
+                label: 'شماره تلفن',
+                align: 'left',
+                field: row => row.leader_info.mobile_number
+              },
+              {
+                name: 'leader_info.last_academy_name',
+                required: true,
+                label: 'دانشگاه',
+                align: 'left',
+                field: row => row.leader_info.last_academy_name
+              },
+              {
+                name: 'leader_info.living_city',
+                required: true,
+                label: 'شهر',
+                align: 'left',
+                field: row => row.leader_info.living_city
+              }
+            ]
+          },
+          inputs: [
+            { type: 'hidden', name: 'classroom', value: classroomId }
+          ],
+          // itemIndicatorKey: row => row.firstname + ' ' + row.lastname,
+          itemIndicatorKey: 'leader_info.id',
+          // itemIndicatorKey: 'firstname',
+          itemIdentifyKey: 'leader_info.id',
+          itemIdentifyKeyOfIndexTable: 'leader',
+          indexConfig: {
+            itemIndicatorKey: row => row.leader_info.firstname + ' ' + row.leader_info.lastname,
+            itemIdentifyKey: 'leader'
+            // itemIdentifyKey: 'id'
+          },
+
+          value: null,
+          selected: null,
+          col: 'col-md-3 col-12'
+        },
+        { type: FormBuilderInputEditorComp, name: 'description', responseKey: 'description', label: 'توضیحات', col: 'col-12' },
+        { type: 'hidden', name: 'classroom', value: classroomId },
+        { type: BtnControlComp, name: 'btn', responseKey: 'btn', label: 'ویرایش گروه', placeholder: ' ', atClick: () => {}, col: 'col-md-6' }
+      ],
+
+      addNewTeamRegistrationLoading: false,
+      addTeamRegistrationInputs: [
+        {
+          type: EntityInputComp,
+          name: 'leaders',
+          selectionMode: 'multiple',
+          popUpButtonConfig: {
+            label: 'اختصاص عضو جدید',
+            outline: true,
+            buttonColor: 'deep-purple',
+            buttonTextColor: 'white',
+            buttonBadgeColor: 'pink'
+          },
+          dialogConfirmButtonConfig: {
+            label: 'تایید',
+            buttonColor: 'deep-purple',
+            buttonTextColor: 'white',
+            buttonBadgeColor: 'pink'
+          },
+
+          apiAddress: APIGateway.registration.APIAdresses.base,
+          tableTitle: 'لیست کاربران',
+          showTableItemsRouteName: 'Admin.BlockManagement.Show',
+          tableKeys: {
+            data: 'results',
+            total: 'count',
+            currentPage: 'current',
+            perPage: 'per_page',
+            pageKey: 'page'
+          },
+          table: {
+            columns: [
+              {
+                name: 'id',
+                required: true,
+                label: 'شناسه',
+                align: 'left',
+                field: row => row.owner_info.id
+              },
+              {
+                name: 'fullname',
+                required: true,
+                label: 'نام و نام خانوادگی',
+                align: 'left',
+                field: row => row.owner_info.firstname + ' ' + row.owner_info.lastname
+              },
+              {
+                name: 'national_code',
+                required: true,
+                label: 'کد ملی',
+                align: 'left',
+                field: row => row.owner_info.national_code
+              },
+              {
+                name: 'mobile_number',
+                required: true,
+                label: 'شماره همراه',
+                align: 'left',
+                field: row => row.owner_info.mobile_number
+              }
+            ]
+          },
+          inputs: [
+            { type: 'hidden', name: 'classroom', value: classroomId }
+          ],
+          itemIndicatorKey: row => row.owner_info.firstname + ' ' + row.owner_info.lastname,
+          // itemIndicatorKey: 'firstname',
+          itemIdentifyKey: 'id',
+          onConfirmed: this.onConfirmedSelectedRegistrations,
+
+          value: [],
+          selected: [],
+          col: 'col-md-12 col-12'
+        }
+      ],
+      teamRegistrationListInputs: [
+        { type: 'hidden', name: 'team', value: teamId }
+      ],
+      teamRegistrationListApi: APIGateway.teamRegistrations.APIAdresses.base,
+      teamRegistrationListTable: {
+        columns: [
+          {
+            name: 'number',
+            required: true,
+            label: 'شماره',
+            align: 'left',
+            field: () => ''
+          },
+          {
+            name: 'id',
+            required: true,
+            label: 'شناسه',
+            align: 'left',
+            field: row => row.registration_info.owner_info.id
+          },
+          {
+            name: 'title',
+            required: true,
+            label: 'جنسیت',
+            align: 'left',
+            field: row => (row.registration_info.owner_info.gender === 1) ? 'مذکر' : ((row.registration_info.owner_info.gender === 2) ? 'مونث' : '-')
+          },
+          {
+            name: 'creation_time',
+            required: true,
+            label: 'نام و نام خانوادگی',
+            align: 'left',
+            field: row => row.registration_info.owner_info.firstname + ' ' + row.registration_info.owner_info.lastname
+          },
+          {
+            name: 'creation_time',
+            required: true,
+            label: 'کدملی',
+            align: 'left',
+            field: row => row.registration_info.owner_info.national_code
+          },
+          {
+            name: 'creation_time',
+            required: true,
+            label: 'شماره تلفن',
+            align: 'left',
+            field: row => row.registration_info.owner_info.mobile_number
+          },
+          {
+            name: 'creation_time',
+            required: true,
+            label: 'دانشگاه',
+            align: 'left',
+            field: row => row.registration_info.owner_info.last_academy_name
+          },
+          {
+            name: 'creation_time',
+            required: true,
+            label: 'شهر',
+            align: 'left',
+            field: row => row.registration_info.owner_info.living_city
+          },
+          {
+            name: 'actions',
+            required: true,
+            label: 'عملیات',
+            align: 'left',
+            field: ''
+          }
+        ]
+      },
+      teamRegistrationListTableKeys: {
+        data: 'results',
+        total: 'count',
+        currentPage: 'current',
+        perPage: 'per_page',
+        pageKey: 'page'
+      }
+    }
+  },
+  mounted() {
+    this.setActionBtn()
+    this.mounted = true
+  },
+  methods: {
+    onConfirmedSelectedRegistrations (data) {
+      const registrations = data.map(item => item.id)
+      this.addNewLeaderLoading = true
+      APIGateway.team.appendRegistrations({ teamId: this.$route.params.team_id, registrations })
+        .then(() => {
+          this.$refs.teamRegistrationList.search()
+          this.addNewLeaderLoading = false
+        })
+        .catch(() => {
+          this.addNewLeaderLoading = false
+        })
+    },
+    setActionBtn () {
+      FormBuilderAssist.setAttributeByName(this.inputs, 'btn', 'atClick', this.edit)
+    },
+    afterLoadInputData () {
+      this.entityLoading = false
+    },
+    edit() {
+      this.entityLoading = true
+      this.$refs.entityEdit.editEntity(false)
+        .then(() => {
+          this.$refs.entityEdit.getData()
+          this.entityLoading = false
+        })
+        .catch(() => {
+          this.$refs.entityEdit.getData()
+          this.entityLoading = false
+        })
+    },
+    getRemoveMessage (row) {
+      return 'آیا از حذف ' + row.registration_info.owner_info.firstname + ' ' + row.registration_info.owner_info.lastname + ' اطمینان دارید؟'
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.AdminTeamShow {
+  .title {
+    font-style: normal;
+    font-weight: 700;
+    font-size: 24px;
+    line-height: 140%;
+    color: #424242;
+    margin-bottom: 27px;
+    display: flex;
+    flex-flow: row;
+    position: relative;
+    .static-title {
+
+    }
+    .dynamic-title {
+
+    }
+    .back-action {
+      position: absolute;
+      right: 0;
+      top: 0;
+    }
+  }
+  :deep(.form) {
+    padding: 24px;
+  }
+}
+</style>

+ 21 - 0
src/components/Widgets/Team/AdminTeamShow/OptionPanel.vue

@@ -0,0 +1,21 @@
+<template>
+  <option-panel-tabs v-model:options="localOptions">
+    <template #main-tab>
+      ...
+    </template>
+  </option-panel-tabs>
+</template>
+
+<script>
+import { defineComponent } from 'vue'
+import { mixinOptionPanel } from 'quasar-ui-q-page-builder'
+import OptionPanelTabs from 'quasar-ui-q-page-builder/src/components/OptionPanelComponents/OptionPanelTabs.vue'
+
+export default defineComponent({
+  name: 'OptionPanel',
+  components: {
+    OptionPanelTabs
+  },
+  mixins: [mixinOptionPanel]
+})
+</script>

+ 23 - 0
src/pages/Admin/Classroom/Team/create.vue

@@ -0,0 +1,23 @@
+<template>
+  <q-page-builder v-model:sections="currenSections"
+                  v-model:options="pageConfig"
+                  :editable="pageBuilderEditable"
+                  :loading="pageBuilderLoading" />
+</template>
+
+<script>
+import { mixinPageOptions } from 'src/mixin/Mixins.js'
+
+export default {
+  name: 'Admin.Classroom.Team.Create',
+  mixins: [mixinPageOptions],
+  data: () => {
+    return {
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'AdminTeamCreate' }], options: { style: { paddingTop: '' } } }], options: { className: '', height: 'auto', boxed: true, boxedWidth: 1200, gutterXSize: 'md', gutterYSize: 'md', absolute: 'none', paddingOfBoxedInFullWidth: '10px', alignment: { justifyContent: { global: null, xl: null, lg: null, md: null, sm: null, xs: null }, alignItems: { global: null, xl: null, lg: null, md: null, sm: null, xs: null }, alignContent: { global: null, xl: null, lg: null, md: null, sm: null, xs: null } }, style: { maxWidth: '1200px', width: '1200px' } } }] } }]
+    }
+  },
+  created() {
+    this.currenSections = this.sections
+  }
+}
+</script>

+ 23 - 0
src/pages/Admin/Classroom/Team/show.vue

@@ -0,0 +1,23 @@
+<template>
+  <q-page-builder v-model:sections="currenSections"
+                  v-model:options="pageConfig"
+                  :editable="pageBuilderEditable"
+                  :loading="pageBuilderLoading" />
+</template>
+
+<script>
+import { mixinPageOptions } from 'src/mixin/Mixins.js'
+
+export default {
+  name: 'Admin.Classroom.Team.Show',
+  mixins: [mixinPageOptions],
+  data: () => {
+    return {
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'AdminTeamShow' }], options: { style: { paddingTop: '' } } }], options: { className: '', height: 'auto', boxed: true, boxedWidth: 1200, gutterXSize: 'md', gutterYSize: 'md', absolute: 'none', paddingOfBoxedInFullWidth: '10px', alignment: { justifyContent: { global: null, xl: null, lg: null, md: null, sm: null, xs: null }, alignItems: { global: null, xl: null, lg: null, md: null, sm: null, xs: null }, alignContent: { global: null, xl: null, lg: null, md: null, sm: null, xs: null } }, style: { maxWidth: '1200px', width: '1200px' } } }] } }]
+    }
+  },
+  created() {
+    this.currenSections = this.sections
+  }
+}
+</script>

+ 1 - 2
src/pages/Admin/User/index.vue

@@ -145,8 +145,7 @@ export default {
             align: 'left',
             field: ''
           }
-        ],
-        data: []
+        ]
       },
       tableKeys: {
         data: 'results',

+ 3 - 2
src/router/routes.js

@@ -560,11 +560,12 @@ const routes = [
               { name: 'Admin.Classroom.Session.AttendanceSheetList', path: ':classroom_id/session/:session_id/session_attendance_sheets', component: () => import('pages/Admin/Classroom/SessionActivitySheets/sessionActivitySheets.vue') },
               { name: 'Admin.Classroom.Session.AttendanceSheet.Assignment', path: ':classroom_id/session/:session_id/session_attendance_sheet/:session_attendance_sheet_id/assignment', component: () => import('pages/Admin/Classroom/SessionActivitySheets/Assignment.vue') },
               { name: 'Admin.Classroom.Session.AttendanceSheet.Attendance', path: ':classroom_id/session/:session_id/session_attendance_sheet/:session_attendance_sheet_id/attendance', component: () => import('pages/Admin/Classroom/SessionActivitySheets/Attendance.vue') },
-              { name: 'Admin.Classroom.Project.Create', path: ':classroom_id/project/create', component: () => import('src/pages/Admin/Classroom/project/create.vue'), breadcrumbs: { title: 'ساخت دوره آموزشی' } },
+              { name: 'Admin.Classroom.Project.Create', path: ':classroom_id/project/create', component: () => import('src/pages/Admin/Classroom/project/create.vue') },
               { name: 'Admin.Classroom.Project.Show', path: ':classroom_id/project/:project_id', component: () => import('src/pages/Admin/Classroom/project/show.vue') },
               { name: 'Admin.Classroom.Project.Members', path: ':classroom_id/project/:project_id/members', component: () => import('src/pages/Admin/Classroom/project/members.vue') },
               { name: 'Admin.Classroom.projectAttendanceSheets.Show', path: ':classroom_id/project/:project_id/projectAttendanceSheet/:project_attendance_sheets_id', component: () => import('src/pages/Admin/Classroom/ProjectAttendanceSheet/show.vue') },
-              { name: 'Admin.Classroom.Project', path: ':id', component: () => import('src/pages/Admin/Classroom/show.vue') },
+              { name: 'Admin.Classroom.Team.Create', path: ':classroom_id/team/create', component: () => import('src/pages/Admin/Classroom/Team/create.vue') },
+              { name: 'Admin.Classroom.Team.Show', path: ':classroom_id/team/:team_id', component: () => import('src/pages/Admin/Classroom/Team/show.vue') },
               { name: 'Admin.Classroom.Ticket', path: 'ticket', component: () => import('src/pages/Admin/Classroom/Ticket.vue'), breadcrumbs: { title: 'درخواست ها دوره های آموزشی' } }
             ]
           },

+ 4 - 4
yarn.lock

@@ -6125,10 +6125,10 @@ quasar-app-extension-q-page-builder@^0.1.63:
   dependencies:
     quasar-ui-q-page-builder "^0.1.63"
 
-quasar-crud@^0.3.53:
-  version "0.3.53"
-  resolved "https://registry.yarnpkg.com/quasar-crud/-/quasar-crud-0.3.53.tgz#f48d432dbe8a0be5a7e4b866fa0841d494d47e3d"
-  integrity sha512-9mqnMJ8rtS9Ack/eqgGgNwEaTNPFquUZb/Ia2P+cOp85wWimDOtauZJ6EO58YnjXl7k9zTOdvzP4kq/XHYy9Jw==
+quasar-crud@^0.3.55:
+  version "0.3.55"
+  resolved "https://registry.yarnpkg.com/quasar-crud/-/quasar-crud-0.3.55.tgz#b6fe74eb8538fe671344622a1fa1cf62d942c8a2"
+  integrity sha512-Lr5HR1tgYeT7VhM2UXlAj7SItgsYy0tCwO8ptLlV8h8cij7329PISjzEwa2CIYyf8AbsWRDZc3wgTkOMP+062Q==
   dependencies:
     "@quasar/extras" "^1.16.5"
     axios "^1.4.0"