webui/src/routes/+page.svelte

185 lines
4.2 KiB
Svelte
Raw Normal View History

2023-11-17 00:05:35 +00:00
<script lang="ts">
import { PUBLIC_BASE_URL } from '$lib/config';
import { screenSize, updateScreenSize } from '$lib/screen';
2023-11-17 00:05:35 +00:00
2024-09-03 10:11:14 +00:00
import { Container, Row, Toast, ToastBody } from '@sveltestrap/sveltestrap';
2024-12-12 22:04:13 +00:00
import { replaceState } from '$app/navigation';
2023-11-17 00:05:35 +00:00
2023-11-19 19:27:22 +00:00
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
2023-11-17 00:05:35 +00:00
import Control from './Control.svelte';
import Settings from './Settings.svelte';
2023-11-19 19:27:22 +00:00
import Status from './Status.svelte';
2024-06-08 22:23:39 +00:00
import { uiSettings } from '$lib/uiSettings';
2023-11-17 00:05:35 +00:00
2023-11-17 02:15:23 +00:00
let settings = writable({
2024-09-05 11:10:58 +00:00
fgColor: '0',
bgColor: '0'
2023-11-19 19:27:22 +00:00
});
2023-11-17 00:05:35 +00:00
2023-11-18 12:55:55 +00:00
let status = writable({
2023-11-19 19:27:22 +00:00
data: ['L', 'O', 'A', 'D', 'I', 'N', 'G'],
espFreeHeap: 0,
espHeapSize: 0,
connectionStatus: {
price: false,
blocks: false
},
2023-11-18 12:55:55 +00:00
leds: []
2023-11-19 19:27:22 +00:00
});
2023-11-18 12:55:55 +00:00
2023-11-24 23:42:37 +00:00
const fetchStatusData = () => {
2024-09-02 23:26:24 +00:00
fetch(`${PUBLIC_BASE_URL}/api/status`, { credentials: 'same-origin' })
2023-11-24 23:42:37 +00:00
.then((res) => res.json())
.then((data) => {
status.set(data);
});
};
const fetchSettingsData = () => {
2024-09-02 23:26:24 +00:00
fetch(PUBLIC_BASE_URL + `/api/settings`, { credentials: 'same-origin' })
2023-11-17 00:05:35 +00:00
.then((res) => res.json())
.then((data) => {
data.fgColor = String(data.fgColor);
data.bgColor = String(data.bgColor);
2023-11-19 19:27:22 +00:00
data.timePerScreen = data.timerSeconds / 60;
2023-11-17 02:15:23 +00:00
2023-11-19 19:27:22 +00:00
if (data.fgColor > 65535) {
data.fgColor = '65535';
}
2023-11-17 12:12:22 +00:00
2023-11-19 19:27:22 +00:00
if (data.bgColor > 65535) {
data.bgColor = '65535';
}
2023-11-17 00:05:35 +00:00
settings.set(data);
});
2023-11-24 23:42:37 +00:00
};
2023-11-18 12:55:55 +00:00
2024-12-12 22:04:13 +00:00
let sections: (HTMLElement | null)[];
let observer: IntersectionObserver;
const SM_BREAKPOINT = 576;
const setupObserver = () => {
if (window.innerWidth < SM_BREAKPOINT) {
observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const id = entry.target.id;
replaceState(`#${id}`);
// Update nav pills
document.querySelectorAll('.nav-link').forEach((link) => {
link.classList.remove('active');
if (link.getAttribute('href') === `#${id}`) {
link.classList.add('active');
}
});
}
});
},
{
threshold: 0.25 // Trigger when section is 50% visible
}
);
sections = ['control', 'status', 'settings'].map((id) => document.getElementById(id));
sections.forEach((section) => observer.observe(section!));
}
};
2023-11-24 23:42:37 +00:00
onMount(() => {
2024-12-12 22:04:13 +00:00
setupObserver();
2023-11-24 23:42:37 +00:00
fetchSettingsData();
fetchStatusData();
2023-11-18 12:55:55 +00:00
2023-11-19 19:27:22 +00:00
const evtSource = new EventSource(`${PUBLIC_BASE_URL}/events`);
2023-11-18 12:55:55 +00:00
2023-11-19 19:27:22 +00:00
evtSource.addEventListener('status', (e) => {
let dataObj = JSON.parse(e.data);
status.set(dataObj);
});
function handleResize() {
2024-12-12 22:04:13 +00:00
if (observer) {
observer.disconnect();
}
setupObserver();
updateScreenSize();
}
// Add an event listener to update the screen size when the window is resized
window.addEventListener('resize', handleResize);
// Call the function initially to set the initial screen size
updateScreenSize();
// Cleanup function to remove the event listener when the component is destroyed
return () => {
window.removeEventListener('resize', handleResize);
};
2023-11-17 00:05:35 +00:00
});
2023-11-21 20:22:29 +00:00
$: {
const lgBreakpoint = parseInt(
getComputedStyle(document.documentElement).getPropertyValue('--bs-breakpoint-lg')
);
if ($screenSize >= lgBreakpoint) {
uiSettings.set({
inputSize: 'sm',
selectClass: 'form-select-sm',
btnSize: 'sm'
});
} else {
uiSettings.set({
inputSize: 'lg',
selectClass: 'form-select-lg',
btnSize: 'xl'
});
}
}
2023-11-21 20:22:29 +00:00
let toastIsOpen = false;
let toastColor = 'success';
let toastBody = '';
export const showToast = (event) => {
toastIsOpen = true;
toastColor = event.detail.color;
toastBody = event.detail.text;
};
2023-11-17 00:05:35 +00:00
</script>
2023-11-17 18:10:46 +00:00
<svelte:head>
<title>BTClock</title>
2023-11-17 18:10:46 +00:00
</svelte:head>
2023-11-17 00:05:35 +00:00
<Container fluid>
2024-08-31 15:10:26 +00:00
<Row>
2024-09-11 18:16:55 +00:00
<Control bind:settings on:showToast={showToast} bind:status lg="3" xxl="4"></Control>
2024-12-12 22:04:13 +00:00
2024-08-31 15:10:26 +00:00
<Status bind:settings bind:status lg="6" xxl="4"></Status>
2024-12-12 22:04:13 +00:00
2024-08-31 15:10:26 +00:00
<Settings bind:settings on:showToast={showToast} on:formReset={fetchSettingsData} lg="3" xxl="4"
></Settings>
2023-11-17 00:05:35 +00:00
</Row>
</Container>
2023-11-21 20:22:29 +00:00
<div class="position-fixed bottom-0 end-0 p-2">
<div class="">
<Toast
isOpen={toastIsOpen}
2024-08-31 17:54:43 +00:00
class="me-1 bg-{toastColor} text-bg-{toastColor}"
2023-11-21 20:22:29 +00:00
autohide
on:close={() => (toastIsOpen = false)}
>
<ToastBody>
{toastBody}
</ToastBody>
</Toast>
</div>
</div>