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:
BIN
Platform-clean.zip
Normal file
BIN
Platform-clean.zip
Normal file
Binary file not shown.
@@ -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>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 201 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,19 +0,0 @@
|
||||
%PDF-1.0
|
||||
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj
|
||||
2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj
|
||||
3 0 obj<</Type/Page/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</Font<</F1 4 0 R>>>>/Contents 5 0 R>>endobj
|
||||
4 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica>>endobj
|
||||
5 0 obj<</Length 200>>
|
||||
stream
|
||||
BT /F1 18 Tf 72 700 Td (State Farm Insurance Policy) Tj ET
|
||||
BT /F1 12 Tf 72 670 Td (Policy Number: SF-2024-881234) Tj ET
|
||||
BT /F1 12 Tf 72 650 Td (Policyholder: Yusuf Suleman) Tj ET
|
||||
BT /F1 12 Tf 72 630 Td (Deductible: 500 dollars) Tj ET
|
||||
endstream
|
||||
endobj
|
||||
xref
|
||||
0 6
|
||||
trailer<</Size 6/Root 1 0 R>>
|
||||
startxref
|
||||
0
|
||||
%%EOF
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user