Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions src/lib/components/DataTable.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<script>
import { _ } from 'svelte-i18n';
let { historicalData } = $props();

let dataArray = $derived(historicalData); // Assume data is an array of objects

// Filter data for current day
function getCurrentDayData(dataArray) {
const today = new Date();
today.setHours(0, 0, 0, 0);

return dataArray.filter((item) => {
const itemDate = new Date(item.created_at);
itemDate.setHours(0, 0, 0, 0);
return itemDate.getTime() === today.getTime();
});
}

// Get visible columns
function getVisibleColumns(dataArray) {
const excludedColumns = ['is_simulated', 'dev_eui', 'smoke_detected', 'id', 'vape_detected'];
const allKeys = dataArray.length > 0 ? Object.keys(dataArray[0]) : [];

return allKeys.filter((key) => {
if (excludedColumns.includes(key)) return false;
const hasNonNullValue = dataArray.some((item) => item[key] !== null);
return hasNonNullValue;
});
}

// Format column names
function formatColumnName(key) {
return key
.split('_')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
}

// Format cell value
function formatCellValue(key, value) {
if (key === 'created_at') {
return new Date(value).toLocaleString();
}
if (typeof value === 'boolean') {
return value ? 'Yes' : 'No';
}
if (typeof value === 'number') {
return value.toFixed(2);
}
return value;
}

let filteredData = $derived(getCurrentDayData(dataArray));
let visibleColumns = $derived(getVisibleColumns(filteredData));
</script>

<div class="min-h-screen w-full text-gray-900">
<div class="mx-auto w-full p-4">
<div
class="overflow-hidden rounded-lg border border-gray-200/70 bg-white shadow-lg dark:border-white/10 dark:bg-neutral-900"
>
<!-- Header -->
<div
class="bg-gradient-to-r from-blue-600 to-blue-700 px-6 py-4 dark:from-blue-700 dark:to-indigo-800"
>
<h1 class="text-2xl font-bold text-white">{$_('Sensor Data - Today')}</h1>
</div>

<!-- Table wrapper -->
<div class="overflow-x-auto">
{#if filteredData.length === 0}
<div class="p-12 text-center text-gray-500 dark:text-gray-400">
<p class="text-lg">{$_('No data available for today')}</p>
</div>
{:else}
<table class="w-full text-sm">
<thead
class="border-b border-gray-200 bg-gray-50 dark:border-white/10 dark:bg-neutral-800"
>
<tr>
{#each visibleColumns as column}
<th
class="text-md px-6 py-3 text-left font-semibold tracking-wide text-gray-700 uppercase dark:text-gray-200"
>
{$_(column)}
</th>
{/each}
</tr>
</thead>

<tbody class="divide-y divide-gray-200 dark:divide-white/10">
{#each filteredData as row, rowIndex}
<tr
class="transition-colors duration-150 even:bg-transparent hover:bg-gray-50 dark:even:bg-white/5 dark:hover:bg-white/10"
>
{#each visibleColumns as column}
<td
class="px-6 py-3 text-lg whitespace-nowrap text-gray-900 dark:text-gray-100"
>
{formatCellValue(column, row[column])}
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
{/if}
</div>
</div>
</div>
</div>
1 change: 1 addition & 0 deletions src/lib/i18n/locales/en.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const strings = {
'Sensor Data - Today': 'Sensor Data - Today',
soil_moisture: 'Volumetric Water Content',
moisture: 'Volumetric Water Content',
Moisture: 'Volumetric Water Content',
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/locales/ja.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const strings = {
'Sensor Data - Today': 'センサーデータ - 本日',
soil_moisture: '土壌水分量',
moisture: '土壌水分量',
Moisture: '土壌水分量',
Expand Down
4 changes: 2 additions & 2 deletions src/lib/utilities/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ export const getTextColorByKey = (key: string, isMetadata: boolean = false): str
};

/**
* Default options for number formatting. This sets the maximum number of fraction digits to 1.
* Default options for number formatting. This sets the maximum number of fraction digits to 2.
*/
const defaultNumberFormatOptions: Intl.NumberFormatOptions = { maximumFractionDigits: 1 };
const defaultNumberFormatOptions: Intl.NumberFormatOptions = { maximumFractionDigits: 2 };

/**
* Custom format options for various statistics keys.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@
// Cleanup on destroy
import { onDestroy } from 'svelte';
import BatteryLevel from '$lib/components/BatteryLevel.svelte';
import DataTable from '$lib/components/DataTable.svelte';
onDestroy(() => {
teardownRealtime();
if (staleCheckIntervalId) clearInterval(staleCheckIntervalId);
Expand Down Expand Up @@ -599,8 +600,12 @@

<!-- Full-width Calendar Section -->
<section class="mb-12 px-4">
<h2>{$_('Weather & Data')}</h2>
<WeatherCalendar events={calendarEvents} />
{#if device.cw_device_type?.data_table_v2 === 'cw_air_data'}
<DataTable {historicalData} />
{:else}
<h2>{$_('Weather & Data')}</h2>
<WeatherCalendar events={calendarEvents} />
{/if}
</section>

<style lang="postcss">
Expand Down