active nav style; fixed stats; added age; fixed sunday issue; frame style, 1st step;

This commit is contained in:
Spencer Flagg 2024-02-06 15:40:39 +01:00
parent 725bb127b0
commit 26784b4aba
6 changed files with 110 additions and 26 deletions

View file

@ -1,6 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
import { convertMinutes } from '$lib/utils';
export let actions = []; // Array of actions passed to the component
@ -36,16 +37,6 @@
// Update immediately when the component has access to actions
updateTimes();
function convertMinutes(minutes: number): string {
if (minutes < 60) {
return `${minutes}m`;
} else {
const hours = Math.floor(minutes / 60);
const remainingMinutes = minutes % 60;
return `${hours}h${remainingMinutes}m`;
}
}
onMount(() => {
const interval = setInterval(updateTimes, 2000); // Update every 2 minutes

9
src/lib/utils.ts Normal file
View file

@ -0,0 +1,9 @@
export function convertMinutes(minutes: number): string {
if (minutes < 60) {
return `${minutes}m`;
} else {
const hours = Math.floor(minutes / 60);
const remainingMinutes = minutes % 60;
return `${hours}h${remainingMinutes}m`;
}
}

View file

@ -6,6 +6,7 @@
</svelte:head>
<script lang="ts">
import { page } from '$app/stores';
import { currentUser } from '$lib/pocketbase';
import 'normalize.css/normalize.css';
import 'milligram/dist/milligram.min.css';
@ -16,18 +17,18 @@
<main class="container">
<header>
<h1>Coover Tracker</h1>
<h1><a href="/">Coover Tracker</a></h1>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/" class={$page.url.pathname === '/' ? 'active' : ''}>Home</a></li>
{#if $currentUser}
<li><a href="/stats">Stats</a></li>
<li><a href="/calendar">Calendar</a></li>
<li><a href="/stats" class={$page.url.pathname === '/stats' ? 'active' : ''}>Stats</a></li>
<li><a href="/calendar" class={$page.url.pathname === '/calendar' ? 'active' : ''}>Calendar</a></li>
{/if}
<li>
<a href="/signin">
<a href="/signin" class={$page.url.pathname === '/signin' ? 'active' : ''}>
{#if $currentUser}
<strong>( {$currentUser.username} )</strong>
( {$currentUser.username} )
{:else}
'Sign In'
{/if}

View file

@ -12,6 +12,7 @@
// Adjust currentWeekStart to the beginning of the week
currentWeekStart.setDate(currentWeekStart.getDate() - currentWeekStart.getDay());
currentWeekStart.setHours(0, 0, 0, 0);
const oldestDataDate: Date = new Date('2024-01-22');
// Reactive store to hold actions
@ -62,7 +63,7 @@
// Function to get the day of the week from a date string
const getDayOfWeek = (dateString: string) => {
return new Date(dateString).getDay();
return new Date(dateString).getDay(); // 0 = Sunday, 1 = Monday, etc.
};
// Function to get the hour of the day from a date string

View file

@ -1,6 +1,8 @@
<script lang="ts">
import { onMount } from 'svelte';
import { pb } from '$lib/pocketbase';
import { parse } from 'svelte/compiler';
import { convertMinutes } from '$lib/utils';
type Action = {
type: string;
@ -78,7 +80,7 @@
}
const totalNaps = Array.from(daysMap.values()).reduce((acc, naps) => acc + naps, 0);
return daysMap.size > 0 ? totalNaps / daysMap.size : 0;
return daysMap.size > 0 ? parseFloat((totalNaps / daysMap.size).toFixed(1)) : 0;
}
function calculateAvgSleepPerDay(actions: Action[]): number {
@ -161,7 +163,7 @@
totalDays += interval;
}
return parseFloat((totalDays / (poopDates.length - 1)).toFixed(2));
return parseFloat((totalDays / (poopDates.length - 1)).toFixed(1));
}
function calculateAvgMealsPerDay(actions: any[]): number {
@ -194,18 +196,77 @@
// Return the average to one decimal place
return parseFloat(average.toFixed(1));
}
function calculateAgeFormatted(birthdate: Date): string {
const now = new Date();
const birthDate = new Date(birthdate);
const diffInMilliseconds = now.getTime() - birthDate.getTime();
const diffInDays = diffInMilliseconds / (1000 * 3600 * 24);
const diffInWeeks = diffInDays / 7;
const diffInMonths = diffInDays / 30.4375; // Average days per month in a year
const diffInYears = diffInDays / 365.25; // Average, accounting for leap years
// Determine the largest unit (years, months, weeks, days) for the age
if (diffInYears >= 1) {
return formatAge(diffInYears, 'year');
} else if (diffInMonths >= 1) {
return formatAge(diffInMonths, 'month');
} else if (diffInWeeks >= 1) {
return formatAge(diffInWeeks, 'week');
} else {
return formatAge(diffInDays, 'day');
}
}
function formatAge(value: number, unit: string): string {
// Round to nearest quarter
const nearestQuarter = Math.round(value * 4) / 4;
const integerPart = Math.floor(nearestQuarter);
const fractionPart = nearestQuarter - integerPart;
let fractionString = '';
switch (fractionPart) {
case 0.25:
fractionString = '¼';
break;
case 0.5:
fractionString = '½';
break;
case 0.75:
fractionString = '¾';
break;
case 0:
fractionString = '';
break;
default:
// This case should not happen with rounding to nearest quarter
break;
}
const ageString = `${integerPart}${fractionString} ${unit}${integerPart > 1 || integerPart === 0 ? 's' : ''}`;
return ageString;
}
</script>
<section>
<h2>Stats</h2>
<p>(diapers and meals should be correct now)</p>
<ul>
<li>{stats.avgSleepPerNap} min / nap</li>
<li>{stats.avgNapsPerDay} naps / day</li>
<!-- <li>{stats.avgSleepPerDay} min of sleep / day</li> -->
<li>{stats.avgSleepPerNap * stats.avgNapsPerDay} min of sleep / day</li>
<li>{stats.avgDiaperChanges} diapers / day</li>
<li>{stats.avgPoops} days between poops</li>
<li>{calculateAgeFormatted(new Date('2023-08-30'))} old</li>
</ul>
<h3>Input</h3>
<ul>
<li>{stats.avgEatingTimes} meals / day</li>
</ul>
<h3>Output</h3>
<ul>
<li>{stats.avgDiaperChanges} diapers / day</li>
<li>{stats.avgPoops} days between poops</li>
</ul>
<h3>Downtime</h3>
<ul>
<li>{convertMinutes(stats.avgSleepPerNap)} / nap</li>
<li>{stats.avgNapsPerDay} naps / day</li>
<!-- <li>{stats.avgSleepPerDay} min of sleep / day</li> -->
<li>{convertMinutes(Math.round(stats.avgSleepPerNap * stats.avgNapsPerDay))} of sleep / day</li>
</ul>
</section>

View file

@ -90,6 +90,10 @@ nav ul li {
list-style: none;
}
nav ul li a.active{
font-weight: bold;
}
header {
position: sticky;
@ -98,6 +102,11 @@ header {
z-index: 1;
margin: 0 -2rem;
padding: 2rem 2rem 0 2rem;
border-radius: 3rem 3rem 0 0;
}
h1 a {
color: inherit;
}
/* aside {
@ -139,4 +148,16 @@ section {
line-height: 1;
min-width: 10ch;
text-align: center;
}
main.container {
max-width: 80rem;
background: var(--c-bkg);
border-radius: 3rem;
margin: 3rem auto;
padding-bottom: 3rem;
}
body {
background: #303443;
}