diff --git a/apps/mana/apps/web/src/lib/modules/wetter/ListView.svelte b/apps/mana/apps/web/src/lib/modules/wetter/ListView.svelte
index 23aeee591..86ac215a5 100644
--- a/apps/mana/apps/web/src/lib/modules/wetter/ListView.svelte
+++ b/apps/mana/apps/web/src/lib/modules/wetter/ListView.svelte
@@ -35,6 +35,14 @@
await locationsStore.addLocation(name, lat, lon);
}
+ async function removeLocation(id: string) {
+ await locationsStore.removeLocation(id);
+ }
+
+ async function setDefaultLocation(id: string) {
+ await locationsStore.setDefault(id);
+ }
+
onMount(() => {
if (weatherStore.weatherData) return;
@@ -66,6 +74,8 @@
{selectedLon}
onSelect={selectLocation}
onSave={saveLocation}
+ onRemove={removeLocation}
+ onSetDefault={setDefaultLocation}
/>
diff --git a/apps/mana/apps/web/src/lib/modules/wetter/components/LocationPicker.svelte b/apps/mana/apps/web/src/lib/modules/wetter/components/LocationPicker.svelte
index 9a5c29af0..0690fb3ac 100644
--- a/apps/mana/apps/web/src/lib/modules/wetter/components/LocationPicker.svelte
+++ b/apps/mana/apps/web/src/lib/modules/wetter/components/LocationPicker.svelte
@@ -1,5 +1,6 @@
+
{#if locations.length > 0}
@@ -71,68 +89,127 @@
{/each}
+ {:else}
+
Keine Orte gespeichert
{/if}
-
+
{#if showSearch}
-
+
+
- {#if searchResults.length > 0}
-
- {#each searchResults as result}
-
selectSearchResult(result)}
- onkeydown={(e: KeyboardEvent) => {
- if (e.key === 'Enter') selectSearchResult(result);
- }}
- >
-
{result.name}
-
- {result.admin1 ? `${result.admin1}, ` : ''}{result.country}
-
-
{
- e.stopPropagation();
- const name = result.admin1 ? `${result.name}, ${result.admin1}` : result.name;
- onSave(name, result.lat, result.lon);
- selectSearchResult(result);
+ {#if searchResults.length > 0}
+
+ {#each searchResults as result}
+ {@const saved = alreadySaved(result)}
+
{
+ if (!saved) saveAndSelect(result);
+ else selectSearchResult(result);
+ }}
+ onkeydown={(e: KeyboardEvent) => {
+ if (e.key === 'Enter') {
+ if (!saved) saveAndSelect(result);
+ else selectSearchResult(result);
+ }
}}
>
- +
+ {result.name}
+
+ {result.admin1 ? `${result.admin1}, ` : ''}{result.country}
+
+ {#if saved}
+ Gespeichert
+ {:else}
+ Speichern
+ {/if}
+
+ {/each}
+
+ {/if}
+
+ {/if}
+
+
+ {#if showManage}
+
+
Gespeicherte Orte
+ {#each locations as loc (loc.id)}
+
+
+ {#if loc.isDefault}★{/if}
+ {loc.name}
+
+
{loc.lat.toFixed(2)}, {loc.lon.toFixed(2)}
+
+ {#if !loc.isDefault}
+ onSetDefault(loc.id)}
+ >
+ ★
+
+ {/if}
+ onRemove(loc.id)}>
+ ×
- {/each}
-
- {/if}
+
+ {/each}
+
★ = Standard-Ort beim Oeffnen
+
{/if}
@@ -153,7 +230,15 @@
flex-wrap: wrap;
flex: 1;
}
+ .no-locations {
+ font-size: 0.8rem;
+ color: var(--text-tertiary, #6b7280);
+ flex: 1;
+ }
.loc-chip {
+ display: flex;
+ align-items: center;
+ gap: 4px;
padding: 6px 12px;
border-radius: 20px;
font-size: 0.8rem;
@@ -168,6 +253,13 @@
color: #38bdf8;
border-color: rgba(56, 189, 248, 0.3);
}
+ .default-dot {
+ width: 5px;
+ height: 5px;
+ border-radius: 50%;
+ background: #38bdf8;
+ flex-shrink: 0;
+ }
.picker-actions {
display: flex;
gap: 4px;
@@ -184,10 +276,36 @@
display: flex;
align-items: center;
justify-content: center;
+ color: var(--text-secondary, #9ca3af);
}
- .action-btn:hover {
+ .action-btn:hover,
+ .action-btn.active {
background: var(--card-bg-hover, rgba(255, 255, 255, 0.1));
+ color: var(--text-primary, #f3f4f6);
}
+ .manage-btn {
+ font-size: 0.85rem;
+ }
+
+ /* Panels */
+ .panel {
+ background: var(--card-bg, rgba(255, 255, 255, 0.06));
+ border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
+ border-radius: 12px;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ }
+ .panel-title {
+ font-size: 0.75rem;
+ font-weight: 500;
+ color: var(--text-secondary, #9ca3af);
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ }
+
+ /* Search */
.search-form {
display: flex;
gap: 8px;
@@ -197,7 +315,7 @@
padding: 8px 12px;
border-radius: 8px;
border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.1));
- background: var(--card-bg, rgba(255, 255, 255, 0.06));
+ background: var(--card-bg, rgba(255, 255, 255, 0.04));
color: var(--text-primary, #f3f4f6);
font-size: 0.85rem;
outline: none;
@@ -221,23 +339,19 @@
.search-results {
display: flex;
flex-direction: column;
- gap: 2px;
- background: var(--card-bg, rgba(255, 255, 255, 0.06));
- border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.08));
- border-radius: 10px;
- overflow: hidden;
}
.result-item {
display: flex;
align-items: center;
gap: 8px;
- padding: 10px 12px;
+ padding: 8px 6px;
border: none;
background: none;
color: var(--text-primary, #f3f4f6);
cursor: pointer;
text-align: left;
width: 100%;
+ border-radius: 6px;
}
.result-item:hover {
background: var(--card-bg-hover, rgba(255, 255, 255, 0.06));
@@ -251,22 +365,74 @@
color: var(--text-secondary, #9ca3af);
flex: 1;
}
- .save-btn {
- width: 24px;
- height: 24px;
- border-radius: 12px;
- border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.15));
+ .save-label {
+ font-size: 0.7rem;
+ color: #38bdf8;
+ flex-shrink: 0;
+ }
+ .already-saved {
+ font-size: 0.7rem;
+ color: var(--text-tertiary, #6b7280);
+ flex-shrink: 0;
+ }
+
+ /* Manage panel */
+ .manage-panel {
+ gap: 4px;
+ }
+ .manage-row {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 8px 6px;
+ border-radius: 6px;
+ }
+ .manage-row:hover {
+ background: var(--card-bg-hover, rgba(255, 255, 255, 0.04));
+ }
+ .manage-name {
+ font-size: 0.85rem;
+ color: var(--text-primary, #f3f4f6);
+ flex: 1;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ }
+ .default-star {
+ color: #f59e0b;
+ font-size: 0.8rem;
+ }
+ .manage-coords {
+ font-size: 0.7rem;
+ color: var(--text-tertiary, #6b7280);
+ }
+ .manage-actions {
+ display: flex;
+ gap: 4px;
+ }
+ .manage-action {
+ width: 26px;
+ height: 26px;
+ border-radius: 6px;
+ border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.1));
background: none;
color: var(--text-secondary, #9ca3af);
- font-size: 1rem;
+ font-size: 0.9rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
- flex-shrink: 0;
}
- .save-btn:hover {
- background: var(--accent-subtle, rgba(56, 189, 248, 0.15));
- color: #38bdf8;
+ .manage-action:hover {
+ background: var(--card-bg-hover, rgba(255, 255, 255, 0.08));
+ color: #f59e0b;
+ }
+ .manage-action.delete:hover {
+ color: #ef4444;
+ }
+ .manage-hint {
+ font-size: 0.65rem;
+ color: var(--text-tertiary, #6b7280);
+ margin: 4px 0 0;
}
diff --git a/apps/mana/apps/web/src/routes/(app)/wetter/+page.svelte b/apps/mana/apps/web/src/routes/(app)/wetter/+page.svelte
index 346a164b2..f3bf252d2 100644
--- a/apps/mana/apps/web/src/routes/(app)/wetter/+page.svelte
+++ b/apps/mana/apps/web/src/routes/(app)/wetter/+page.svelte
@@ -35,6 +35,14 @@
await locationsStore.addLocation(name, lat, lon);
}
+ async function removeLocation(id: string) {
+ await locationsStore.removeLocation(id);
+ }
+
+ async function setDefaultLocation(id: string) {
+ await locationsStore.setDefault(id);
+ }
+
// On mount: use default location, or first saved, or GPS
onMount(() => {
const defaultLoc = locations.find((l) => l.isDefault) ?? locations[0];
@@ -72,6 +80,8 @@
{selectedLon}
onSelect={selectLocation}
onSave={saveLocation}
+ onRemove={removeLocation}
+ onSetDefault={setDefaultLocation}
/>