Add button to sheet and shift selector

This commit is contained in:
Roman Krček
2025-09-07 22:15:03 +02:00
parent 9de5646519
commit dcba02260a

View File

@@ -17,6 +17,7 @@
let sortColumn = $state<keyof RowData | null>(null);
let sortDirection = $state<'asc' | 'desc'>('asc');
let lastCheckedId: string | null = $state(null);
const ROW_LIMIT = 200;
@@ -85,20 +86,52 @@
} finally {
isLoading = false;
}
} // Run on component mount
}
function handleRowClick(event: MouseEvent, clickedId: string) {
const clickedRow = rows.find((r) => r.id === clickedId);
if (!clickedRow || !clickedRow._valid) return;
// Handle shift-clicking for range selection
if (event.shiftKey && lastCheckedId) {
const lastIndex = displayData.findIndex((r) => r.id === lastCheckedId);
const currentIndex = displayData.findIndex((r) => r.id === clickedId);
if (lastIndex !== -1 && currentIndex !== -1) {
const start = Math.min(lastIndex, currentIndex);
const end = Math.max(lastIndex, currentIndex);
const isChecked = !clickedRow._checked; // The state to apply to the range
for (let i = start; i <= end; i++) {
const rowToSelect = displayData[i];
if (rowToSelect && rowToSelect._valid) {
// Prevent checking more than the limit
if (isChecked && selectedCount >= ROW_LIMIT && !rowToSelect._checked) {
continue;
}
rowToSelect._checked = isChecked;
}
}
}
} else {
// Normal click, just toggle the state
if (!clickedRow._checked && selectedCount >= ROW_LIMIT) {
// Do not allow checking more than the limit
} else {
clickedRow._checked = !clickedRow._checked;
}
}
// Update the last checked ID for the next shift-click
lastCheckedId = clickedId;
}
// Run on component mount
onMount(() => {
ensureToken();
fetchAndProcessData();
});
// Function to toggle a single row's checked state
function toggleRow(id: string) {
const row = rows.find((r) => r.id === id);
if (row && row._valid) {
row._checked = !row._checked;
}
}
// Function to toggle select-all: selects first 200 eligible items in current view
function toggleSelectAll(event: Event) {
const target = event.target as HTMLInputElement;
@@ -169,28 +202,33 @@
<div>
<h2 class="mb-2 text-xl font-semibold text-gray-900">Filter and Select Rows</h2>
<p class="text-sm text-gray-700">
Review your data and select which rows to include. Select a batch of max 200 items by using the top checkbox.
Review your data and select which rows to include. Select a batch of max 200 items by using
the top checkbox.
</p>
<p class="text-sm text-gray-700">
<p class="mt-1 text-sm text-gray-700">
Tip: Hold <kbd
class="rounded-md border border-gray-400 bg-gray-200 px-1.5 py-0.5 text-xs font-semibold"
>Shift</kbd
> and click two checkboxes to select a range of rows.
</p>
<p class="mt-1 text-sm text-gray-700">
Already printed or invalid data is marked in the status column.
</p>
</div>
<div class="flex flex-col space-y-2">
{#if $selectedSheet?.id}
<p class="mt-1 text-sm text-gray-500">
Need to make changes?
<a
href={`https://docs.google.com/spreadsheets/d/${$selectedSheet.id}/edit`}
target="_blank"
rel="noopener noreferrer"
class="text-blue-600 underline hover:text-blue-800"
class="inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
>
Open the spreadsheet
Open Sheet
</a>
</p>
{/if}
</div>
<button
onclick={fetchAndProcessData}
class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:cursor-wait disabled:opacity-50"
class="inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:cursor-wait disabled:opacity-50"
disabled={isLoading}
>
{#if isLoading}
@@ -220,6 +258,7 @@
{/if}
</button>
</div>
</div>
{#if isLoading}
<div class="py-12 text-center">
@@ -313,7 +352,7 @@
class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 disabled:cursor-not-allowed disabled:bg-gray-200"
checked={row._checked}
disabled={!row._valid || (selectedCount >= ROW_LIMIT && !row._checked)}
onchange={() => toggleRow(row.id)}
onclick={(e) => handleRowClick(e, row.id)}
/>
</td>
<td class="whitespace-nowrap px-4 py-3 text-sm">{row._rowIndex}</td>