Untitled

 avatar
unknown
plain_text
5 months ago
9.6 kB
4
Indexable
<script lang="ts">
  // Importaciones necesarias
  import { env } from '$env/dynamic/public';
  import { onMount } from 'svelte';
  import { accessToken, isLoadingOnAction, toast } from '$lib/store';
  import { page as _page } from '$app/stores';

  import SelectDropdown from '$lib/components/shared/SelectDropdown.svelte';
  import LogDetailsModal from '$lib/components/client/aapc/LogDetailsModal.svelte';
  import Pagination from '$lib/components/Pagination.svelte';

  // Si usas Tailwind CSS u otro framework, asegúrate de que las clases CSS estén definidas
  import ArrowUp from '$lib/components/svg/ArrowUp.svelte';
  import ArrowDown from '$lib/components/svg/ArrowDown.svelte';

  // Variables y estados
  let swoogoKeys: any[] = [];
  let events: any[] = [];
  let logs: any[] = [];
  let selectedSwoogoKey: any = null;
  let selectedEvent: any = null;

  let logDetails = '';

  let columns: any[] = [
    { name: 'Reg Id', key: 'regId', sortable: true },
    { name: 'Full Name', key: 'fullName', sortable: true },
    { name: 'Email', key: 'email', sortable: true },
    { name: 'Status', key: 'status', sortable: true },
    { name: 'Updated At', key: 'updatedAt', sortable: true },
  ];

  let selectedSort: string = 'createdAt:DESC';

  // Variables de paginación
  let page = 1;
  let limit = 10;
  let totalItems = 0;
  let totalPages = 0;

  let searchText = '';

  // Función para manejar la búsqueda (si aplica)
  const onSearch = (searchText: string) => {
    // Implementa la lógica de búsqueda si es necesario
  };

  // Observa cambios en selectedSwoogoKey para actualizar los eventos
  $: if (selectedSwoogoKey) {
    fetchEvents();
  }

  // Observa cambios en selectedEvent para actualizar los logs
  $: if (selectedSwoogoKey && selectedEvent) {
    fetchLogs();
  }

  // Función para manejar cambios de página y tamaño de página
  function handlePageChange(event) {
    page = event.detail.currentPage;
    limit = event.detail.pageSize;
    fetchLogs();
  }

  // Función para formatear fechas
  const formatDate = (date: string) => {
    const d = new Date(date);
    const months = [
      'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
      'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
    ];
    return `${d.getDate()}-${months[d.getMonth()]}-${d.getFullYear()} ${d.getHours()}:${d.getMinutes()}`;
  };

  // Funciones para obtener datos del servidor
  const fetchKeys = async () => {
    $isLoadingOnAction = true;
    try {
      const res = await fetch(`${env.PUBLIC_API_URL}/client/ats/api-keys`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${$accessToken}`
        }
      });

      const data = await res.json();

      if (data.success) {
        swoogoKeys = data.data.filter((key: any) => key.platform === 'Swoogo');
      } else {
        $toast = {
          ...$toast,
          show: true,
          message: 'Failed to fetch keys',
          type: 'error'
        };
      }
    } catch (err: any) {
      console.error(err);
      $toast = {
        ...$toast,
        show: true,
        message: 'Failed to fetch keys',
        type: 'error'
      };
    } finally {
      $isLoadingOnAction = false;
    }
  };

  const fetchEvents = async () => {
    $isLoadingOnAction = true;
    try {
      const res = await fetch(`${env.PUBLIC_API_URL}/client/ats/events/active-events?swoogoAccount=${selectedSwoogoKey.id}`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${$accessToken}`
        }
      });
      const data = await res.json();
      if (data.success) {
        events = data.data.map((event: any) => ({
          name: event.name,
          eventId: event.eventId
        }));
      } else {
        $toast = {
          ...$toast,
          show: true,
          message: 'Failed to fetch events',
          type: 'error'
        };
      }
    } catch (err: any) {
      console.error(err);
      $toast = {
        ...$toast,
        show: true,
        message: 'Failed to fetch events',
        type: 'error'
      };
    } finally {
      $isLoadingOnAction = false;
    }
  };

  const fetchLogs = async () => {
    $isLoadingOnAction = true;
    try {
      const res = await fetch(
        `${env.PUBLIC_API_URL}/client/ats/logs?eventId=${selectedEvent.eventId}&sort=${selectedSort}&page=${page}&limit=${limit}&search=${searchText}`,
        {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${$accessToken}`
          }
        }
      );

      const data = await res.json();

      if (data.success) {
        logs = data.data;
        totalItems = data.total;
        totalPages = Math.ceil(totalItems / limit);
      } else {
        $toast = {
          ...$toast,
          show: true,
          message: 'Failed to fetch logs',
          type: 'error'
        };
      }
    } catch (err: any) {
      console.error(err);
      $toast = {
        ...$toast,
        show: true,
        message: 'Failed to fetch logs',
        type: 'error'
      };
    } finally {
      $isLoadingOnAction = false;
    }
  };

  // onMount para cargar las llaves al inicio
  onMount(async () => {
    await fetchKeys();
  });
</script>

<h1 class="font-medium text-left text-[#383F51] py-8 px-4 w-full h-[72px] flex justify-between items-center border-b-[1px] border-black shadow-[0_1px_4px_rgba(0,0,0,0.2)] text-[20px] font-roboto">
  Integration Mapping
</h1>

<div class="pt-8 pb-4 px-10 max-w-full flex flex-col overflow-hidden h-full">
  <div class="mt-8 pb-4 max-w-full flex flex-col overflow-hidden relative w-full flex-grow">
    <div class="relative z-10 flex gap-8 items-start">
      <div class="flex flex-col w-[300px]">
        <h2 class="font-semibold text-xl" style="color: #383F51;">
          Select Swoogo Account
        </h2>
        <SelectDropdown
          options={swoogoKeys}
          displayProp="accountName"
          bind:selectedOption={selectedSwoogoKey}
          class="w-full"
        />
      </div>

      <div class="flex flex-col w-[300px]">
        <h2 class="font-semibold text-xl" style="color: #383F51;">
          Select Event
        </h2>
        <SelectDropdown
          options={events}
          displayProp="name"
          bind:selectedOption={selectedEvent}
          class="w-full"
        />
      </div>
    </div>

    <div>
      <h2 class="mt-8 mb-4 ml-4" style="color: #383F51;">
        ATS Keys
      </h2>
    </div>

    <div class="overflow-auto rounded-lg border w-full mt-2 relative z-0">
      <table class="w-full fixed-table">
        <thead class="sticky top-0 z-10">
          <tr class="bg-white">
            <th class="fixed-column" style="width: 100px;">
              Sl No.
            </th>
            {#each columns as header}
              <th class="fixed-column">
                <span class="flex justify-between items-center">
                  <span>{header.name}</span>
                  {#if header.sortable}
                    <span class="flex justify-center items-center space-x-0.5">
                      <button on:click={() => (selectedSort = header.key + ':ASC')}>
                        <ArrowUp class="w-2.5 h-2.5" />
                      </button>
                      <button on:click={() => (selectedSort = header.key + ':DESC')}>
                        <ArrowDown class="w-2.5 h-2.5" />
                      </button>
                    </span>
                  {/if}
                </span>
              </th>
            {/each}
          </tr>
        </thead>
        <tbody>
          {#each logs as log, i}
            <tr class="border-b hover:bg-sail-50 transition duration-300 ease-in-out">
              <td class="fixed-column" style="width: 100px;">
                {(page - 1) * limit + i + 1}
              </td>
              <td class="fixed-column">{log.regId}</td>
              <td class="fixed-column">{log.fullName}</td>
              <td class="fixed-column">{log.email}</td>
              <td class={`py-2 px-6 text-sm ${log.status === 'Failed' ? '!text-red-500 font-semibold' : '!text-green-500 font-semibold'}`}>
                {log.status}
                {#if log.status === 'Failed' && log.details}
                  <button
                    class="text-blue-500 underline ml-2"
                    on:click={() => {
                      logDetails = log.details;
                    }}
                  >
                    View logs
                  </button>
                {/if}
              </td>
              <td class="fixed-column">
                {log.updatedAt ? formatDate(log.updatedAt) : formatDate(log.createdAt)}
              </td>
            </tr>
          {/each}
        </tbody>
      </table>
    </div>

    <!-- Componente de paginación -->
    <Pagination
      bind:currentPage={page}
      bind:pageSize={limit}
      {totalItems}
      on:pageChange={handlePageChange}
      on:pageSizeChange={handlePageChange}
    />
  </div>

  {#if logDetails}
    <LogDetailsModal details={logDetails} on:close={() => (logDetails = '')} />
  {/if}
</div>

<style>
  .fixed-table {
    table-layout: fixed;
    width: 100%;
  }
  .fixed-column {
    width: 25%;
    text-align: left;
    padding: 8px 12px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  td, th {
    /* Si usas Tailwind CSS */
    @apply text-sm text-black-500 py-2 px-3 border-t border-black-100;
  }
</style>
Editor is loading...
Leave a Comment