Skip to content

Commit 17c97ee

Browse files
committed
Use inline SVG for avatar placeholders
Replace external default avatar URLs with a base64 inline SVG to ensure consistent fallback across pet panels and the data manager. Add image onerror handlers to revert to the placeholder when loading fails. Convert Svelte on:click directives to standard onclick attributes for uniform event binding.
1 parent e0545f1 commit 17c97ee

File tree

3 files changed

+20
-13
lines changed

3 files changed

+20
-13
lines changed

src/lib/components/panels/PetPanel.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@
241241
ageUnit: normalizeAgeUnit(newPet.ageUnit),
242242
gender: normalizeGender(newPet.gender),
243243
size: normalizeSize(newPet.size),
244-
profileImageUrl: newPet.profileImageUrl || '/images/default-pet.png',
244+
profileImageUrl: newPet.profileImageUrl || '',
245245
createdAt: new Date().toISOString(),
246246
journalEntries: [],
247247
};

src/lib/components/panels/Viewport.svelte

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
import type { PetPanelData } from '$lib/types/Pet';
1515
import type { JournalEntry } from '$lib/types/JournalEntry';
1616
17+
// Inline placeholder avatar (rounded square with simple mark)
18+
const AVATAR_PLACEHOLDER =
19+
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHJ4PSIxNiIgZmlsbD0iI0Q2REM2RSIvPjx0ZXh0IHg9IjI0IiB5PSIyOSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9IkFwcGxlIENvbG9yIEVtb2ppIiBmb250LXNpemU9IjE2IiBmaWxsPSIjRkZGIj7wn5i98J+YvTwvdGV4dD48L3N2Zz4=';
20+
1721
let selectedPet: PetPanelData | null = null;
1822
let selectedPetId: string | null = null;
1923
let pets: PetPanelData[] = [];
@@ -187,9 +191,12 @@
187191
<div class="flex items-center space-x-3">
188192
{#if selectedPet}
189193
<img
190-
src={selectedPet.profileImageUrl || '/images/default-pet.png'}
194+
src={selectedPet.profileImageUrl || AVATAR_PLACEHOLDER}
191195
alt={selectedPet.name}
192196
class="w-12 h-12 rounded-full object-cover"
197+
onerror={(e) => {
198+
(e.target as HTMLImageElement).src = AVATAR_PLACEHOLDER;
199+
}}
193200
/>
194201
{/if}
195202
<div>
@@ -217,7 +224,7 @@
217224
{#if currentView === 'memories' || currentView === 'dataManager'}
218225
<div class="flex space-x-2">
219226
<button
220-
on:click={() => {
227+
onclick={() => {
221228
// return to dashboard; select first active pet if available
222229
const firstActive = (pets || []).find((p) => !p.archived) || null;
223230
if (firstActive) {
@@ -238,23 +245,23 @@
238245
class="nav-button px-3 py-1 rounded-md text-sm"
239246
data-active={currentView === 'dashboard'}
240247
disabled={!selectedPet || isArchived(selectedPet)}
241-
on:click={() => uiHelpers.setView('dashboard')}
248+
onclick={() => uiHelpers.setView('dashboard')}
242249
>
243250
Dashboard
244251
</button>
245252
<button
246253
class="nav-button px-3 py-1 rounded-md text-sm"
247254
data-active={currentView === 'journal'}
248255
disabled={!selectedPet || isArchived(selectedPet)}
249-
on:click={() => uiHelpers.setView('journal')}
256+
onclick={() => uiHelpers.setView('journal')}
250257
>
251258
New Entry
252259
</button>
253260
<button
254261
class="nav-button px-3 py-1 rounded-md text-sm"
255262
data-active={currentView === 'history'}
256263
disabled={!selectedPet || isArchived(selectedPet)}
257-
on:click={() => uiHelpers.setView('history')}
264+
onclick={() => uiHelpers.setView('history')}
258265
>
259266
History
260267
</button>
@@ -273,12 +280,12 @@
273280
</h3>
274281
<p>Mark {selectedPet?.name} as passed away?</p>
275282
<div class="flex justify-end gap-2">
276-
<button class="button-secondary" on:click={() => uiHelpers.setView('dashboard')}
283+
<button class="button-secondary" onclick={() => uiHelpers.setView('dashboard')}
277284
>Cancel</button
278285
>
279286
<button
280287
class="button"
281-
on:click={() => {
288+
onclick={() => {
282289
if (selectedPet) {
283290
petHelpers.archive(selectedPet.id);
284291
if (selectedPetId === selectedPet.id) {
@@ -587,14 +594,14 @@
587594
<!-- Actions -->
588595
<div class="flex justify-end space-x-3">
589596
<button
590-
on:click={() => uiHelpers.setView('dashboard')}
597+
onclick={() => uiHelpers.setView('dashboard')}
591598
class="button-secondary"
592599
disabled={isSubmitting}
593600
>
594601
Cancel
595602
</button>
596603
<button
597-
on:click={submitJournalEntry}
604+
onclick={submitJournalEntry}
598605
class="button flex items-center space-x-2"
599606
disabled={!journalInput.trim() || isSubmitting}
600607
>
@@ -623,7 +630,7 @@
623630
<div class="empty-state text-center py-12">
624631
<Calendar size={48} style="color: var(--petalytics-subtle);" class="mx-auto mb-4" />
625632
<p class="text-lg mb-2" style="color: var(--petalytics-text);">No entries yet</p>
626-
<button on:click={() => uiHelpers.setView('journal')} class="button">
633+
<button onclick={() => uiHelpers.setView('journal')} class="button">
627634
Write First Entry
628635
</button>
629636
</div>

src/lib/components/ui/DataManager.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,12 @@
106106
<div class="cli-row px-2 py-2">
107107
<div class="flex items-center gap-2">
108108
<img
109-
src={pet.profileImageUrl || '/images/default-pet.png'}
109+
src={pet.profileImageUrl || 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHJ4PSIxNiIgZmlsbD0iI0YzNEY0RiIvPjxzdmcgeD0iOCIgeT0iOCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiBmaWxsPSJ3aGl0ZSI+PHBhdGggZD0iTTUuMjUgNEM0LjU1OTY0IDQgNCA0LjU1OTY0IDQgNS4yNVYxMC43NUM0IDExLjQ0MDQgNC41NTk2NCAxMiA1LjI1IDEySDEwLjc1QzExLjQ0MDQgMTIgMTIgMTEuNDQwNCAxMiAxMC43NVY1LjI1QzEyIDQuNTU5NjQgMTEuNDQwNCA0IDEwLjc1IDRINS4yNVoiLz48L3N2Zz48L3N2Zz4='}
110110
alt={pet.name}
111111
class="w-8 h-8 rounded-full object-cover"
112112
onerror={(e) => {
113113
(e.target as HTMLImageElement).src =
114-
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iMTYiIGZpbGw9IiNGMzRGNEYiLz4KPHN2ZyB4PSI4IiB5PSI4IiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIGZpbGw9IndoaXRlIj4KICA8cGF0aCBkPSJNNS4yNSA0QzQuNTU5NjQgNCA0IDQuNTU5NjQgNCA1LjI1VjEwLjc1QzQgMTEuNDQwNCA0LjU1OTY0IDEyIDUuMjUgMTJIMTAuNzVDMTEuNDQwNCAxMiAxMiAxMS40NDA0IDEyIDEwLjc1VjUuMjVDMTIgNC41NTk2NCAxMS40NDA0IDQgMTAuNzUgNEg1LjI1WiIvPgo8L3N2Zz4KPC9zdmc+';
114+
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHJ4PSIxNiIgZmlsbD0iI0YzNEY0RiIvPjxzdmcgeD0iOCIgeT0iOCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiBmaWxsPSJ3aGl0ZSI+PHBhdGggZD0iTTUuMjUgNEM0LjU1OTY0IDQgNCA0LjU1OTY0IDQgNS4yNVYxMC43NUM0IDExLjQ0MDQgNC41NTk2NCAxMiA1LjI1IDEySDEwLjc1QzExLjQ0MDQgMTIgMTIgMTEuNDQwNCAxMiAxMC43NVY1LjI1QzEyIDQuNTU5NjQgMTEuNDQwNCA0IDEwLjc1IDRINS4yNVoiLz48L3N2Zz48L3N2Zz4=';
115115
}}
116116
/>
117117
<div>

0 commit comments

Comments
 (0)