Skip to content

Commit 570602e

Browse files
committed
refactor: remove unused ThemeSelector import and clean up layout component
1 parent c6680d4 commit 570602e

File tree

5 files changed

+112
-194
lines changed

5 files changed

+112
-194
lines changed

src/app.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ body {
106106
font-family: 'JetBrains Mono', monospace;
107107
}
108108

109+
/* (Removed global app scaling to restore 100% size) */
110+
109111
/* Panel styles */
110112
.panel {
111113
background: var(--petalytics-surface);

src/lib/components/panels/GuardianPanel.svelte

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<script lang="ts">
22
import { onMount } from 'svelte';
3-
import ThemeSelector from '../ui/ThemeSelector.svelte';
43
import DataManager from '../ui/DataManager.svelte';
54
import { ChevronLeft, ChevronRight, User, Key, Settings, CheckCircle, AlertCircle, Terminal } from 'lucide-svelte';
65
import { guardianHelpers } from '$lib/stores/guardian.js';
Lines changed: 106 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<script lang="ts">
22
import { onMount } from 'svelte';
3-
import { Plus, Heart, ArrowLeft, Upload } from 'lucide-svelte';
3+
import { Upload, Terminal } from 'lucide-svelte';
44
import { petStore, selectedPetStore, petHelpers, selectedPetHelpers } from '$lib/stores/pets.js';
5-
import { fade } from 'svelte/transition';
65
import type { PetPanelData } from '$lib/types/Pet.js';
76
87
let pets: PetPanelData[] = [];
@@ -54,7 +53,6 @@
5453
const file = target.files?.[0];
5554
if (file) {
5655
if (file.size > 5 * 1024 * 1024) {
57-
// 5MB limit
5856
formErrors.image = 'Image must be less than 5MB';
5957
return;
6058
}
@@ -113,209 +111,134 @@
113111
function selectPet(petId: string) {
114112
selectedPetHelpers.select(petId);
115113
}
114+
115+
function handleActivate(e: KeyboardEvent, action: () => void) {
116+
if (e.key === 'Enter' || e.key === ' ') {
117+
e.preventDefault();
118+
action();
119+
}
120+
}
116121
</script>
117122

118-
<div class="panel-container h-full flex flex-col">
119-
<div class="panel-header">
120-
<div class="flex items-center justify-between">
121-
<div class="flex items-center space-x-2">
122-
{#if showCreateForm}
123-
<button on:click={toggleCreateForm} class="p-1 hover:opacity-70 transition-opacity">
124-
<ArrowLeft size={16} style="color: var(--petalytics-accent);" />
125-
</button>
126-
{:else}
127-
<Heart size={18} style="color: var(--petalytics-accent);" />
128-
{/if}
129-
<h2 class="text-lg font-semibold">
130-
{showCreateForm ? 'Add New Pet' : 'Your Pets'}
131-
</h2>
132-
</div>
133-
{#if !showCreateForm}
134-
<button
135-
on:click={toggleCreateForm}
136-
class="flex items-center space-x-1 px-2 py-1 rounded-md button-secondary"
137-
>
138-
<Plus size={16} />
139-
<span class="text-sm">Add</span>
140-
</button>
141-
{/if}
123+
<div class="pet-panel h-full" style="background: var(--petalytics-bg);">
124+
<div class="cli-header p-3 border-b font-mono text-sm" style="border-color: var(--petalytics-border); background: var(--petalytics-surface);">
125+
<div class="flex items-center space-x-2" style="color: var(--petalytics-pine);">
126+
<Terminal size={14} />
127+
<span>pets@petalytics:~$</span>
142128
</div>
143129
</div>
144130

145-
<div class="panel-content flex-1 p-4 overflow-y-auto">
131+
<div class="cli-content p-3 font-mono text-sm overflow-y-auto" style="color: var(--petalytics-text);">
132+
<!-- Toggle create form -->
133+
<div class="cli-row px-2 py-1" role="button" tabindex="0" aria-expanded={showCreateForm} onclick={toggleCreateForm} onkeydown={(e) => handleActivate(e, toggleCreateForm)}>
134+
<span class="label">add_pet</span>
135+
<span class="value">{showCreateForm ? 'show' : 'hidden'}</span>
136+
</div>
137+
146138
{#if showCreateForm}
147-
<!-- Pet Creation Form -->
148-
<div class="create-form space-y-4" transition:fade={{ duration: 200 }}>
149-
<!-- Profile Image Upload -->
150-
<div class="section">
151-
<label
152-
for="pet-profile-image"
153-
class="block text-sm font-medium mb-2"
154-
style="color: var(--petalytics-subtle);"
155-
>
156-
Profile Photo
157-
</label>
158-
<div class="flex flex-col items-center space-y-3">
159-
{#if newPet.profileImageUrl}
160-
<img
161-
src={newPet.profileImageUrl}
162-
alt="Pet preview"
163-
class="w-24 h-24 rounded-full object-cover border-2"
164-
style="border-color: var(--petalytics-border);"
165-
/>
166-
{:else}
167-
<div
168-
class="w-24 h-24 rounded-full border-2 border-dashed flex items-center justify-center cursor-pointer hover:opacity-70 transition-opacity"
169-
style="border-color: var(--petalytics-border);"
170-
on:click={() => imageInput.click()}
171-
on:keydown={(e) => e.key === 'Enter' && imageInput.click()}
172-
role="button"
173-
tabindex="0"
174-
>
175-
<Upload size={24} style="color: var(--petalytics-subtle);" />
176-
</div>
177-
{/if}
178-
<input
179-
id="pet-profile-image"
180-
bind:this={imageInput}
181-
type="file"
182-
accept="image/*"
183-
on:change={handleImageUpload}
184-
class="hidden"
185-
/>
186-
{#if formErrors.image}
187-
<p class="text-sm text-red-400">{formErrors.image}</p>
188-
{/if}
189-
</div>
139+
<div class="mt-2 p-2 rounded" style="background: var(--petalytics-overlay);">
140+
<!-- name -->
141+
<div class="cli-row px-2 py-1">
142+
<span class="label">name</span>
143+
<input class="value bg-transparent border-none outline-none input-inline" bind:value={newPet.name} placeholder="Pet Name" />
190144
</div>
145+
{#if formErrors.name}
146+
<p class="px-2 text-xs" style="color: var(--petalytics-love);">{formErrors.name}</p>
147+
{/if}
191148

192-
<!-- Pet Name -->
193-
<div class="section">
194-
<input type="text" bind:value={newPet.name} class="input w-full" placeholder="Pet Name" />
195-
{#if formErrors.name}
196-
<p class="text-sm text-red-400 mt-1">{formErrors.name}</p>
197-
{/if}
149+
<!-- breed -->
150+
<div class="cli-row px-2 py-1">
151+
<span class="label">breed</span>
152+
<input class="value bg-transparent border-none outline-none input-inline" bind:value={newPet.breed} placeholder="Breed" />
198153
</div>
154+
{#if formErrors.breed}
155+
<p class="px-2 text-xs" style="color: var(--petalytics-love);">{formErrors.breed}</p>
156+
{/if}
199157

200-
<!-- Breed -->
201-
<div class="section">
202-
<input type="text" bind:value={newPet.breed} class="input w-full" placeholder="Breed" />
203-
{#if formErrors.breed}
204-
<p class="text-sm text-red-400 mt-1">{formErrors.breed}</p>
205-
{/if}
158+
<!-- age -->
159+
<div class="cli-row px-2 py-1">
160+
<span class="label">age</span>
161+
<input class="value bg-transparent border-none outline-none input-inline" type="number" min="0" max="30" bind:value={newPet.age} placeholder="Age" />
206162
</div>
163+
{#if formErrors.age}
164+
<p class="px-2 text-xs" style="color: var(--petalytics-love);">{formErrors.age}</p>
165+
{/if}
207166

208-
<!-- Age and Gender -->
209-
<div class="grid grid-cols-2 gap-3">
210-
<div>
211-
<input
212-
type="number"
213-
bind:value={newPet.age}
214-
class="input w-full"
215-
placeholder="Age"
216-
min="0"
217-
max="30"
218-
/>
219-
{#if formErrors.age}
220-
<p class="text-xs text-red-400 mt-1">{formErrors.age}</p>
221-
{/if}
222-
</div>
167+
<!-- gender -->
168+
<div class="cli-row px-2 py-1">
169+
<span class="label">gender</span>
170+
<select class="value bg-transparent border-none outline-none input-inline" bind:value={newPet.gender}>
171+
<option value="">Select gender</option>
172+
<option value="male">male</option>
173+
<option value="female">female</option>
174+
</select>
175+
</div>
176+
{#if formErrors.gender}
177+
<p class="px-2 text-xs" style="color: var(--petalytics-love);">{formErrors.gender}</p>
178+
{/if}
223179

224-
<div>
225-
<select bind:value={newPet.gender} class="input w-full">
226-
<option value="">Gender</option>
227-
<option value="male">Male</option>
228-
<option value="female">Female</option>
229-
</select>
230-
{#if formErrors.gender}
231-
<p class="text-xs text-red-400 mt-1">{formErrors.gender}</p>
180+
<!-- profile image upload -->
181+
<div class="cli-row px-2 py-1" style="align-items: flex-start;">
182+
<span class="label">profile_image</span>
183+
<div class="value flex items-center justify-end gap-2">
184+
{#if newPet.profileImageUrl}
185+
<img src={newPet.profileImageUrl} alt="preview" class="w-10 h-10 rounded-full object-cover border" style="border-color: var(--petalytics-border);" />
232186
{/if}
187+
<button type="button" class="arrow-btn" onclick={() => imageInput.click()}>upload</button>
188+
<input id="pet-profile-image" bind:this={imageInput} type="file" accept="image/*" onchange={handleImageUpload} class="hidden" />
233189
</div>
234190
</div>
191+
{#if formErrors.image}
192+
<p class="px-2 text-xs" style="color: var(--petalytics-love);">{formErrors.image}</p>
193+
{/if}
235194

236-
<!-- Form Actions -->
237-
<div class="flex space-x-3 pt-4">
238-
<button on:click={createPet} class="button flex-1">Create Pet</button>
239-
<button on:click={toggleCreateForm} class="button-secondary flex-1">Cancel</button>
195+
<div class="flex gap-2 px-2 pt-2">
196+
<button class="button flex-1" type="button" onclick={createPet}>create</button>
197+
<button class="button-secondary flex-1" type="button" onclick={toggleCreateForm}>cancel</button>
240198
</div>
241199
</div>
200+
{/if}
201+
202+
<!-- Separator -->
203+
<div class="my-3"><div class="border-t" style="border-color: var(--petalytics-border);"></div></div>
204+
205+
<!-- Pets list -->
206+
<div class="cli-row px-2 py-1">
207+
<span style="color: var(--petalytics-subtle);">#</span>
208+
<span class="ml-2" style="color: var(--petalytics-gold);">pets</span>
209+
</div>
210+
211+
{#if pets.length === 0}
212+
<div class="px-2 py-4" style="color: var(--petalytics-subtle);">no pets yet — use add_pet to create one</div>
242213
{:else}
243-
<!-- Pet Grid -->
244-
<div class="pets-grid">
245-
{#if pets.length === 0}
246-
<div class="empty-state text-center py-8">
247-
<Heart size={48} style="color: var(--petalytics-subtle); margin: 0 auto 1rem;" />
248-
<p class="text-lg font-medium mb-2" style="color: var(--petalytics-text);">
249-
No pets yet
250-
</p>
251-
<p class="text-sm mb-4" style="color: var(--petalytics-subtle);">
252-
Add your first pet to get started with tracking their journal
253-
</p>
254-
<button on:click={toggleCreateForm} class="button">Add Your First Pet</button>
255-
</div>
256-
{:else}
257-
<div class="grid grid-cols-2 gap-3">
258-
{#each pets as pet}
259-
<div
260-
class="pet-card p-3 rounded-lg border cursor-pointer transition-all hover:opacity-80"
261-
class:selected={selectedPetId === pet.id}
262-
style="
263-
background: var(--petalytics-surface);
264-
border-color: {selectedPetId === pet.id
265-
? 'var(--petalytics-accent)'
266-
: 'var(--petalytics-border)'};
267-
"
268-
on:click={() => selectPet(pet.id)}
269-
on:keydown={(e) => e.key === 'Enter' && selectPet(pet.id)}
270-
role="button"
271-
tabindex="0"
272-
>
273-
<div class="flex flex-col items-center space-y-2">
274-
<img
275-
src={pet.profileImageUrl || '/images/default-pet.png'}
276-
alt={pet.name}
277-
class="w-16 h-16 rounded-full object-cover"
278-
/>
279-
<div class="text-center">
280-
<p class="font-medium text-sm truncate" style="color: var(--petalytics-text);">
281-
{pet.name}
282-
</p>
283-
<p class="text-xs truncate" style="color: var(--petalytics-subtle);">
284-
{pet.breed}
285-
</p>
286-
<p class="text-xs" style="color: var(--petalytics-subtle);">
287-
{pet.age}
288-
{pet.age === 1 ? 'year' : 'years'} old
289-
</p>
290-
</div>
291-
</div>
292-
</div>
293-
{/each}
294-
</div>
295-
{/if}
296-
</div>
214+
{#each pets as pet}
215+
<div class="cli-row px-2 py-1" role="button" tabindex="0" data-selected={selectedPetId === pet.id} onclick={() => selectPet(pet.id)} onkeydown={(e) => handleActivate(e, () => selectPet(pet.id))}>
216+
<span class="label" style="color: var(--petalytics-text);">{pet.name}</span>
217+
<span class="value" style="color: var(--petalytics-subtle);">
218+
{pet.breed} | {pet.age}{pet.age === 1 ? 'y' : 'y'}
219+
</span>
220+
</div>
221+
{/each}
297222
{/if}
298223
</div>
299224
</div>
300225

301226
<style>
302-
.pet-card.selected {
303-
box-shadow: 0 0 0 2px var(--petalytics-accent);
304-
}
305-
306-
.panel-header {
307-
background: var(--petalytics-overlay);
308-
border-bottom: 1px solid var(--petalytics-border);
309-
padding: 0.75rem 1rem;
310-
font-weight: 500;
311-
color: var(--petalytics-text);
312-
}
313-
314-
.panel-content {
315-
background: var(--petalytics-surface);
316-
}
317-
318-
.section {
319-
margin-bottom: 1rem;
320-
}
227+
.cli-row {
228+
display: flex;
229+
align-items: center;
230+
border: 1px solid transparent;
231+
border-radius: 6px;
232+
transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
233+
}
234+
.cli-row[role="button"] { cursor: pointer; }
235+
.cli-row:hover { background: var(--petalytics-highlight-low); border-color: var(--petalytics-border); }
236+
.cli-row:focus-within, .cli-row[role="button"]:focus-visible { outline: none; background: var(--petalytics-highlight-med); border-color: var(--petalytics-accent); box-shadow: 0 0 0 2px color-mix(in oklab, var(--petalytics-accent) 40%, transparent); }
237+
.cli-row[data-selected="true"], .cli-row[aria-expanded="true"] { background: var(--petalytics-highlight-high); border-color: var(--petalytics-accent); }
238+
.label { color: var(--petalytics-foam); }
239+
.value { margin-left: auto; text-align: right; flex: 1 1 auto; }
240+
.input-inline { padding: 0; }
241+
.arrow-btn { font-family: 'JetBrains Mono', monospace; font-size: 0.85rem; line-height: 1rem; background: transparent; border: 1px solid var(--petalytics-border); color: var(--petalytics-subtle); padding: 0.15rem 0.5rem; border-radius: 4px; cursor: pointer; }
242+
.arrow-btn:hover { background: var(--petalytics-highlight-low); color: var(--petalytics-text); }
243+
.arrow-btn:focus-visible { outline: none; border-color: var(--petalytics-accent); box-shadow: 0 0 0 2px color-mix(in oklab, var(--petalytics-accent) 35%, transparent); }
321244
</style>

src/lib/components/ui/AIInsightsCard.svelte

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import type { AnalysisResult } from '$lib/utils/ai-analysis';
55
66
export let entryId = '';
7-
// eslint-disable-next-line svelte/valid-compile
87
export let petId = '';
98
export let compact = false;
109
@@ -16,7 +15,7 @@
1615
</script>
1716

1817
{#if analysis}
19-
<div class="ai-insights" class:compact>
18+
<div class="ai-insights" class:compact data-pet-id={petId}>
2019
{#if !compact}
2120
<div class="flex items-center space-x-2 mb-3">
2221
<Brain size={16} style="color: var(--petalytics-accent);" />
@@ -78,9 +77,9 @@
7877
</div>
7978
{/if}
8079
</div>
81-
</div>
80+
</div>
8281
{:else}
83-
<div class="no-analysis text-xs" style="color: var(--petalytics-muted);">
82+
<div class="no-analysis text-xs" style="color: var(--petalytics-muted);" data-pet-id={petId}>
8483
AI analysis pending...
8584
</div>
8685
{/if}

src/routes/+layout.svelte

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts">
22
import '../app.css';
33
import favicon from '$lib/assets/favicon.svg';
4-
import ThemeSelector from '$lib/components/ui/ThemeSelector.svelte';
4+
55
66
let { children } = $props();
77
</script>
@@ -16,9 +16,4 @@
1616
/>
1717
</svelte:head>
1818

19-
<!-- Theme selector in top-right corner -->
20-
<div class="fixed top-4 right-4 z-50 w-48">
21-
<ThemeSelector />
22-
</div>
23-
2419
{@render children?.()}

0 commit comments

Comments
 (0)