mirror of
				https://github.com/KevinMidboe/hivemonitor.git
				synced 2025-10-29 17:40:25 +00:00 
			
		
		
		
	Defined app routes & layout for footer & modal components
This commit is contained in:
		
							
								
								
									
										91
									
								
								src/lib/components/FooterNavigation.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/lib/components/FooterNavigation.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| <script lang="ts"> | ||||
| 	import { page } from '$app/stores'; | ||||
| 	import HiveIcon from '$lib/icons/hive.svelte'; | ||||
| 	import DashboardIcon from '$lib/icons/DashboardIcon.svelte'; | ||||
| 	import AlarmIcon from '$lib/icons/AlarmIcon.svelte'; | ||||
| 	import SettingIcon from '$lib/icons/SettingIcon.svelte'; | ||||
|  | ||||
| 	const navItems = [ | ||||
| 		{ title: 'Hives', path: '/', component: HiveIcon }, | ||||
| 		{ title: 'Dashboard', path: '/dashboard', component: DashboardIcon }, | ||||
| 		{ title: 'Alarms', path: '/alarms', component: AlarmIcon }, | ||||
| 		{ title: 'Settings', path: '/settings', component: SettingIcon } | ||||
| 	]; | ||||
| </script> | ||||
|  | ||||
| <footer> | ||||
| 	{#each navItems as nav} | ||||
| 		<a | ||||
| 			href={nav.path} | ||||
| 			class="item" | ||||
| 			aria-current={$page.url.pathname == nav.path ? 'page' : undefined} | ||||
| 		> | ||||
| 			<div class="icon"> | ||||
| 				<svelte:component this={nav.component} /> | ||||
| 			</div> | ||||
|  | ||||
| 			<span class="title">{nav.title}</span> | ||||
| 		</a> | ||||
| 	{/each} | ||||
| </footer> | ||||
|  | ||||
| <style lang="scss"> | ||||
| 	footer { | ||||
| 		position: fixed; | ||||
| 		bottom: 0; | ||||
| 		width: 100%; | ||||
| 		background-color: var(--highlight); | ||||
| 		display: flex; | ||||
| 		justify-content: space-evenly; | ||||
|  | ||||
| 		a.item { | ||||
| 			position: relative; | ||||
| 			display: flex; | ||||
| 			flex-direction: column; | ||||
| 			align-items: center; | ||||
| 			cursor: pointer; | ||||
| 			padding: 0.6rem 0.5rem 0.2rem; | ||||
| 			color: var(--color); | ||||
| 			font-size: 0.8rem; | ||||
| 			transition: all 200ms ease; | ||||
| 			will-change: font-weight; | ||||
|  | ||||
| 			.icon { | ||||
| 				width: 20px; | ||||
| 				height: 20px; | ||||
| 				fill: var(--color); | ||||
| 				transition: inherit; | ||||
| 				margin-bottom: 0.2rem; | ||||
| 			} | ||||
|  | ||||
| 			&::after { | ||||
| 				transition: inherit; | ||||
| 				content: ''; | ||||
| 				position: absolute; | ||||
| 				top: 0; | ||||
| 				width: 50%; | ||||
| 				height: 3px; | ||||
| 				background-color: var(--brand); | ||||
| 				opacity: 0; | ||||
| 			} | ||||
|  | ||||
| 			&[aria-current='page'] { | ||||
| 				color: var(--brand); | ||||
| 				font-weight: bold; | ||||
| 				letter-spacing: -0.3px; | ||||
|  | ||||
| 				.icon { | ||||
| 					fill: var(--brand) !important; | ||||
| 				} | ||||
|  | ||||
| 				&::after { | ||||
| 					opacity: 1; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	:global(a.item[aria-current='page'] svg) { | ||||
| 		fill: var(--brand) !important; | ||||
| 	} | ||||
| </style> | ||||
							
								
								
									
										70
									
								
								src/lib/components/Modal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/lib/components/Modal.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| <script lang="ts"> | ||||
| 	import { onDestroy } from 'svelte'; | ||||
| 	import { browser } from '$app/environment'; | ||||
| 	import { swipe } from 'svelte-gestures'; | ||||
| 	import { modal, modalOpen, resetModal } from '$lib/store'; | ||||
|  | ||||
| 	import type { Unsubscriber } from 'svelte/store'; | ||||
|  | ||||
| 	let isOpenSubscription: Unsubscriber; | ||||
| 	let modalElement: HTMLElement; | ||||
|  | ||||
| 	function swipeHandler(event: CustomEvent) { | ||||
| 		if (event.detail.direction === 'right') resetModal(); | ||||
| 	} | ||||
|  | ||||
| 	function toggleHandler(isOpen: boolean) { | ||||
| 		if (!browser || !modalElement) return; | ||||
| 		const app = document.getElementById('app'); | ||||
| 		if (!app) return | ||||
|  | ||||
| 		if (isOpen) { | ||||
| 			app.classList.add('no-scroll'); | ||||
| 			app.inert = true; | ||||
| 			app.setAttribute('aria-hidden', 'true') | ||||
| 		} else { | ||||
| 			setTimeout(() => (modalElement.scrollTop = 0), 500); | ||||
| 			app.classList.remove('no-scroll'); | ||||
| 			app.inert = false; | ||||
| 			app.setAttribute('aria-hidden', 'false') | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	isOpenSubscription = modalOpen.subscribe(toggleHandler); | ||||
| 	onDestroy(() => isOpenSubscription()); | ||||
| </script> | ||||
|  | ||||
| <svelte:body aria-haspopup="dialog" /> | ||||
| <div | ||||
| 	class={`modal ${$modalOpen ? 'open' : ''}`} | ||||
| 	use:swipe={{ timeframe: 1000, minSwipeDistance: 1, touchAction: 'pan-right' }} | ||||
| 	on:swipe={swipeHandler} | ||||
| 	bind:this={modalElement} | ||||
| 	role="dialog" | ||||
| 	aria-modal="true" | ||||
| 	aria-live="assertive" | ||||
| 	aria-labelledby="modal-title" | ||||
| > | ||||
| 	{#if $modal?.opens} | ||||
| 		<svelte:component this={$modal?.opens} data={$modal?.data} /> | ||||
| 	{/if} | ||||
| </div> | ||||
|  | ||||
| <style lang="scss"> | ||||
| 	.modal { | ||||
| 		position: fixed; | ||||
| 		top: 0; | ||||
| 		left: 100vw; | ||||
| 		background-color: var(--background); | ||||
| 		height: 100vh; | ||||
| 		height: -webkit-fill-available; | ||||
| 		width: calc(100vw - 2rem); | ||||
| 		transition: left 400ms ease; | ||||
| 		padding: 0 1rem; | ||||
| 		overflow-y: scroll; | ||||
|  | ||||
| 		&.open { | ||||
| 			left: 0; | ||||
| 		} | ||||
| 	} | ||||
| </style> | ||||
							
								
								
									
										69
									
								
								src/lib/components/modals/GatewayModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/lib/components/modals/GatewayModal.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| <script lang="ts"> | ||||
| 	import { onMount } from 'svelte'; | ||||
| 	import { gatewayMessageQueue } from '$lib/store'; | ||||
| 	import ModalHeader from './ModalHeader.svelte'; | ||||
| 	import HighTemperature from '../cards/HighTemperature.svelte'; | ||||
| 	import LowBattery from '../cards/LowBattery.svelte'; | ||||
| 	import NoData from '../cards/NoData.svelte'; | ||||
| 	import SegmentedControls from '../SegmentedControls.svelte'; | ||||
| 	import NetworkIcon from '$lib/icons/network.svelte'; | ||||
| 	import SyncDisplay from '../displays/SyncDisplay.svelte'; | ||||
| 	import TemperatureDisplay from '../displays/TemperatureDisplay.svelte'; | ||||
| 	import DateSeparator from '../DateSeparator.svelte'; | ||||
| 	import type { IGatewayTelemetry } from '$lib/interfaces/ITelemetry'; | ||||
|  | ||||
| 	export let data: any = {}; | ||||
|  | ||||
| 	let telemetry: IGatewayTelemetry; | ||||
| 	const segments = ['general', 'activity', 'alarms']; | ||||
| 	let selectedSection: string = segments[0]; | ||||
|  | ||||
| 	function segmentSelected(event: CustomEvent) { | ||||
| 		selectedSection = event.detail; | ||||
| 	} | ||||
|  | ||||
| 	onMount(() => | ||||
| 		gatewayMessageQueue.subscribe((msg) => { | ||||
| 			if (msg.gateway_name === data.gateway_name) telemetry = msg; | ||||
| 		}) | ||||
| 	); | ||||
| </script> | ||||
|  | ||||
| <div> | ||||
| 	<ModalHeader title={data?.gateway_name} subtitle="ID273827" icon={NetworkIcon} /> | ||||
|  | ||||
| 	<SegmentedControls {segments} on:change={segmentSelected} /> | ||||
|  | ||||
| 	{#if selectedSection === segments[0]} | ||||
| 		<section class="display"> | ||||
| 			<SyncDisplay date="{telemetry?.t || data?.t }" /> | ||||
| 			<TemperatureDisplay temperature="{telemetry?.temperature}" /> | ||||
| 		</section> | ||||
|  | ||||
| 		<p> | ||||
| 			Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut | ||||
| 			labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco | ||||
| 			laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in | ||||
| 			voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat | ||||
| 			non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | ||||
| 		</p> | ||||
| 	{:else if selectedSection === segments[1]} | ||||
| 		<HighTemperature temperature="24" borderLess={true} /> | ||||
| 		<DateSeparator date={new Date()} /> | ||||
| 		<!-- <LowTemperature temperature="24" /> --> | ||||
| 		<LowBattery battery="9" borderLess={true} /> | ||||
| 		<DateSeparator date={new Date(1689845512000)} /> | ||||
| 		<HighTemperature temperature="23" borderLess={true} /> | ||||
| 		<DateSeparator date={new Date(1682580799000)} /> | ||||
| 	{:else if selectedSection === segments[2]} | ||||
| 		<NoData time="0.3" /> | ||||
| 	{/if} | ||||
| </div> | ||||
|  | ||||
| <style lang="scss"> | ||||
| 	section.display { | ||||
| 		display: grid; | ||||
| 		grid-template-columns: 1fr 1fr; | ||||
| 		grid-gap: 1rem; | ||||
| 	} | ||||
| </style> | ||||
							
								
								
									
										94
									
								
								src/lib/components/modals/HiveModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/lib/components/modals/HiveModal.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| <script lang="ts"> | ||||
| 	import { onMount } from 'svelte'; | ||||
| 	import { hiveMessageQueue } from '$lib/store'; | ||||
| 	import ModalHeader from './ModalHeader.svelte'; | ||||
| 	import LowTemperature from '../cards/LowTemperature.svelte'; | ||||
| 	import HighTemperature from '../cards/HighTemperature.svelte'; | ||||
| 	import NoData from '../cards/NoData.svelte'; | ||||
| 	import SegmentedControls from '../SegmentedControls.svelte'; | ||||
| 	import HiveLogo from '$lib/icons/hive.svelte'; | ||||
| 	import HumidityDisplay from '../displays/HumidityDisplay.svelte'; | ||||
| 	import TemperatureDisplay from '../displays/TemperatureDisplay.svelte'; | ||||
| 	import QueenDisplay from '../displays/QueenDisplay.svelte'; | ||||
| 	import WeightDisplay from '../displays/WeightDisplay.svelte'; | ||||
| 	import DateSeparator from '../DateSeparator.svelte'; | ||||
| 	import WeightChanged from '../cards/WeightChanged.svelte'; | ||||
| 	import BatteryDisplay from '../displays/BatteryDisplay.svelte'; | ||||
| 	import type { IHiveTelemetry } from '$lib/interfaces/ITelemetry'; | ||||
|  | ||||
| 	export let data: any = {}; | ||||
|  | ||||
| 	let telemetry: IHiveTelemetry; | ||||
| 	const segments = ['general', 'activity', 'alarms']; | ||||
| 	let selectedSection: string = segments[0]; | ||||
|  | ||||
| 	function segmentSelected(event: CustomEvent) { | ||||
| 		selectedSection = event.detail; | ||||
| 	} | ||||
|  | ||||
| 	onMount(() => | ||||
| 		hiveMessageQueue.subscribe((msg) => { | ||||
| 			if (msg.hive_name === data.hive_name) telemetry = msg; | ||||
| 		}) | ||||
| 	); | ||||
| </script> | ||||
|  | ||||
| <div> | ||||
| 	<ModalHeader title={data?.hive_name} subtitle="Rosendal" icon={HiveLogo} /> | ||||
|  | ||||
| 	<SegmentedControls {segments} on:change={segmentSelected} /> | ||||
|  | ||||
| 	{#if selectedSection === segments[0]} | ||||
| 		<section class="display"> | ||||
| 			<QueenDisplay /> | ||||
| 			<WeightDisplay weight={telemetry?.weight} /> | ||||
| 			<TemperatureDisplay temperature={telemetry?.temperature} /> | ||||
| 			<HumidityDisplay humidity={telemetry?.humidity} /> | ||||
| 			<BatteryDisplay battery={telemetry?.battery_level} /> | ||||
| 		</section> | ||||
| 	{:else if selectedSection === segments[1]} | ||||
| 		<HighTemperature temperature="32" borderLess={true} /> | ||||
| 		<DateSeparator date={new Date()} /> | ||||
| 		<LowTemperature temperature="8" borderLess={true} /> | ||||
| 		<DateSeparator date={new Date(1689845512000)} /> | ||||
| 		<WeightChanged from="21" to="22" borderLess={true} /> | ||||
| 		<DateSeparator date={new Date(1683717412000)} /> | ||||
| 		<HighTemperature temperature="26" borderLess={true} /> | ||||
| 		<DateSeparator date={new Date(1682580799000)} /> | ||||
|  | ||||
| 		<p> | ||||
| 			Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut | ||||
| 			labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco | ||||
| 			laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in | ||||
| 			voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat | ||||
| 			non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | ||||
| 		</p> | ||||
|  | ||||
| 		<p> | ||||
| 			Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut | ||||
| 			labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco | ||||
| 			laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in | ||||
| 			voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat | ||||
| 			non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | ||||
| 		</p> | ||||
|  | ||||
| 		<p> | ||||
| 			Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut | ||||
| 			labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco | ||||
| 			laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in | ||||
| 			voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat | ||||
| 			non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. | ||||
| 		</p> | ||||
| 	{:else if selectedSection === segments[2]} | ||||
| 		<NoData time="0.3" /> | ||||
| 		<LowTemperature temperature="24" /> | ||||
| 	{/if} | ||||
| </div> | ||||
|  | ||||
| <style lang="scss"> | ||||
| 	section.display { | ||||
| 		display: grid; | ||||
| 		grid-template-columns: 1fr 1fr; | ||||
| 		grid-gap: 1rem; | ||||
| 	} | ||||
| </style> | ||||
							
								
								
									
										139
									
								
								src/lib/components/modals/ModalHeader.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/lib/components/modals/ModalHeader.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | ||||
| <script lang="ts"> | ||||
| 	import { onMount } from 'svelte'; | ||||
| 	import { resetModal } from '$lib/store'; | ||||
| 	import ArrowLeft from '$lib/icons/ArrowLeft.svelte'; | ||||
|  | ||||
| 	export let title: string; | ||||
| 	export let subtitle: string; | ||||
| 	export let icon: any; | ||||
|  | ||||
| 	let bodyTitleEl: HTMLElement; | ||||
| 	let headerTitleEl: HTMLElement; | ||||
|  | ||||
| 	function createObserver() { | ||||
| 		const observer = new IntersectionObserver(handleIntersect, { | ||||
| 			root: null, | ||||
| 			rootMargin: '-20px 10000px 0px 0px', | ||||
| 			threshold: 1 | ||||
| 		}); | ||||
| 		observer.observe(bodyTitleEl); | ||||
| 	} | ||||
|  | ||||
| 	function handleIntersect(entries: IntersectionObserverEntry[]) { | ||||
| 		entries.forEach((entry) => toggleTitle(!entry.isIntersecting)); | ||||
| 	} | ||||
|  | ||||
| 	function toggleTitle(show = true) { | ||||
| 		if (!headerTitleEl || !bodyTitleEl) return; | ||||
|  | ||||
| 		if (show) { | ||||
| 			headerTitleEl.classList.add('show'); | ||||
| 			bodyTitleEl.classList.add('hide'); | ||||
| 		} else { | ||||
| 			headerTitleEl.classList.remove('show'); | ||||
| 			bodyTitleEl.classList.remove('hide'); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	onMount(() => createObserver()); | ||||
| </script> | ||||
|  | ||||
| <div class="top"> | ||||
| 	<button class="back" on:click={resetModal} aria-label="Close"> | ||||
| 		<ArrowLeft fill="var(--color)" /> | ||||
| 	</button> | ||||
| 	<span id="header-title" bind:this={headerTitleEl}>{title}</span> | ||||
| </div> | ||||
|  | ||||
| <div bind:this={bodyTitleEl} class="title-container"> | ||||
| 	<div class="hive-icon"> | ||||
| 		<div class="img"> | ||||
| 			<svelte:component this={icon} /> | ||||
| 		</div> | ||||
| 	</div> | ||||
|  | ||||
| 	<div> | ||||
| 		<h1 id="modal-title">{title}</h1> | ||||
| 		<span>{subtitle}</span> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <style lang="scss"> | ||||
| 	.top { | ||||
| 		position: sticky; | ||||
| 		top: 0; | ||||
| 		display: flex; | ||||
| 		background-color: var(--background); | ||||
| 		padding: 1rem 0; | ||||
| 		z-index: 10; | ||||
|  | ||||
| 		#header-title { | ||||
| 			display: block; | ||||
| 			width: 100%; | ||||
| 			text-align: center; | ||||
| 			align-items: center; | ||||
| 			line-height: 1.8; | ||||
| 			font-size: 1.2rem; | ||||
| 			text-transform: capitalize; | ||||
| 			font-weight: bold; | ||||
| 			opacity: 0; | ||||
| 			transition: visibility 350ms ease, opacity 350ms ease; | ||||
| 			visibility: hidden; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	button.back { | ||||
| 		height: 35px; | ||||
| 		width: 35px; | ||||
| 		padding: 0.2rem; | ||||
|  | ||||
| 		border-radius: unset; | ||||
| 		border: unset; | ||||
| 		font-size: unset; | ||||
| 		font-weight: unset; | ||||
| 		font-family: unset; | ||||
| 		background-color: unset; | ||||
| 		transition: unset; | ||||
| 	} | ||||
|  | ||||
| 	.title-container { | ||||
| 		display: flex; | ||||
| 		transition: opacity 350ms ease; | ||||
| 		opacity: 100%; | ||||
| 		margin-bottom: 1.75rem; | ||||
| 		align-items: center; | ||||
|  | ||||
| 		.hive-icon { | ||||
| 			background-color: var(--highlight); | ||||
| 			display: grid; | ||||
| 			place-items: center; | ||||
| 			min-height: 65px; | ||||
| 			min-width: 65px; | ||||
| 			max-height: 65px; | ||||
| 			max-width: 65px; | ||||
| 			border-radius: 1rem; | ||||
| 			margin-right: 1rem; | ||||
|  | ||||
| 			.img { | ||||
| 				height: 40px; | ||||
| 				width: 40px; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		h1 { | ||||
| 			font-size: 1.66rem; | ||||
| 			text-transform: capitalize; | ||||
| 			margin: 0; | ||||
| 			margin-bottom: 0.2rem; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	:global(#header-title.show) { | ||||
| 		visibility: visible !important; | ||||
| 		opacity: 100% !important; | ||||
| 	} | ||||
|  | ||||
| 	:global(.title-container.hide) { | ||||
| 		opacity: 0 !important; | ||||
| 	} | ||||
| </style> | ||||
							
								
								
									
										17
									
								
								src/routes/+layout.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/routes/+layout.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| <script lang="ts"> | ||||
| 	import { onMount } from 'svelte'; | ||||
| 	import { PUBLIC_MQTT_BROKER_WS_URL } from '$env/static/public'; | ||||
| 	import FooterNavigation from '$lib/components/FooterNavigation.svelte'; | ||||
| 	import Modal from '$lib/components/Modal.svelte'; | ||||
| 	import setupMQTTClient from '$lib/mqttClient'; | ||||
|  | ||||
| 	onMount(() => setupMQTTClient(PUBLIC_MQTT_BROKER_WS_URL)); | ||||
| </script> | ||||
|  | ||||
| <div id="app"> | ||||
| 	<slot /> | ||||
|  | ||||
| 	<FooterNavigation /> | ||||
| </div> | ||||
|  | ||||
| <Modal /> | ||||
							
								
								
									
										29
									
								
								src/routes/+page.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/routes/+page.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <script lang="ts"> | ||||
| 	import HiveSummary from '$lib/components/HiveSummary.svelte'; | ||||
| 	import GatewaySummary from '$lib/components/GatewaySummary.svelte'; | ||||
| 	import HighTemperature from '$lib/components/cards/HighTemperature.svelte'; | ||||
| 	import LowTemperature from '$lib/components/cards/LowTemperature.svelte'; | ||||
| 	import LowBattery from '$lib/components/cards/LowBattery.svelte'; | ||||
| 	import NoData from '$lib/components/cards/NoData.svelte'; | ||||
| 	import WeightChanged from '$lib/components/cards/WeightChanged.svelte'; | ||||
| </script> | ||||
|  | ||||
| <main> | ||||
| 	<h1>Hive monitor</h1> | ||||
|  | ||||
| 	<span class="header">Hives</span> | ||||
| 	<HiveSummary /> | ||||
|  | ||||
| 	<span class="header">Gateways</span> | ||||
| 	<GatewaySummary /> | ||||
|  | ||||
| 	<span class="header">Alerts</span> | ||||
| 	<HighTemperature temperature="32" /> | ||||
| 	<LowTemperature temperature="10" /> | ||||
| 	<LowBattery battery="19" /> | ||||
| 	<NoData time="1" /> | ||||
| 	<WeightChanged from="19" to="20" /> | ||||
| </main> | ||||
|  | ||||
| <style lang="scss"> | ||||
| </style> | ||||
							
								
								
									
										28
									
								
								src/routes/alarms/+page.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/routes/alarms/+page.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <script lang="ts"> | ||||
|   import HighTemperature from '$lib/components/cards/HighTemperature.svelte'; | ||||
|   import LowTemperature from '$lib/components/cards/LowTemperature.svelte'; | ||||
|   import LowBattery from '$lib/components/cards/LowBattery.svelte'; | ||||
|   import NoData from '$lib/components/cards/NoData.svelte'; | ||||
|   import WeightChanged from '$lib/components/cards/WeightChanged.svelte'; | ||||
|  | ||||
| </script> | ||||
|  | ||||
| <main> | ||||
|   <h1>Alarms</h1> | ||||
|  | ||||
|   <span class="header">Alerts</span> | ||||
|   <HighTemperature temperature="32" /> | ||||
|   <LowTemperature temperature="10" /> | ||||
|   <LowBattery battery="19" /> | ||||
|   <NoData time="1" /> | ||||
|   <WeightChanged from="21" to="22" /> | ||||
|  | ||||
|  | ||||
|   <p class="read-the-docs"> | ||||
|     Click on the Vite and Svelte logos to learn more | ||||
|   </p> | ||||
|  | ||||
| </main> | ||||
|  | ||||
| <style lang="scss"> | ||||
| </style> | ||||
							
								
								
									
										13
									
								
								src/routes/dashboard/+page.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/routes/dashboard/+page.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <script lang="ts"> | ||||
|   import GatewaySummary from '$lib/components/GatewaySummary.svelte'; | ||||
| </script> | ||||
|  | ||||
| <main> | ||||
|   <h1>Dashboard</h1> | ||||
|  | ||||
|   <span class="header">Gateways</span> | ||||
|   <GatewaySummary /> | ||||
| </main> | ||||
|  | ||||
| <style lang="scss"> | ||||
| </style> | ||||
							
								
								
									
										18
									
								
								src/routes/settings/+page.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/routes/settings/+page.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| <script lang="ts"> | ||||
| </script> | ||||
|  | ||||
| <main> | ||||
|   <h1>Settings</h1> | ||||
| </main> | ||||
|  | ||||
| <style lang="scss"> | ||||
| </style> | ||||
|  | ||||
|  | ||||
|  | ||||
| <!--  | ||||
| from machine import ADC, Pin | ||||
| adc = ADC(Pin(35)) | ||||
| (adc.read() / 4095) * 2 * 3.3 * 1.1 | ||||
|  | ||||
| let battery_voltage = (ADC.read(battery)/4095)*2*3.3*1.1; --> | ||||
		Reference in New Issue
	
	Block a user