mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 18:01:09 +02:00
i18n(drink+habits+picture): translate 3 list views via $_()
- drink/ListView: route through drink.list_view.* (today/log/empty + create form + ctx-menu); drops unused PencilSimple equivalent - habits/ListView: route through habits.list_view.* (voice capture + tally grid + create form + ctx-menu); drops unused PencilSimple icon import - picture/ListView: route through picture.list_view.* (drop overlay, action strip, view-mode titles, search placeholder, empty states, lightbox actions) Baseline 833 → 818 (-15).
This commit is contained in:
parent
0986d07a7d
commit
4237d84c18
4 changed files with 67 additions and 46 deletions
|
|
@ -25,6 +25,7 @@
|
|||
import { DynamicIcon } from '@mana/shared-ui/atoms';
|
||||
import { IconPicker } from '@mana/shared-ui/molecules';
|
||||
import { Trash, Pause, Play } from '@mana/shared-icons';
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
let entries$ = useAllDrinkEntries();
|
||||
let presets$ = useAllDrinkPresets();
|
||||
|
|
@ -84,7 +85,9 @@
|
|||
? [
|
||||
{
|
||||
id: 'archive',
|
||||
label: ctxMenuPreset.state.target.isArchived ? 'Aktivieren' : 'Archivieren',
|
||||
label: ctxMenuPreset.state.target.isArchived
|
||||
? $_('drink.list_view.ctx_activate')
|
||||
: $_('drink.list_view.ctx_archive'),
|
||||
icon: ctxMenuPreset.state.target.isArchived ? Play : Pause,
|
||||
action: () => {
|
||||
const target = ctxMenuPreset.state.target;
|
||||
|
|
@ -94,7 +97,7 @@
|
|||
{ id: 'div', label: '', type: 'divider' as const },
|
||||
{
|
||||
id: 'delete',
|
||||
label: 'Löschen',
|
||||
label: $_('drink.list_view.ctx_delete'),
|
||||
icon: Trash,
|
||||
variant: 'danger' as const,
|
||||
action: () => {
|
||||
|
|
@ -112,7 +115,7 @@
|
|||
? [
|
||||
{
|
||||
id: 'delete',
|
||||
label: 'Löschen',
|
||||
label: $_('drink.list_view.ctx_delete'),
|
||||
icon: Trash,
|
||||
variant: 'danger' as const,
|
||||
action: () => {
|
||||
|
|
@ -171,7 +174,7 @@
|
|||
<!-- Daily Progress -->
|
||||
<div class="progress-section">
|
||||
<div class="progress-header">
|
||||
<span class="progress-label">Heute</span>
|
||||
<span class="progress-label">{$_('drink.list_view.section_today')}</span>
|
||||
<span class="progress-value" class:goal-reached={goalReached}>
|
||||
{formatMl(todayTotalMl)}
|
||||
<span class="progress-goal">/ {formatMl(DEFAULT_DAILY_GOAL_ML)}</span>
|
||||
|
|
@ -206,7 +209,7 @@
|
|||
{#if !showCreate}
|
||||
<button class="preset-item add-btn" onclick={() => (showCreate = true)}>
|
||||
<span class="add-icon">+</span>
|
||||
<span class="preset-name">Neu</span>
|
||||
<span class="preset-name">{$_('drink.list_view.action_new')}</span>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -228,7 +231,7 @@
|
|||
<input
|
||||
class="create-input"
|
||||
type="text"
|
||||
placeholder="Name (z.B. Espresso)..."
|
||||
placeholder={$_('drink.list_view.placeholder_name')}
|
||||
bind:value={newName}
|
||||
autofocus
|
||||
/>
|
||||
|
|
@ -271,9 +274,11 @@
|
|||
onclick={() => {
|
||||
showCreate = false;
|
||||
showIconPicker = false;
|
||||
}}>Abbrechen</button
|
||||
}}>{$_('drink.list_view.action_cancel')}</button
|
||||
>
|
||||
<button type="submit" class="btn-create" disabled={!newName.trim()}
|
||||
>{$_('drink.list_view.action_create')}</button
|
||||
>
|
||||
<button type="submit" class="btn-create" disabled={!newName.trim()}>Erstellen</button>
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
|
|
@ -281,7 +286,7 @@
|
|||
<!-- Today's Log -->
|
||||
{#if todayEntries.length > 0}
|
||||
<div class="today-log">
|
||||
<div class="log-label">Verlauf</div>
|
||||
<div class="log-label">{$_('drink.list_view.section_log')}</div>
|
||||
{#each todayEntries as entry (entry.id)}
|
||||
{#if editingId === entry.id}
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
|
|
@ -328,9 +333,9 @@
|
|||
|
||||
{#if activePresets.length === 0 && !showCreate}
|
||||
<div class="empty">
|
||||
<p>Noch keine Getränke-Presets.</p>
|
||||
<p>{$_('drink.list_view.empty_title')}</p>
|
||||
<button class="empty-add-btn" onclick={() => (showCreate = true)}
|
||||
>Erstes Getränk anlegen</button
|
||||
>{$_('drink.list_view.empty_action')}</button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,9 @@
|
|||
import { toastStore } from '@mana/shared-ui/toast';
|
||||
import { DynamicIcon } from '@mana/shared-ui/atoms';
|
||||
import { IconPicker } from '@mana/shared-ui/molecules';
|
||||
import { PencilSimple, Trash, Pause, Play } from '@mana/shared-icons';
|
||||
import { Trash, Pause, Play } from '@mana/shared-icons';
|
||||
import VoiceCaptureBar from '$lib/components/voice/VoiceCaptureBar.svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
let { navigate, goBack, params }: ViewProps = $props();
|
||||
|
||||
|
|
@ -70,10 +71,12 @@
|
|||
async function handleVoiceComplete(blob: Blob, durationMs: number) {
|
||||
const result = await habitsStore.logFromVoice(blob, durationMs, 'de');
|
||||
if (!result) {
|
||||
toastStore.error('Routine nicht erkannt. Versuche den Namen direkt zu sagen, z.B. "Kaffee".');
|
||||
toastStore.error($_('habits.list_view.voice_error_unrecognized'));
|
||||
return;
|
||||
}
|
||||
toastStore.success(`${result.habitTitle} geloggt`);
|
||||
toastStore.success(
|
||||
$_('habits.list_view.voice_logged', { values: { title: result.habitTitle } })
|
||||
);
|
||||
// Reuse the existing pulse animation by finding the matching habit id
|
||||
const matched = habits.find((h) => h.title === result.habitTitle);
|
||||
if (matched) {
|
||||
|
|
@ -103,7 +106,7 @@
|
|||
? [
|
||||
{
|
||||
id: 'log',
|
||||
label: 'Loggen',
|
||||
label: $_('habits.list_view.ctx_log'),
|
||||
icon: Play,
|
||||
action: () => {
|
||||
const target = ctxMenu.state.target;
|
||||
|
|
@ -112,7 +115,9 @@
|
|||
},
|
||||
{
|
||||
id: 'archive',
|
||||
label: ctxMenu.state.target.isArchived ? 'Aktivieren' : 'Archivieren',
|
||||
label: ctxMenu.state.target.isArchived
|
||||
? $_('habits.list_view.ctx_activate')
|
||||
: $_('habits.list_view.ctx_archive'),
|
||||
icon: ctxMenu.state.target.isArchived ? Play : Pause,
|
||||
action: () => {
|
||||
const target = ctxMenu.state.target;
|
||||
|
|
@ -125,7 +130,7 @@
|
|||
{ id: 'div', label: '', type: 'divider' as const },
|
||||
{
|
||||
id: 'delete',
|
||||
label: 'Löschen',
|
||||
label: $_('habits.list_view.ctx_delete'),
|
||||
icon: Trash,
|
||||
variant: 'danger' as const,
|
||||
action: () => {
|
||||
|
|
@ -152,9 +157,9 @@
|
|||
<div class="habits-list-view">
|
||||
<!-- Voice quick-log -->
|
||||
<VoiceCaptureBar
|
||||
idleLabel="Routine sprechen"
|
||||
idleLabel={$_('habits.list_view.voice_idle_label')}
|
||||
feature="habits-voice-log"
|
||||
reason="Routinen-Logs werden in deinem persönlichen Kalender gespeichert. Dafür brauchst du ein Mana-Konto."
|
||||
reason={$_('habits.list_view.voice_reason')}
|
||||
onComplete={handleVoiceComplete}
|
||||
/>
|
||||
|
||||
|
|
@ -185,7 +190,7 @@
|
|||
{#if !showCreate}
|
||||
<button class="tally-item add-btn" onclick={() => (showCreate = true)}>
|
||||
<span class="add-icon">+</span>
|
||||
<span class="tally-name">Neu</span>
|
||||
<span class="tally-name">{$_('habits.list_view.action_new')}</span>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -207,7 +212,7 @@
|
|||
<input
|
||||
class="create-input"
|
||||
type="text"
|
||||
placeholder="Routinen-Name..."
|
||||
placeholder={$_('habits.list_view.placeholder_name')}
|
||||
bind:value={newTitle}
|
||||
autofocus
|
||||
/>
|
||||
|
|
@ -243,9 +248,11 @@
|
|||
onclick={() => {
|
||||
showCreate = false;
|
||||
showIconPicker = false;
|
||||
}}>Abbrechen</button
|
||||
}}>{$_('habits.list_view.action_cancel')}</button
|
||||
>
|
||||
<button type="submit" class="btn-create" disabled={!newTitle.trim()}
|
||||
>{$_('habits.list_view.action_create')}</button
|
||||
>
|
||||
<button type="submit" class="btn-create" disabled={!newTitle.trim()}>Erstellen</button>
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
|
|
@ -253,7 +260,7 @@
|
|||
<!-- Recent Logs -->
|
||||
{#if todayLogs.length > 0}
|
||||
<div class="recent-logs">
|
||||
<div class="recent-label">Heute</div>
|
||||
<div class="recent-label">{$_('habits.list_view.section_today')}</div>
|
||||
{#each todayLogs as log (log.id)}
|
||||
{@const habit = habitMap.get(log.habitId)}
|
||||
{#if habit}
|
||||
|
|
@ -279,9 +286,9 @@
|
|||
|
||||
{#if activeHabits.length === 0 && !showCreate}
|
||||
<div class="empty">
|
||||
<p>Noch keine Routinen angelegt.</p>
|
||||
<p>{$_('habits.list_view.empty_title')}</p>
|
||||
<button class="empty-add-btn" onclick={() => (showCreate = true)}
|
||||
>Erste Routine erstellen</button
|
||||
>{$_('habits.list_view.empty_action')}</button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
getImagesByTags,
|
||||
} from './queries';
|
||||
import type { Image, LocalImage } from './types';
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
const MEDIA_URL = import.meta.env.PUBLIC_MANA_MEDIA_URL || 'http://localhost:3015';
|
||||
|
||||
|
|
@ -240,7 +241,7 @@
|
|||
{#if dragActive}
|
||||
<div class="drop-overlay">
|
||||
<UploadSimple size={40} weight="bold" />
|
||||
<span>Bilder ablegen</span>
|
||||
<span>{$_('picture.list_view.drop_overlay')}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
|
@ -250,15 +251,19 @@
|
|||
type="button"
|
||||
class="action-btn action-btn-upload"
|
||||
onclick={() => fileInput?.click()}
|
||||
title="Bilder hochladen"
|
||||
title={$_('picture.list_view.action_upload_title')}
|
||||
>
|
||||
<UploadSimple size={14} />
|
||||
<span class="action-label">Upload</span>
|
||||
<span class="action-label">{$_('picture.list_view.action_upload')}</span>
|
||||
</button>
|
||||
|
||||
<a href="/picture/generate" class="action-btn action-btn-primary" title="Neues Bild generieren">
|
||||
<a
|
||||
href="/picture/generate"
|
||||
class="action-btn action-btn-primary"
|
||||
title={$_('picture.list_view.action_generate_title')}
|
||||
>
|
||||
<Plus size={14} />
|
||||
<span class="action-label">Generieren</span>
|
||||
<span class="action-label">{$_('picture.list_view.action_generate')}</span>
|
||||
</a>
|
||||
|
||||
<button
|
||||
|
|
@ -266,10 +271,10 @@
|
|||
onclick={() => imagesStore.toggleFavoritesFilter()}
|
||||
class="action-btn"
|
||||
class:action-btn-active={imagesStore.showFavoritesOnly}
|
||||
title="Nur Favoriten anzeigen"
|
||||
title={$_('picture.list_view.action_favorites_title')}
|
||||
>
|
||||
<Heart size={12} weight={imagesStore.showFavoritesOnly ? 'fill' : 'regular'} />
|
||||
<span class="action-label">Favoriten</span>
|
||||
<span class="action-label">{$_('picture.list_view.action_favorites')}</span>
|
||||
{#if favoriteCount > 0}<span class="action-count">{favoriteCount}</span>{/if}
|
||||
</button>
|
||||
|
||||
|
|
@ -281,7 +286,7 @@
|
|||
onclick={() => pictureViewStore.setViewMode('single')}
|
||||
class="view-btn"
|
||||
class:active={pictureViewStore.viewMode === 'single'}
|
||||
title="Liste"
|
||||
title={$_('picture.list_view.view_list_title')}
|
||||
>
|
||||
<Rows size={12} />
|
||||
</button>
|
||||
|
|
@ -289,7 +294,7 @@
|
|||
onclick={() => pictureViewStore.setViewMode('grid3')}
|
||||
class="view-btn"
|
||||
class:active={pictureViewStore.viewMode === 'grid3'}
|
||||
title="Mittel"
|
||||
title={$_('picture.list_view.view_medium_title')}
|
||||
>
|
||||
<GridFour size={12} />
|
||||
</button>
|
||||
|
|
@ -297,7 +302,7 @@
|
|||
onclick={() => pictureViewStore.setViewMode('grid5')}
|
||||
class="view-btn"
|
||||
class:active={pictureViewStore.viewMode === 'grid5'}
|
||||
title="Klein"
|
||||
title={$_('picture.list_view.view_small_title')}
|
||||
>
|
||||
<SquaresFour size={12} />
|
||||
</button>
|
||||
|
|
@ -314,7 +319,7 @@
|
|||
<input
|
||||
type="text"
|
||||
bind:value={searchQuery}
|
||||
placeholder="Prompts durchsuchen…"
|
||||
placeholder={$_('picture.list_view.placeholder_search')}
|
||||
class="w-full rounded-md border border-border bg-background py-1 pl-8 pr-2.5 text-xs text-foreground placeholder:text-muted-foreground focus:border-primary focus:ring-1 focus:ring-primary"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -359,14 +364,19 @@
|
|||
{#if filteredImages.length === 0}
|
||||
<div class="empty-state">
|
||||
<SquaresFour size={48} weight="thin" class="text-muted-foreground/30" />
|
||||
<h3>{allImages.length === 0 ? 'Noch keine Bilder' : 'Keine Ergebnisse'}</h3>
|
||||
<h3>
|
||||
{allImages.length === 0
|
||||
? $_('picture.list_view.empty_no_images')
|
||||
: $_('picture.list_view.empty_no_results')}
|
||||
</h3>
|
||||
<p>
|
||||
{allImages.length === 0
|
||||
? 'Generiere dein erstes Bild mit KI oder lade welche hoch'
|
||||
: 'Passe deine Filter an'}
|
||||
? $_('picture.list_view.empty_hint_no_images')
|
||||
: $_('picture.list_view.empty_hint_no_results')}
|
||||
</p>
|
||||
{#if allImages.length === 0}
|
||||
<a href="/picture/generate" class="empty-cta">Erstes Bild generieren</a>
|
||||
<a href="/picture/generate" class="empty-cta">{$_('picture.list_view.empty_cta_first')}</a
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
|
|
@ -409,7 +419,9 @@
|
|||
weight={selectedImage.isFavorite ? 'fill' : 'regular'}
|
||||
class={selectedImage.isFavorite ? 'text-red-500' : 'text-muted-foreground'}
|
||||
/>
|
||||
{selectedImage.isFavorite ? 'Entfernen' : 'Favorit'}
|
||||
{selectedImage.isFavorite
|
||||
? $_('picture.list_view.action_unfavorite')
|
||||
: $_('picture.list_view.action_favorite')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
|
|
@ -417,7 +429,7 @@
|
|||
class="flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-sm font-medium transition-colors hover:bg-muted"
|
||||
>
|
||||
<Archive size={14} class="text-muted-foreground" />
|
||||
Archivieren
|
||||
{$_('picture.list_view.action_archive')}
|
||||
</button>
|
||||
{/if}
|
||||
{/snippet}
|
||||
|
|
|
|||
|
|
@ -106,12 +106,10 @@
|
|||
"apps/mana/apps/web/src/lib/modules/core/widgets/RecentContactsWidget.svelte": 2,
|
||||
"apps/mana/apps/web/src/lib/modules/core/widgets/TasksTodayWidget.svelte": 1,
|
||||
"apps/mana/apps/web/src/lib/modules/core/widgets/UpcomingEventsWidget.svelte": 1,
|
||||
"apps/mana/apps/web/src/lib/modules/drink/ListView.svelte": 5,
|
||||
"apps/mana/apps/web/src/lib/modules/goals/ListView.svelte": 1,
|
||||
"apps/mana/apps/web/src/lib/modules/guides/ListView.svelte": 1,
|
||||
"apps/mana/apps/web/src/lib/modules/habits/components/HabitDetail.svelte": 5,
|
||||
"apps/mana/apps/web/src/lib/modules/habits/components/HabitForm.svelte": 3,
|
||||
"apps/mana/apps/web/src/lib/modules/habits/ListView.svelte": 5,
|
||||
"apps/mana/apps/web/src/lib/modules/inventory/ListView.svelte": 1,
|
||||
"apps/mana/apps/web/src/lib/modules/inventory/views/DetailView.svelte": 5,
|
||||
"apps/mana/apps/web/src/lib/modules/journal/ListView.svelte": 6,
|
||||
|
|
@ -133,7 +131,6 @@
|
|||
"apps/mana/apps/web/src/lib/modules/photos/ListView.svelte": 4,
|
||||
"apps/mana/apps/web/src/lib/modules/picture/components/ImageLightbox.svelte": 3,
|
||||
"apps/mana/apps/web/src/lib/modules/picture/components/ReferenceImagePicker.svelte": 1,
|
||||
"apps/mana/apps/web/src/lib/modules/picture/ListView.svelte": 5,
|
||||
"apps/mana/apps/web/src/lib/modules/places/ListView.svelte": 2,
|
||||
"apps/mana/apps/web/src/lib/modules/plants/views/DetailView.svelte": 1,
|
||||
"apps/mana/apps/web/src/lib/modules/playground/ListView.svelte": 2,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue