feat: rewrite devices page as phone-card grid
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,15 +2,24 @@
|
|||||||
import { listDevices } from '$lib/api/devices.remote';
|
import { listDevices } from '$lib/api/devices.remote';
|
||||||
import { dashboardWs } from '$lib/stores/dashboard-ws.svelte';
|
import { dashboardWs } from '$lib/stores/dashboard-ws.svelte';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import DeviceCard from '$lib/components/DeviceCard.svelte';
|
||||||
|
|
||||||
const initialDevices = await listDevices();
|
const initialDevices = await listDevices();
|
||||||
|
|
||||||
let devices = $state(
|
let devices = $state(
|
||||||
initialDevices.map((d: Record<string, string>) => ({
|
initialDevices.map((d) => ({
|
||||||
deviceId: d.deviceId,
|
deviceId: d.deviceId,
|
||||||
name: d.name,
|
name: d.name,
|
||||||
status: d.status as 'online' | 'offline',
|
status: d.status as 'online' | 'offline',
|
||||||
lastSeen: d.lastSeen
|
model: d.model,
|
||||||
|
manufacturer: d.manufacturer,
|
||||||
|
androidVersion: d.androidVersion,
|
||||||
|
screenWidth: d.screenWidth,
|
||||||
|
screenHeight: d.screenHeight,
|
||||||
|
batteryLevel: d.batteryLevel,
|
||||||
|
isCharging: d.isCharging,
|
||||||
|
lastSeen: d.lastSeen,
|
||||||
|
lastGoal: d.lastGoal
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -26,7 +35,20 @@
|
|||||||
devices = [...devices];
|
devices = [...devices];
|
||||||
} else {
|
} else {
|
||||||
devices = [
|
devices = [
|
||||||
{ deviceId: id, name, status: 'online', lastSeen: new Date().toISOString() },
|
{
|
||||||
|
deviceId: id,
|
||||||
|
name,
|
||||||
|
status: 'online',
|
||||||
|
model: null,
|
||||||
|
manufacturer: null,
|
||||||
|
androidVersion: null,
|
||||||
|
screenWidth: null,
|
||||||
|
screenHeight: null,
|
||||||
|
batteryLevel: null,
|
||||||
|
isCharging: false,
|
||||||
|
lastSeen: new Date().toISOString(),
|
||||||
|
lastGoal: null
|
||||||
|
},
|
||||||
...devices
|
...devices
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -37,6 +59,14 @@
|
|||||||
existing.status = 'offline';
|
existing.status = 'offline';
|
||||||
devices = [...devices];
|
devices = [...devices];
|
||||||
}
|
}
|
||||||
|
} else if (msg.type === 'device_status') {
|
||||||
|
const id = msg.deviceId as string;
|
||||||
|
const existing = devices.find((d) => d.deviceId === id);
|
||||||
|
if (existing) {
|
||||||
|
existing.batteryLevel = msg.batteryLevel as number;
|
||||||
|
existing.isCharging = msg.isCharging as boolean;
|
||||||
|
devices = [...devices];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return unsub;
|
return unsub;
|
||||||
@@ -56,24 +86,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="space-y-3">
|
<div class="grid grid-cols-2 gap-6 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
|
||||||
{#each devices as d (d.deviceId)}
|
{#each devices as d (d.deviceId)}
|
||||||
<a
|
<DeviceCard {...d} />
|
||||||
href="/dashboard/devices/{d.deviceId}"
|
|
||||||
class="flex items-center justify-between rounded-lg border border-neutral-200 p-4 hover:border-neutral-400"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<p class="font-medium">{d.name}</p>
|
|
||||||
<p class="text-sm text-neutral-500">
|
|
||||||
{d.status === 'online' ? 'Connected now' : `Last seen ${new Date(d.lastSeen).toLocaleString()}`}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
class="inline-block h-2 w-2 rounded-full {d.status === 'online'
|
|
||||||
? 'bg-green-500'
|
|
||||||
: 'bg-neutral-300'}"
|
|
||||||
></span>
|
|
||||||
</a>
|
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user