diff --git a/Provider/frontend/.env.development b/Provider/frontend/.env.development new file mode 100644 index 0000000..36e66ab --- /dev/null +++ b/Provider/frontend/.env.development @@ -0,0 +1,3 @@ +# Set this to your ESP32's IP address for local development +# Example: VITE_API_BASE=http://192.168.1.100 +VITE_API_BASE=http://ESP32_IP_HERE diff --git a/Provider/frontend/.env.production b/Provider/frontend/.env.production new file mode 100644 index 0000000..a301423 --- /dev/null +++ b/Provider/frontend/.env.production @@ -0,0 +1,2 @@ +# Production: empty = relative URLs (frontend served from same ESP32) +VITE_API_BASE= diff --git a/Provider/frontend/src/App.svelte b/Provider/frontend/src/App.svelte index 8f8e2b4..9a2ae9b 100644 --- a/Provider/frontend/src/App.svelte +++ b/Provider/frontend/src/App.svelte @@ -1,19 +1,211 @@
-
-
-

{title}

-

{subtitle}

-
- - Hello World — Frontend is running! +
+ +
+

Calendink Provider

+

ESP32-S3 System Dashboard

+
+ + +
+ {#if status === "loading"} +
+ + Connecting to ESP32... +
+ {:else if status === "ok"} +
+ + Connected +
+ {:else if status === "rebooting"} +
+ + Rebooting... +
+ {:else} +
+ + Offline — {errorMsg} +
+ {/if} +
+ + +
+
+

+ System Info +

+
+
+ {#each infoItems as item} +
+
+ {item.icon} + {item.label} +
+ + {#if status === "loading"} + + {:else} + {item.value} + {/if} + +
+ {/each}
+ + +
+
+
+

+ Device Control +

+

+ Restart the ESP32 microcontroller +

+
+ +
+
+ + + {#if showRebootConfirm} +
+
+

+ Confirm Reboot +

+

+ Are you sure you want to reboot the ESP32? The device will be + temporarily unavailable. +

+
+ + +
+
+
+ {/if} + + +

+ Auto-refreshes every 5s +

diff --git a/Provider/frontend/src/lib/api.js b/Provider/frontend/src/lib/api.js new file mode 100644 index 0000000..ec60df5 --- /dev/null +++ b/Provider/frontend/src/lib/api.js @@ -0,0 +1,35 @@ +/** + * API layer for Calendink Provider ESP32-S3 dashboard. + * + * VITE_API_BASE controls the backend URL: + * - Development (PC): "http://" (set in .env.development) + * - Production (ESP32): "" (empty = relative URLs, same origin) + */ + +const API_BASE = import.meta.env.VITE_API_BASE || ''; + +/** + * Fetch system information from the ESP32. + * @returns {Promise<{chip: string, freeHeap: number, uptime: number, firmware: string, connection: string}>} + */ +export async function getSystemInfo() { + const res = await fetch(`${API_BASE}/api/system/info`); + if (!res.ok) { + throw new Error(`HTTP ${res.status}: ${res.statusText}`); + } + return res.json(); +} + +/** + * Send a reboot command to the ESP32. + * @returns {Promise<{message: string}>} + */ +export async function reboot() { + const res = await fetch(`${API_BASE}/api/system/reboot`, { + method: 'POST', + }); + if (!res.ok) { + throw new Error(`HTTP ${res.status}: ${res.statusText}`); + } + return res.json(); +}