margins for table
This commit is contained in:
@@ -9,6 +9,8 @@
|
|||||||
let error = null;
|
let error = null;
|
||||||
let filter = 'all'; // all, worked, confirmed, unworked
|
let filter = 'all'; // all, worked, confirmed, unworked
|
||||||
let sort = 'name'; // name, status
|
let sort = 'name'; // name, status
|
||||||
|
let groupedData = [];
|
||||||
|
let bands = [];
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await loadAwardData();
|
await loadAwardData();
|
||||||
@@ -40,6 +42,9 @@
|
|||||||
|
|
||||||
award = data.award;
|
award = data.award;
|
||||||
entities = data.entities || [];
|
entities = data.entities || [];
|
||||||
|
|
||||||
|
// Group data for table display
|
||||||
|
groupDataForTable();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e.message;
|
error = e.message;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -47,6 +52,93 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function groupDataForTable() {
|
||||||
|
// Group by entity name, then create band columns
|
||||||
|
const entityMap = new Map();
|
||||||
|
const bandsSet = new Set();
|
||||||
|
|
||||||
|
entities.forEach((entity) => {
|
||||||
|
const entityName = entity.entityName || entity.entity || 'Unknown';
|
||||||
|
|
||||||
|
if (!entityMap.has(entityName)) {
|
||||||
|
entityMap.set(entityName, {
|
||||||
|
entityName,
|
||||||
|
bands: new Map(),
|
||||||
|
worked: entity.worked,
|
||||||
|
confirmed: entity.confirmed,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const entityData = entityMap.get(entityName);
|
||||||
|
|
||||||
|
if (entity.band) {
|
||||||
|
bandsSet.add(entity.band);
|
||||||
|
|
||||||
|
if (!entityData.bands.has(entity.band)) {
|
||||||
|
entityData.bands.set(entity.band, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add QSO info to this band
|
||||||
|
entityData.bands.get(entity.band).push({
|
||||||
|
callsign: entity.callsign,
|
||||||
|
mode: entity.mode,
|
||||||
|
confirmed: entity.confirmed,
|
||||||
|
qsoDate: entity.qsoDate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Convert bands Set to sorted array
|
||||||
|
bands = Array.from(bandsSet).sort();
|
||||||
|
|
||||||
|
// Convert Map to array
|
||||||
|
groupedData = Array.from(entityMap.values());
|
||||||
|
|
||||||
|
// Apply filtering
|
||||||
|
applyFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyFilter() {
|
||||||
|
// Re-group from original entities with filter applied
|
||||||
|
const filteredEntities = getFilteredEntities();
|
||||||
|
|
||||||
|
const entityMap = new Map();
|
||||||
|
const bandsSet = new Set();
|
||||||
|
|
||||||
|
filteredEntities.forEach((entity) => {
|
||||||
|
const entityName = entity.entityName || entity.entity || 'Unknown';
|
||||||
|
|
||||||
|
if (!entityMap.has(entityName)) {
|
||||||
|
entityMap.set(entityName, {
|
||||||
|
entityName,
|
||||||
|
bands: new Map(),
|
||||||
|
worked: entity.worked,
|
||||||
|
confirmed: entity.confirmed,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const entityData = entityMap.get(entityName);
|
||||||
|
|
||||||
|
if (entity.band) {
|
||||||
|
bandsSet.add(entity.band);
|
||||||
|
|
||||||
|
if (!entityData.bands.has(entity.band)) {
|
||||||
|
entityData.bands.set(entity.band, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
entityData.bands.get(entity.band).push({
|
||||||
|
callsign: entity.callsign,
|
||||||
|
mode: entity.mode,
|
||||||
|
confirmed: entity.confirmed,
|
||||||
|
qsoDate: entity.qsoDate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bands = Array.from(bandsSet).sort();
|
||||||
|
groupedData = Array.from(entityMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
function getFilteredEntities() {
|
function getFilteredEntities() {
|
||||||
let filtered = [...entities];
|
let filtered = [...entities];
|
||||||
|
|
||||||
@@ -88,16 +180,9 @@
|
|||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatusClass(entity) {
|
// Re-apply filter when filter/sort changes
|
||||||
if (entity.confirmed) return 'confirmed';
|
$: if (entities.length > 0) {
|
||||||
if (entity.worked) return 'worked';
|
applyFilter();
|
||||||
return 'unworked';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStatusText(entity) {
|
|
||||||
if (entity.confirmed) return 'Confirmed';
|
|
||||||
if (entity.worked) return 'Worked';
|
|
||||||
return 'Not Worked';
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -187,44 +272,46 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="entities-list">
|
<div class="table-container">
|
||||||
{#if getFilteredEntities().length === 0}
|
{#if groupedData.length === 0}
|
||||||
<div class="empty">No entities match the current filter.</div>
|
<div class="empty">No entities match the current filter.</div>
|
||||||
{:else}
|
{:else}
|
||||||
{#each getFilteredEntities() as entity (entity.entity)}
|
<table class="award-table">
|
||||||
<div class="entity-card {getStatusClass(entity)}">
|
<thead>
|
||||||
<div class="entity-info">
|
<tr>
|
||||||
<div class="entity-name">
|
<th class="entity-column">Entity</th>
|
||||||
{entity.entityName || entity.entity || 'Unknown'}
|
{#each bands as band}
|
||||||
{#if entity.points}
|
<th class="band-column">{band}</th>
|
||||||
<span class="points-badge">{entity.points} pts</span>
|
{/each}
|
||||||
{/if}
|
</tr>
|
||||||
{#if entity.entityId && entity.entityId !== entity.entityName}
|
</thead>
|
||||||
<span class="entity-id">({entity.entityId})</span>
|
<tbody>
|
||||||
{/if}
|
{#each groupedData as row}
|
||||||
</div>
|
<tr class="{row.confirmed ? 'confirmed' : row.worked ? 'worked' : 'unworked'}">
|
||||||
<div class="entity-details">
|
<td class="entity-cell">
|
||||||
{#if entity.callsign}
|
<div class="entity-name">{row.entityName}</div>
|
||||||
<span class="callsign">{entity.callsign}</span>
|
</td>
|
||||||
{/if}
|
{#each bands as band}
|
||||||
{#if entity.band}
|
{@const qsos = row.bands.get(band) || []}
|
||||||
<span class="band">{entity.band}</span>
|
<td class="band-cell">
|
||||||
{/if}
|
{#if qsos.length > 0}
|
||||||
{#if entity.mode}
|
<div class="qso-list">
|
||||||
<span class="mode">{entity.mode}</span>
|
{#each qsos as qso}
|
||||||
{/if}
|
<div class="qso-entry {qso.confirmed ? 'qso-confirmed' : 'qso-worked'}">
|
||||||
{#if entity.qsoDate}
|
<span class="callsign">{qso.callsign}</span>
|
||||||
<span class="date">{entity.qsoDate}</span>
|
<span class="mode">{qso.mode}</span>
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<div class="entity-status">
|
{:else}
|
||||||
<span class="status-badge {getStatusClass(entity)}">
|
<div class="no-qso">-</div>
|
||||||
{getStatusText(entity)}
|
{/if}
|
||||||
</span>
|
</td>
|
||||||
</div>
|
{/each}
|
||||||
</div>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -250,6 +337,16 @@
|
|||||||
color: #d32f2f;
|
color: #d32f2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.award-table {
|
||||||
|
border: 1px solid #000;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.award-table td {
|
||||||
|
border: 1px solid #000;
|
||||||
|
padding: 0px 3px 0px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
.award-header {
|
.award-header {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user