<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSV File Manager</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.2/papaparse.min.js"></script>
  <script src="https://cdn.tailwindcss.com"></script>
  <script>
    tailwind.config = {
      darkMode: 'class',
    };
  </script>
  <style>
    body.dark {
      background-color: #1a202c;
      color: #a0aec0;
    }
    .dark-mode {
      background-color: #1a202c;
      color: #a0aec0;
    }
    .dark-mode table {
      background-color: #2d3748;
      color: #cbd5e0;
    }
    .dark-mode th, .dark-mode td {
      border-color: #4a5568;
    }
    ::-webkit-scrollbar {
      width: 8px;
      height: 8px;
    }
    ::-webkit-scrollbar-thumb {
      background: #4a5568;
      border-radius: 4px;
    }
    ::-webkit-scrollbar-thumb:hover {
      background: #718096;
    }
    ::-webkit-scrollbar-track {
      background: #2d3748;
    }
  </style>
</head>
<body class="bg-gray-900 min-h-screen dark">
  <div id="app" class="p-8">
    <div class="max-w-7xl mx-auto space-y-6">
      <!-- Table and Controls -->
      <div class="bg-gray-800 shadow rounded-lg p-6 space-y-4">
        <!-- Filter Controls and Search Bar -->
        <div class="flex flex-wrap items-center justify-between border-b pb-4 mb-4 border-gray-600 gap-4">
          <!-- Dropdown for Filter Columns -->
          <div class="relative">
            <button
              class="px-4 py-2 bg-gray-700 text-white rounded-lg shadow hover:bg-gray-600 focus:ring-2 focus:ring-indigo-500 focus:outline-none"
              @click="isFilterOpen = !isFilterOpen"
            >
              Filter Columns
            </button>
            <div
              v-if="isFilterOpen"
              class="absolute mt-2 w-48 bg-gray-800 border border-gray-700 rounded-lg shadow-lg p-4"
            >
              <div v-for="column in columns" :key="column.key" class="flex items-center space-x-2">
                <input
                  type="checkbox"
                  :id="column.key"
                  v-model="selectedColumns"
                  :value="column.key"
                  class="rounded border-gray-600 bg-gray-700"
                >
                <label :for="column.key" class="text-sm text-gray-300">{{ column.label }}</label>
              </div>
            </div>
          </div>

          <!-- Search Bar -->
          <div class="flex-grow">
            <input
              v-model="searchQuery"
              type="text"
              placeholder="Search..."
              class="w-full px-4 py-2 bg-gray-700 border border-gray-600 rounded-lg text-gray-300 placeholder-gray-500 focus:ring-2 focus:ring-indigo-500 focus:outline-none"
            >
          </div>


            <div class="flex space-x-2">
              <label for="csvFileInput" class="px-4 py-2 bg-indigo-600 text-white rounded-lg shadow hover:bg-indigo-700 transition cursor-pointer">
                Import
              </label>
              <input id="csvFileInput" type="file" class="hidden" accept=".csv" @change="handleFileUpload">
            </div>
<!-- Export Button and Menu -->
<!-- Export Button and Menu Container -->
<div class="relative inline-block">
  <button
    class="px-4 py-2 bg-indigo-600 text-white rounded-lg shadow hover:bg-indigo-700 focus:ring-2 focus:ring-indigo-500 focus:outline-none"
    @click="isExportMenuOpen = !isExportMenuOpen"
  >
    Export
  </button>
  <div
    v-if="isExportMenuOpen"
    class="absolute top-full mt-2 w-32 bg-gray-800 border border-gray-700 rounded-lg shadow-lg z-10"
  >
    <button
      @click="exportData('csv')"
      class="block w-full text-left px-4 py-2 text-sm text-gray-300 hover:bg-gray-700"
    >
      CSV
    </button>
    <button
      @click="exportData('json')"
      class="block w-full text-left px-4 py-2 text-sm text-gray-300 hover:bg-gray-700"
    >
      JSON
    </button>
  </div>
