Untitled

 avatar
unknown
plain_text
10 months ago
18 kB
17
Indexable
<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
import {
  DocumentIcon,
  CalendarIcon,
  EyeIcon,
  PencilSquareIcon,
  MapPinIcon,
} from '@heroicons/vue/24/outline'
import Pagination from '@/components/ui/pagination/Pagination.vue'
import DocumentTimelineTracker from '@/components/Dashboard/TimelineTracker/DocumentTimelineTracker.vue'
import EditdocumentDrawer from '@/components/Dashboard/IncomingDocuments/IncomingDocument(ForEdit)/EditDocumentDrawer.vue'
import ViewDocumentDrawer from '@/components/Dashboard/IncomingDocuments/IncomingDocument(ForView)/ViewDocumentDrawer.vue'
import { useAuthStore } from '@/components/store/authStore'
import apiClient from '@/services/api'

// Component state
const allDocuments = ref([])
const currentPage = ref(1)
const itemsPerPage = ref(10)
const totalItems = ref(0)
const isTimelineOpen = ref(false)
const selectedDocumentId = ref<number | null>(null)
const selectedDocumentNo = ref<string | null>(null)
const isLoading = ref(true)

const isEditDrawerOpen = ref(false)
const isViewDrawerOpen = ref(false)
const documentToView = ref(null) // 🆕 NEW: Document for view drawer
const documentToEdit = ref(null)

const authStore = useAuthStore()
const isGuest = computed(() => authStore.user.value?.role === 'guest')

const formatReferredOffice = (referredOffice: any, doc: any) => {
  if (!doc) return '—'


  const reroutedOffices = parseOffices(doc.rerouted?.office_rerouted)
  if (reroutedOffices.length > 0) {
    // Show Rerouted offices
    return reroutedOffices.join(', ')
  }

  const referredOffices = parseOffices(doc.referred_office)

  const ardMsOffices = ['Admin Division', 'Finance Division', 'Legal Division', 'PMD', 'RSCIG']
  const ardTsOffices = ['CDD', 'ED', 'LPDD', 'SMD', 'OARDTS-Task Force']

  if (referredOffices.includes('ARD MS') && referredOffices.includes('ARD TS')) {
    const oardData = doc.oard || {}
    const finalActionOffices = parseOffices(oardData.final_action_office)

    const hasArdMsSelection = finalActionOffices.some((office) =>
      ardMsOffices.map((o) => o.toUpperCase()).includes(office.toUpperCase()),
    )

    const hasArdTsSelection = finalActionOffices.some((office) =>
      ardTsOffices.map((o) => o.toUpperCase()).includes(office.toUpperCase()),
    )

    if (hasArdMsSelection && !hasArdTsSelection) {
      return 'Waiting for ARD TS'
    }

    // Case 2: ARD TS has selected but ARD MS hasn't
    if (!hasArdMsSelection && hasArdTsSelection) {
      return 'Waiting for ARD MS'
    }


    if (finalActionOffices.length > 0) {
      return finalActionOffices.join(', ')
    }
  }

  const cleanOffices = referredOffices.filter((office) => office && office.trim() !== '')
  return cleanOffices.length > 0 ? cleanOffices.join(', ') : '—'
}

// Helper function to parse office strings/arrays
const parseOffices = (officeData: any): string[] => {
  if (!officeData) return []

  try {
    if (typeof officeData === 'string') {
      return JSON.parse(officeData)
    }
    if (Array.isArray(officeData)) {
      return officeData
    }
  } catch (e) {
    console.warn('Error parsing offices:', e)
  }
  return []
}

// Data fetching
const fetchAllDocuments = async () => {
  try {
    isLoading.value = true
    const response = await apiClient.get('/dms/documents', {
      params: {
        page: currentPage.value,
        per_page: itemsPerPage.value,
        sort_by: 'created_at',
        sort_order: 'desc',
      },
    })

    allDocuments.value = response.data.data
    totalItems.value = response.data.total
    currentPage.value = response.data.current_page
  } catch (error) {
    console.error('Failed to fetch documents:', error)
  } finally {
    isLoading.value = false
  }
}

