added times to calendar; added counters; improved element structure and styles slightly;

This commit is contained in:
Spencer Flagg 2024-01-24 17:43:18 +01:00
parent 55df8e8dad
commit 781ef76416
6 changed files with 150 additions and 34 deletions

View file

@ -0,0 +1,56 @@
<script>
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
export let actions = []; // Array of actions passed to the component
// Stores for each action type
let awakeMinutes = writable(0);
let asleepMinutes = writable(0);
let foodMinutes = writable(0);
let diaperMinutes = writable(0);
let poopDays = writable(0);
const getLastActionTime = (type) => {
const lastAction = actions.filter(action => action.type === type).pop();
return lastAction ? new Date(lastAction.created) : null;
};
const calculateDiffMinutes = (date) => {
const now = new Date();
return date ? Math.floor((now - date) / 60000) : null; // Convert milliseconds to minutes
};
const calculateDiffDays = (date) => {
const now = new Date();
return date ? Math.floor((now - date) / (1000 * 60 * 60 * 24)) : null; // Convert milliseconds to days
};
const updateTimes = () => {
awakeMinutes.set(calculateDiffMinutes(getLastActionTime("awake")));
asleepMinutes.set(calculateDiffMinutes(getLastActionTime("asleep")));
foodMinutes.set(calculateDiffMinutes(getLastActionTime("food")));
diaperMinutes.set(calculateDiffMinutes(getLastActionTime("diaper")));
poopDays.set(calculateDiffDays(getLastActionTime("poop")));
};
// Update immediately when the component has access to actions
updateTimes();
onMount(() => {
const interval = setInterval(updateTimes, 1000); // Update every minute
return () => {
clearInterval(interval); // Cleanup on component destruction
};
});
</script>
<div class="column">
{#if $awakeMinutes !== null && $awakeMinutes < $asleepMinutes}<p>Awake for {$awakeMinutes} minutes</p>{/if}
{#if $asleepMinutes !== null && $asleepMinutes < $awakeMinutes}<p>Sleeping for {$asleepMinutes} minutes</p>{/if}
{#if $foodMinutes !== null}<p>Ate {$foodMinutes} minutes ago</p>{/if}
{#if $diaperMinutes !== null}<p>Diaper changed {$diaperMinutes} minutes ago</p>{/if}
{#if $poopDays === 0}<p>Pooped today</p>{:else if $poopDays !== null}<p>Pooped {$poopDays} days ago</p>{/if}
</div>

View file

@ -18,12 +18,23 @@
<header>
<h1>Coover Tracker</h1>
<nav>
<a href="/">Home</a>
{#if $currentUser}
<a href="/stats">Stats</a>
<a href="/calendar">Calendar</a>
{/if}
<a href="/signin">{ $currentUser ? $currentUser.username : 'Sign In'}</a>
<ul>
<li><a href="/">Home</a></li>
{#if $currentUser}
<li><a href="/stats">Stats</a></li>
<li><a href="/calendar">Calendar</a></li>
{/if}
<li>
<a href="/signin">
{#if $currentUser}
<strong>( {$currentUser.username} )</strong>
{:else}
'Sign In'
{/if}
</a>
</li>
</ul>
</nav>
</header>

View file

@ -1,7 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import { pb, currentUser } from '$lib/pocketbase';
import { user } from '$lib/userStore';
import Counters from '$lib/components/counters.svelte';
type Action = {
type: string;
@ -39,18 +39,25 @@
</script>
{#if $currentUser}
<div>
<button on:click={() => recordAction('awake')}>Awake</button>
<button on:click={() => recordAction('asleep')}>Asleep</button>
<button on:click={() => recordAction('food')}>Food</button>
<button on:click={() => recordAction('diaper')}>Diaper</button>
<button on:click={() => recordAction('poop')}>Poop</button>
<aside>
<button on:click={() => recordAction('awake')}>Awake</button>
<button on:click={() => recordAction('asleep')}>Asleep</button>
<button on:click={() => recordAction('food')}>Food</button>
<button on:click={() => recordAction('diaper')}>Diaper</button>
<button on:click={() => recordAction('poop')}>Poop</button>
</aside>
<h2>Today</h2>
<ul>
{#each actions as action}
<li>{action.type} at {new Date(action.created).toLocaleTimeString('en-NL', { hour: '2-digit', minute: '2-digit' })}</li>
{/each}
</ul>
</div>
<section>
<h2>Today</h2>
<div class="container">
<div class="row">
<ul class="column">
{#each actions as action}
<li>{action.type} at {new Date(action.created).toLocaleTimeString('en-NL', { hour: '2-digit', minute: '2-digit' })}</li>
{/each}
</ul>
<Counters {actions} />
</div>
</div>
</section>
{/if}

View file

@ -34,20 +34,26 @@ import { onMount } from 'svelte';
// Generate hours for the grid
const hours = Array.from({ length: 24 }, (_, i) => i);
// Function to format hour in HH:mm format
const formatHour = (hour: number) => {
return `${hour.toString().padStart(2, '0')}:00`;
};
</script>
<style>
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-columns: 60px repeat(7, 1fr); /* Adjusted for hour column */
text-align: center;
}
.day-header {
.day-header, .hour-label {
font-weight: bold;
border: 1px solid #ccc;
}
.hour {
border: 1px solid #ccc;
min-height: 60px;
height: 60px;
}
.event {
background-color: lightblue;
@ -55,21 +61,41 @@ import { onMount } from 'svelte';
padding: 2px;
text-align: left;
}
.event--food {
background-color: lightgreen;
}
.event--poop {
background-color: burlywood;
}
.event--asleep {
background-color: lightblue;
}
.event--awake {
background-color: gold;
}
.event--diaper {
background-color: lightpink;
}
</style>
<div class="calendar">
<!-- Empty cell for top-left corner -->
<div></div>
<!-- Day Headers -->
{#each daysOfWeek as day}
<div class="day-header">{day}</div>
{/each}
<!-- Calendar Grid -->
<!-- Hour Labels and Calendar Grid -->
{#each hours as hour}
<div class="hour-label">{formatHour(hour)}</div> <!-- Hour label -->
{#each daysOfWeek as _, dayIndex}
<div class="hour">
{#each actions as action}
{#if getDayOfWeek(action.created) === dayIndex && getHourOfDay(action.created) === hour}
<div class="event">{action.type}</div>
<div class="event event--{action.type}">{action.type}</div>
{/if}
{/each}
</div>

View file

@ -152,7 +152,7 @@
totalDays += interval;
}
return totalDays / (poopDates.length - 1);
return parseFloat((totalDays / (poopDates.length - 1)).toFixed(2));
}
function calculateAvgMealsPerDay(actions: Action[]): number {
@ -174,14 +174,14 @@
}
</script>
<main>
<section>
<h2>Stats</h2>
<ul>
<li>Average Sleep per Nap: {stats.avgSleepPerNap} minutes</li>
<li>Average Naps per Day: {stats.avgNapsPerDay} naps</li>
<li>Average Sleep per Day: {stats.avgSleepPerDay} minutes</li>
<li>Average Diaper Changes per Day: {stats.avgDiaperChanges}</li>
<li>Average Days Between Poops: {stats.avgPoops}</li>
<li>Average Number of Meals per Day: {stats.avgEatingTimes}</li>
<li>{stats.avgSleepPerNap} min / nap</li>
<li>{stats.avgNapsPerDay} naps / day</li>
<li>{stats.avgSleepPerDay} min of sleep / day</li>
<li>{stats.avgDiaperChanges} diapers / day</li>
<li>{stats.avgPoops} days between poops</li>
<li>{stats.avgEatingTimes} meals / day</li>
</ul>
</main>
</section>

View file

@ -15,4 +15,20 @@ button,
input[type="submit"] {
background-color: var(--c-primary);
border-color: var(--c-primary);
}
nav ul {
list-style: circle inside;
display: flex;
list-style: none;
gap: 1em;
justify-content: end;
}
header {
padding-top: 2rem;
}
section {
margin-top: 4rem;
}