</div>
</div>


        <!-- Table -->
        <div class="overflow-x-auto">
          <div class="max-h-96 overflow-y-auto">
            <table class="min-w-full bg-gray-700 border border-gray-600 rounded-lg shadow">
              <thead class="bg-gray-600">
                <tr>
                  <th
                    v-for="column in visibleColumns"
                    :key="column.key"
                    class="px-6 py-3 text-left text-sm font-medium text-gray-200 cursor-pointer"
                    @click="sortColumn(column.key)"
                  >
                    {{ column.label }}
                    <span
                      v-if="sortKey === column.key"
                      class="ml-2 inline-block"
                      :class="sortOrder === 'asc' ? 'rotate-0' : 'rotate-180'"
                    >
                      &#x25B2;
                    </span>
                  </th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(row, rowIndex) in filteredAndPaginatedData" :key="rowIndex" class="even:bg-gray-800">
                  <td v-for="column in visibleColumns" :key="column.key" class="px-6 py-3 text-sm text-gray-300">
                    {{ row[column.key] }}
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
          <!-- Pagination Controls -->
          <div class="flex justify-between items-center mt-4 space-y-4 flex-wrap">
            <div class="flex items-center space-x-2">
              <button
                class="px-4 py-2 bg-gray-600 text-white rounded shadow hover:bg-gray-700"
                :disabled="currentPage === 1"
                @click="currentPage--"
              >
                Previous
              </button>
              <span class="text-sm text-gray-300">Page {{ currentPage }} of {{ totalPages }}</span>
              <button
                class="px-4 py-2 bg-gray-600 text-white rounded shadow hover:bg-gray-700"
                :disabled="currentPage === totalPages"
                @click="currentPage++"
              >
                Next
              </button>
              <label>
                <select
                  v-model="itemsPerPage"
                  class="ml-4 px-2 py-1 bg-gray-700 text-white rounded border border-gray-600"
                >
                  <option value="10">10 rows</option>
                  <option value="25">25 rows</option>
                  <option value="50">50 rows</option>
                </select>
              </label>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <script>
    const app = Vue.createApp({
      data() {
        return {
          data: [],
          columns: [],
          selectedColumns: [],
          searchQuery: '',
          sortKey: '',
          sortOrder: 'asc',
          currentPage: 1,
          itemsPerPage: 20,
          isFilterOpen: false, // State for dropdown
          isExportMenuOpen: false, // State for export menu
        };
      },
      computed: {
        visibleColumns() {
          return this.columns.filter((column) => this.selectedColumns.includes(column.key));
        },
        filteredData() {
          const lowerQuery = this.searchQuery.toLowerCase();
          return this.data.filter((row) =>
            Object.values(row).some((value) =>
              String(value).toLowerCase().includes(lowerQuery)
            )
          );
        },
        filteredAndPaginatedData() {
          const start = (this.currentPage - 1) * this.itemsPerPage;
          const end = start + this.itemsPerPage;
          return this.filteredData.slice(start, end);
        },
        totalPages() {
          return Math.ceil(this.filteredData.length / this.itemsPerPage);
        },
      },
      methods: {
        handleFileUpload(event) {
          const file = event.target.files[0];
          if (file) {
            Papa.parse(file, {
              header: true,
              complete: (results) => {
                this.data = results.data;
                this.columns = Object.keys(this.data[0] || {}).map((key) => ({
                  key,
                  label: key.replace(/_/g, ' ').toUpperCase(),
                }));
                this.selectedColumns = this.columns.map((col) => col.key);
              },
            });
          }
        },
        sortColumn(key) {
          if (this.sortKey === key) {
            this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
          } else {
            this.sortKey = key;
            this.sortOrder = 'asc';
          }
        },
        exportData(format) {
          const exportColumns = this.visibleColumns.map(column => column.key);
          const exportData = this.filteredData.map(row => {
            const newRow = {};
            exportColumns.forEach(key => {
              newRow[key] = row[key];
            });
            return newRow;
          });
          if (format === 'csv') {
            const csv = Papa.unparse(exportData);
            const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
            const link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = 'export.csv';
            link.click();
          } else if (format === 'json') {
            const json = JSON.stringify(exportData, null, 2);
            const blob = new Blob([json], { type: 'application/json;charset=utf-8;' });
            const link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = 'export.json';
            link.click();
          }
        },
      },
      mounted() {
        document.body.classList.add('dark'); // Default to dark mode
      },
    });

    app.mount('#app');
  </script>
</body>
</html>
