ali пре 2 година
родитељ
комит
d1f10f1151
39 измењених фајлова са 2726 додато и 864 уклоњено
  1. 4 0
      src/api/APIGateway.js
  2. 71 0
      src/api/models/Donation.js
  3. 71 0
      src/api/models/DonationCategory.js
  4. 14 0
      src/components/Template/SideBard/AdminPanelSideBar.vue
  5. 116 0
      src/components/Widgets/Donation/AdminDonationCreate/AdminDonationCreate.vue
  6. 21 0
      src/components/Widgets/Donation/AdminDonationCreate/OptionPanel.vue
  7. 119 0
      src/components/Widgets/Donation/AdminDonationList/AdminDonationList.vue
  8. 21 0
      src/components/Widgets/Donation/AdminDonationList/OptionPanel.vue
  9. 138 0
      src/components/Widgets/Donation/AdminDonationShow/AdminDonationShow.vue
  10. 21 0
      src/components/Widgets/Donation/AdminDonationShow/OptionPanel.vue
  11. 120 0
      src/components/Widgets/Donation/DonationList/DonationList.vue
  12. 21 0
      src/components/Widgets/Donation/DonationList/OptionPanel.vue
  13. 65 0
      src/components/Widgets/Donation/DonationList/components/DonationItem.vue
  14. 173 0
      src/components/Widgets/Donation/DonationShow/DonationShow.vue
  15. 21 0
      src/components/Widgets/Donation/DonationShow/OptionPanel.vue
  16. 113 0
      src/components/Widgets/DonationCategory/AdminDonationCategoryCreate/AdminDonationCategoryCreate.vue
  17. 21 0
      src/components/Widgets/DonationCategory/AdminDonationCategoryCreate/OptionPanel.vue
  18. 134 0
      src/components/Widgets/DonationCategory/AdminDonationCategoryList/AdminDonationCategoryList.vue
  19. 21 0
      src/components/Widgets/DonationCategory/AdminDonationCategoryList/OptionPanel.vue
  20. 112 0
      src/components/Widgets/DonationCategory/AdminDonationCategoryShow/AdminDonationCategoryShow.vue
  21. 21 0
      src/components/Widgets/DonationCategory/AdminDonationCategoryShow/OptionPanel.vue
  22. 106 0
      src/components/Widgets/DonationCategory/DonationCategoryList/DonationCategoryList.vue
  23. 21 0
      src/components/Widgets/DonationCategory/DonationCategoryList/OptionPanel.vue
  24. 65 0
      src/components/Widgets/DonationCategory/DonationCategoryList/components/DonationCategoryItem.vue
  25. 31 0
      src/models/Donation.js
  26. 20 0
      src/models/DonationCategory.js
  27. 23 0
      src/pages/Admin/Donation/Create.vue
  28. 23 0
      src/pages/Admin/Donation/List.vue
  29. 23 0
      src/pages/Admin/Donation/Show.vue
  30. 23 0
      src/pages/Admin/DonationCategory/Create.vue
  31. 23 0
      src/pages/Admin/DonationCategory/List.vue
  32. 23 0
      src/pages/Admin/DonationCategory/Show.vue
  33. 15 0
      src/pages/BasicDynamicPage.vue
  34. 353 0
      src/router/public/Admin.js
  35. 30 0
      src/router/public/Auth.js
  36. 47 0
      src/router/public/Document.js
  37. 108 0
      src/router/public/Public.js
  38. 364 0
      src/router/public/UserPanel.js
  39. 10 864
      src/router/routes.js

+ 4 - 0
src/api/APIGateway.js

@@ -15,6 +15,7 @@ import PaymentAPI from 'src/api/models/Payment.js'
 import SessionAPI from 'src/api/models/Session.js'
 import ContentAPI from 'src/api/models/Content.js'
 import ProjectAPI from 'src/api/models/Project.js'
+import DonationAPI from 'src/api/models/Donation.js'
 import QuestionApi from 'src/api/models/Question.js'
 import ClassroomAPI from 'src/api/models/Classroom.js'
 import AnswerBookApi from 'src/api/models/AnswerBook.js'
@@ -35,6 +36,7 @@ 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 DonationCategoryApi from 'src/api/models/DonationCategory.js'
 import TeamRegistrationsAPI from 'src/api/models/TeamRegistrations.js'
 import EventRegistrationApi from 'src/api/models/EventRegistration.js'
 import ClassroomRegistrationAPI from 'src/api/models/ClassroomRegistration.js'
@@ -60,6 +62,7 @@ export const APIGateway = {
   payment: new PaymentAPI(),
   session: new SessionAPI(),
   content: new ContentAPI(),
+  donation: new DonationAPI(),
   question: new QuestionApi(),
   classroom: new ClassroomAPI(),
   answerBook: new AnswerBookApi(),
@@ -80,6 +83,7 @@ export const APIGateway = {
   instalmentOffer: new InstalmentOfferAPI(),
   classroomGrader: new ClassroomGraderAPI(),
   classroomLeaders: new ClassroomLeadersAPI(),
+  donationCategory: new DonationCategoryApi(),
   teamRegistrations: new TeamRegistrationsAPI(),
   eventRegistration: new EventRegistrationApi(),
   classroomRegistration: new ClassroomRegistrationAPI(),

+ 71 - 0
src/api/models/Donation.js

@@ -0,0 +1,71 @@
+import { appApi } from 'src/boot/axios.js'
+import APIRepository from '../classes/APIRepository.js'
+import { Donation, DonationList } from 'src/models/Donation.js'
+
+export default class DonationAPI extends APIRepository {
+  constructor() {
+    super('donation', appApi)
+    this.APIAdresses = {
+      base: '/dma/donations',
+      byId: (id) => '/dma/donations/' + id
+    }
+    this.CacheList = {
+      base: this.name + this.APIAdresses.base
+    }
+    this.restUrl = (id) => this.APIAdresses.base + '/' + id
+    /* Setting the callback functions for the CRUD operations. */
+    this.setCrudCallbacks({
+      get: (response) => { return new Donation(response.data) },
+      post: (response) => { return new Donation(response.data) },
+      put: (response) => { return new Donation(response.data) },
+      delete: (response) => { return response.data }
+    })
+  }
+
+  index(data) {
+    return this.sendRequest({
+      apiMethod: 'get',
+      api: this.api,
+      request: this.APIAdresses.base,
+      data: this.getNormalizedSendData({
+        category: null, // Number
+        per_page: 10, // Number
+        page: 1 // Number
+      }, data),
+      resolveCallback: (response) => {
+        const paginate = response.data
+        const results = response.data.results
+        delete paginate.results
+        return {
+          list: new DonationList(results),
+          paginate
+          // {
+          //   "count": 1,
+          //   "num_pages": 1,
+          //   "per_page": 10,
+          //   "current": 1,
+          //   "next": null,
+          //   "previous": null,
+          // }
+        }
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+
+  get (id) {
+    return this.sendRequest({
+      apiMethod: 'get',
+      api: this.api,
+      request: this.APIAdresses.byId(id),
+      resolveCallback: (response) => {
+        return new Donation(response.data)
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+}

+ 71 - 0
src/api/models/DonationCategory.js

@@ -0,0 +1,71 @@
+import { appApi } from 'src/boot/axios.js'
+import APIRepository from '../classes/APIRepository.js'
+import { DonationCategory, DonationCategoryList } from 'src/models/DonationCategory.js'
+
+export default class DonationCategoryAPI extends APIRepository {
+  constructor() {
+    super('donation-category', appApi)
+    this.APIAdresses = {
+      base: '/dma/donations/categories',
+      byId: (id) => '/dma/donations/categories/' + id
+    }
+    this.CacheList = {
+      base: this.name + this.APIAdresses.base
+    }
+    this.restUrl = (id) => this.APIAdresses.base + '/' + id
+    /* Setting the callback functions for the CRUD operations. */
+    this.setCrudCallbacks({
+      get: (response) => { return new DonationCategory(response.data) },
+      post: (response) => { return new DonationCategory(response.data) },
+      put: (response) => { return new DonationCategory(response.data) },
+      delete: (response) => { return response.data }
+    })
+  }
+
+  index(data) {
+    return this.sendRequest({
+      apiMethod: 'get',
+      api: this.api,
+      request: this.APIAdresses.base,
+      data: this.getNormalizedSendData({
+        parent__isnull: null, // String (true, false)
+        per_page: 10, // Number
+        page: 1 // Number
+      }, data),
+      resolveCallback: (response) => {
+        const paginate = response.data
+        const results = response.data.results
+        delete paginate.results
+        return {
+          list: new DonationCategoryList(results),
+          paginate
+          // {
+          //   "count": 1,
+          //   "num_pages": 1,
+          //   "per_page": 10,
+          //   "current": 1,
+          //   "next": null,
+          //   "previous": null,
+          // }
+        }
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+
+  get (id) {
+    return this.sendRequest({
+      apiMethod: 'get',
+      api: this.api,
+      request: this.APIAdresses.byId(id),
+      resolveCallback: (response) => {
+        return new DonationCategory(response.data)
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+}

+ 14 - 0
src/components/Template/SideBard/AdminPanelSideBar.vue

@@ -202,6 +202,20 @@ export default {
               routeName: 'Admin.Invoice.Ticket.List',
               show: true,
               active: false
+            },
+            {
+              title: 'دسته های کمک های مالی',
+              roles: ['superuser', 'financial_department_head'],
+              routeName: 'Admin.DonationCategory.List',
+              show: true,
+              active: false
+            },
+            {
+              title: 'لیست کمک های مالی',
+              roles: ['superuser', 'financial_department_head'],
+              routeName: 'Admin.Donation.List',
+              show: true,
+              active: false
             }
           ]
         },

+ 116 - 0
src/components/Widgets/Donation/AdminDonationCreate/AdminDonationCreate.vue

@@ -0,0 +1,116 @@
+<template>
+  <div class="AdminDonationCreate"
+       :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 { FormBuilderAssist } from 'quasar-form-builder'
+import BtnControl from 'src/components/Control/btn.vue'
+
+const BtnControlComp = shallowRef(BtnControl)
+
+export default {
+  name: 'AdminDonationCreate',
+  components: { EntityCreate },
+  mixins: [mixinWidget],
+  data: () => {
+    return {
+      mounted: false,
+      entityLoading: false,
+      api: APIGateway.donation.APIAdresses.base,
+      entityIdKey: 'id',
+      entityParamKey: 'id',
+      showRouteName: 'Admin.Donation.Show',
+      inputs: [
+        { type: 'select', name: 'category', responseKey: 'category', label: 'دسته', placeholder: ' ', options: [], col: 'col-md-6 col-12' },
+        { type: 'file', name: 'thumbnail', responseKey: 'thumbnail', label: 'عکس', placeholder: ' ', col: 'col-md-6 col-12' },
+        { type: 'input', name: 'title', responseKey: 'title', label: 'عنوان', placeholder: ' ', col: 'col-md-12 col-12' },
+        { type: 'inputEditor', name: 'description', responseKey: 'description', label: 'توضیحات', col: 'col-12' },
+        { type: BtnControlComp, name: 'btn', responseKey: 'btn', label: 'تعریف کمک مالی', placeholder: ' ', atClick: () => {}, col: 'col-md-6' }
+      ]
+    }
+  },
+  mounted() {
+    this.setActionBtn()
+    this.loadCategories()
+    this.mounted = true
+  },
+  methods: {
+    setActionBtn () {
+      FormBuilderAssist.setAttributeByName(this.inputs, 'btn', 'atClick', this.onSubmit)
+    },
+    loadCategories () {
+      APIGateway.donationCategory.index({ per_page: 99999 })
+        .then(({ list }) => {
+          FormBuilderAssist.setAttributeByName(this.inputs, 'category', 'options', list.list.map(item => {
+            return {
+              label: item.title,
+              value: item.id
+            }
+          }))
+        })
+    },
+    onSubmit () {
+      this.create()
+    },
+    create() {
+      this.entityLoading = true
+      this.$refs.entityCreate.createEntity()
+        .then(() => {
+          this.entityLoading = false
+        })
+        .catch(() => {
+          this.entityLoading = false
+        })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.AdminDonationCreate {
+  .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/Donation/AdminDonationCreate/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>

+ 119 - 0
src/components/Widgets/Donation/AdminDonationList/AdminDonationList.vue

@@ -0,0 +1,119 @@
+<template>
+  <div class="AdminDonationList"
+       :style="localOptions.style">
+    <div class="more-action">
+      <q-btn label="کمک مالی جدید"
+             color="primary"
+             :to="{name: 'Admin.Donation.Create'}" />
+    </div>
+    <entity-index v-if="mounted"
+                  v-model:value="inputs"
+                  title="لیست کمک های مالی"
+                  :api="api"
+                  :table="table"
+                  :table-keys="tableKeys"
+                  :create-route-name="createRouteName"
+                  :show-search-button="false"
+                  :show-expand-button="false"
+                  :show-reload-button="false">
+      <template #entity-index-table-cell="{inputData}">
+        <template v-if="inputData.col.name === 'number'">
+          {{ inputData.rowNumber }}
+        </template>
+        <template v-else-if="inputData.col.name === 'thumbnail'">
+          <q-img :src="inputData.col.value"
+                 width="100px" />
+        </template>
+        <template v-else-if="inputData.col.name === 'action'">
+          <q-btn color="primary"
+                 :to="{name: 'Admin.Donation.Show', params: {id: inputData.props.row.id}}">
+            مشاهده جزییات
+          </q-btn>
+        </template>
+        <template v-else>
+          {{ inputData.col.value }}
+        </template>
+      </template>
+    </entity-index>
+  </div>
+</template>
+
+<script>
+import { EntityIndex } from 'quasar-crud'
+import { mixinWidget } from 'src/mixin/Mixins.js'
+import { APIGateway } from 'src/api/APIGateway.js'
+
+export default {
+  name: 'AdminDonationList',
+  components: { EntityIndex },
+  mixins: [mixinWidget],
+  data: () => {
+    return {
+      api: APIGateway.donation.APIAdresses.base,
+      tableKeys: {
+        data: 'results',
+        total: 'count',
+        currentPage: 'current',
+        perPage: 'per_page',
+        pageKey: 'page'
+      },
+      inputs: [],
+      table: {
+        columns: [
+          {
+            name: 'number',
+            required: true,
+            label: 'شماره',
+            align: 'left',
+            field: () => ''
+          },
+          {
+            name: 'thumbnail',
+            required: true,
+            label: 'تصویر',
+            align: 'left',
+            field: row => row.thumbnail
+          },
+          {
+            name: 'title',
+            required: true,
+            label: 'عنوان',
+            align: 'left',
+            field: row => row.title
+          },
+          {
+            name: 'category_info',
+            required: true,
+            label: 'دسته',
+            align: 'left',
+            field: row => row.category_info?.title
+          },
+          {
+            name: 'action',
+            required: true,
+            label: 'جزییات',
+            align: 'left',
+            field: row => ''
+          }
+        ]
+      },
+      mounted: false,
+      createRouteName: ''
+    }
+  },
+  mounted() {
+    this.mounted = true
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.AdminDonationList {
+  .more-action {
+    display: flex;
+    flex-flow: row;
+    justify-content: flex-end;
+    margin-bottom: 10px;
+  }
+}
+</style>

+ 21 - 0
src/components/Widgets/Donation/AdminDonationList/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>

+ 138 - 0
src/components/Widgets/Donation/AdminDonationShow/AdminDonationShow.vue

@@ -0,0 +1,138 @@
+<template>
+  <div class="AdminDonationShow"
+       :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-route-name="showRouteName"
+                 :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" />
+  </div>
+</template>
+
+<script>
+import { shallowRef } from 'vue'
+import { EntityEdit } 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'
+
+const BtnControlComp = shallowRef(BtnControl)
+
+export default {
+  name: 'AdminDonationShow',
+  components: {
+    EntityEdit
+  },
+  mixins: [mixinWidget],
+  data: () => {
+    return {
+      mounted: false,
+      entityLoading: true,
+      api: null,
+      entityIdKey: 'id',
+      entityParamKey: 'id',
+      showRouteName: 'Admin.Donation.Show',
+      indexRouteName: 'Admin.Donation.List',
+      inputs: [
+        { type: 'select', name: 'category', responseKey: 'category', label: 'دسته', placeholder: ' ', options: [], col: 'col-md-6 col-12' },
+        { type: 'file', name: 'thumbnail', responseKey: 'thumbnail', label: 'عکس', placeholder: ' ', col: 'col-md-6 col-12' },
+        { type: 'input', name: 'title', responseKey: 'title', label: 'عنوان', placeholder: ' ', col: 'col-md-12 col-12' },
+        { type: 'inputEditor', name: 'description', responseKey: 'description', label: 'توضیحات', col: 'col-12' },
+        { type: BtnControlComp, name: 'btn', responseKey: 'btn', label: 'تعریف کمک مالی', placeholder: ' ', atClick: () => {}, col: 'col-md-6' }
+      ]
+    }
+  },
+  created() {
+    this.api = APIGateway.donation.APIAdresses.byId(this.$route.params.id)
+  },
+  mounted() {
+    this.setActionBtn()
+    this.loadCategories()
+    this.mounted = true
+  },
+  methods: {
+    loadCategories () {
+      APIGateway.donationCategory.index({ per_page: 99999 })
+        .then(({ list }) => {
+          FormBuilderAssist.setAttributeByName(this.inputs, 'category', 'options', list.list.map(item => {
+            return {
+              label: item.title,
+              value: item.id
+            }
+          }))
+        })
+    },
+    setActionBtn () {
+      this.inputs.forEach((item, index) => {
+        if (item.name === 'btn') {
+          this.inputs[index].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
+        })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.AdminDonationShow {
+  .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/Donation/AdminDonationShow/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>

+ 120 - 0
src/components/Widgets/Donation/DonationList/DonationList.vue

@@ -0,0 +1,120 @@
+<template>
+  <div class="DonationList"
+       :style="localOptions.style">
+    <div class="more-action">
+      <breadcrumbs />
+    </div>
+    <entity-index v-if="mounted"
+                  ref="entityIndex"
+                  v-model:value="inputs"
+                  :api="api"
+                  :table="table"
+                  :table-keys="tableKeys"
+                  :create-route-name="createRouteName"
+                  :default-layout="false"
+                  :table-grid-size="true"
+                  :show-search-button="false"
+                  :show-expand-button="false"
+                  :show-reload-button="false">
+      <template #entity-index-table-cell="{inputData}">
+        <template v-if="inputData.col.name === 'action'">
+          <q-btn color="primary"
+                 :to="{name: 'UserPanel.Ticket.Show', params: {id: inputData.props.row.id}}">
+            مشاهده جزییات
+          </q-btn>
+        </template>
+        <template v-else>
+          {{ inputData.col.value }}
+        </template>
+      </template>
+      <template #entity-index-table-item-cell="{inputData}">
+        <div class="col-md-6 col-12 q-pa-sm">
+          <donation-item :donation="getDonation(inputData.props.row)" />
+        </div>
+      </template>
+    </entity-index>
+  </div>
+</template>
+
+<script>
+import { EntityIndex } from 'quasar-crud'
+import { Donation } from 'src/models/Donation.js'
+import { mixinWidget } from 'src/mixin/Mixins.js'
+import { APIGateway } from 'src/api/APIGateway.js'
+import DonationItem from './components/DonationItem.vue'
+import { DonationCategory } from 'src/models/DonationCategory.js'
+import Breadcrumbs from 'src/components/Widgets/Breadcrumbs/Breadcrumbs.vue'
+
+export default {
+  name: 'DonationList',
+  components: { EntityIndex, DonationItem, Breadcrumbs },
+  mixins: [mixinWidget],
+  data () {
+    return {
+      api: APIGateway.donation.APIAdresses.base,
+      tableKeys: {
+        data: 'results',
+        total: 'count',
+        currentPage: 'current',
+        perPage: 'per_page',
+        pageKey: 'page'
+      },
+      inputs: [],
+      table: {
+        columns: []
+      },
+      donationCategory: new DonationCategory(),
+      mounted: false,
+      createRouteName: ''
+    }
+  },
+  mounted() {
+    this.mounted = true
+    this.getDonationCategory()
+  },
+  methods: {
+    getDonation (donation) {
+      return new Donation(donation)
+    },
+    getDonationCategory () {
+      this.donationCategory.loading = true
+      APIGateway.donationCategory.get(this.$route.params.donation_category_id)
+        .then((donationCategory) => {
+          this.donationCategory = new DonationCategory(donationCategory)
+          this.updateBreadcrumbs(this.donationCategory)
+        })
+    },
+    updateBreadcrumbs (donationCategory) {
+      this.$store.commit('AppLayout/updateBreadcrumbs', {
+        visible: true,
+        loading: false,
+        path: [
+          {
+            label: 'خانه',
+            to: { name: 'Public.Home' }
+          },
+          {
+            label: 'پرداخت کمک مالی',
+            to: { name: 'Public.DonationCategory.List' }
+          },
+          {
+            label: donationCategory.title,
+            to: { name: 'Public.DonationCategory.Show', params: { donation_category_id: donationCategory.id } }
+          }
+        ]
+      })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.DonationList {
+  .more-action {
+    display: flex;
+    flex-flow: row;
+    justify-content: flex-start;
+    margin-bottom: 24px;
+  }
+}
+</style>

+ 21 - 0
src/components/Widgets/Donation/DonationList/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>

+ 65 - 0
src/components/Widgets/Donation/DonationList/components/DonationItem.vue

@@ -0,0 +1,65 @@
+<template>
+  <q-card flat
+          class="donation-categoty__item">
+    <q-card-section class="donation-categoty__wrapper">
+      <div class="row">
+        <div class="col-md-5 col-12 donation-categoty__thumbnail-col">
+          <q-img class="donation-categoty__thumbnail"
+                 :src="donation.thumbnail" />
+        </div>
+        <div class="col-md-7 col-12">
+          <div class="donation-categoty__title">
+            {{ donation.title }}
+          </div>
+          <div class="donation-categoty__description ellipsis-3-lines"
+               v-html="donation.description" />
+          <div class="donation-categoty__actions">
+            <q-btn flat
+                   :to="{name: 'Public.DonationCategory.Donation.Show', params: {donation_category_id: $route.params.donation_category_id, donation_id: donation.id}}">
+              جزییات بیشتر
+              <q-icon name="keyboard_backspace" />
+            </q-btn>
+          </div>
+        </div>
+      </div>
+    </q-card-section>
+  </q-card>
+</template>
+
+<script>
+import { Donation } from 'src/models/Donation'
+
+export default {
+  name: 'DonationItem',
+  props: {
+    donation: {
+      type: Donation,
+      default: new Donation()
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.donation-categoty__item {
+  border-radius: 8px;
+  background-color: #FBF4EA;
+  .donation-categoty__wrapper {
+    position: relative;
+    padding-bottom: 48px;
+    .donation-categoty__thumbnail-col {
+      padding-right: 16px;
+      .donation-categoty__thumbnail {
+        width: 100%;
+      }
+    }
+    .donation-categoty__actions {
+      display: flex;
+      justify-content: flex-end;
+      position: absolute;
+      right: 16px;
+      bottom: 16px;
+    }
+  }
+}
+</style>

+ 173 - 0
src/components/Widgets/Donation/DonationShow/DonationShow.vue

@@ -0,0 +1,173 @@
+<template>
+  <div class="DonationShow"
+       :style="localOptions.style">
+    <div class="more-action">
+      <breadcrumbs />
+    </div>
+    <div class="main-section">
+      <div v-if="donationCategory.id"
+           class="show-donation-category-section">
+        <div class="donation-category-content">
+          <q-banner class="donation-category-title">
+            {{donationCategory.title}}
+          </q-banner>
+          <div class="donation-category-description"
+               v-html="donationCategory.description" />
+        </div>
+        <div class="donation-category-thumbnail">
+          <q-img :src="donationCategory.thumbnail" />
+        </div>
+      </div>
+      <div v-if="donation.id"
+           class="show-donation-section">
+        <div class="show-donation-payment-section">
+          <q-banner class="donation-category-title">
+            پرداخت
+            {{donation.title}}
+          </q-banner>
+        </div>
+        <div class="show-donation-info-section">
+          <div class="donation-content">
+            <q-banner class="donation-title">
+              {{donation.title}}
+            </q-banner>
+            <div class="donation-description"
+                 v-html="donation.description" />
+          </div>
+          <div class="donation-thumbnail">
+            <q-img :src="donation.thumbnail" />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Donation } from 'src/models/Donation.js'
+import { mixinWidget } from 'src/mixin/Mixins.js'
+import { APIGateway } from 'src/api/APIGateway.js'
+import { DonationCategory } from 'src/models/DonationCategory.js'
+import Breadcrumbs from 'src/components/Widgets/Breadcrumbs/Breadcrumbs.vue'
+
+export default {
+  name: 'DonationList',
+  components: { Breadcrumbs },
+  mixins: [mixinWidget],
+  data () {
+    return {
+      api: APIGateway.donation.APIAdresses.base,
+      tableKeys: {
+        data: 'results',
+        total: 'count',
+        currentPage: 'current',
+        perPage: 'per_page',
+        pageKey: 'page'
+      },
+      inputs: [],
+      table: {
+        columns: []
+      },
+      donation: new Donation(),
+      donationCategory: new DonationCategory(),
+      mounted: false,
+      createRouteName: ''
+    }
+  },
+  mounted() {
+    this.getDonation()
+  },
+  methods: {
+    getDonation () {
+      this.donation.loading = true
+      APIGateway.donation.get(this.$route.params.donation_category_id)
+        .then((donation) => {
+          this.donation = new Donation(donation)
+          console.log('this.donation', this.donation)
+          this.getDonationCategory()
+        })
+    },
+    getDonationCategory () {
+      this.donationCategory.loading = true
+      APIGateway.donationCategory.get(this.$route.params.donation_category_id)
+        .then((donationCategory) => {
+          this.donationCategory = new DonationCategory(donationCategory)
+          this.updateBreadcrumbs(this.donationCategory, this.donation)
+        })
+    },
+    updateBreadcrumbs (donationCategory, donation) {
+      this.$store.commit('AppLayout/updateBreadcrumbs', {
+        visible: true,
+        loading: false,
+        path: [
+          {
+            label: 'خانه',
+            to: { name: 'Public.Home' }
+          },
+          {
+            label: 'پرداخت کمک مالی',
+            to: { name: 'Public.DonationCategory.List' }
+          },
+          {
+            label: donationCategory.title,
+            to: { name: 'Public.DonationCategory.Show', params: { donation_category_id: donationCategory.id } }
+          },
+          {
+            label: donation.title,
+            to: { name: 'Public.DonationCategory.Donation.Show', params: { donation_category_id: donationCategory.id, donation_id: donation.id } }
+          }
+        ]
+      })
+      this.mounted = true
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.DonationShow {
+  .more-action {
+    display: flex;
+    flex-flow: row;
+    justify-content: flex-start;
+    margin-bottom: 24px;
+  }
+  .main-section {
+    .show-donation-category-section {
+      display: flex;
+      justify-content: flex-start;
+      gap: 16px;
+      .donation-category-thumbnail {
+        width: 30%;
+      }
+      .donation-category-content {
+        width: 70%;
+        .donation-category-title {
+          margin-bottom: 16px;
+        }
+        .donation-category-description {}
+      }
+    }
+    .show-donation-section {
+      .show-donation-payment-section {
+        margin-bottom: 16px;
+      }
+      .show-donation-info-section {
+        display: flex;
+        justify-content: flex-start;
+        gap: 16px;
+        .donation-thumbnail {
+          width: 30%;
+        }
+        .donation-content {
+          width: 70%;
+          .donation-title {
+            margin-bottom: 16px;
+          }
+          .donation-description {}
+        }
+      }
+    }
+  }
+}
+</style>

+ 21 - 0
src/components/Widgets/Donation/DonationShow/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>

+ 113 - 0
src/components/Widgets/DonationCategory/AdminDonationCategoryCreate/AdminDonationCategoryCreate.vue

@@ -0,0 +1,113 @@
+<template>
+  <div class="AdminDonationCategoryCreate"
+       :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="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 { FormBuilderAssist } from 'quasar-form-builder'
+import BtnControl from 'src/components/Control/btn.vue'
+
+const BtnControlComp = shallowRef(BtnControl)
+
+export default {
+  name: 'AdminDonationCategoryCreate',
+  components: { EntityCreate },
+  mixins: [mixinWidget],
+  props: {
+    title: {
+      type: String,
+      default: 'ایجاد دسته کمک های مالی'
+    },
+    parent: {
+      type: Number,
+      default: null
+    }
+  },
+  data: () => {
+    return {
+      mounted: false,
+      entityLoading: false,
+      api: APIGateway.donationCategory.APIAdresses.base,
+      entityIdKey: 'id',
+      entityParamKey: 'id',
+      showRouteName: 'Admin.DonationCategory.Show',
+      indexRouteName: 'Admin.DonationCategory.List',
+      inputs: [
+        { type: 'input', name: 'title', responseKey: 'title', label: 'عنوان', placeholder: ' ', col: 'col-md-6 col-12' },
+        { type: 'file', name: 'thumbnail', responseKey: 'thumbnail', label: 'عکس', placeholder: ' ', col: 'col-md-6 col-12' },
+        { type: 'inputEditor', name: 'description', responseKey: 'description', label: 'توضیحات', placeholder: ' ', col: 'col-md-12 col-12' },
+        { type: BtnControlComp, name: 'btn', responseKey: 'btn', label: 'تایید', placeholder: ' ', atClick: () => {}, col: 'col-12' }
+      ]
+    }
+  },
+  mounted() {
+    this.setActionBtn()
+    this.mounted = true
+  },
+  methods: {
+    setActionBtn () {
+      FormBuilderAssist.setAttributeByName(this.inputs, 'btn', 'atClick', this.onSubmit)
+    },
+    onSubmit () {
+      this.create()
+    },
+    create() {
+      const redirect = !this.parent
+      this.entityLoading = true
+      this.$refs.entityCreate.createEntity(redirect)
+        .then(() => {
+          this.entityLoading = false
+          this.$emit('onCreated')
+        })
+        .catch(() => {
+          this.entityLoading = false
+        })
+    },
+    setInputOptions (name, options) {
+      FormBuilderAssist.setAttributeByName(this.inputs, name, 'options', options)
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.AdminDonationCategoryCreate {
+  :deep(.q-card.entity-create) {
+    .q-card__section {
+      .q-expansion-item {
+        .q-expansion-item__container {
+          .q-item {
+            display: none;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 21 - 0
src/components/Widgets/DonationCategory/AdminDonationCategoryCreate/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>

+ 134 - 0
src/components/Widgets/DonationCategory/AdminDonationCategoryList/AdminDonationCategoryList.vue

@@ -0,0 +1,134 @@
+<template>
+  <div class="AdminDonationCategoryList"
+       :style="localOptions.style">
+    <div v-if="!parent"
+         class="more-action">
+      <q-btn label="دسته جدید"
+             color="primary"
+             :to="{name: 'Admin.DonationCategory.Create'}" />
+    </div>
+    <entity-index v-if="mounted"
+                  v-model:value="inputs"
+                  :title="title"
+                  :api="api"
+                  :table="table"
+                  :table-keys="tableKeys"
+                  :create-route-name="createRouteName"
+                  :show-search-button="false"
+                  :show-expand-button="false"
+                  :show-reload-button="false">
+      <template #entity-index-table-cell="{inputData}">
+        <template v-if="inputData.col.name === 'number'">
+          {{ inputData.rowNumber }}
+        </template>
+        <template v-else-if="inputData.col.name === 'thumbnail'">
+          <q-img :src="inputData.col.value"
+                 width="100px" />
+        </template>
+        <template v-else-if="inputData.col.name === 'action'">
+          <q-btn color="primary"
+                 :to="{name: 'Admin.DonationCategory.Show', params: {id: inputData.props.row.id}}">
+            مشاهده جزییات
+          </q-btn>
+        </template>
+        <template v-else>
+          {{ inputData.col.value }}
+        </template>
+      </template>
+    </entity-index>
+  </div>
+</template>
+
+<script>
+import Assist from 'assets/js/Assist.js'
+import { EntityIndex } from 'quasar-crud'
+import { mixinWidget } from 'src/mixin/Mixins.js'
+import { APIGateway } from 'src/api/APIGateway.js'
+
+export default {
+  name: 'AdminDonationCategoryList',
+  components: { EntityIndex },
+  mixins: [mixinWidget],
+  props: {
+    title: {
+      type: String,
+      default: 'لیست دسته بندی های کمک های مالی'
+    }
+  },
+  data: () => {
+    return {
+      api: APIGateway.donationCategory.APIAdresses.base,
+      tableKeys: {
+        data: 'results',
+        total: 'count',
+        currentPage: 'current',
+        perPage: 'per_page',
+        pageKey: 'page'
+      },
+      inputs: [],
+      table: {
+        columns: [
+          {
+            name: 'number',
+            required: true,
+            label: 'شماره',
+            align: 'left',
+            field: () => ''
+          },
+          {
+            name: 'thumbnail',
+            required: true,
+            label: 'تصویر',
+            align: 'left',
+            field: row => row.thumbnail
+          },
+          {
+            name: 'title',
+            required: true,
+            label: 'نام دسته',
+            align: 'left',
+            field: row => row.title
+          },
+          {
+            name: 'creation_time',
+            required: true,
+            label: 'تاریخ ایجاد',
+            align: 'left',
+            field: row => Assist.miladiToShamsi(row.creation_time)
+          },
+          {
+            name: 'action',
+            required: true,
+            label: 'جزییات',
+            align: 'left',
+            field: row => ''
+          }
+        ]
+      },
+      mounted: false,
+      createRouteName: ''
+    }
+  },
+  mounted() {
+    this.mounted = true
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.AdminDonationCategoryList {
+  :deep(.entity-index) {
+    .q-card__section {
+      .q-item {
+        display: none;
+      }
+    }
+  }
+  .more-action {
+    display: flex;
+    flex-flow: row;
+    justify-content: flex-end;
+    margin-bottom: 10px;
+  }
+}
+</style>

+ 21 - 0
src/components/Widgets/DonationCategory/AdminDonationCategoryList/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>

+ 112 - 0
src/components/Widgets/DonationCategory/AdminDonationCategoryShow/AdminDonationCategoryShow.vue

@@ -0,0 +1,112 @@
+<template>
+  <div class="AdminDonationCategoryShow"
+       :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-route-name="showRouteName"
+                 :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" />
+  </div>
+</template>
+
+<script>
+import { shallowRef } from 'vue'
+import { mixinWidget } from 'src/mixin/Mixins.js'
+import { APIGateway } from 'src/api/APIGateway.js'
+import { EntityEdit, EntityCreate } from 'quasar-crud'
+import { FormBuilderAssist } from 'quasar-form-builder'
+import BtnControl from 'src/components/Control/btn.vue'
+import { DonationCategory } from 'src/models/DonationCategory.js'
+
+const BtnControlComp = shallowRef(BtnControl)
+
+export default {
+  name: 'AdminDonationCategoryShow',
+  components: {
+    EntityEdit
+  },
+  mixins: [mixinWidget, EntityCreate],
+  data: () => {
+    return {
+      listKey: Date.now(),
+      replyText: null,
+      mounted: false,
+      entityLoading: true,
+      donationCategory: new DonationCategory(),
+      api: null,
+      entityIdKey: 'id',
+      entityParamKey: 'id',
+      showRouteName: 'Admin.DonationCategory.Show',
+      inputs: [
+        { type: 'input', name: 'title', responseKey: 'title', label: 'عنوان', value: null, placeholder: ' ', col: 'col-md-6 col-12' },
+        { type: 'file', name: 'thumbnail', responseKey: 'thumbnail', label: 'عکس', value: null, placeholder: ' ', col: 'col-md-6 col-12' },
+        { type: 'inputEditor', name: 'description', responseKey: 'description', label: 'توضیحات', value: null, placeholder: ' ', col: 'col-md-12 col-12' },
+        { type: BtnControlComp, name: 'btn', responseKey: 'btn', label: 'تایید', placeholder: ' ', ignoreValue: false, atClick: () => {}, col: 'col-12' },
+        { type: 'hidden', name: 'parent', responseKey: 'parent', value: null },
+        { type: 'hidden', name: 'id', responseKey: 'id', value: null }
+      ]
+    }
+  },
+  computed: {
+    repliesInfo () {
+      return this.inputs.find(input => input.name === 'replies_info').value
+    }
+  },
+  created() {
+    this.donationCategory.loading = true
+    this.api = APIGateway.donationCategory.APIAdresses.byId(this.$route.params.id)
+  },
+  mounted() {
+    this.mounted = true
+    this.setActionBtn()
+  },
+  methods: {
+    setActionBtn () {
+      FormBuilderAssist.setAttributeByName(this.inputs, 'btn', 'atClick', this.edit)
+    },
+    afterLoadInputData (data) {
+      this.donationCategory = new DonationCategory(data)
+      this.donationCategory.loading = false
+      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
+        })
+    },
+    onCreated () {
+      this.listKey = Date.now()
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.AdminDonationCategoryShow {
+}
+</style>

+ 21 - 0
src/components/Widgets/DonationCategory/AdminDonationCategoryShow/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>

+ 106 - 0
src/components/Widgets/DonationCategory/DonationCategoryList/DonationCategoryList.vue

@@ -0,0 +1,106 @@
+<template>
+  <div class="DonationList"
+       :style="localOptions.style">
+    <div class="more-action">
+      <breadcrumbs />
+    </div>
+    <entity-index v-if="mounted"
+                  ref="entityIndex"
+                  v-model:value="inputs"
+                  :api="api"
+                  :table="table"
+                  :table-keys="tableKeys"
+                  :create-route-name="createRouteName"
+                  :default-layout="false"
+                  :table-grid-size="true"
+                  :show-search-button="false"
+                  :show-expand-button="false"
+                  :show-reload-button="false">
+      <template #entity-index-table-cell="{inputData}">
+        <template v-if="inputData.col.name === 'action'">
+          <q-btn color="primary"
+                 :to="{name: 'UserPanel.Ticket.Show', params: {id: inputData.props.row.id}}">
+            مشاهده جزییات
+          </q-btn>
+        </template>
+        <template v-else>
+          {{ inputData.col.value }}
+        </template>
+      </template>
+      <template #entity-index-table-item-cell="{inputData}">
+        <div class="col-md-6 col-12 q-pa-sm">
+          <donation-category-item :donation-category="getDonationCategory(inputData.props.row)" />
+        </div>
+      </template>
+    </entity-index>
+  </div>
+</template>
+
+<script>
+import { EntityIndex } from 'quasar-crud'
+import { mixinWidget } from 'src/mixin/Mixins.js'
+import { APIGateway } from 'src/api/APIGateway.js'
+import { DonationCategory } from 'src/models/DonationCategory.js'
+import DonationCategoryItem from './components/DonationCategoryItem.vue'
+import Breadcrumbs from 'src/components/Widgets/Breadcrumbs/Breadcrumbs.vue'
+
+export default {
+  name: 'DonationList',
+  components: { EntityIndex, DonationCategoryItem, Breadcrumbs },
+  mixins: [mixinWidget],
+  data () {
+    return {
+      api: APIGateway.donationCategory.APIAdresses.base,
+      tableKeys: {
+        data: 'results',
+        total: 'count',
+        currentPage: 'current',
+        perPage: 'per_page',
+        pageKey: 'page'
+      },
+      inputs: [],
+      table: {
+        columns: []
+      },
+      mounted: false,
+      createRouteName: ''
+    }
+  },
+  mounted() {
+    this.mounted = true
+    this.updateBreadcrumbs()
+  },
+  methods: {
+    getDonationCategory (donationCategory) {
+      return new DonationCategory(donationCategory)
+    },
+    updateBreadcrumbs () {
+      this.$store.commit('AppLayout/updateBreadcrumbs', {
+        visible: true,
+        loading: false,
+        path: [
+          {
+            label: 'خانه',
+            to: { name: 'Public.Home' }
+          },
+          {
+            label: 'پرداخت کمک مالی',
+            to: { name: 'Public.DonationCategory.List' }
+          }
+        ]
+      })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.DonationList {
+  .more-action {
+    display: flex;
+    flex-flow: row;
+    justify-content: flex-start;
+    margin-bottom: 24px;
+  }
+}
+</style>

+ 21 - 0
src/components/Widgets/DonationCategory/DonationCategoryList/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>

+ 65 - 0
src/components/Widgets/DonationCategory/DonationCategoryList/components/DonationCategoryItem.vue

@@ -0,0 +1,65 @@
+<template>
+  <q-card flat
+          class="donation-categoty__item">
+    <q-card-section class="donation-categoty__wrapper">
+      <div class="row">
+        <div class="col-md-5 col-12 donation-categoty__thumbnail-col">
+          <q-img class="donation-categoty__thumbnail"
+                 :src="donationCategory.thumbnail" />
+        </div>
+        <div class="col-md-7 col-12">
+          <div class="donation-categoty__title">
+            {{ donationCategory.title }}
+          </div>
+          <div class="donation-categoty__description ellipsis-3-lines"
+               v-html="donationCategory.description" />
+          <div class="donation-categoty__actions">
+            <q-btn flat
+                   :to="{name: 'Public.DonationCategory.Show', params: {donation_category_id: donationCategory.id}}">
+              جزییات بیشتر
+              <q-icon name="keyboard_backspace" />
+            </q-btn>
+          </div>
+        </div>
+      </div>
+    </q-card-section>
+  </q-card>
+</template>
+
+<script>
+import { DonationCategory } from 'src/models/DonationCategory'
+
+export default {
+  name: 'DonationCategoryItem',
+  props: {
+    donationCategory: {
+      type: DonationCategory,
+      default: new DonationCategory()
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.donation-categoty__item {
+  border-radius: 8px;
+  background-color: #FBF4EA;
+  .donation-categoty__wrapper {
+    position: relative;
+    padding-bottom: 48px;
+    .donation-categoty__thumbnail-col {
+      padding-right: 16px;
+      .donation-categoty__thumbnail {
+        width: 100%;
+      }
+    }
+    .donation-categoty__actions {
+      display: flex;
+      justify-content: flex-end;
+      position: absolute;
+      right: 16px;
+      bottom: 16px;
+    }
+  }
+}
+</style>

+ 31 - 0
src/models/Donation.js

@@ -0,0 +1,31 @@
+import { Collection, Model } from 'js-abstract-model'
+import { DonationCategory } from 'src/models/DonationCategory.js'
+
+class Donation extends Model {
+  constructor (data) {
+    super(data, [
+      { key: 'id' },
+      { key: 'title' },
+      { key: 'description' },
+      { key: 'summary' },
+      { key: 'thumbnail' },
+      { key: 'category' },
+      {
+        key: 'category_info',
+        relatedModel: DonationCategory
+      }
+    ])
+
+    if (!this.thumbnail) {
+      this.thumbnail = '/img/sample-post-thumbnail.jpg'
+    }
+  }
+}
+
+class DonationList extends Collection {
+  model () {
+    return Donation
+  }
+}
+
+export { Donation, DonationList }

+ 20 - 0
src/models/DonationCategory.js

@@ -0,0 +1,20 @@
+import { Collection, Model } from 'js-abstract-model'
+
+class DonationCategory extends Model {
+  constructor (data) {
+    super(data, [
+      { key: 'id' },
+      { key: 'title' },
+      { key: 'thumbnail' },
+      { key: 'description' }
+    ])
+  }
+}
+
+class DonationCategoryList extends Collection {
+  model () {
+    return DonationCategory
+  }
+}
+
+export { DonationCategory, DonationCategoryList }

+ 23 - 0
src/pages/Admin/Donation/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.Donation.Show',
+  mixins: [mixinPageOptions],
+  data: () => {
+    return {
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'AdminDonationCreate' }], options: {} }], 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/Donation/List.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.Donation.List',
+  mixins: [mixinPageOptions],
+  data: () => {
+    return {
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'AdminDonationList' }], options: {} }], 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/Donation/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.Donation.Show',
+  mixins: [mixinPageOptions],
+  data: () => {
+    return {
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'AdminDonationShow' }], 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/DonationCategory/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.DonationCategory.Show',
+  mixins: [mixinPageOptions],
+  data: () => {
+    return {
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'AdminDonationCategoryCreate' }], options: {} }], 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/DonationCategory/List.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.DonationCategory.List',
+  mixins: [mixinPageOptions],
+  data: () => {
+    return {
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'AdminDonationCategoryList' }], options: {} }], 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/DonationCategory/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.DonationCategory.Show',
+  mixins: [mixinPageOptions],
+  data: () => {
+    return {
+      sections: [{ data: { rows: [{ cols: [{ widgets: [{ name: 'AdminDonationCategoryShow' }], options: {} }], 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>

+ 15 - 0
src/pages/BasicDynamicPage.vue

@@ -0,0 +1,15 @@
+<template>
+  <q-page-builder v-model:sections="currenSections"
+                  v-model:options="pageConfig"
+                  :editable="pageBuilderEditable"
+                  :loading="pageBuilderLoading" />
+</template>
+
+<script>
+import { mixinSEO, mixinPageOptions, mixinPrefetchServerData } from 'src/mixin/Mixins.js'
+
+export default {
+  name: 'BasicDynamicPage',
+  mixins: [mixinPrefetchServerData, mixinPageOptions, mixinSEO]
+}
+</script>

+ 353 - 0
src/router/public/Admin.js

@@ -0,0 +1,353 @@
+import { Authenticated, canSeeAdminPanel } from 'src/router/middleware/middleware'
+
+export default {
+  path: 'admin',
+  name: 'Admin',
+  layoutConfig: {
+    layoutView: 'hHh LpR lfr',
+    layoutHeaderType: 'admin',
+    layoutHeaderBordered: true,
+    layoutLeftDrawer: true,
+    layoutLeftDrawerVisible: true,
+    layoutLeftSideBarType: 'admin',
+    layoutLeftDrawerBordered: true,
+    layoutLeftDrawerWidth: 240,
+    layoutFooterType: 'panel',
+    layoutFooter: true
+  },
+  meta: { middlewares: [Authenticated, canSeeAdminPanel] },
+  component: () => import('src/layouts/AdminLayout.vue'),
+  children: [
+    {
+      name: 'Admin.Settings',
+      path: 'settings',
+      component: () => import('src/pages/Admin/Settings.vue'),
+      breadcrumbs: { title: 'تنظیمات' }
+    },
+    {
+      name: 'Admin.User',
+      path: 'users',
+      component: () => import('layouts/bareLayout.vue'),
+      breadcrumbs: { title: 'کاربران' },
+      children: [
+        { name: 'Admin.User.Index', path: '', component: () => import('src/pages/Admin/User/index.vue') },
+        { name: 'Admin.User.Show', path: ':id', component: () => import('src/pages/Admin/User/show.vue'), breadcrumbs: { title: 'اطلاعات کاربری' } },
+        { name: 'Admin.User.ClassroomInfo', path: ':id/classroom/:classroom_id', component: () => import('src/pages/Admin/User/UserClassroomInfo.vue'), breadcrumbs: { title: 'اطلاعات کاربری' } }
+      ]
+    },
+    {
+      name: 'Admin.Category',
+      path: 'categories',
+      component: () => import('layouts/bareLayout.vue'),
+      breadcrumbs: { title: 'دسته بندی ها' },
+      children: [
+        { name: 'Admin.Category.Index', path: '', component: () => import('src/pages/Admin/Category/index.vue') },
+        { name: 'Admin.Category.Create', path: 'create', component: () => import('src/pages/Admin/Category/create.vue') },
+        { name: 'Admin.Category.Show', path: ':id', component: () => import('src/pages/Admin/Category/show.vue') }
+      ]
+    },
+    {
+      name: 'Admin.Category.DiscussionCircles',
+      path: 'discussion-circles-categories',
+      component: () => import('layouts/bareLayout.vue'),
+      breadcrumbs: { title: 'دسته بندی ها' },
+      children: [
+        { name: 'Admin.Category.DiscussionCircles.Index', path: '', component: () => import('src/pages/Admin/DiscussionCirclesCategory/index.vue') },
+        { name: 'Admin.Category.DiscussionCircles.Create', path: 'create', component: () => import('src/pages/Admin/DiscussionCirclesCategory/create.vue') },
+        { name: 'Admin.Category.DiscussionCircles.Show', path: ':id', component: () => import('src/pages/Admin/DiscussionCirclesCategory/show.vue') }
+      ]
+    },
+    {
+      name: 'Admin.Unit',
+      path: 'units',
+      component: () => import('src/layouts/bareLayout.vue'),
+      breadcrumbs: { title: 'طلیعه حکمت' },
+      children: [
+        // { name: 'Admin.Category.Index', path: '', component: () => import('src/pages/Admin/Category/index.vue') },
+        // { name: 'Admin.Category.Create', path: 'create', component: () => import('src/pages/Admin/Category/create.vue') },
+        { name: 'Admin.Unit.Show', path: ':id', component: () => import('src/pages/Admin/Unit/show.vue') },
+        {
+          name: 'Admin.Unit.Questions',
+          path: ':unit_id/session_template/:session_template_id/questions',
+          component: () => import('src/layouts/bareLayout.vue'),
+          children: [
+            { name: 'Admin.Unit.Questions.Index', path: '', component: () => import('src/pages/Admin/Unit/QuestionsList.vue') },
+            { name: 'Admin.Unit.Questions.Create', path: 'create', component: () => import('src/pages/Admin/Unit/QuestionsCreate.vue') }
+            // { name: 'Admin.Unit.Questions.Show', path: ':id', component: () => import('src/pages/Admin/Unit/QuestionsShow.vue') }
+          ]
+        },
+        { name: 'Admin.Unit.Questions.Show', path: ':unit_id/questions/:id', component: () => import('src/pages/Admin/Unit/QuestionsShow.vue') },
+        {
+          name: 'Admin.Unit.TestSet',
+          path: ':unit_id/test_set',
+          component: () => import('src/layouts/bareLayout.vue'),
+          children: [
+            { name: 'Admin.Unit.TestSet.Show', path: ':id', component: () => import('src/pages/Admin/TestSet/Show.vue') },
+            { name: 'Admin.Unit.TestSet.Create', path: 'create', component: () => import('src/pages/Admin/TestSet/Create.vue') }
+          ]
+        }
+      ]
+    },
+    {
+      name: 'Admin.SessionTemplate',
+      path: 'session-templates',
+      component: () => import('layouts/bareLayout.vue'),
+      breadcrumbs: { title: 'طلیعه حکمت' },
+      children: [
+        { name: 'Admin.SessionTemplate.Index', path: '', component: () => import('src/pages/Admin/SessionTemplate/index.vue') },
+        { name: 'Admin.SessionTemplate.Create', path: 'create', component: () => import('src/pages/Admin/SessionTemplate/create.vue') },
+        { name: 'Admin.SessionTemplate.Show', path: ':id', component: () => import('src/pages/Admin/SessionTemplate/show.vue') }
+      ]
+    },
+    {
+      path: 'ticket',
+      name: 'Admin.Ticket',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        {
+          path: '',
+          name: 'Admin.Ticket.List',
+          component: () => import('src/pages/Admin/Ticket/List.vue')
+        },
+        {
+          path: 'educational',
+          name: 'Admin.Ticket.List.Educational',
+          component: () => import('src/pages/Admin/Ticket/EducationalList.vue')
+        },
+        {
+          path: 'create',
+          name: 'Admin.Ticket.Create',
+          component: () => import('src/pages/Admin/Ticket/Create.vue')
+        },
+        {
+          path: ':id',
+          name: 'Admin.Ticket.Show',
+          component: () => import('src/pages/Admin/Ticket/Show.vue')
+        }
+      ]
+    },
+    {
+      name: 'Admin.Classroom',
+      path: 'classrooms',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        { name: 'Admin.Classroom.Index', path: '', component: () => import('src/pages/Admin/Classroom/index.vue') },
+        { name: 'Admin.Classroom.Create', path: 'create', component: () => import('src/pages/Admin/Classroom/create.vue'), breadcrumbs: { title: 'ساخت دوره آموزشی' } },
+        { name: 'Admin.Classroom.Show', path: ':id', component: () => import('src/pages/Admin/Classroom/show.vue') },
+        { name: 'Admin.Classroom.UserClass', path: ':classroom_id/user/:user_id', component: () => import('src/pages/Admin/Classroom/showUserClass.vue') },
+        { 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') },
+        { name: 'Admin.Classroom.Project.Show', path: ':classroom_id/project/:project_id', component: () => import('src/pages/Admin/Classroom/project/show.vue') },
+        { name: 'Admin.Classroom.Project.UserInfo', path: ':classroom_id/project/:project_id/user/:user_id', component: () => import('src/pages/Admin/Classroom/project/showUserProject.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.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: 'درخواست ها دوره های آموزشی' } },
+
+        { name: 'Admin.Classroom.TestSet.Index', path: ':classroom_id/unit/:unit_id/test_set', component: () => import('src/pages/Admin/TestSet/Index.vue') },
+        { name: 'Admin.Classroom.TestSet.Test.Show', path: ':classroom_id/test_set/:test_set_id/test/:id', component: () => import('src/pages/Admin/Test/Show.vue') },
+        { name: 'Admin.Classroom.TestSet.Test.Create', path: ':classroom_id/test_set/:test_set_id/test/create', component: () => import('src/pages/Admin/Test/Create.vue') },
+
+        { name: 'Admin.Classroom.Test.AnswerBooks.Index', path: ':classroom_id/test/:test_id/answer_books', component: () => import('src/pages/Admin/Classroom/ClassroomAnswerBooks.vue') },
+        { name: 'Admin.Classroom.Test.AnswerBooks.ShowGrade', path: ':classroom_id/test/:test_id/answer_books/:answer_book_id/show_grades', component: () => import('src/pages/Admin/Classroom/ClassroomAnswerBookShowGrade.vue') }
+      ]
+    },
+    {
+      name: 'Admin.Event',
+      path: 'events',
+      component: () => import('layouts/bareLayout.vue'),
+      breadcrumbs: { title: 'دوره های آموزشی', route: { name: 'Admin.Event.Index' } },
+      children: [
+        { name: 'Admin.Event.Index', path: '', component: () => import('src/pages/Admin/Event/index.vue') },
+        { name: 'Admin.Event.Create', path: 'create', component: () => import('src/pages/Admin/Event/create.vue'), breadcrumbs: { title: 'ساخت دوره آموزشی' } },
+        { name: 'Admin.Event.Show', path: ':id', component: () => import('src/pages/Admin/Event/show.vue') },
+        { name: 'Admin.Event.Session.AttendanceSheetList', path: ':classroom_id/session/:session_id/session_attendance_sheets', component: () => import('pages/Admin/Event/SessionActivitySheets/sessionActivitySheets.vue') },
+        { name: 'Admin.Event.Session.AttendanceSheet.Assignment', path: ':classroom_id/session/:session_id/session_attendance_sheet/:session_attendance_sheet_id/assignment', component: () => import('pages/Admin/Event/SessionActivitySheets/Assignment.vue') },
+        { name: 'Admin.Event.Session.AttendanceSheet.Attendance', path: ':classroom_id/session/:session_id/session_attendance_sheet/:session_attendance_sheet_id/attendance', component: () => import('pages/Admin/Event/SessionActivitySheets/Attendance.vue') },
+        { name: 'Admin.Event.Project.Create', path: ':classroom_id/project/create', component: () => import('src/pages/Admin/Event/project/create.vue'), breadcrumbs: { title: 'ساخت دوره آموزشی' } },
+        { name: 'Admin.Event.Project.Show', path: ':classroom_id/project/:project_id', component: () => import('src/pages/Admin/Event/project/show.vue') },
+        { name: 'Admin.Event.Project.Members', path: ':classroom_id/project/:project_id/members', component: () => import('src/pages/Admin/Event/project/members.vue') },
+        { name: 'Admin.Event.projectAttendanceSheets.Show', path: ':classroom_id/project/:project_id/projectAttendanceSheet/:project_attendance_sheets_id', component: () => import('src/pages/Admin/Event/ProjectAttendanceSheet/show.vue') },
+        // { name: 'Admin.Event.Project', path: ':id', component: () => import('src/pages/Admin/Event/show.vue') },
+        { name: 'Admin.Event.Ticket', path: 'ticket', component: () => import('src/pages/Admin/Event/Ticket.vue'), breadcrumbs: { title: 'درخواست ها دوره های آموزشی' } },
+
+        { name: 'Admin.Event.TestSet.Index', path: 'test_set', component: () => import('src/pages/Admin/Event/Test/Index.vue') },
+        { name: 'Admin.Event.TestSet.Create', path: 'test_set/create', component: () => import('src/pages/Admin/Event/Test/Create.vue') },
+        { name: 'Admin.Event.TestSet.Show', path: 'test_set/:test_set_id', component: () => import('src/pages/Admin/Event/Test/Show.vue') },
+
+        { name: 'Admin.Event.TestSet.Questions.Index', path: 'test_set/:test_set_id/questions', component: () => import('src/pages/Admin/Event/Question/Index.vue') },
+        { name: 'Admin.Event.TestSet.Questions.Create', path: 'test_set/questions/create', component: () => import('src/pages/Admin/Event/Question/Create.vue') },
+        { name: 'Admin.Event.TestSet.Questions.Show', path: 'test_set/questions/:question_id', component: () => import('src/pages/Admin/Event/Question/Show.vue') },
+
+        { name: 'Admin.Event.TestSet.Test.Create', path: ':event_id/test_set/:test_set_id/test/create', component: () => import('src/pages/Admin/Event/Question/Show.vue') }
+      ]
+    },
+    {
+      name: 'Admin.Classroom.DiscussionCircles',
+      path: 'discussion-circles-classrooms',
+      component: () => import('layouts/bareLayout.vue'),
+      breadcrumbs: { title: 'دوره های آموزشی', route: { name: 'Admin.Classroom.DiscussionCircles.Index' } },
+      children: [
+        { name: 'Admin.Classroom.DiscussionCircles.Index', path: '', component: () => import('src/pages/Admin/DiscussionCirclesClassroom/index.vue') },
+        { name: 'Admin.Classroom.DiscussionCircles.Create', path: 'create', component: () => import('src/pages/Admin/DiscussionCirclesClassroom/create.vue'), breadcrumbs: { title: 'ساخت دوره آموزشی' } },
+        { name: 'Admin.Classroom.DiscussionCircles.Show', path: ':id', component: () => import('src/pages/Admin/DiscussionCirclesClassroom/show.vue'), breadcrumbs: { title: 'مشاهده اطلاعات دوره آموزشی' } },
+        { name: 'Admin.Classroom.DiscussionCircles.Ticket', path: 'ticket', component: () => import('src/pages/Admin/DiscussionCirclesClassroom/Ticket.vue'), breadcrumbs: { title: 'درخواست ها دوره های آموزشی' } }
+      ]
+    },
+    {
+      path: 'content',
+      name: 'Admin.Content',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        { path: '', name: 'Admin.Content.List', component: () => import('src/pages/Admin/Content/List.vue') },
+        { path: 'create', name: 'Admin.Content.Create', component: () => import('src/pages/Admin/Content/Create.vue') },
+        { path: ':id', name: 'Admin.Content.Show', component: () => import('src/pages/Admin/Content/Show.vue') },
+        { name: 'Admin.Content.Ticket', path: 'ticket', component: () => import('src/pages/Admin/Content/Ticket.vue'), breadcrumbs: { title: 'درخواست ها دوره های آموزشی' } }
+      ]
+    },
+    {
+      path: 'donation',
+      name: 'Admin.Donation',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        { path: '', name: 'Admin.Donation.List', component: () => import('src/pages/Admin/Donation/List.vue') },
+        { path: 'create', name: 'Admin.Donation.Create', component: () => import('src/pages/Admin/Donation/Create.vue') },
+        { path: ':id', name: 'Admin.Donation.Show', component: () => import('src/pages/Admin/Donation/Show.vue') }
+      ]
+    },
+    {
+      path: 'post',
+      name: 'Admin.Post',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        { path: '', name: 'Admin.Post.List', component: () => import('src/pages/Admin/Post/List.vue') },
+        { path: 'create', name: 'Admin.Post.Create', component: () => import('src/pages/Admin/Post/Create.vue') },
+        { path: ':id', name: 'Admin.Post.Show', component: () => import('src/pages/Admin/Post/Show.vue') }
+      ]
+    },
+    {
+      path: 'media',
+      name: 'Admin.Media',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        // { path: '', name: 'Admin.Content.List', component: () => import('src/pages/Admin/Content/List.vue') },
+        // { path: 'create', name: 'Admin.Content.Create', component: () => import('src/pages/Admin/Content/Create.vue') },
+        { path: ':id', name: 'Admin.Media.Show', component: () => import('src/pages/Admin/Media/Show.vue') }
+        // { name: 'Admin.Content.Ticket', path: 'ticket', component: () => import('src/pages/Admin/Classroom/Ticket.vue'), breadcrumbs: { title: 'درخواست ها دوره های آموزشی' } }
+      ]
+    },
+    {
+      path: 'content-category',
+      name: 'Admin.ContentCategory',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        { path: '', name: 'Admin.ContentCategory.List', component: () => import('src/pages/Admin/ContentCategory/List.vue') },
+        { path: 'create', name: 'Admin.ContentCategory.Create', component: () => import('src/pages/Admin/ContentCategory/Create.vue') },
+        { path: ':id', name: 'Admin.ContentCategory.Show', component: () => import('src/pages/Admin/ContentCategory/Show.vue') }
+      ]
+    },
+    {
+      path: 'donation-category',
+      name: 'Admin.DonationCategory',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        { path: '', name: 'Admin.DonationCategory.List', component: () => import('src/pages/Admin/DonationCategory/List.vue') },
+        { path: 'create', name: 'Admin.DonationCategory.Create', component: () => import('src/pages/Admin/DonationCategory/Create.vue') },
+        { path: ':id', name: 'Admin.DonationCategory.Show', component: () => import('src/pages/Admin/DonationCategory/Show.vue') }
+      ]
+    },
+    {
+      path: 'post-category',
+      name: 'Admin.PostCategory',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        { path: '', name: 'Admin.PostCategory.List', component: () => import('src/pages/Admin/PostCategory/List.vue') },
+        { path: 'create', name: 'Admin.PostCategory.Create', component: () => import('src/pages/Admin/PostCategory/Create.vue') },
+        { path: ':id', name: 'Admin.PostCategory.Show', component: () => import('src/pages/Admin/PostCategory/Show.vue') }
+      ]
+    },
+    {
+      name: 'Admin.Session',
+      path: 'session',
+      component: () => import('layouts/bareLayout.vue'),
+      breadcrumbs: { title: 'طلیعه حکمت' },
+      children: [
+        { name: 'Admin.Session.Index', path: '', component: () => import('src/pages/Admin/Session/index.vue') },
+        { name: 'Admin.Session.Create', path: 'create', component: () => import('src/pages/Admin/Session/create.vue') },
+        { name: 'Admin.Session.Show', path: ':id', component: () => import('src/pages/Admin/Session/show.vue') },
+        { name: 'Admin.Session.UserClass', path: ':session_id/user/:user_id', component: () => import('src/pages/Admin/Session/showUserSession.vue') }
+      ]
+    },
+    {
+      path: 'invoice',
+      name: 'Admin.Invoice',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        {
+          path: '',
+          name: 'Admin.Invoice.List',
+          component: () => import('src/pages/Admin/Invoice/List.vue')
+        },
+        {
+          path: ':id',
+          name: 'Admin.Invoice.Show',
+          component: () => import('src/pages/Admin/Invoice/Show.vue')
+        },
+        {
+          path: 'ticket',
+          name: 'Admin.Invoice.Ticket',
+          component: () => import('layouts/bareLayout.vue'),
+          children: [
+            {
+              path: '',
+              name: 'Admin.Invoice.Ticket.List',
+              component: () => import('src/pages/Admin/Invoice/Ticket/List.vue')
+            },
+            {
+              path: ':id',
+              name: 'Admin.Invoice.Ticket.Show',
+              component: () => import('src/pages/Admin/Invoice/Ticket/Show.vue')
+            }
+          ]
+        }
+      ]
+    },
+    {
+      path: 'payment',
+      name: 'Admin.Payment',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        {
+          path: '',
+          name: 'Admin.Payment.List',
+          component: () => import('src/pages/Admin/Payment/List.vue')
+        },
+        {
+          path: ':id',
+          name: 'Admin.Payment.Show',
+          component: () => import('src/pages/Admin/Payment/Show.vue')
+        }
+      ]
+    },
+    {
+      path: 'transaction',
+      name: 'Admin.Transaction',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        {
+          path: '',
+          name: 'Admin.Transaction.List',
+          component: () => import('src/pages/Admin/Transaction/List.vue')
+        },
+        {
+          path: ':id',
+          name: 'Admin.Transaction.Show',
+          component: () => import('src/pages/Admin/Transaction/Show.vue')
+        }
+      ]
+    }
+  ]
+}

+ 30 - 0
src/router/public/Auth.js

@@ -0,0 +1,30 @@
+export default {
+  path: '/auth',
+  name: 'Auth',
+  layoutConfig: {
+    layoutHeaderVisible: false,
+    layoutHeader: false,
+    layoutLeftDrawer: false,
+    layoutFooter: false,
+    layoutFooterVisible: false
+  },
+  component: () => import('layouts/bareLayout.vue'),
+  children: [
+    {
+      path: '/login/admin',
+      name: 'AdminLogin',
+      // meta: {
+      //   middlewares: [notLogedIn]
+      // },
+      component: () => import('src/pages/Auth/Login.vue')
+    },
+    {
+      path: '/login',
+      name: 'Login',
+      // meta: {
+      //   middlewares: [notLogedIn]
+      // },
+      component: () => import('src/pages/Auth/Login.vue')
+    }
+  ]
+}

+ 47 - 0
src/router/public/Document.js

@@ -0,0 +1,47 @@
+import { Authenticated } from 'src/router/middleware/middleware'
+
+export default {
+  path: 'document',
+  name: 'Document',
+  component: () => import('layouts/bareLayout.vue'),
+  children: [
+    {
+      path: 'component',
+      name: 'component',
+      component: () => import('src/pages/Document/component.vue'),
+      breadcrumbs: { title: 'component' },
+      meta: {
+        middlewares: [Authenticated]
+      }
+    },
+    {
+      path: 'theme',
+      name: 'Document.Theme',
+      component: () => import('layouts/bareLayout.vue'),
+      breadcrumbs: { title: 'Theme' },
+      children: [
+        {
+          path: 'controls',
+          name: 'Document.Theme.Controls',
+          component: () => import('src/pages/Document/Theme/Controls.vue'),
+          breadcrumbs: { title: 'Controls' }
+        }
+      ]
+    },
+    {
+      path: 'debug',
+      name: 'Document.Debug',
+      component: () => import('src/pages/Document/debug.vue')
+    },
+    {
+      path: 'icon-sax',
+      name: 'Document.IconSax',
+      component: () => import('src/pages/Document/IconSax.vue')
+    },
+    {
+      path: '/form-generator',
+      name: 'formGenerator',
+      component: () => import('src/pages/Document/formGenerator.vue')
+    }
+  ]
+}

+ 108 - 0
src/router/public/Public.js

@@ -0,0 +1,108 @@
+import { canSeeUserProfilePanel } from 'src/router/middleware/middleware'
+
+export default {
+  path: '',
+  name: 'Public',
+  component: () => import('layouts/bareLayout.vue'),
+  meta: { middlewares: [canSeeUserProfilePanel] },
+  children: [
+    {
+      name: 'Public.Home',
+      path: '',
+      layoutConfig: {
+        layoutView: 'lhh Lpr fff'
+      },
+      meta: {
+        hasDynamicSetting: true
+      },
+      component: () => import('src/pages/Public/index.vue')
+    },
+    {
+      path: 'post',
+      name: 'Public.Post',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        { path: '', name: 'Public.Post.List', component: () => import('src/pages/Public/Post/List.vue') },
+        { path: 'news', name: 'Public.Post.List.News', component: () => import('src/pages/Public/Post/News.vue') },
+        { path: 'guide', name: 'Public.Post.List.Guide', component: () => import('src/pages/Public/Post/Guide.vue') },
+        { path: ':id', name: 'Public.Post.Show', component: () => import('src/pages/Public/Post/Show.vue') }
+      ]
+    },
+    { path: 'post_category/:category_id', name: 'Public.PostCategory.Show', component: () => import('src/pages/Public/Post/ChildCategoryPostList.vue') },
+    {
+      name: 'Public.AllClassrooms',
+      path: 'all-classrooms',
+      meta: {
+        hasDynamicSetting: true
+      },
+      component: () => import('src/pages/Public/classrooms.vue')
+    },
+    {
+      name: 'Public.ShowClassroomInfo',
+      path: 'classroom/:id',
+      meta: {
+        hasDynamicSetting: true
+      },
+      component: () => import('src/pages/Public/ShowClassroomInfo.vue')
+    },
+    {
+      name: 'Public.AllEvents',
+      path: 'all-events',
+      meta: {
+        hasDynamicSetting: true
+      },
+      component: () => import('src/pages/Public/Events.vue')
+    },
+    {
+      name: 'Public.ShowEventInfo',
+      path: 'event/:id',
+      meta: {
+        hasDynamicSetting: true
+      },
+      component: () => import('src/pages/Public/ShowEventInfo.vue')
+    },
+    {
+      path: 'donation-category',
+      name: 'Public.DonationCategory',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        { path: '', name: 'Public.DonationCategory.List', component: () => import('src/pages/BasicDynamicPage.vue') },
+        { path: ':donation_category_id', name: 'Public.DonationCategory.Show', component: () => import('src/pages/BasicDynamicPage.vue') },
+        { path: ':donation_category_id/donation', name: 'Public.DonationCategory.Donation.list', component: () => import('src/pages/BasicDynamicPage.vue') },
+        { path: ':donation_category_id/donation/:donation_id', name: 'Public.DonationCategory.Donation.Show', component: () => import('src/pages/BasicDynamicPage.vue') }
+      ]
+    },
+    {
+      name: 'Public.FAQ',
+      path: 'faq',
+      meta: {
+        hasDynamicSetting: true
+      },
+      component: () => import('src/pages/Public/FAQ.vue')
+    },
+    {
+      name: 'Public.Rules',
+      path: 'rules',
+      meta: {
+        hasDynamicSetting: true
+      },
+      component: () => import('src/pages/Public/Rules.vue')
+    },
+    {
+      name: 'Public.AboutUs',
+      path: 'about-us',
+      meta: {
+        hasDynamicSetting: true
+      },
+      component: () => import('src/pages/Public/AboutUs.vue')
+    },
+    {
+      name: 'Public.ContactUs',
+      path: 'contact-us',
+      meta: {
+        hasDynamicSetting: true
+      },
+      component: () => import('src/pages/Public/ContactUs.vue')
+    }
+  ]
+}

+ 364 - 0
src/router/public/UserPanel.js

@@ -0,0 +1,364 @@
+import { Authenticated, canSeeUserProfilePanel, HasOverdueInstalment } from 'src/router/middleware/middleware'
+
+export default {
+  path: 'panel',
+  name: 'UserPanel',
+  layoutConfig: {
+    layoutView: 'hHh LpR lfr',
+    layoutHeaderType: 'user-panel',
+    layoutHeaderBordered: true,
+    layoutLeftDrawer: true,
+    layoutLeftDrawerVisible: true,
+    layoutLeftSideBarType: 'user-panel',
+    layoutLeftDrawerBordered: true,
+    layoutLeftDrawerWidth: 240,
+    layoutFooterType: 'panel',
+    layoutFooter: true
+  },
+  meta: { middlewares: [Authenticated, canSeeUserProfilePanel] },
+  component: () => import('src/layouts/UserPanelLayout.vue'),
+  children: [
+    {
+      name: 'UserPanel.ShopCompleteInfo',
+      path: 'shop/completeInfo',
+      layoutConfig: {
+        layoutView: 'hHh LpR fff',
+        layoutHeaderType: 'main',
+        layoutHeaderBordered: true,
+        layoutLeftDrawer: false,
+        layoutLeftDrawerVisible: false,
+        layoutFooter: true
+      },
+      component: () => import('src/pages/User/Shop/completeInfo.vue')
+    },
+    {
+      name: 'UserPanel.ShopPaymentFromWallet',
+      path: 'shop/payment-from-wallet',
+      layoutConfig: {
+        layoutView: 'hHh LpR fff',
+        layoutHeaderType: 'main',
+        layoutHeaderBordered: true,
+        layoutLeftDrawer: false,
+        layoutLeftDrawerVisible: false,
+        layoutFooter: true
+      },
+      meta: { middlewares: [Authenticated] },
+      component: () => import('src/pages/User/Shop/paymentFromWallet.vue')
+    },
+    {
+      name: 'UserPanel.PaymentResult',
+      path: 'shop/payment-result',
+      meta: { middlewares: [Authenticated] },
+      component: () => import('src/pages/User/Shop/paymentResult.vue')
+    },
+    {
+      path: 'profile',
+      name: 'UserPanel.Profile',
+      component: () => import('src/layouts/bareLayout.vue'),
+      meta: { middlewares: [Authenticated] },
+      children: [
+        {
+          name: 'UserPanel.Profile.OverdueInstalments',
+          path: 'overdue-instalments',
+          component: () => import('src/pages/User/Profile/OverdueInstalment.vue')
+        },
+        {
+          name: 'UserPanel.Profile.AllDiscussionCirclesClassrooms',
+          path: 'all-discussion-circles-classrooms',
+          component: () => import('src/pages/User/Profile/DiscussionCirclesClassrooms.vue'),
+          meta: {
+            breadcrumbs: {
+              visible: true,
+              loading: false,
+              path: [
+                {
+                  label: 'حلقه های مباحثاتی من',
+                  to: { name: 'UserPanel.Profile.AllDiscussionCirclesClassrooms' }
+                }
+              ]
+            },
+            middlewares: [HasOverdueInstalment]
+          }
+        },
+        {
+          name: 'UserPanel.Profile.AllClassrooms',
+          path: 'all-classrooms',
+          component: () => import('src/pages/User/Profile/classrooms.vue'),
+          meta: {
+            breadcrumbs: {
+              visible: true,
+              loading: false,
+              path: [
+                {
+                  label: 'دوره های من',
+                  to: { name: 'UserPanel.Profile.AllClassrooms' }
+                }
+              ]
+            },
+            middlewares: [HasOverdueInstalment]
+          }
+        },
+        {
+          name: 'UserPanel.Profile.ClassroomInfo',
+          path: 'classroom/:id',
+          component: () => import('src/pages/User/Profile/classroomInfo.vue'),
+          meta: {
+            middlewares: [HasOverdueInstalment]
+          }
+        },
+        {
+          name: 'UserPanel.Profile.Test',
+          path: 'test/:id',
+          component: () => import('src/pages/User/Profile/test.vue'),
+          meta: {
+            middlewares: [HasOverdueInstalment]
+          }
+        },
+        {
+          name: 'UserPanel.Profile.AllEvents',
+          path: 'all-events',
+          component: () => import('src/pages/User/Profile/Events.vue'),
+          meta: {
+            breadcrumbs: {
+              visible: true,
+              loading: false,
+              path: [
+                {
+                  label: 'رویدادهای من',
+                  to: { name: 'UserPanel.Profile.AllEvents' }
+                }
+              ]
+            },
+            middlewares: [HasOverdueInstalment]
+          }
+        },
+        {
+          name: 'UserPanel.Profile.EventInfo',
+          path: 'event/:id',
+          component: () => import('src/pages/User/Profile/EventInfo.vue'),
+          meta: {
+            middlewares: [HasOverdueInstalment]
+          }
+        },
+        { name: 'UserPanel.Profile.Classroom.Project.Show', path: 'classroom/:classroom_id/project/:project_id', component: () => import('src/pages/User/Profile/projectInfo.vue') },
+        {
+          name: 'UserPanel.Profile.SessionInfo',
+          path: 'session/:id',
+          component: () => import('src/pages/User/Profile/sessionInfo.vue'),
+          meta: {
+            middlewares: [HasOverdueInstalment]
+          }
+        },
+        {
+          name: 'UserPanel.Profile.UserInfo',
+          path: 'user-info',
+          component: () => import('src/pages/User/Profile/profile.vue')
+        },
+        {
+          name: 'UserPanel.Leader',
+          path: 'leader',
+          component: () => import('layouts/bareLayout.vue'),
+          children: [
+            { name: 'UserPanel.Leader.Teams.Index', path: 'teams', component: () => import('pages/Admin/Leader/MyTeams.vue') },
+            { name: 'UserPanel.Leader.Teams.Show', path: 'teams/:team_id', component: () => import('pages/Admin/Leader/ShowTeam.vue') }
+          ]
+        },
+        {
+          name: 'UserPanel.Test',
+          path: 'test/:test_id',
+          component: () => import('layouts/bareLayout.vue'),
+          children: [
+            { name: 'UserPanel.Test.AnswerBook.Confirmation', path: 'answer_book/:answer_book_id/confirmation', component: () => import('src/pages/User/Test/Confirmation.vue') },
+            { name: 'UserPanel.Test.AnswerBook.Participate.AllQuestions', path: 'answer_book/:answer_book_id/participate/all_questions', component: () => import('src/pages/User/Test/ParticipateAllQuestions.vue') },
+            { name: 'UserPanel.Test.AnswerBook.Participate.SingleQuestion', path: 'answer_book/:answer_book_id/participate/question/:question_number', component: () => import('src/pages/User/Test/ParticipateSingleQuestion.vue') },
+            { name: 'UserPanel.Test.AnswerBook.Show', path: 'answer_book/:answer_book_id/show', component: () => import('src/pages/User/Test/Show.vue') },
+            { name: 'UserPanel.Test.AnswerBook.SendObjection', path: 'answer_book/:answer_book_id/sendObjection', component: () => import('src/pages/User/Test/SendObjection.vue') }
+          ]
+        },
+        {
+          name: 'UserPanel.Classroom.MyAsGraderClassroom',
+          path: 'my_as_a_grader_classrooms',
+          component: () => import('src/layouts/bareLayout.vue'),
+          children: [
+            { name: 'UserPanel.Classroom.MyAsGraderClassroom.Index', path: '', component: () => import('src/pages/Admin/Classroom/MyAsGraderClassrooms.vue') },
+            { name: 'UserPanel.Classroom.MyAsGraderClassroom.AnswerBooks', path: ':classroom_id/answer_books', component: () => import('src/pages/Admin/Classroom/ClassroomAnswerBooksForGrader.vue') },
+            { name: 'UserPanel.Classroom.MyAsGraderClassroom.AnswerBooks.ShowGrade', path: ':classroom_id/answer_books/:answer_book_id/show_grades', component: () => import('src/pages/Admin/Classroom/ClassroomAnswerBookShowGradeForGrader.vue') },
+            { name: 'UserPanel.Classroom.MyAsGraderClassroom.AnswerBooks.SubmitGrade', path: ':classroom_id/answer_books/:answer_book_id/submit_grade', component: () => import('src/pages/Admin/Classroom/ClassroomAnswerBookSubmitGrade.vue') }
+          ]
+        }
+      ]
+    },
+    {
+      path: 'invoice',
+      name: 'UserPanel.Invoice',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        {
+          path: '',
+          name: 'UserPanel.Invoice.List',
+          meta: {
+            breadcrumbs: {
+              visible: true,
+              loading: false,
+              path: [
+                {
+                  label: 'بخش مالی'
+                },
+                {
+                  label: 'صورتحساب ها',
+                  to: { name: 'UserPanel.Invoice.List' }
+                }
+              ]
+            }
+          },
+          component: () => import('src/pages/User/Invoice/List.vue')
+        },
+        {
+          path: 'thankyou',
+          name: 'UserPanel.Invoice.Thankyou',
+          component: () => import('src/pages/User/Invoice/Thankyou.vue')
+        },
+        {
+          path: ':id',
+          name: 'UserPanel.Invoice.Show',
+          meta: {
+            breadcrumbs: {
+              visible: true,
+              loading: false,
+              path: [
+                {
+                  label: 'بخش مالی'
+                },
+                {
+                  label: 'صورتحساب ها',
+                  to: { name: 'UserPanel.Invoice.List' }
+                },
+                {
+                  label: 'جزییات صورتحساب'
+                }
+              ]
+            }
+          },
+          component: () => import('src/pages/User/Invoice/Show.vue')
+        },
+        {
+          path: 'ticket',
+          name: 'UserPanel.Invoice.Ticket',
+          component: () => import('layouts/bareLayout.vue'),
+          children: [
+            {
+              path: '',
+              name: 'UserPanel.Invoice.Ticket.List',
+              component: () => import('src/pages/User/Invoice/Ticket/List.vue')
+            },
+            {
+              path: ':id',
+              name: 'UserPanel.Invoice.Ticket.Show',
+              component: () => import('src/pages/User/Invoice/Ticket/Show.vue')
+            },
+            {
+              path: 'create',
+              name: 'UserPanel.Invoice.Ticket.Create',
+              component: () => import('src/pages/User/Invoice/Ticket/Create.vue')
+            }
+          ]
+        }
+      ]
+    },
+    {
+      path: 'ticket',
+      name: 'UserPanel.Ticket',
+      component: () => import('layouts/bareLayout.vue'),
+      children: [
+        {
+          path: '',
+          name: 'UserPanel.Ticket.List',
+          component: () => import('src/pages/User/Ticket/List.vue')
+        },
+        {
+          path: ':id',
+          name: 'UserPanel.Ticket.Show',
+          meta: {
+            breadcrumbs: {
+              visible: true,
+              loading: false,
+              path: [
+                {
+                  label: 'درخواست ها',
+                  to: { name: 'UserPanel.Ticket.List' }
+                },
+                {
+                  label: 'جزییات درخواست'
+                }
+              ]
+            }
+          },
+          component: () => import('src/pages/User/Ticket/Show.vue')
+        },
+        {
+          path: 'create',
+          name: 'UserPanel.Ticket.Create',
+          meta: { middlewares: [Authenticated] },
+          component: () => import('src/pages/User/Ticket/Create.vue')
+        }
+      ]
+    },
+    {
+      path: 'wallet',
+      name: 'UserPanel.Wallet',
+      component: () => import('src/pages/User/Wallet/Show.vue'),
+      meta: {
+        breadcrumbs: {
+          visible: true,
+          loading: false,
+          path: [
+            {
+              label: 'بخش مالی'
+            },
+            {
+              label: 'کیف پول الکترونیک',
+              to: { name: 'UserPanel.Wallet' }
+            }
+          ]
+        }
+      }
+    },
+    {
+      path: 'payment',
+      name: 'UserPanel.Payment',
+      component: () => import('src/layouts/bareLayout.vue'),
+      children: [
+        {
+          path: '',
+          name: 'UserPanel.Payment.List',
+          component: () => import('src/pages/User/Payment/List.vue')
+        },
+        {
+          path: 'transactions',
+          name: 'UserPanel.Payment.TransactionList',
+          component: () => import('src/pages/User/Payment/TransactionList.vue')
+        },
+        {
+          name: 'UserPanel.Payment.Show',
+          path: ':id',
+          component: () => import('src/pages/User/Payment/Show.vue'),
+          meta: {
+            breadcrumbs: {
+              visible: true,
+              loading: false,
+              path: [
+                {
+                  label: 'کیف پول الکترونیک',
+                  to: { name: 'UserPanel.Wallet' }
+                },
+                {
+                  label: 'جزییات پرداخت'
+                }
+              ]
+            }
+          }
+        }
+      ]
+    }
+  ]
+}

+ 10 - 864
src/router/routes.js

@@ -1,4 +1,8 @@
-import { /* notLogedIn, */Authenticated, canSeeAdminPanel, canSeeUserProfilePanel, HasOverdueInstalment } from './middleware/middleware.js'
+import Auth from 'src/router/public/Auth.js'
+import Admin from 'src/router/public/Admin.js'
+import Public from 'src/router/public/Public.js'
+import Document from 'src/router/public/Document.js'
+import UserPanel from 'src/router/public/UserPanel.js'
 
 const routes = [
   {
@@ -37,869 +41,11 @@ const routes = [
       hasDynamicSetting: true
     },
     children: [
-      {
-        path: '/auth',
-        name: 'Auth',
-        layoutConfig: {
-          layoutHeaderVisible: false,
-          layoutHeader: false,
-          layoutLeftDrawer: false,
-          layoutFooter: false,
-          layoutFooterVisible: false
-        },
-        component: () => import('layouts/bareLayout.vue'),
-        children: [
-          {
-            path: '/login/admin',
-            name: 'AdminLogin',
-            // meta: {
-            //   middlewares: [notLogedIn]
-            // },
-            component: () => import('src/pages/Auth/Login.vue')
-          },
-          {
-            path: '/login',
-            name: 'Login',
-            // meta: {
-            //   middlewares: [notLogedIn]
-            // },
-            component: () => import('src/pages/Auth/Login.vue')
-          }
-        ]
-      },
-      {
-        path: '',
-        name: 'Public',
-        component: () => import('layouts/bareLayout.vue'),
-        meta: { middlewares: [canSeeUserProfilePanel] },
-        children: [
-          {
-            name: 'Public.Home',
-            path: '',
-            layoutConfig: {
-              layoutView: 'lhh Lpr fff'
-            },
-            meta: {
-              hasDynamicSetting: true
-            },
-            component: () => import('src/pages/Public/index.vue')
-          },
-          {
-            path: 'post',
-            name: 'Public.Post',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              { path: '', name: 'Public.Post.List', component: () => import('src/pages/Public/Post/List.vue') },
-              { path: 'news', name: 'Public.Post.List.News', component: () => import('src/pages/Public/Post/News.vue') },
-              { path: 'guide', name: 'Public.Post.List.Guide', component: () => import('src/pages/Public/Post/Guide.vue') },
-              { path: ':id', name: 'Public.Post.Show', component: () => import('src/pages/Public/Post/Show.vue') }
-            ]
-          },
-          { path: 'post_category/:category_id', name: 'Public.PostCategory.Show', component: () => import('src/pages/Public/Post/ChildCategoryPostList.vue') },
-          {
-            name: 'Public.AllClassrooms',
-            path: 'all-classrooms',
-            meta: {
-              hasDynamicSetting: true
-            },
-            component: () => import('src/pages/Public/classrooms.vue')
-          },
-          {
-            name: 'Public.ShowClassroomInfo',
-            path: 'classroom/:id',
-            meta: {
-              hasDynamicSetting: true
-            },
-            component: () => import('src/pages/Public/ShowClassroomInfo.vue')
-          },
-          {
-            name: 'Public.AllEvents',
-            path: 'all-events',
-            meta: {
-              hasDynamicSetting: true
-            },
-            component: () => import('src/pages/Public/Events.vue')
-          },
-          {
-            name: 'Public.ShowEventInfo',
-            path: 'event/:id',
-            meta: {
-              hasDynamicSetting: true
-            },
-            component: () => import('src/pages/Public/ShowEventInfo.vue')
-          },
-          {
-            name: 'Public.FAQ',
-            path: 'faq',
-            meta: {
-              hasDynamicSetting: true
-            },
-            component: () => import('src/pages/Public/FAQ.vue')
-          },
-          {
-            name: 'Public.Rules',
-            path: 'rules',
-            meta: {
-              hasDynamicSetting: true
-            },
-            component: () => import('src/pages/Public/Rules.vue')
-          },
-          {
-            name: 'Public.AboutUs',
-            path: 'about-us',
-            meta: {
-              hasDynamicSetting: true
-            },
-            component: () => import('src/pages/Public/AboutUs.vue')
-          },
-          {
-            name: 'Public.ContactUs',
-            path: 'contact-us',
-            meta: {
-              hasDynamicSetting: true
-            },
-            component: () => import('src/pages/Public/ContactUs.vue')
-          }
-        ]
-      },
-      {
-        path: 'panel',
-        name: 'UserPanel',
-        layoutConfig: {
-          layoutView: 'hHh LpR lfr',
-          layoutHeaderType: 'user-panel',
-          layoutHeaderBordered: true,
-          layoutLeftDrawer: true,
-          layoutLeftDrawerVisible: true,
-          layoutLeftSideBarType: 'user-panel',
-          layoutLeftDrawerBordered: true,
-          layoutLeftDrawerWidth: 240,
-          layoutFooterType: 'panel',
-          layoutFooter: true
-        },
-        meta: { middlewares: [Authenticated, canSeeUserProfilePanel] },
-        component: () => import('src/layouts/UserPanelLayout.vue'),
-        children: [
-          {
-            name: 'UserPanel.ShopCompleteInfo',
-            path: 'shop/completeInfo',
-            layoutConfig: {
-              layoutView: 'hHh LpR fff',
-              layoutHeaderType: 'main',
-              layoutHeaderBordered: true,
-              layoutLeftDrawer: false,
-              layoutLeftDrawerVisible: false,
-              layoutFooter: true
-            },
-            component: () => import('src/pages/User/Shop/completeInfo.vue')
-          },
-          {
-            name: 'UserPanel.ShopPaymentFromWallet',
-            path: 'shop/payment-from-wallet',
-            layoutConfig: {
-              layoutView: 'hHh LpR fff',
-              layoutHeaderType: 'main',
-              layoutHeaderBordered: true,
-              layoutLeftDrawer: false,
-              layoutLeftDrawerVisible: false,
-              layoutFooter: true
-            },
-            meta: { middlewares: [Authenticated] },
-            component: () => import('src/pages/User/Shop/paymentFromWallet.vue')
-          },
-          {
-            name: 'UserPanel.PaymentResult',
-            path: 'shop/payment-result',
-            meta: { middlewares: [Authenticated] },
-            component: () => import('src/pages/User/Shop/paymentResult.vue')
-          },
-          {
-            path: 'profile',
-            name: 'UserPanel.Profile',
-            component: () => import('src/layouts/bareLayout.vue'),
-            meta: { middlewares: [Authenticated] },
-            children: [
-              {
-                name: 'UserPanel.Profile.OverdueInstalments',
-                path: 'overdue-instalments',
-                component: () => import('src/pages/User/Profile/OverdueInstalment.vue')
-              },
-              {
-                name: 'UserPanel.Profile.AllDiscussionCirclesClassrooms',
-                path: 'all-discussion-circles-classrooms',
-                component: () => import('src/pages/User/Profile/DiscussionCirclesClassrooms.vue'),
-                meta: {
-                  breadcrumbs: {
-                    visible: true,
-                    loading: false,
-                    path: [
-                      {
-                        label: 'حلقه های مباحثاتی من',
-                        to: { name: 'UserPanel.Profile.AllDiscussionCirclesClassrooms' }
-                      }
-                    ]
-                  },
-                  middlewares: [HasOverdueInstalment]
-                }
-              },
-              {
-                name: 'UserPanel.Profile.AllClassrooms',
-                path: 'all-classrooms',
-                component: () => import('src/pages/User/Profile/classrooms.vue'),
-                meta: {
-                  breadcrumbs: {
-                    visible: true,
-                    loading: false,
-                    path: [
-                      {
-                        label: 'دوره های من',
-                        to: { name: 'UserPanel.Profile.AllClassrooms' }
-                      }
-                    ]
-                  },
-                  middlewares: [HasOverdueInstalment]
-                }
-              },
-              {
-                name: 'UserPanel.Profile.ClassroomInfo',
-                path: 'classroom/:id',
-                component: () => import('src/pages/User/Profile/classroomInfo.vue'),
-                meta: {
-                  middlewares: [HasOverdueInstalment]
-                }
-              },
-              {
-                name: 'UserPanel.Profile.Test',
-                path: 'test/:id',
-                component: () => import('src/pages/User/Profile/test.vue'),
-                meta: {
-                  middlewares: [HasOverdueInstalment]
-                }
-              },
-              {
-                name: 'UserPanel.Profile.AllEvents',
-                path: 'all-events',
-                component: () => import('src/pages/User/Profile/Events.vue'),
-                meta: {
-                  breadcrumbs: {
-                    visible: true,
-                    loading: false,
-                    path: [
-                      {
-                        label: 'رویدادهای من',
-                        to: { name: 'UserPanel.Profile.AllEvents' }
-                      }
-                    ]
-                  },
-                  middlewares: [HasOverdueInstalment]
-                }
-              },
-              {
-                name: 'UserPanel.Profile.EventInfo',
-                path: 'event/:id',
-                component: () => import('src/pages/User/Profile/EventInfo.vue'),
-                meta: {
-                  middlewares: [HasOverdueInstalment]
-                }
-              },
-              { name: 'UserPanel.Profile.Classroom.Project.Show', path: 'classroom/:classroom_id/project/:project_id', component: () => import('src/pages/User/Profile/projectInfo.vue') },
-              {
-                name: 'UserPanel.Profile.SessionInfo',
-                path: 'session/:id',
-                component: () => import('src/pages/User/Profile/sessionInfo.vue'),
-                meta: {
-                  middlewares: [HasOverdueInstalment]
-                }
-              },
-              {
-                name: 'UserPanel.Profile.UserInfo',
-                path: 'user-info',
-                component: () => import('src/pages/User/Profile/profile.vue')
-              },
-              {
-                name: 'UserPanel.Leader',
-                path: 'leader',
-                component: () => import('layouts/bareLayout.vue'),
-                children: [
-                  { name: 'UserPanel.Leader.Teams.Index', path: 'teams', component: () => import('pages/Admin/Leader/MyTeams.vue') },
-                  { name: 'UserPanel.Leader.Teams.Show', path: 'teams/:team_id', component: () => import('pages/Admin/Leader/ShowTeam.vue') }
-                ]
-              },
-              {
-                name: 'UserPanel.Test',
-                path: 'test/:test_id',
-                component: () => import('layouts/bareLayout.vue'),
-                children: [
-                  { name: 'UserPanel.Test.AnswerBook.Confirmation', path: 'answer_book/:answer_book_id/confirmation', component: () => import('src/pages/User/Test/Confirmation.vue') },
-                  { name: 'UserPanel.Test.AnswerBook.Participate.AllQuestions', path: 'answer_book/:answer_book_id/participate/all_questions', component: () => import('src/pages/User/Test/ParticipateAllQuestions.vue') },
-                  { name: 'UserPanel.Test.AnswerBook.Participate.SingleQuestion', path: 'answer_book/:answer_book_id/participate/question/:question_number', component: () => import('src/pages/User/Test/ParticipateSingleQuestion.vue') },
-                  { name: 'UserPanel.Test.AnswerBook.Show', path: 'answer_book/:answer_book_id/show', component: () => import('src/pages/User/Test/Show.vue') },
-                  { name: 'UserPanel.Test.AnswerBook.SendObjection', path: 'answer_book/:answer_book_id/sendObjection', component: () => import('src/pages/User/Test/SendObjection.vue') }
-                ]
-              },
-              {
-                name: 'UserPanel.Classroom.MyAsGraderClassroom',
-                path: 'my_as_a_grader_classrooms',
-                component: () => import('src/layouts/bareLayout.vue'),
-                children: [
-                  { name: 'UserPanel.Classroom.MyAsGraderClassroom.Index', path: '', component: () => import('src/pages/Admin/Classroom/MyAsGraderClassrooms.vue') },
-                  { name: 'UserPanel.Classroom.MyAsGraderClassroom.AnswerBooks', path: ':classroom_id/answer_books', component: () => import('src/pages/Admin/Classroom/ClassroomAnswerBooksForGrader.vue') },
-                  { name: 'UserPanel.Classroom.MyAsGraderClassroom.AnswerBooks.ShowGrade', path: ':classroom_id/answer_books/:answer_book_id/show_grades', component: () => import('src/pages/Admin/Classroom/ClassroomAnswerBookShowGradeForGrader.vue') },
-                  { name: 'UserPanel.Classroom.MyAsGraderClassroom.AnswerBooks.SubmitGrade', path: ':classroom_id/answer_books/:answer_book_id/submit_grade', component: () => import('src/pages/Admin/Classroom/ClassroomAnswerBookSubmitGrade.vue') }
-                ]
-              }
-            ]
-          },
-          {
-            path: 'invoice',
-            name: 'UserPanel.Invoice',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              {
-                path: '',
-                name: 'UserPanel.Invoice.List',
-                meta: {
-                  breadcrumbs: {
-                    visible: true,
-                    loading: false,
-                    path: [
-                      {
-                        label: 'بخش مالی'
-                      },
-                      {
-                        label: 'صورتحساب ها',
-                        to: { name: 'UserPanel.Invoice.List' }
-                      }
-                    ]
-                  }
-                },
-                component: () => import('src/pages/User/Invoice/List.vue')
-              },
-              {
-                path: 'thankyou',
-                name: 'UserPanel.Invoice.Thankyou',
-                component: () => import('src/pages/User/Invoice/Thankyou.vue')
-              },
-              {
-                path: ':id',
-                name: 'UserPanel.Invoice.Show',
-                meta: {
-                  breadcrumbs: {
-                    visible: true,
-                    loading: false,
-                    path: [
-                      {
-                        label: 'بخش مالی'
-                      },
-                      {
-                        label: 'صورتحساب ها',
-                        to: { name: 'UserPanel.Invoice.List' }
-                      },
-                      {
-                        label: 'جزییات صورتحساب'
-                      }
-                    ]
-                  }
-                },
-                component: () => import('src/pages/User/Invoice/Show.vue')
-              },
-              {
-                path: 'ticket',
-                name: 'UserPanel.Invoice.Ticket',
-                component: () => import('layouts/bareLayout.vue'),
-                children: [
-                  {
-                    path: '',
-                    name: 'UserPanel.Invoice.Ticket.List',
-                    component: () => import('src/pages/User/Invoice/Ticket/List.vue')
-                  },
-                  {
-                    path: ':id',
-                    name: 'UserPanel.Invoice.Ticket.Show',
-                    component: () => import('src/pages/User/Invoice/Ticket/Show.vue')
-                  },
-                  {
-                    path: 'create',
-                    name: 'UserPanel.Invoice.Ticket.Create',
-                    component: () => import('src/pages/User/Invoice/Ticket/Create.vue')
-                  }
-                ]
-              }
-            ]
-          },
-          {
-            path: 'ticket',
-            name: 'UserPanel.Ticket',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              {
-                path: '',
-                name: 'UserPanel.Ticket.List',
-                component: () => import('src/pages/User/Ticket/List.vue')
-              },
-              {
-                path: ':id',
-                name: 'UserPanel.Ticket.Show',
-                meta: {
-                  breadcrumbs: {
-                    visible: true,
-                    loading: false,
-                    path: [
-                      {
-                        label: 'درخواست ها',
-                        to: { name: 'UserPanel.Ticket.List' }
-                      },
-                      {
-                        label: 'جزییات درخواست'
-                      }
-                    ]
-                  }
-                },
-                component: () => import('src/pages/User/Ticket/Show.vue')
-              },
-              {
-                path: 'create',
-                name: 'UserPanel.Ticket.Create',
-                meta: { middlewares: [Authenticated] },
-                component: () => import('src/pages/User/Ticket/Create.vue')
-              }
-            ]
-          },
-          {
-            path: 'wallet',
-            name: 'UserPanel.Wallet',
-            component: () => import('src/pages/User/Wallet/Show.vue'),
-            meta: {
-              breadcrumbs: {
-                visible: true,
-                loading: false,
-                path: [
-                  {
-                    label: 'بخش مالی'
-                  },
-                  {
-                    label: 'کیف پول الکترونیک',
-                    to: { name: 'UserPanel.Wallet' }
-                  }
-                ]
-              }
-            }
-          },
-          {
-            path: 'payment',
-            name: 'UserPanel.Payment',
-            component: () => import('src/layouts/bareLayout.vue'),
-            children: [
-              {
-                path: '',
-                name: 'UserPanel.Payment.List',
-                component: () => import('src/pages/User/Payment/List.vue')
-              },
-              {
-                path: 'transactions',
-                name: 'UserPanel.Payment.TransactionList',
-                component: () => import('src/pages/User/Payment/TransactionList.vue')
-              },
-              {
-                name: 'UserPanel.Payment.Show',
-                path: ':id',
-                component: () => import('src/pages/User/Payment/Show.vue'),
-                meta: {
-                  breadcrumbs: {
-                    visible: true,
-                    loading: false,
-                    path: [
-                      {
-                        label: 'کیف پول الکترونیک',
-                        to: { name: 'UserPanel.Wallet' }
-                      },
-                      {
-                        label: 'جزییات پرداخت'
-                      }
-                    ]
-                  }
-                }
-              }
-            ]
-          }
-        ]
-      },
-      {
-        path: 'admin',
-        name: 'Admin',
-        layoutConfig: {
-          layoutView: 'hHh LpR lfr',
-          layoutHeaderType: 'admin',
-          layoutHeaderBordered: true,
-          layoutLeftDrawer: true,
-          layoutLeftDrawerVisible: true,
-          layoutLeftSideBarType: 'admin',
-          layoutLeftDrawerBordered: true,
-          layoutLeftDrawerWidth: 240,
-          layoutFooterType: 'panel',
-          layoutFooter: true
-        },
-        meta: { middlewares: [Authenticated, canSeeAdminPanel] },
-        component: () => import('src/layouts/AdminLayout.vue'),
-        children: [
-          {
-            name: 'Admin.Settings',
-            path: 'settings',
-            component: () => import('src/pages/Admin/Settings.vue'),
-            breadcrumbs: { title: 'تنظیمات' }
-          },
-          {
-            name: 'Admin.User',
-            path: 'users',
-            component: () => import('layouts/bareLayout.vue'),
-            breadcrumbs: { title: 'کاربران' },
-            children: [
-              { name: 'Admin.User.Index', path: '', component: () => import('src/pages/Admin/User/index.vue') },
-              { name: 'Admin.User.Show', path: ':id', component: () => import('src/pages/Admin/User/show.vue'), breadcrumbs: { title: 'اطلاعات کاربری' } },
-              { name: 'Admin.User.ClassroomInfo', path: ':id/classroom/:classroom_id', component: () => import('src/pages/Admin/User/UserClassroomInfo.vue'), breadcrumbs: { title: 'اطلاعات کاربری' } }
-            ]
-          },
-          {
-            name: 'Admin.Category',
-            path: 'categories',
-            component: () => import('layouts/bareLayout.vue'),
-            breadcrumbs: { title: 'دسته بندی ها' },
-            children: [
-              { name: 'Admin.Category.Index', path: '', component: () => import('src/pages/Admin/Category/index.vue') },
-              { name: 'Admin.Category.Create', path: 'create', component: () => import('src/pages/Admin/Category/create.vue') },
-              { name: 'Admin.Category.Show', path: ':id', component: () => import('src/pages/Admin/Category/show.vue') }
-            ]
-          },
-          {
-            name: 'Admin.Category.DiscussionCircles',
-            path: 'discussion-circles-categories',
-            component: () => import('layouts/bareLayout.vue'),
-            breadcrumbs: { title: 'دسته بندی ها' },
-            children: [
-              { name: 'Admin.Category.DiscussionCircles.Index', path: '', component: () => import('src/pages/Admin/DiscussionCirclesCategory/index.vue') },
-              { name: 'Admin.Category.DiscussionCircles.Create', path: 'create', component: () => import('src/pages/Admin/DiscussionCirclesCategory/create.vue') },
-              { name: 'Admin.Category.DiscussionCircles.Show', path: ':id', component: () => import('src/pages/Admin/DiscussionCirclesCategory/show.vue') }
-            ]
-          },
-          {
-            name: 'Admin.Unit',
-            path: 'units',
-            component: () => import('src/layouts/bareLayout.vue'),
-            breadcrumbs: { title: 'طلیعه حکمت' },
-            children: [
-              // { name: 'Admin.Category.Index', path: '', component: () => import('src/pages/Admin/Category/index.vue') },
-              // { name: 'Admin.Category.Create', path: 'create', component: () => import('src/pages/Admin/Category/create.vue') },
-              { name: 'Admin.Unit.Show', path: ':id', component: () => import('src/pages/Admin/Unit/show.vue') },
-              {
-                name: 'Admin.Unit.Questions',
-                path: ':unit_id/session_template/:session_template_id/questions',
-                component: () => import('src/layouts/bareLayout.vue'),
-                children: [
-                  { name: 'Admin.Unit.Questions.Index', path: '', component: () => import('src/pages/Admin/Unit/QuestionsList.vue') },
-                  { name: 'Admin.Unit.Questions.Create', path: 'create', component: () => import('src/pages/Admin/Unit/QuestionsCreate.vue') }
-                  // { name: 'Admin.Unit.Questions.Show', path: ':id', component: () => import('src/pages/Admin/Unit/QuestionsShow.vue') }
-                ]
-              },
-              { name: 'Admin.Unit.Questions.Show', path: ':unit_id/questions/:id', component: () => import('src/pages/Admin/Unit/QuestionsShow.vue') },
-              {
-                name: 'Admin.Unit.TestSet',
-                path: ':unit_id/test_set',
-                component: () => import('src/layouts/bareLayout.vue'),
-                children: [
-                  { name: 'Admin.Unit.TestSet.Show', path: ':id', component: () => import('src/pages/Admin/TestSet/Show.vue') },
-                  { name: 'Admin.Unit.TestSet.Create', path: 'create', component: () => import('src/pages/Admin/TestSet/Create.vue') }
-                ]
-              }
-            ]
-          },
-          {
-            name: 'Admin.SessionTemplate',
-            path: 'session-templates',
-            component: () => import('layouts/bareLayout.vue'),
-            breadcrumbs: { title: 'طلیعه حکمت' },
-            children: [
-              { name: 'Admin.SessionTemplate.Index', path: '', component: () => import('src/pages/Admin/SessionTemplate/index.vue') },
-              { name: 'Admin.SessionTemplate.Create', path: 'create', component: () => import('src/pages/Admin/SessionTemplate/create.vue') },
-              { name: 'Admin.SessionTemplate.Show', path: ':id', component: () => import('src/pages/Admin/SessionTemplate/show.vue') }
-            ]
-          },
-          {
-            path: 'ticket',
-            name: 'Admin.Ticket',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              {
-                path: '',
-                name: 'Admin.Ticket.List',
-                component: () => import('src/pages/Admin/Ticket/List.vue')
-              },
-              {
-                path: 'educational',
-                name: 'Admin.Ticket.List.Educational',
-                component: () => import('src/pages/Admin/Ticket/EducationalList.vue')
-              },
-              {
-                path: 'create',
-                name: 'Admin.Ticket.Create',
-                component: () => import('src/pages/Admin/Ticket/Create.vue')
-              },
-              {
-                path: ':id',
-                name: 'Admin.Ticket.Show',
-                component: () => import('src/pages/Admin/Ticket/Show.vue')
-              }
-            ]
-          },
-          {
-            name: 'Admin.Classroom',
-            path: 'classrooms',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              { name: 'Admin.Classroom.Index', path: '', component: () => import('src/pages/Admin/Classroom/index.vue') },
-              { name: 'Admin.Classroom.Create', path: 'create', component: () => import('src/pages/Admin/Classroom/create.vue'), breadcrumbs: { title: 'ساخت دوره آموزشی' } },
-              { name: 'Admin.Classroom.Show', path: ':id', component: () => import('src/pages/Admin/Classroom/show.vue') },
-              { name: 'Admin.Classroom.UserClass', path: ':classroom_id/user/:user_id', component: () => import('src/pages/Admin/Classroom/showUserClass.vue') },
-              { 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') },
-              { name: 'Admin.Classroom.Project.Show', path: ':classroom_id/project/:project_id', component: () => import('src/pages/Admin/Classroom/project/show.vue') },
-              { name: 'Admin.Classroom.Project.UserInfo', path: ':classroom_id/project/:project_id/user/:user_id', component: () => import('src/pages/Admin/Classroom/project/showUserProject.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.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: 'درخواست ها دوره های آموزشی' } },
-
-              { name: 'Admin.Classroom.TestSet.Index', path: ':classroom_id/unit/:unit_id/test_set', component: () => import('src/pages/Admin/TestSet/Index.vue') },
-              { name: 'Admin.Classroom.TestSet.Test.Show', path: ':classroom_id/test_set/:test_set_id/test/:id', component: () => import('src/pages/Admin/Test/Show.vue') },
-              { name: 'Admin.Classroom.TestSet.Test.Create', path: ':classroom_id/test_set/:test_set_id/test/create', component: () => import('src/pages/Admin/Test/Create.vue') },
-
-              { name: 'Admin.Classroom.Test.AnswerBooks.Index', path: ':classroom_id/test/:test_id/answer_books', component: () => import('src/pages/Admin/Classroom/ClassroomAnswerBooks.vue') },
-              { name: 'Admin.Classroom.Test.AnswerBooks.ShowGrade', path: ':classroom_id/test/:test_id/answer_books/:answer_book_id/show_grades', component: () => import('src/pages/Admin/Classroom/ClassroomAnswerBookShowGrade.vue') }
-            ]
-          },
-          {
-            name: 'Admin.Event',
-            path: 'events',
-            component: () => import('layouts/bareLayout.vue'),
-            breadcrumbs: { title: 'دوره های آموزشی', route: { name: 'Admin.Event.Index' } },
-            children: [
-              { name: 'Admin.Event.Index', path: '', component: () => import('src/pages/Admin/Event/index.vue') },
-              { name: 'Admin.Event.Create', path: 'create', component: () => import('src/pages/Admin/Event/create.vue'), breadcrumbs: { title: 'ساخت دوره آموزشی' } },
-              { name: 'Admin.Event.Show', path: ':id', component: () => import('src/pages/Admin/Event/show.vue') },
-              { name: 'Admin.Event.Session.AttendanceSheetList', path: ':classroom_id/session/:session_id/session_attendance_sheets', component: () => import('pages/Admin/Event/SessionActivitySheets/sessionActivitySheets.vue') },
-              { name: 'Admin.Event.Session.AttendanceSheet.Assignment', path: ':classroom_id/session/:session_id/session_attendance_sheet/:session_attendance_sheet_id/assignment', component: () => import('pages/Admin/Event/SessionActivitySheets/Assignment.vue') },
-              { name: 'Admin.Event.Session.AttendanceSheet.Attendance', path: ':classroom_id/session/:session_id/session_attendance_sheet/:session_attendance_sheet_id/attendance', component: () => import('pages/Admin/Event/SessionActivitySheets/Attendance.vue') },
-              { name: 'Admin.Event.Project.Create', path: ':classroom_id/project/create', component: () => import('src/pages/Admin/Event/project/create.vue'), breadcrumbs: { title: 'ساخت دوره آموزشی' } },
-              { name: 'Admin.Event.Project.Show', path: ':classroom_id/project/:project_id', component: () => import('src/pages/Admin/Event/project/show.vue') },
-              { name: 'Admin.Event.Project.Members', path: ':classroom_id/project/:project_id/members', component: () => import('src/pages/Admin/Event/project/members.vue') },
-              { name: 'Admin.Event.projectAttendanceSheets.Show', path: ':classroom_id/project/:project_id/projectAttendanceSheet/:project_attendance_sheets_id', component: () => import('src/pages/Admin/Event/ProjectAttendanceSheet/show.vue') },
-              // { name: 'Admin.Event.Project', path: ':id', component: () => import('src/pages/Admin/Event/show.vue') },
-              { name: 'Admin.Event.Ticket', path: 'ticket', component: () => import('src/pages/Admin/Event/Ticket.vue'), breadcrumbs: { title: 'درخواست ها دوره های آموزشی' } },
-
-              { name: 'Admin.Event.TestSet.Index', path: 'test_set', component: () => import('src/pages/Admin/Event/Test/Index.vue') },
-              { name: 'Admin.Event.TestSet.Create', path: 'test_set/create', component: () => import('src/pages/Admin/Event/Test/Create.vue') },
-              { name: 'Admin.Event.TestSet.Show', path: 'test_set/:test_set_id', component: () => import('src/pages/Admin/Event/Test/Show.vue') },
-
-              { name: 'Admin.Event.TestSet.Questions.Index', path: 'test_set/:test_set_id/questions', component: () => import('src/pages/Admin/Event/Question/Index.vue') },
-              { name: 'Admin.Event.TestSet.Questions.Create', path: 'test_set/questions/create', component: () => import('src/pages/Admin/Event/Question/Create.vue') },
-              { name: 'Admin.Event.TestSet.Questions.Show', path: 'test_set/questions/:question_id', component: () => import('src/pages/Admin/Event/Question/Show.vue') },
-
-              { name: 'Admin.Event.TestSet.Test.Create', path: ':event_id/test_set/:test_set_id/test/create', component: () => import('src/pages/Admin/Event/Question/Show.vue') }
-            ]
-          },
-          {
-            name: 'Admin.Classroom.DiscussionCircles',
-            path: 'discussion-circles-classrooms',
-            component: () => import('layouts/bareLayout.vue'),
-            breadcrumbs: { title: 'دوره های آموزشی', route: { name: 'Admin.Classroom.DiscussionCircles.Index' } },
-            children: [
-              { name: 'Admin.Classroom.DiscussionCircles.Index', path: '', component: () => import('src/pages/Admin/DiscussionCirclesClassroom/index.vue') },
-              { name: 'Admin.Classroom.DiscussionCircles.Create', path: 'create', component: () => import('src/pages/Admin/DiscussionCirclesClassroom/create.vue'), breadcrumbs: { title: 'ساخت دوره آموزشی' } },
-              { name: 'Admin.Classroom.DiscussionCircles.Show', path: ':id', component: () => import('src/pages/Admin/DiscussionCirclesClassroom/show.vue'), breadcrumbs: { title: 'مشاهده اطلاعات دوره آموزشی' } },
-              { name: 'Admin.Classroom.DiscussionCircles.Ticket', path: 'ticket', component: () => import('src/pages/Admin/DiscussionCirclesClassroom/Ticket.vue'), breadcrumbs: { title: 'درخواست ها دوره های آموزشی' } }
-            ]
-          },
-          {
-            path: 'content',
-            name: 'Admin.Content',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              { path: '', name: 'Admin.Content.List', component: () => import('src/pages/Admin/Content/List.vue') },
-              { path: 'create', name: 'Admin.Content.Create', component: () => import('src/pages/Admin/Content/Create.vue') },
-              { path: ':id', name: 'Admin.Content.Show', component: () => import('src/pages/Admin/Content/Show.vue') },
-              { name: 'Admin.Content.Ticket', path: 'ticket', component: () => import('src/pages/Admin/Content/Ticket.vue'), breadcrumbs: { title: 'درخواست ها دوره های آموزشی' } }
-            ]
-          },
-          {
-            path: 'post',
-            name: 'Admin.Post',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              { path: '', name: 'Admin.Post.List', component: () => import('src/pages/Admin/Post/List.vue') },
-              { path: 'create', name: 'Admin.Post.Create', component: () => import('src/pages/Admin/Post/Create.vue') },
-              { path: ':id', name: 'Admin.Post.Show', component: () => import('src/pages/Admin/Post/Show.vue') }
-            ]
-          },
-          {
-            path: 'media',
-            name: 'Admin.Media',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              // { path: '', name: 'Admin.Content.List', component: () => import('src/pages/Admin/Content/List.vue') },
-              // { path: 'create', name: 'Admin.Content.Create', component: () => import('src/pages/Admin/Content/Create.vue') },
-              { path: ':id', name: 'Admin.Media.Show', component: () => import('src/pages/Admin/Media/Show.vue') }
-              // { name: 'Admin.Content.Ticket', path: 'ticket', component: () => import('src/pages/Admin/Classroom/Ticket.vue'), breadcrumbs: { title: 'درخواست ها دوره های آموزشی' } }
-            ]
-          },
-          {
-            path: 'content-category',
-            name: 'Admin.ContentCategory',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              { path: '', name: 'Admin.ContentCategory.List', component: () => import('src/pages/Admin/ContentCategory/List.vue') },
-              { path: 'create', name: 'Admin.ContentCategory.Create', component: () => import('src/pages/Admin/ContentCategory/Create.vue') },
-              { path: ':id', name: 'Admin.ContentCategory.Show', component: () => import('src/pages/Admin/ContentCategory/Show.vue') }
-            ]
-          },
-          {
-            path: 'post-category',
-            name: 'Admin.PostCategory',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              { path: '', name: 'Admin.PostCategory.List', component: () => import('src/pages/Admin/PostCategory/List.vue') },
-              { path: 'create', name: 'Admin.PostCategory.Create', component: () => import('src/pages/Admin/PostCategory/Create.vue') },
-              { path: ':id', name: 'Admin.PostCategory.Show', component: () => import('src/pages/Admin/PostCategory/Show.vue') }
-            ]
-          },
-          {
-            name: 'Admin.Session',
-            path: 'session',
-            component: () => import('layouts/bareLayout.vue'),
-            breadcrumbs: { title: 'طلیعه حکمت' },
-            children: [
-              { name: 'Admin.Session.Index', path: '', component: () => import('src/pages/Admin/Session/index.vue') },
-              { name: 'Admin.Session.Create', path: 'create', component: () => import('src/pages/Admin/Session/create.vue') },
-              { name: 'Admin.Session.Show', path: ':id', component: () => import('src/pages/Admin/Session/show.vue') },
-              { name: 'Admin.Session.UserClass', path: ':session_id/user/:user_id', component: () => import('src/pages/Admin/Session/showUserSession.vue') }
-            ]
-          },
-          {
-            path: 'invoice',
-            name: 'Admin.Invoice',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              {
-                path: '',
-                name: 'Admin.Invoice.List',
-                component: () => import('src/pages/Admin/Invoice/List.vue')
-              },
-              {
-                path: ':id',
-                name: 'Admin.Invoice.Show',
-                component: () => import('src/pages/Admin/Invoice/Show.vue')
-              },
-              {
-                path: 'ticket',
-                name: 'Admin.Invoice.Ticket',
-                component: () => import('layouts/bareLayout.vue'),
-                children: [
-                  {
-                    path: '',
-                    name: 'Admin.Invoice.Ticket.List',
-                    component: () => import('src/pages/Admin/Invoice/Ticket/List.vue')
-                  },
-                  {
-                    path: ':id',
-                    name: 'Admin.Invoice.Ticket.Show',
-                    component: () => import('src/pages/Admin/Invoice/Ticket/Show.vue')
-                  }
-                ]
-              }
-            ]
-          },
-          {
-            path: 'payment',
-            name: 'Admin.Payment',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              {
-                path: '',
-                name: 'Admin.Payment.List',
-                component: () => import('src/pages/Admin/Payment/List.vue')
-              },
-              {
-                path: ':id',
-                name: 'Admin.Payment.Show',
-                component: () => import('src/pages/Admin/Payment/Show.vue')
-              }
-            ]
-          },
-          {
-            path: 'transaction',
-            name: 'Admin.Transaction',
-            component: () => import('layouts/bareLayout.vue'),
-            children: [
-              {
-                path: '',
-                name: 'Admin.Transaction.List',
-                component: () => import('src/pages/Admin/Transaction/List.vue')
-              },
-              {
-                path: ':id',
-                name: 'Admin.Transaction.Show',
-                component: () => import('src/pages/Admin/Transaction/Show.vue')
-              }
-            ]
-          }
-        ]
-      },
-      {
-        path: 'document',
-        name: 'Document',
-        component: () => import('layouts/bareLayout.vue'),
-        children: [
-          {
-            path: 'component',
-            name: 'component',
-            component: () => import('src/pages/Document/component.vue'),
-            breadcrumbs: { title: 'component' },
-            meta: {
-              middlewares: [Authenticated]
-            }
-          },
-          {
-            path: 'theme',
-            name: 'Document.Theme',
-            component: () => import('layouts/bareLayout.vue'),
-            breadcrumbs: { title: 'Theme' },
-            children: [
-              {
-                path: 'controls',
-                name: 'Document.Theme.Controls',
-                component: () => import('src/pages/Document/Theme/Controls.vue'),
-                breadcrumbs: { title: 'Controls' }
-              }
-            ]
-          },
-          {
-            path: 'debug',
-            name: 'Document.Debug',
-            component: () => import('src/pages/Document/debug.vue')
-          },
-          {
-            path: 'icon-sax',
-            name: 'Document.IconSax',
-            component: () => import('src/pages/Document/IconSax.vue')
-          },
-          {
-            path: '/form-generator',
-            name: 'formGenerator',
-            component: () => import('src/pages/Document/formGenerator.vue')
-          }
-        ]
-      }
+      Auth,
+      Admin,
+      Public,
+      Document,
+      UserPanel
     ]
   }