refactor: separate podcasts from downloads — own route + nav item
- /podcasts — new page with PodcastPlayer (headphones icon) - /downloads — old media page renamed (download icon) - /media — kept for backward compat (same as downloads) - Nav: Reader → Podcasts → Downloads → Brain Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,9 @@
|
||||
CalendarDays,
|
||||
CircleDot,
|
||||
Compass,
|
||||
Download,
|
||||
Dumbbell,
|
||||
Headphones,
|
||||
Landmark,
|
||||
LibraryBig,
|
||||
Menu,
|
||||
@@ -42,7 +44,8 @@
|
||||
{ id: 'budget', href: '/budget', label: 'Budget', icon: Landmark },
|
||||
{ id: 'inventory', href: '/inventory', label: 'Inventory', icon: Package2 },
|
||||
{ id: 'reader', href: '/reader', label: 'Reader', icon: BookOpen },
|
||||
{ id: 'media', href: '/media', label: 'Media', icon: LibraryBig },
|
||||
{ id: 'media', href: '/podcasts', label: 'Podcasts', icon: Headphones },
|
||||
{ id: 'downloads', href: '/downloads', label: 'Downloads', icon: Download },
|
||||
{ id: 'brain', href: '/brain', label: 'Brain', icon: Brain },
|
||||
{ id: 'settings', href: '/settings', label: 'Settings', icon: Settings2 }
|
||||
];
|
||||
|
||||
@@ -24,7 +24,7 @@ export const load: LayoutServerLoad = async ({ cookies, url }) => {
|
||||
// Hides nav items but does NOT block direct URL access.
|
||||
// This is intentional: all shared services are accessible to all authenticated users.
|
||||
// Hiding reduces clutter for users who don't need certain apps day-to-day.
|
||||
const allApps = ['tasks', 'trips', 'fitness', 'inventory', 'budget', 'reader', 'media', 'brain'];
|
||||
const allApps = ['tasks', 'trips', 'fitness', 'inventory', 'budget', 'reader', 'media', 'downloads', 'brain'];
|
||||
const hiddenByUser: Record<string, string[]> = {
|
||||
'madiha': ['inventory', 'reader', 'brain'],
|
||||
};
|
||||
|
||||
75
frontend-v2/src/routes/(app)/downloads/+page.svelte
Normal file
75
frontend-v2/src/routes/(app)/downloads/+page.svelte
Normal file
@@ -0,0 +1,75 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import BookSearch from '$lib/components/media/BookSearch.svelte';
|
||||
import MusicSearch from '$lib/components/media/MusicSearch.svelte';
|
||||
import BookLibrary from '$lib/components/media/BookLibrary.svelte';
|
||||
|
||||
type MediaTab = 'books' | 'music' | 'library';
|
||||
|
||||
const urlMode = page.url.searchParams.get('mode');
|
||||
let activeTab = $state<MediaTab>(urlMode === 'music' ? 'music' : urlMode === 'library' ? 'library' : 'books');
|
||||
</script>
|
||||
|
||||
<div class="page">
|
||||
<div class="app-surface">
|
||||
<div class="page-header">
|
||||
<div class="page-title">DOWNLOADS</div>
|
||||
<div class="page-subtitle">
|
||||
{#if activeTab === 'books'}Book Downloads
|
||||
{:else if activeTab === 'music'}Music Downloads
|
||||
{:else}Book Library{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="media-tabs">
|
||||
<button class="tab" class:active={activeTab === 'books'} onclick={() => activeTab = 'books'}>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
|
||||
Books
|
||||
</button>
|
||||
<button class="tab" class:active={activeTab === 'music'} onclick={() => activeTab = 'music'}>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>
|
||||
Music
|
||||
</button>
|
||||
<button class="tab" class:active={activeTab === 'library'} onclick={() => activeTab = 'library'}>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
|
||||
Library
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if activeTab === 'books'}
|
||||
<BookSearch />
|
||||
{:else if activeTab === 'music'}
|
||||
<MusicSearch />
|
||||
{:else}
|
||||
<BookLibrary />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.page-subtitle {
|
||||
font-size: var(--text-2xl);
|
||||
font-weight: 300;
|
||||
color: var(--text-1);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.media-tabs {
|
||||
display: flex; gap: var(--sp-1); margin-bottom: var(--sp-5);
|
||||
border-bottom: 1px solid var(--border); padding-bottom: 0;
|
||||
}
|
||||
.tab {
|
||||
display: flex; align-items: center; gap: var(--sp-2);
|
||||
flex: 1; padding: 10px var(--sp-2) 12px; font-size: var(--text-base); font-weight: 500;
|
||||
color: var(--text-3); background: none; border: none; border-bottom: 2px solid transparent;
|
||||
cursor: pointer; font-family: var(--font); transition: all var(--transition);
|
||||
text-align: center; justify-content: center; margin-bottom: -1px;
|
||||
}
|
||||
.tab:hover { color: var(--text-2); }
|
||||
.tab.active { color: var(--text-1); border-bottom-color: var(--accent); font-weight: 600; }
|
||||
.tab svg { width: 16px; height: 16px; flex-shrink: 0; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.page-subtitle { font-size: var(--text-xl); }
|
||||
}
|
||||
</style>
|
||||
@@ -3,27 +3,20 @@
|
||||
import BookSearch from '$lib/components/media/BookSearch.svelte';
|
||||
import MusicSearch from '$lib/components/media/MusicSearch.svelte';
|
||||
import BookLibrary from '$lib/components/media/BookLibrary.svelte';
|
||||
import PodcastPlayer from '$lib/components/media/PodcastPlayer.svelte';
|
||||
|
||||
type MediaTab = 'books' | 'music' | 'library' | 'podcasts';
|
||||
type MediaTab = 'books' | 'music' | 'library';
|
||||
|
||||
const urlMode = page.url.searchParams.get('mode');
|
||||
let activeTab = $state<MediaTab>(
|
||||
urlMode === 'music' ? 'music'
|
||||
: urlMode === 'library' ? 'library'
|
||||
: urlMode === 'podcasts' ? 'podcasts'
|
||||
: 'books'
|
||||
);
|
||||
let activeTab = $state<MediaTab>(urlMode === 'music' ? 'music' : urlMode === 'library' ? 'library' : 'books');
|
||||
</script>
|
||||
|
||||
<div class="page">
|
||||
<div class="app-surface">
|
||||
<div class="page-header">
|
||||
<div class="page-title">MEDIA</div>
|
||||
<div class="page-title">DOWNLOADS</div>
|
||||
<div class="page-subtitle">
|
||||
{#if activeTab === 'books'}Book Downloads
|
||||
{:else if activeTab === 'music'}Music Downloads
|
||||
{:else if activeTab === 'podcasts'}Podcast Player
|
||||
{:else}Book Library{/if}
|
||||
</div>
|
||||
</div>
|
||||
@@ -37,10 +30,6 @@
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>
|
||||
Music
|
||||
</button>
|
||||
<button class="tab" class:active={activeTab === 'podcasts'} onclick={() => activeTab = 'podcasts'}>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="20" r="1"/></svg>
|
||||
Podcasts
|
||||
</button>
|
||||
<button class="tab" class:active={activeTab === 'library'} onclick={() => activeTab = 'library'}>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
|
||||
Library
|
||||
@@ -51,8 +40,6 @@
|
||||
<BookSearch />
|
||||
{:else if activeTab === 'music'}
|
||||
<MusicSearch />
|
||||
{:else if activeTab === 'podcasts'}
|
||||
<PodcastPlayer />
|
||||
{:else}
|
||||
<BookLibrary />
|
||||
{/if}
|
||||
|
||||
22
frontend-v2/src/routes/(app)/podcasts/+page.svelte
Normal file
22
frontend-v2/src/routes/(app)/podcasts/+page.svelte
Normal file
@@ -0,0 +1,22 @@
|
||||
<script lang="ts">
|
||||
import PodcastPlayer from '$lib/components/media/PodcastPlayer.svelte';
|
||||
</script>
|
||||
|
||||
<div class="page">
|
||||
<div class="app-surface">
|
||||
<div class="page-header">
|
||||
<div class="page-title">PODCASTS</div>
|
||||
<div class="page-subtitle">Your podcast library</div>
|
||||
</div>
|
||||
<PodcastPlayer />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.page-subtitle {
|
||||
font-size: var(--text-2xl);
|
||||
font-weight: 300;
|
||||
color: var(--text-1);
|
||||
line-height: 1.2;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user