// Watch for page changes to refetch data
watch([currentPage, itemsPerPage], () => {
  fetchAllDocuments()
})

onMounted(() => {
  fetchAllDocuments()
})

// Function to open the edit drawer and set the selected document
const openEditDrawer = (doc: any) => {
  documentToEdit.value = doc
  isEditDrawerOpen.value = true
}

// Function to close the edit drawer and refresh the document list
const closeEditDrawer = () => {
  isEditDrawerOpen.value = false
  documentToEdit.value = null
  fetchAllDocuments()
}

// 🆕 NEW: Function to open the view drawer
const openViewDrawer = (doc: any) => {
  documentToView.value = doc
  isViewDrawerOpen.value = true
}

// 🆕 NEW: Function to close the view drawer
const closeViewDrawer = () => {
  isViewDrawerOpen.value = false
  documentToView.value = null
}

// Timeline actions
const openTimeline = (documentId: number, documentNo: string) => {
  selectedDocumentId.value = documentId
  selectedDocumentNo.value = documentNo
  isTimelineOpen.value = true
}

const closeTimeline = () => {
  isTimelineOpen.value = false
  selectedDocumentId.value = null
  selectedDocumentNo.value = null
}

// Pagination logic
const handlePageChange = (page: number) => {
  currentPage.value = page
}

const handleItemsPerPageChange = (items: number) => {
  itemsPerPage.value = items
  currentPage.value = 1
}
</script>

<template>
  <div class="bg-white rounded-lg shadow p-4 md:p-6 font-sans">
    <div class="flex flex-col sm:flex-row sm:items-center justify-between mb-4 md:mb-6">
      <h2 class="text-lg md:text-xl font-medium text-gray-900 mb-2 sm:mb-0">Incoming Documents</h2>
    </div>

    <div v-if="isLoading">
      <div class="hidden lg:block overflow-x-auto rounded-lg">
        <table class="min-w-full divide-y divide-gray-200">
          <thead class="bg-gray-50">
            <tr>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider rounded-tl-lg"
              >
                Document No.
              </th>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider"
              >
                Subject
              </th>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider"
              >
                Document Deadline
              </th>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider"
              >
                ARTA Deadline
              </th>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider"
              >
                Referred To
              </th>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider rounded-tr-lg"
              >
                Actions
              </th>
            </tr>
          </thead>
          <tbody class="bg-white divide-y divide-gray-100 animate-pulse">
            <tr v-for="n in 5" :key="n" class="hover:bg-gray-50 transition-colors">
              <td class="px-4 py-3 whitespace-nowrap text-sm text-center">
                <div class="h-4 bg-gray-200 rounded w-24 mx-auto"></div>
              </td>
              <td class="px-4 py-3 text-sm text-center max-w-xs">
                <div class="h-4 bg-gray-200 rounded w-32 mx-auto"></div>
              </td>
              <td class="px-4 py-3 text-sm text-center">
                <div class="h-4 bg-gray-200 rounded w-20 mx-auto"></div>
              </td>
              <td class="px-4 py-3 text-sm text-center">
                <div class="h-4 bg-gray-200 rounded w-20 mx-auto"></div>
              </td>
              <td class="px-4 py-3 text-sm text-center">
                <div class="h-4 bg-gray-200 rounded w-16 mx-auto"></div>
              </td>
              <td class="px-4 py-3 text-sm text-center">
                <div class="flex justify-center space-x-2">
                  <div class="w-8 h-8 bg-gray-200 rounded-full"></div>
                  <div class="w-8 h-8 bg-gray-200 rounded-full"></div>
                  <div class="w-8 h-8 bg-gray-200 rounded-full"></div>
                </div>
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      <div class="block lg:hidden space-y-3">
        <div
          v-for="n in 5"
          :key="n"
          class="bg-white border border-gray-200 rounded-lg p-4 shadow-sm animate-pulse"
        >
          <div class="flex items-start justify-between mb-3">
            <div class="flex items-center space-x-2 min-w-0 flex-1">
              <div class="w-5 h-5 bg-gray-200 rounded-full"></div>
              <div class="min-w-0 flex-1">
                <div class="h-4 bg-gray-200 rounded w-24 mb-1"></div>
                <div class="h-3 bg-gray-200 rounded w-16"></div>
              </div>
            </div>
            <div class="h-4 bg-gray-200 rounded w-12"></div>
          </div>
          <div class="mb-3">
            <div class="h-4 bg-gray-200 rounded w-20 mb-1"></div>
            <div class="h-4 bg-gray-200 rounded w-full"></div>
          </div>
          <div class="flex justify-end space-x-2 pt-3 border-t border-gray-100">
            <div class="w-8 h-8 bg-gray-200 rounded-full"></div>
            <div class="w-8 h-8 bg-gray-200 rounded-full"></div>
            <div class="w-8 h-8 bg-gray-200 rounded-full"></div>
          </div>
        </div>
      </div>
    </div>

    <div
      v-else-if="allDocuments.length === 0"
      class="text-center py-12 border-2 border-dashed border-gray-200 rounded-lg bg-gray-50"
    >
      <DocumentIcon class="mx-auto h-10 w-10 text-gray-400" />
      <h3 class="mt-2 text-base font-medium text-gray-900">No Incoming Documents Found</h3>
      <p class="mt-1 text-sm text-gray-500">Documents logged into the system will appear here.</p>
    </div>
    <div v-else>
      <div class="hidden lg:block overflow-x-auto rounded-lg">
        <table class="min-w-full divide-y divide-gray-200">
          <thead class="bg-gray-50">
            <tr>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider rounded-tl-lg"
              >
                Document No.
              </th>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider"
              >
                Subject
              </th>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider"
              >
                Document Deadline
              </th>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider"
              >
                ARTA Deadline
              </th>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider"
              >
                Referred To
              </th>
              <th
                class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider rounded-tr-lg"
              >
                Actions
              </th>
            </tr>
          </thead>
          <tbody class="bg-white divide-y divide-gray-100">
            <tr
              v-for="doc in allDocuments"
              :key="doc.incoming_initial_id"
              class="hover:bg-gray-50 transition-colors"
            >
              <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700 text-center">
                <span class="inline-flex items-center">
                  <DocumentIcon class="w-4 h-4 mr-1 text-gray-400" />
                  {{ doc.document_no }}
                </span>
              </td>
              <td class="px-4 py-3 text-sm text-gray-700 text-center max-w-xs">
                <div class="truncate" :title="doc.subject">{{ doc.subject }}</div>
              </td>
              <td class="px-4 py-3 text-sm text-gray-700 text-center">
                <span v-if="doc.document_deadline" class="inline-flex items-center">
                  <CalendarIcon class="w-4 h-4 mr-1 text-gray-400" />
                  {{ doc.document_deadline }}
                </span>
                <span v-else>—</span>
              </td>
              <td class="px-4 py-3 text-sm text-gray-700 text-center">
                <span v-if="doc.arta_deadline" class="inline-flex items-center">
                  <CalendarIcon class="w-4 h-4 mr-1 text-gray-400" />
                  {{ doc.arta_deadline }}
                </span>
                <span v-else>—</span>
              </td>
              <td class="px-4 py-3 text-sm text-gray-700 text-center">
                {{ formatReferredOffice(doc.current_office, doc) }}
              </td>
              <td class="px-4 py-3 text-sm text-center">
                <div class="flex justify-center space-x-2">
                  <button
                    @click="openViewDrawer(doc)"
                    class="text-gray-500 hover:text-blue-600 p-2 rounded-full hover:bg-gray-100 transition-colors duration-200"
                    title="View"
                  >
                    <EyeIcon class="w-5 h-5" />
                  </button>
                  <button
                    :disabled="isGuest"
                    :class="{
                      'text-gray-500 hover:text-blue-600 p-2 rounded-full hover:bg-gray-100 transition-colors duration-200':
                        !isGuest,
                      'opacity-50 cursor-not-allowed': isGuest,
                    }"
                    title="Edit Document"
                    @click="openEditDrawer(doc)"
                  >
                    <PencilSquareIcon class="w-5 h-5" />
                  </button>
                  <button
                    class="text-red-500 hover:text-red-600 p-2 rounded-full hover:bg-gray-100 transition-colors duration-200"
                    title="Track Location"
                    @click="openTimeline(doc.incoming_initial_id, doc.document_no)"
                  >
                    <MapPinIcon class="w-5 h-5" />
                  </button>
                </div>
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      <div class="block lg:hidden space-y-3">
        <div
          v-for="doc in allDocuments"
          :key="doc.incoming_initial_id"
          class="bg-white border border-gray-200 rounded-lg p-4 shadow-sm hover:shadow-md transition-shadow duration-200"
        >
          <div class="flex items-start justify-between mb-3">
            <div class="flex items-center space-x-2 min-w-0 flex-1">
              <DocumentIcon class="w-5 h-5 text-gray-400 flex-shrink-0" />
              <div class="min-w-0 flex-1">
                <div class="text-sm font-semibold text-gray-900">
                  {{ doc.document_no }}
                </div>
                <div class="text-xs text-gray-500">Document Number</div>
              </div>
            </div>
            <span class="text-xs font-semibold text-gray-800">
              {{ formatReferredOffice(doc.current_office, doc) }}
            </span>
          </div>

          <div class="mb-3">
            <div class="text-sm font-medium text-gray-700 mb-1">Subject</div>
            <div class="text-sm text-gray-600 leading-relaxed">
              {{ doc.subject }}
            </div>
          </div>

          <div class="flex justify-end space-x-2 pt-3 border-t border-gray-100">
            <button
              @click="openViewDrawer(doc)"
              class="flex items-center justify-center text-gray-500 hover:text-blue-600 p-3 rounded-lg hover:bg-blue-50 transition-all duration-200 min-w-[44px]"
              title="View Document"
            >
              <EyeIcon class="w-5 h-5" />
            </button>
            <button
              :disabled="isGuest"
              :class="{
                'flex items-center justify-center text-gray-500 hover:text-blue-600 p-3 rounded-lg hover:bg-blue-50 transition-all duration-200 min-w-[44px]':
                  !isGuest,
                'opacity-50 cursor-not-allowed': isGuest,
              }"
              title="Edit Document"
              @click="openEditDrawer(doc)"
            >
              <PencilSquareIcon class="w-5 h-5" />
            </button>
            <button
              class="flex items-center justify-center text-red-500 hover:text-red-600 p-3 rounded-lg hover:bg-red-50 transition-all duration-200 min-w-[44px]"
              title="Track Location"
              @click="openTimeline(doc.incoming_initial_id, doc.document_no)"
            >
              <MapPinIcon class="w-5 h-5" />
            </button>
          </div>
        </div>
      </div>

      <div class="mt-8 border-gray-200 pt-6 overflow-x-auto">
        <Pagination
          :total-items="totalItems"
          :initial-page="currentPage"
          :initial-items-per-page="itemsPerPage"
          @page-change="handlePageChange"
          @items-per-page-change="handleItemsPerPageChange"
        />
      </div>
    </div>

    <EditdocumentDrawer
      :is-open="isEditDrawerOpen"
      :document="documentToEdit"
      @close="closeEditDrawer"
    />

    <ViewDocumentDrawer
      :is-open="isViewDrawerOpen"
      :document="documentToView"
      @close="closeViewDrawer"
    />

    <DocumentTimelineTracker
      :is-open="isTimelineOpen"
      :document-no="selectedDocumentNo"
      document-type="incoming"
      @close="closeTimeline"
    />
  </div>
</template>
Editor is loading...
Leave a Comment