Skip to content

Commit 243305d

Browse files
committed
feat: enhance PetPanel and Viewport with auto-selection of pets and improved pet details display
1 parent 98f23bb commit 243305d

File tree

2 files changed

+75
-56
lines changed

2 files changed

+75
-56
lines changed

src/lib/components/panels/PetPanel.svelte

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts">
22
import { onMount } from 'svelte';
33
import { Upload, Terminal } from 'lucide-svelte';
4-
import { petStore, selectedPetStore, petHelpers, selectedPetHelpers } from '$lib/stores/pets.js';
4+
import { petStore, selectedPetStore, petHelpers, selectedPetHelpers } from '$lib/stores/pets';
55
import type { PetPanelData } from '$lib/types/Pet.js';
66
77
let pets: PetPanelData[] = [];
@@ -87,6 +87,10 @@
8787
onMount(() => {
8888
petStore.subscribe((value) => {
8989
pets = value;
90+
// If no selected pet and we have pets, auto-select the first one
91+
if (!selectedPetId && pets.length > 0) {
92+
selectedPetHelpers.select(pets[0].id);
93+
}
9094
});
9195
selectedPetStore.subscribe((value) => {
9296
selectedPetId = value;
@@ -184,6 +188,8 @@
184188
};
185189
186190
petHelpers.add(pet);
191+
// Auto-select the newly created pet
192+
selectedPetHelpers.select(pet.id);
187193
toggleCreateForm();
188194
}
189195

src/lib/components/panels/Viewport.svelte

Lines changed: 68 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
<script lang="ts">
22
import { onMount } from 'svelte';
3-
import { selectedPetStore, petHelpers, selectedPetHelpers } from '$lib/stores/pets';
3+
import { petStore, selectedPetStore, petHelpers, selectedPetHelpers } from '$lib/stores/pets';
44
import { aiAnalysisHelpers, isAnalyzing } from '$lib/stores/ai-analysis';
5-
import { PenTool, Brain, Calendar, Heart, Activity } from 'lucide-svelte';
5+
import { PenTool, Brain, Calendar, Activity } from 'lucide-svelte';
66
import AIInsightsCard from '../ui/AIInsightsCard.svelte';
77
import EmptyState from '../ui/EmptyState.svelte';
88
import Skeleton from '../ui/Skeleton.svelte';
99
import type { PetPanelData } from '$lib/types/Pet';
1010
import type { JournalEntry } from '$lib/types/JournalEntry';
1111
1212
let selectedPet: PetPanelData | null = null;
13+
let selectedPetId: string | null = null;
14+
let pets: PetPanelData[] = [];
1315
let currentView = 'dashboard'; // dashboard, journal, history
1416
let journalInput = '';
1517
let selectedMood = '';
@@ -18,16 +20,46 @@
1820
let loading = false;
1921
2022
// Computed values
21-
$: lastEntry = selectedPet?.journalEntries?.length ? selectedPet.journalEntries[selectedPet.journalEntries.length - 1] : null;
23+
$: lastEntry = selectedPet?.journalEntries?.length
24+
? selectedPet.journalEntries[selectedPet.journalEntries.length - 1]
25+
: null;
26+
27+
function formatAge(pet: PetPanelData): string {
28+
if (!pet || (pet.age === undefined || pet.age === null)) return '';
29+
const unit = pet.ageUnit || 'years';
30+
const abbr = unit === 'years' ? 'y' : unit === 'months' ? 'm' : 'w';
31+
return `${pet.age} ${abbr}`;
32+
}
33+
34+
function petSubtitle(pet: PetPanelData): string {
35+
const parts: string[] = [];
36+
if (pet.species) parts.push(pet.species);
37+
if (pet.breed) parts.push(pet.breed);
38+
const age = formatAge(pet);
39+
if (age) parts.push(age);
40+
return parts.join(' | ');
41+
}
2242
2343
onMount(() => {
24-
// Load pets and selected pet from storage
25-
petHelpers.load();
26-
selectedPetHelpers.load();
44+
// Subscribe first so incoming loads propagate into state
45+
petStore.subscribe((list) => {
46+
pets = list || [];
47+
if (selectedPetId) {
48+
selectedPet = pets.find((p) => p.id === selectedPetId) || null;
49+
} else if (!selectedPetId && pets.length > 0) {
50+
// Auto-select the first pet to show a summary by default
51+
selectedPetHelpers.select(pets[0].id);
52+
}
53+
});
2754
2855
selectedPetStore.subscribe((petId) => {
29-
selectedPet = petId ? petHelpers.getPet(petId) : null;
56+
selectedPetId = petId;
57+
selectedPet = petId ? pets.find((p) => p.id === petId) || null : null;
3058
});
59+
60+
// Load from storage (will trigger subscriptions above)
61+
petHelpers.load();
62+
selectedPetHelpers.load();
3163
});
3264
3365
async function submitJournalEntry() {
@@ -75,44 +107,29 @@
75107
}
76108
</script>
77109

78-
<div class="viewport-container h-full flex flex-col">
79-
{#if loading}
80-
<!-- Loading State with Skeleton -->
81-
<div class="space-y-4">
82-
<Skeleton height="h-8" />
83-
<Skeleton avatar height="h-20" />
84-
<Skeleton height="h-6" />
85-
<Skeleton height="h-4" />
86-
</div>
87-
{:else if !lastEntry}
88-
<!-- No entries state -->
89-
<EmptyState
90-
icon="file-text"
91-
title="No journal entries yet"
92-
description="Start documenting {selectedPet?.name || 'your pet'}'s daily activities, moods, and special moments."
93-
actionText="Create First Entry"
94-
onAction={() => {
95-
console.log('Create entry clicked');
96-
// Could dispatch event to show journal form
97-
}}
98-
/>
99-
{:else}
100-
<!-- Enhanced Welcome Screen -->
101-
<div class="welcome-screen h-full flex items-center justify-center">
102-
<EmptyState
103-
icon="heart"
104-
title="Welcome to Petalytics! 🐾"
105-
description="Create your first pet profile to start journaling and get AI-powered insights about your furry friend's well-being."
106-
actionText="Create Your First Pet"
107-
onAction={() => {
108-
// Focus on pet panel - could dispatch event to parent
109-
console.log('Create pet clicked');
110-
}}
111-
/>
110+
<div class="viewport-container h-full flex flex-col font-mono">
111+
{#if loading}
112+
<!-- Loading State with Skeleton -->
113+
<div class="space-y-4">
114+
<Skeleton height="h-8" />
115+
<Skeleton avatar height="h-20" />
116+
<Skeleton height="h-6" />
117+
<Skeleton height="h-4" />
112118
</div>
119+
{:else if !selectedPet}
120+
<EmptyState
121+
icon="file-text"
122+
title="No pet selected"
123+
description="Select a pet from the left panel to view details, add journal entries, and see AI insights."
124+
actionText="Add a Pet"
125+
onAction={() => {
126+
console.log('Add a Pet clicked');
127+
}}
128+
/>
129+
{:else}
113130
<div class="pet-viewport h-full flex flex-col">
114131
<!-- Header with pet info and navigation -->
115-
<div class="viewport-header p-4 border-b" style="border-color: var(--petalytics-border);">
132+
<div class="viewport-header p-4 border-b" style="border-color: var(--petalytics-border); background: var(--petalytics-overlay);">
116133
<div class="flex items-center justify-between">
117134
<div class="flex items-center space-x-3">
118135
<img
@@ -121,12 +138,8 @@
121138
class="w-12 h-12 rounded-full object-cover"
122139
/>
123140
<div>
124-
<h2 class="text-xl font-bold" style="color: var(--petalytics-text);">
125-
{selectedPet.name}
126-
</h2>
127-
<p class="text-sm" style="color: var(--petalytics-subtle);">
128-
{selectedPet.age} year old {selectedPet.breed}
129-
</p>
141+
<h2 class="text-xl font-bold" style="color: var(--petalytics-text);">{selectedPet.name}</h2>
142+
<p class="text-xs" style="color: var(--petalytics-subtle);">{petSubtitle(selectedPet)}</p>
130143
</div>
131144
</div>
132145

@@ -177,9 +190,9 @@
177190
style="background: var(--petalytics-surface);"
178191
>
179192
<div class="text-2xl font-bold" style="color: var(--petalytics-accent);">
180-
{selectedPet.age}
193+
{formatAge(selectedPet)}
181194
</div>
182-
<div class="text-xs" style="color: var(--petalytics-subtle);">Years Old</div>
195+
<div class="text-xs" style="color: var(--petalytics-subtle);">Age</div>
183196
</div>
184197
<div
185198
class="stat-card p-4 rounded-lg text-center"
@@ -200,10 +213,10 @@
200213
class="stat-card p-4 rounded-lg text-center"
201214
style="background: var(--petalytics-surface);"
202215
>
203-
<div class="text-2xl font-bold" style="color: var(--petalytics-accent);">
204-
{selectedPet.breed}
216+
<div class="text-2xl font-bold truncate" style="color: var(--petalytics-accent);">
217+
{selectedPet.breed || selectedPet.species || ''}
205218
</div>
206-
<div class="text-xs" style="color: var(--petalytics-subtle);">Breed</div>
219+
<div class="text-xs" style="color: var(--petalytics-subtle);">Breed / Species</div>
207220
</div>
208221
</div>
209222

@@ -273,7 +286,7 @@
273286
well-being.
274287
</p>
275288
{:else}
276-
<AIInsightsCard petId={selectedPet.id} />
289+
<AIInsightsCard petId={selectedPet.id} entryId={lastEntry?.id} />
277290
{/if}
278291
</div>
279292
</div>
@@ -304,7 +317,7 @@
304317
<option value="tired">😴 Tired</option>
305318
<option value="anxious">😰 Anxious</option>
306319
<option value="sad">😢 Sad</option>
307-
<option value="sick">🤒 Unwell</option>
320+
<option value="sick">🩺 Unwell</option>
308321
</select>
309322
</div>
310323

0 commit comments

Comments
 (0)