Sfoglia il codice sorgente

تب دنبال کنندگان یک درس و ارسال پیام به آنها

hgh 1 anno fa
parent
commit
6309f3b9ba
2 ha cambiato i file con 216 aggiunte e 3 eliminazioni
  1. 19 1
      src/api/models/Subscription.js
  2. 197 2
      src/pages/Admin/Unit/show.vue

+ 19 - 1
src/api/models/Subscription.js

@@ -8,7 +8,8 @@ export default class SubscriptionAPI extends APIRepository {
     this.APIAdresses = {
       base: '/mma/subscriptions',
       byId: (id) => '/mma/subscriptions/' + id,
-      myCorrespondingSubscription: '/mma/subscriptions/my_corresponding_subscription'
+      myCorrespondingSubscription: '/mma/subscriptions/my_corresponding_subscription',
+      sendMessage: '/mma/subscriptions/send_message'
     }
     this.restUrl = (id) => this.url + '/' + id
     /* Setting the callback functions for the CRUD operations. */
@@ -85,6 +86,23 @@ export default class SubscriptionAPI extends APIRepository {
     })
   }
 
+  sendMessage (data) {
+    return this.sendRequest({
+      apiMethod: 'post',
+      api: this.api,
+      request: this.APIAdresses.sendMessage,
+      data: this.getNormalizedSendData({
+        source_type: 'UNIT'
+      }, data),
+      resolveCallback: (response) => {
+        return new Subscription(response.data)
+      },
+      rejectCallback: (error) => {
+        return error
+      }
+    })
+  }
+
   seen(id) {
     return this.sendRequest({
       apiMethod: 'put',

+ 197 - 2
src/pages/Admin/Unit/show.vue

@@ -23,6 +23,8 @@
              label="آزمون" />
       <q-tab name="transcriptSheetHistory"
              label="تاریخچه کارنامه" />
+      <q-tab name="subscriptions"
+             label="اطلاع رسانی" />
     </q-tabs>
     <q-separator />
     <q-tab-panels v-if="mounted"
@@ -187,8 +189,94 @@
           </template>
         </entity-index>
       </q-tab-panel>
+      <q-tab-panel name="subscriptions"
+                   class="q-pa-none">
+        <entity-index v-if="mounted"
+                      ref="subscriptionsEntityIndex"
+                      v-model:value="subscriptionsFilterInputs"
+                      title="لیست دنبال کنندگان"
+                      :api="subscriptionsApi"
+                      :table="subscriptionsTable"
+                      :table-keys="subscriptionsTableKeys"
+                      :show-reload-button="false"
+                      :show-search-button="false"
+                      :show-expand-button="false">
+          <template #toolbar>
+            <div class="flex justify-end">
+              <q-btn color="primary"
+                     label="ارسال پیام"
+                     @click="showAlertDialog = true" />
+            </div>
+          </template>
+          <template #after-index-table>
+            <q-separator class="q-my-lg" />
+          </template>
+          <template #entity-index-table-cell="{inputData, showConfirmRemoveDialog}">
+            <template v-if="inputData.col.name === 'actions'">
+              <div class="q-gutter-md">
+                <div class="action-column-entity-index">
+                  <delete-btn @click="showConfirmRemoveDialog(inputData.props.row, 'id', getRemoveMessage(inputData.props.row))" />
+                </div>
+              </div>
+            </template>
+            <template v-else>
+              {{ inputData.col.value }}
+            </template>
+          </template>
+        </entity-index>
+      </q-tab-panel>
     </q-tab-panels>
-  </q-card>
+  </q-card>    <!-- دیالوگ -->
+  <q-dialog v-model="showAlertDialog">
+    <q-card class="my-dialog-card q-pa-md">
+      <q-card-section class="text-center">
+        <div class="text-h6">ارسال پیام</div>
+      </q-card-section>
+      <q-card-section>
+        <q-input v-model="alertMessageText"
+                 type="textarea"
+                 label="متن پیام خود را وارد کنید"
+                 autogrow
+                 :disable="sendingAlertConfirmation"
+                 dense />
+      </q-card-section>
+
+      <q-separator />
+
+      <q-card-actions class="q-gutter-sm"
+                      align="center">
+        <template v-if="!sendingAlertConfirmation">
+          <q-btn v-close-popup
+                 class="full-width-button"
+                 flat
+                 label="انصراف"
+                 color="primary" />
+          <!-- مرحله اول: دکمه ارسال -->
+          <q-btn v-if="!sendingAlertConfirmation"
+                 class="full-width-button"
+                 label="ادامه به ارسال"
+                 color="primary"
+                 :disable="!alertMessageText.trim()"
+                 @click="sendingAlertConfirmation = true" />
+        </template>
+
+        <template v-else>
+          <!-- مرحله دوم: تأیید نهایی -->
+          <div class="text-body2 q-mb-md">آیا مطمئن هستید که می‌خواهید پیام را ارسال کنید؟</div>
+          <q-btn class="full-width-button"
+                 flat
+                 color="grey"
+                 label="خیر"
+                 @click="sendingAlertConfirmation = false" />
+          <q-btn class="full-width-button"
+                 color="red"
+                 label="بله، ارسال کن"
+                 :loading="sendingAlertMessage"
+                 @click="sendAlertMessage" />
+        </template>
+      </q-card-actions>
+    </q-card>
+  </q-dialog>
 </template>
 
 <script>
@@ -219,7 +307,12 @@ export default {
     return {
       tab: 'UnitInfo',
       mounted: false,
+      showAlertDialog: false,
+      alertMessageText: '',
+      sendingAlertConfirmation: false,
+      sendingAlertMessage: false,
       newTranscriptSheetHistoryLoading: false,
+      subscriptionsLoading: false,
       newSessionLoading: false,
       newSessionName: '-',
       newSessionSessionCount: null,
@@ -417,6 +510,73 @@ export default {
         currentPage: 'current',
         perPage: 'per_page',
         pageKey: 'page'
+      },
+
+      subscriptionsApi: APIGateway.subscription.APIAdresses.base,
+      subscriptionsTable: {
+        columns: [
+          {
+            name: 'id',
+            required: true,
+            label: 'شناسه',
+            align: 'left',
+            field: row => row.id
+          },
+          {
+            name: 'mobile_number',
+            required: true,
+            label: 'تلفن همراه',
+            align: 'left',
+            field: row => row.owner_info.mobile_number
+          },
+          {
+            name: 'email',
+            required: true,
+            label: 'ایمیل',
+            align: 'left',
+            field: row => row.owner_info.email
+          },
+          {
+            name: 'is_enabled',
+            required: true,
+            label: 'وضعیت',
+            align: 'left',
+            field: row => row.is_enabled ? 'فعال' : 'غیرفعال'
+          },
+          {
+            name: 'creation_time',
+            required: true,
+            label: 'تاریخ ایجاد',
+            align: 'left',
+            field: row => ShamsiDate.getDateTime(row.creation_time)
+          },
+          {
+            name: 'last_modification_time',
+            required: true,
+            label: 'تاریخ آخرین تغییر',
+            align: 'left',
+            field: row => ShamsiDate.getDateTime(row.last_modification_time)
+          },
+          {
+            name: 'actions',
+            required: true,
+            label: 'عملیات',
+            align: 'left',
+            field: ''
+          }
+        ],
+        data: []
+      },
+      subscriptionsFilterInputs: [
+        { type: 'hidden', name: 'source_type', value: 'UNIT' },
+        { type: 'hidden', name: 'source_id', value: this.$route.params.id }
+      ],
+      subscriptionsTableKeys: {
+        data: 'results',
+        total: 'count',
+        currentPage: 'current',
+        perPage: 'per_page',
+        pageKey: 'page'
       }
     }
   },
@@ -426,6 +586,33 @@ export default {
     this.mounted = true
   },
   methods: {
+    sendAlertMessage() {
+      if (!this.alertMessageText.trim()) {
+        this.$q.notify({
+          type: 'negative',
+          message: 'متن پاسخ را کامل کنید.',
+          position: 'top'
+        })
+        return
+      }
+      this.sendingAlertMessage = true
+      APIGateway.subscription.sendMessage({
+        source_type: 'UNIT',
+        source_id: this.$route.params.id,
+        message: this.alertMessageText
+      })
+        .then(() => {
+          this.alertMessageText = ''
+          this.showAlertDialog = false
+          this.sendingAlertConfirmation = false
+        })
+        .catch((err) => {
+          console.error('خطا در ارسال:', err)
+        })
+        .finally(() => {
+          this.sendingAlertMessage = false
+        })
+    },
     getCategories () {
       this.categories.loading = true
       APIGateway.unitCategory.index()
@@ -452,7 +639,10 @@ export default {
       this.$refs.categoryEntityEdit.editEntity()
     },
     getRemoveMessage (row) {
-      return 'آیا از حذف ' + row.title + ' اطمینان دارید؟'
+      if (row.title) {
+        return 'آیا از حذف ' + row.title + ' اطمینان دارید؟'
+      }
+      return 'آیا از حذف اطمینان دارید؟'
     },
     reloadSessions () {
       this.$refs.sessionEntityIndex.reload()
@@ -494,4 +684,9 @@ export default {
 .btn-go-to-question-bank {
   margin-right: 20px;
 }
+.my-dialog-card {
+  width: 90vw; /* همیشه ۹۰٪ عرض صفحه */
+  max-width: 400px; /* ولی بیشتر از ۴۰۰px نشه */
+  min-width: 300px; /* و حداقل ۳۰۰px باشه که خیلی کوچیک نشه */
+}
 </style>