@digilogiclabs/create-saas-app 2.7.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/generators/template-generator.d.ts.map +1 -1
- package/dist/generators/template-generator.js +12 -10
- package/dist/generators/template-generator.js.map +1 -1
- package/dist/templates/shared/config/web/next.config.mjs +1 -0
- package/dist/templates/shared/loading/web/src/app/loading.tsx +9 -0
- package/dist/templates/web/ui-auth-ai/template/src/app/error.tsx +75 -0
- package/dist/templates/web/ui-auth-ai/template/src/app/loading.tsx +39 -0
- package/dist/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +4 -7
- package/package.json +1 -1
- package/src/templates/shared/config/web/next.config.mjs +1 -0
- package/src/templates/shared/loading/web/src/app/loading.tsx +9 -0
- package/src/templates/web/ui-auth-ai/template/src/app/error.tsx +75 -0
- package/src/templates/web/ui-auth-ai/template/src/app/loading.tsx +39 -0
- package/src/templates/web/ui-auth-payments/template/src/components/providers/app-providers.tsx +4 -7
- package/dist/templates/shared/loading/web/app/loading.tsx +0 -5
- package/dist/templates/web/base/template.backup/.env.example +0 -15
- package/dist/templates/web/ui-auth/template.backup/.env.example +0 -15
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/page.tsx.backup +0 -391
- package/dist/templates/web/ui-auth-payments-ai/template/src/app/page.tsx.bak +0 -391
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx.backup +0 -391
- package/dist/templates/web/ui-auth-payments-audio/template/src/app/page.tsx.bak +0 -391
- package/dist/templates/web/ui-only/template.backup/.env.example +0 -15
- package/src/templates/shared/loading/web/app/loading.tsx +0 -5
- /package/dist/templates/shared/admin/web/{app → src/app}/admin/layout.tsx +0 -0
- /package/dist/templates/shared/auth/keycloak/web/{app → src/app}/api/auth/federated-logout/route.ts +0 -0
- /package/dist/templates/shared/beta/web/{app → src/app}/api/beta-settings/route.ts +0 -0
- /package/dist/templates/shared/beta/web/{app → src/app}/api/validate-beta-code/route.ts +0 -0
- /package/dist/templates/shared/contact/web/{app → src/app}/api/contact/route.ts +0 -0
- /package/dist/templates/shared/contact/web/{app → src/app}/contact/page.tsx +0 -0
- /package/dist/templates/shared/error-pages/web/{app → src/app}/error.tsx +0 -0
- /package/dist/templates/shared/error-pages/web/{app → src/app}/global-error.tsx +0 -0
- /package/dist/templates/shared/error-pages/web/{app → src/app}/not-found.tsx +0 -0
- /package/dist/templates/shared/health/web/{app → src/app}/api/health/route.ts +0 -0
- /package/dist/templates/shared/legal/web/{app → src/app}/(legal)/privacy/page.tsx +0 -0
- /package/dist/templates/shared/legal/web/{app → src/app}/(legal)/terms/page.tsx +0 -0
- /package/dist/templates/shared/payments/web/{app → src/app}/api/webhooks/stripe/route.ts +0 -0
- /package/dist/templates/shared/seo/web/{app → src/app}/api/og/route.tsx +0 -0
- /package/dist/templates/shared/seo/web/{app → src/app}/robots.ts +0 -0
- /package/dist/templates/shared/seo/web/{app → src/app}/sitemap.ts +0 -0
- /package/src/templates/shared/admin/web/{app → src/app}/admin/layout.tsx +0 -0
- /package/src/templates/shared/auth/keycloak/web/{app → src/app}/api/auth/federated-logout/route.ts +0 -0
- /package/src/templates/shared/beta/web/{app → src/app}/api/beta-settings/route.ts +0 -0
- /package/src/templates/shared/beta/web/{app → src/app}/api/validate-beta-code/route.ts +0 -0
- /package/src/templates/shared/contact/web/{app → src/app}/api/contact/route.ts +0 -0
- /package/src/templates/shared/contact/web/{app → src/app}/contact/page.tsx +0 -0
- /package/src/templates/shared/error-pages/web/{app → src/app}/error.tsx +0 -0
- /package/src/templates/shared/error-pages/web/{app → src/app}/global-error.tsx +0 -0
- /package/src/templates/shared/error-pages/web/{app → src/app}/not-found.tsx +0 -0
- /package/src/templates/shared/health/web/{app → src/app}/api/health/route.ts +0 -0
- /package/src/templates/shared/legal/web/{app → src/app}/(legal)/privacy/page.tsx +0 -0
- /package/src/templates/shared/legal/web/{app → src/app}/(legal)/terms/page.tsx +0 -0
- /package/src/templates/shared/payments/web/{app → src/app}/api/webhooks/stripe/route.ts +0 -0
- /package/src/templates/shared/seo/web/{app → src/app}/api/og/route.tsx +0 -0
- /package/src/templates/shared/seo/web/{app → src/app}/robots.ts +0 -0
- /package/src/templates/shared/seo/web/{app → src/app}/sitemap.ts +0 -0
|
@@ -1,391 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
Button,
|
|
5
|
-
Card,
|
|
6
|
-
AudioPlayer,
|
|
7
|
-
PageTransition,
|
|
8
|
-
MobileContainer,
|
|
9
|
-
MobileHero,
|
|
10
|
-
ResponsiveGrid,
|
|
11
|
-
NetworkAwareContent,
|
|
12
|
-
OfflineWrapper,
|
|
13
|
-
SwipeableCard,
|
|
14
|
-
PullToRefresh,
|
|
15
|
-
useNetworkInfo,
|
|
16
|
-
useOfflineState,
|
|
17
|
-
FixedAudioBar,
|
|
18
|
-
PlaylistCard,
|
|
19
|
-
TrackList,
|
|
20
|
-
WaveformVisualizer,
|
|
21
|
-
AudioControls,
|
|
22
|
-
VolumeSlider,
|
|
23
|
-
ProgressBar,
|
|
24
|
-
ShuffleButton,
|
|
25
|
-
RepeatButton,
|
|
26
|
-
LikeButton,
|
|
27
|
-
ShareButton,
|
|
28
|
-
PlaylistSidebar,
|
|
29
|
-
AudioSearch,
|
|
30
|
-
NowPlayingCard,
|
|
31
|
-
useAnimationTokens,
|
|
32
|
-
useGlassmorphism
|
|
33
|
-
} from '@digilogiclabs/saas-factory-ui'
|
|
34
|
-
import { ArrowRight, Zap, Shield, Rocket, CheckCircle, LogOut, User, Music, Wifi, WifiOff } from 'lucide-react'
|
|
35
|
-
import { useAuth } from '@digilogiclabs/saas-factory-auth'
|
|
36
|
-
import Link from 'next/link'
|
|
37
|
-
import { useState } from 'react'
|
|
38
|
-
|
|
39
|
-
export default function Home() {
|
|
40
|
-
const { user, signOut, loading } = useAuth()
|
|
41
|
-
const networkInfo = useNetworkInfo()
|
|
42
|
-
const isOnline = useOfflineState()
|
|
43
|
-
const [isRefreshing, setIsRefreshing] = useState(false)
|
|
44
|
-
const [currentTrack, setCurrentTrack] = useState(null)
|
|
45
|
-
const [isPlaying, setIsPlaying] = useState(false)
|
|
46
|
-
const [showPlaylistSidebar, setShowPlaylistSidebar] = useState(false)
|
|
47
|
-
|
|
48
|
-
// Modern design tokens
|
|
49
|
-
const animations = useAnimationTokens()
|
|
50
|
-
const glass = useGlassmorphism()
|
|
51
|
-
|
|
52
|
-
const projectName = "{{projectName}}"
|
|
53
|
-
const projectDescription = "{{description}}"
|
|
54
|
-
|
|
55
|
-
// Safe CSS class combinations to avoid template literal issues
|
|
56
|
-
const glassCard = [glass.card, glass.border].filter(Boolean).join(' ')
|
|
57
|
-
const glassCardRounded = [glass.card, glass.border, 'rounded-2xl'].filter(Boolean).join(' ')
|
|
58
|
-
const glassCardWithHover = [glass.card, glass.border, 'rounded-2xl', animations.hover.scale, animations.transition.smooth].filter(Boolean).join(' ')
|
|
59
|
-
const glassAccentIcon = [glass.accent, 'rounded-xl', 'flex', 'items-center', 'justify-center', animations.hover.glow].filter(Boolean).join(' ')
|
|
60
|
-
|
|
61
|
-
const gridConfig = {
|
|
62
|
-
columns_1_2: { base: 1, md: 2 },
|
|
63
|
-
columns_1_3: { base: 1, md: 3 },
|
|
64
|
-
columns_1_sm2: { base: 1, sm: 2 },
|
|
65
|
-
columns_1_sm2_md3: { base: 1, sm: 2, md: 3 },
|
|
66
|
-
columns_1_sm2_md4: { base: 1, sm: 2, md: 4 },
|
|
67
|
-
columns_2: { base: 2 },
|
|
68
|
-
columns_2_md3: { base: 2, md: 3 },
|
|
69
|
-
columns_2_2: { base: 2 },
|
|
70
|
-
columns_2_md4: { base: 2, md: 4 }
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Demo playlist data
|
|
74
|
-
const demoPlaylist = [
|
|
75
|
-
{
|
|
76
|
-
id: '1',
|
|
77
|
-
title: 'Midnight Echoes',
|
|
78
|
-
artist: 'Luna Rivers',
|
|
79
|
-
album: 'Digital Dreams',
|
|
80
|
-
duration: 180,
|
|
81
|
-
url: 'https://www.soundjay.com/misc/sounds/bell-ringing-05.mp3',
|
|
82
|
-
coverArt: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjMwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9IiM4QjVDRjYiLz48Y2lyY2xlIGN4PSIxNTAiIGN5PSIxNTAiIHI9IjYwIiBmaWxsPSJ3aGl0ZSIgZmlsbC1vcGFjaXR5PSIwLjIiLz48cGF0aCBkPSJNMTMwIDEyMFYxODBMMTcwIDE1MEwxMzAgMTIwWiIgZmlsbD0id2hpdGUiLz48L3N2Zz4=',
|
|
83
|
-
liked: false
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
id: '2',
|
|
87
|
-
title: 'Neon Nights',
|
|
88
|
-
artist: 'The Frequency',
|
|
89
|
-
album: 'Electric Pulse',
|
|
90
|
-
duration: 210,
|
|
91
|
-
url: 'https://www.soundjay.com/misc/sounds/bell-ringing-05.mp3',
|
|
92
|
-
coverArt: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjMwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9IiNFRjQ0NDQiLz48Y2lyY2xlIGN4PSIxNTAiIGN5PSIxNTAiIHI9IjYwIiBmaWxsPSJ3aGl0ZSIgZmlsbC1vcGFjaXR5PSIwLjIiLz48cGF0aCBkPSJNMTMwIDEyMFYxODBMMTcwIDE1MEwxMzAgMTIwWiIgZmlsbD0id2hpdGUiLz48L3N2Zz4=',
|
|
93
|
-
liked: true
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
id: '3',
|
|
97
|
-
title: 'Ocean Waves',
|
|
98
|
-
artist: 'Ambient Flow',
|
|
99
|
-
album: 'Nature Sounds',
|
|
100
|
-
duration: 195,
|
|
101
|
-
url: 'https://www.soundjay.com/misc/sounds/bell-ringing-05.mp3',
|
|
102
|
-
coverArt: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjMwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9IiMwNjkyQzUiLz48Y2lyY2xlIGN4PSIxNTAiIGN5PSIxNTAiIHI9IjYwIiBmaWxsPSJ3aGl0ZSIgZmlsbC1vcGFjaXR5PSIwLjIiLz48cGF0aCBkPSJNMTMwIDEyMFYxODBMMTcwIDE1MEwxMzAgMTIwWiIgZmlsbD0id2hpdGUiLz48L3N2Zz4=',
|
|
103
|
-
liked: false
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
id: '4',
|
|
107
|
-
title: 'City Lights',
|
|
108
|
-
artist: 'Urban Echo',
|
|
109
|
-
album: 'Metropolitan',
|
|
110
|
-
duration: 225,
|
|
111
|
-
url: 'https://www.soundjay.com/misc/sounds/bell-ringing-05.mp3',
|
|
112
|
-
coverArt: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjMwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9IiNGNTk3MDAiLz48Y2lyY2xlIGN4PSIxNTAiIGN5PSIxNTAiIHI9IjYwIiBmaWxsPSJ3aGl0ZSIgZmlsbC1vcGFjaXR5PSIwLjIiLz48cGF0aCBkPSJNMTMwIDEyMFYxODBMMTcwIDE1MEwxMzAgMTIwWiIgZmlsbD0id2hpdGUiLz48L3N2Zz4=',
|
|
113
|
-
liked: true
|
|
114
|
-
}
|
|
115
|
-
]
|
|
116
|
-
|
|
117
|
-
const heroConfig = {
|
|
118
|
-
badge: {
|
|
119
|
-
text: "🎵 Premium Audio Experience",
|
|
120
|
-
variant: "secondary" as const,
|
|
121
|
-
icon: CheckCircle
|
|
122
|
-
},
|
|
123
|
-
title: {
|
|
124
|
-
text: `Welcome to ${projectName}`,
|
|
125
|
-
highlight: projectName,
|
|
126
|
-
size: "xl" as const
|
|
127
|
-
},
|
|
128
|
-
description: `${projectDescription}. Stream your favorite music with crystal-clear quality, offline downloads, and seamless playback across all your devices.`
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const handleSignOut = async () => {
|
|
132
|
-
try {
|
|
133
|
-
await signOut()
|
|
134
|
-
} catch (err) {
|
|
135
|
-
console.error('Sign out error:', err)
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const handleRefresh = async () => {
|
|
140
|
-
setIsRefreshing(true)
|
|
141
|
-
// Simulate refresh
|
|
142
|
-
await new Promise(resolve => setTimeout(resolve, 1500))
|
|
143
|
-
setIsRefreshing(false)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return (
|
|
147
|
-
<PageTransition type="fade" duration={300}>
|
|
148
|
-
<OfflineWrapper
|
|
149
|
-
cacheStrategy="stale-while-revalidate"
|
|
150
|
-
showOfflineIndicator={true}
|
|
151
|
-
backgroundSync={true}
|
|
152
|
-
>
|
|
153
|
-
<PullToRefresh
|
|
154
|
-
onRefresh={handleRefresh}
|
|
155
|
-
threshold={80}
|
|
156
|
-
loadingIndicator="spinner"
|
|
157
|
-
hapticOnTrigger={true}
|
|
158
|
-
networkAware={true}
|
|
159
|
-
>
|
|
160
|
-
<main className={"min-h-screen" + " " + glass.background.primary + " " + "relative overflow-hidden"}>
|
|
161
|
-
{/* Glassmorphism background overlay */}
|
|
162
|
-
<div className={"absolute inset-0" + " " + glass.background.accent + " " + "opacity-30"} />
|
|
163
|
-
<div className="relative z-10">
|
|
164
|
-
<MobileContainer className="py-8">
|
|
165
|
-
{/* Simple Auth Status */}
|
|
166
|
-
{user && (
|
|
167
|
-
<div className="flex justify-end mb-8">
|
|
168
|
-
<div className="flex items-center gap-4">
|
|
169
|
-
<span className="text-sm text-gray-600 dark:text-gray-300">
|
|
170
|
-
Welcome, {user.email?.split('@')[0]}
|
|
171
|
-
</span>
|
|
172
|
-
<Button variant="outline" size="sm" onClick={handleSignOut}>
|
|
173
|
-
<LogOut className="w-4 h-4 mr-2" />
|
|
174
|
-
Sign Out
|
|
175
|
-
</Button>
|
|
176
|
-
</div>
|
|
177
|
-
</div>
|
|
178
|
-
)}
|
|
179
|
-
|
|
180
|
-
{!user && !loading && (
|
|
181
|
-
<div className="flex justify-end mb-8">
|
|
182
|
-
<div className="flex gap-2">
|
|
183
|
-
<Link href="/login">
|
|
184
|
-
<Button variant="outline" size="sm">Sign In</Button>
|
|
185
|
-
</Link>
|
|
186
|
-
<Link href="/signup">
|
|
187
|
-
<Button size="sm">Sign Up</Button>
|
|
188
|
-
</Link>
|
|
189
|
-
</div>
|
|
190
|
-
</div>
|
|
191
|
-
)}
|
|
192
|
-
|
|
193
|
-
{/* Hero Section with Search */}
|
|
194
|
-
<MobileHero
|
|
195
|
-
badge={heroConfig.badge}
|
|
196
|
-
title={heroConfig.title}
|
|
197
|
-
description={heroConfig.description}
|
|
198
|
-
actions={[
|
|
199
|
-
{
|
|
200
|
-
label: "View Pricing",
|
|
201
|
-
href: "/checkout",
|
|
202
|
-
icon: ArrowRight,
|
|
203
|
-
variant: "default",
|
|
204
|
-
size: "lg"
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
label: "Learn More",
|
|
208
|
-
variant: "outline",
|
|
209
|
-
size: "lg"
|
|
210
|
-
}
|
|
211
|
-
]}
|
|
212
|
-
className="text-center mb-8"
|
|
213
|
-
/>
|
|
214
|
-
|
|
215
|
-
{/* Search Bar with Glassmorphism */}
|
|
216
|
-
<div className="max-w-2xl mx-auto mb-12">
|
|
217
|
-
<div className={glass.card + " " + glass.border + " " + "p-1 rounded-2xl" + " " + animations.hover.lift}>
|
|
218
|
-
<AudioSearch
|
|
219
|
-
placeholder="Search for tracks, artists, or albums..."
|
|
220
|
-
onSearch={(query) => console.log('Searching:', query)}
|
|
221
|
-
showTrending={true}
|
|
222
|
-
recentSearches={['Luna Rivers', 'Ambient Flow', 'Electronic']}
|
|
223
|
-
className="w-full bg-transparent border-none"
|
|
224
|
-
/>
|
|
225
|
-
</div>
|
|
226
|
-
</div>
|
|
227
|
-
|
|
228
|
-
{/* Main Content Area */}
|
|
229
|
-
<div className="grid grid-cols-1 lg:grid-cols-4 gap-8 mb-20">
|
|
230
|
-
{/* Main Content */}
|
|
231
|
-
<div className="lg:col-span-3 space-y-8">
|
|
232
|
-
{/* Now Playing Card with Enhanced Glassmorphism */}
|
|
233
|
-
<div className={`${glass.card} ${glass.border} rounded-3xl p-6 mb-8 ${animations.hover.lift} ${animations.transition.smooth}">
|
|
234
|
-
<NowPlayingCard
|
|
235
|
-
track={currentTrack || demoPlaylist[0]}
|
|
236
|
-
isPlaying={isPlaying}
|
|
237
|
-
onPlayPause={() => setIsPlaying(!isPlaying)}
|
|
238
|
-
showWaveform={true}
|
|
239
|
-
className="bg-transparent"
|
|
240
|
-
/>
|
|
241
|
-
</div>
|
|
242
|
-
|
|
243
|
-
{/* Featured Playlists with Staggered Animation */}
|
|
244
|
-
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
|
245
|
-
<div className={`${glass.card} ${glass.border} rounded-2xl overflow-hidden ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.short}">
|
|
246
|
-
<PlaylistCard
|
|
247
|
-
title="Today's Top Hits"
|
|
248
|
-
description="The most played songs today"
|
|
249
|
-
trackCount={50}
|
|
250
|
-
coverImage="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjMwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9IiNGRjc4NzgiLz48Y2lyY2xlIGN4PSIxNTAiIGN5PSIxNTAiIHI9IjYwIiBmaWxsPSJ3aGl0ZSIgZmlsbC1vcGFjaXR5PSIwLjMiLz48cGF0aCBkPSJNMTMwIDEyMFYxODBMMTcwIDE1MEwxMzAgMTIwWiIgZmlsbD0id2hpdGUiLz48L3N2Zz4="
|
|
251
|
-
onClick={() => console.log('Opening Top Hits playlist')}
|
|
252
|
-
className="bg-transparent border-none"
|
|
253
|
-
/>
|
|
254
|
-
</div>
|
|
255
|
-
<div className={`${glass.card} ${glass.border} rounded-2xl overflow-hidden ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.medium}">
|
|
256
|
-
<PlaylistCard
|
|
257
|
-
title="Chill Vibes"
|
|
258
|
-
description="Relaxing music for focus and creativity"
|
|
259
|
-
trackCount={32}
|
|
260
|
-
coverImage="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjMwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9IiM2MEE1RkEiLz48Y2lyY2xlIGN4PSIxNTAiIGN5PSIxNTAiIHI9IjYwIiBmaWxsPSJ3aGl0ZSIgZmlsbC1vcGFjaXR5PSIwLjMiLz48cGF0aCBkPSJNMTMwIDEyMFYxODBMMTcwIDE1MEwxMzAgMTIwWiIgZmlsbD0id2hpdGUiLz48L3N2Zz4="
|
|
261
|
-
onClick={() => console.log('Opening Chill Vibes playlist')}
|
|
262
|
-
className="bg-transparent border-none"
|
|
263
|
-
/>
|
|
264
|
-
</div>
|
|
265
|
-
<div className={`${glass.card} ${glass.border} rounded-2xl overflow-hidden ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.long}">
|
|
266
|
-
<PlaylistCard
|
|
267
|
-
title="Electronic Pulse"
|
|
268
|
-
description="High-energy electronic and dance music"
|
|
269
|
-
trackCount={28}
|
|
270
|
-
coverImage="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjMwMCIgaGVpZ2h0PSIzMDAiIGZpbGw9IiM5QzI3QjAiLz48Y2lyY2xlIGN4PSIxNTAiIGN5PSIxNTAiIHI9IjYwIiBmaWxsPSJ3aGl0ZSIgZmlsbC1vcGFjaXR5PSIwLjMiLz48cGF0aCBkPSJNMTMwIDEyMFYxODBMMTcwIDE1MEwxMzAgMTIwWiIgZmlsbD0id2hpdGUiLz48L3N2Zz4="
|
|
271
|
-
onClick={() => console.log('Opening Electronic Pulse playlist')}
|
|
272
|
-
className="bg-transparent border-none"
|
|
273
|
-
/>
|
|
274
|
-
</div>
|
|
275
|
-
</div>
|
|
276
|
-
|
|
277
|
-
{/* Track List with Glassmorphism */}
|
|
278
|
-
<div className={`${glass.card} ${glass.border} rounded-2xl overflow-hidden ${animations.transition.smooth}">
|
|
279
|
-
<TrackList
|
|
280
|
-
tracks={demoPlaylist}
|
|
281
|
-
currentTrackId={currentTrack?.id}
|
|
282
|
-
onTrackSelect={(track) => setCurrentTrack(track)}
|
|
283
|
-
onTrackPlay={(track) => {
|
|
284
|
-
setCurrentTrack(track)
|
|
285
|
-
setIsPlaying(true)
|
|
286
|
-
}}
|
|
287
|
-
showArtwork={true}
|
|
288
|
-
showDuration={true}
|
|
289
|
-
showLikeButton={true}
|
|
290
|
-
className="mb-8 bg-transparent"
|
|
291
|
-
/>
|
|
292
|
-
</div>
|
|
293
|
-
</div>
|
|
294
|
-
|
|
295
|
-
{/* Sidebar with Glassmorphism */}
|
|
296
|
-
<div className="lg:col-span-1">
|
|
297
|
-
<div className={`${glass.card} ${glass.border} rounded-2xl overflow-hidden ${animations.hover.lift} ${animations.transition.smooth}">
|
|
298
|
-
<PlaylistSidebar
|
|
299
|
-
playlists={[
|
|
300
|
-
{ id: '1', name: 'Liked Songs', trackCount: 47 },
|
|
301
|
-
{ id: '2', name: 'Recently Played', trackCount: 23 },
|
|
302
|
-
{ id: '3', name: 'My Playlist #1', trackCount: 15 },
|
|
303
|
-
{ id: '4', name: 'Favorites', trackCount: 32 }
|
|
304
|
-
]}
|
|
305
|
-
onPlaylistSelect={(playlist) => console.log('Selected playlist:', playlist)}
|
|
306
|
-
currentPlaylistId="1"
|
|
307
|
-
className="sticky top-4 bg-transparent"
|
|
308
|
-
/>
|
|
309
|
-
</div>
|
|
310
|
-
</div>
|
|
311
|
-
</div>
|
|
312
|
-
|
|
313
|
-
{/* Features Overview with Enhanced Glassmorphism */}
|
|
314
|
-
<ResponsiveGrid columns={gridConfig.columns_1_sm2_md4} gap="lg" className="mb-16">
|
|
315
|
-
<div className={`${glass.card} ${glass.border} text-center p-6 rounded-2xl ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.short}">
|
|
316
|
-
<div className={"mx-auto w-12 h-12" + " " + glass.accent + " " + "rounded-xl flex items-center justify-center mb-4" + " " + animations.hover.glow}>
|
|
317
|
-
<Zap className="h-6 w-6 text-blue-400" />
|
|
318
|
-
</div>
|
|
319
|
-
<h3 className="text-lg font-semibold mb-2">High-Quality Streaming</h3>
|
|
320
|
-
<p className="text-sm text-gray-600 dark:text-gray-300">
|
|
321
|
-
Lossless audio with adaptive bitrate for the best experience
|
|
322
|
-
</p>
|
|
323
|
-
</div>
|
|
324
|
-
|
|
325
|
-
<div className={`${glass.card} ${glass.border} text-center p-6 rounded-2xl ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.medium}">
|
|
326
|
-
<div className={"mx-auto w-12 h-12" + " " + glass.accent + " " + "rounded-xl flex items-center justify-center mb-4" + " " + animations.hover.glow}>
|
|
327
|
-
<Shield className="h-6 w-6 text-green-400" />
|
|
328
|
-
</div>
|
|
329
|
-
<h3 className="text-lg font-semibold mb-2">Secure & Private</h3>
|
|
330
|
-
<p className="text-sm text-gray-600 dark:text-gray-300">
|
|
331
|
-
Your listening habits and data are always protected
|
|
332
|
-
</p>
|
|
333
|
-
</div>
|
|
334
|
-
|
|
335
|
-
<div className={`${glass.card} ${glass.border} text-center p-6 rounded-2xl ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.long}">
|
|
336
|
-
<div className={"mx-auto w-12 h-12" + " " + glass.accent + " " + "rounded-xl flex items-center justify-center mb-4" + " " + animations.hover.glow}>
|
|
337
|
-
<Rocket className="h-6 w-6 text-purple-400" />
|
|
338
|
-
</div>
|
|
339
|
-
<h3 className="text-lg font-semibold mb-2">Offline Support</h3>
|
|
340
|
-
<p className="text-sm text-gray-600 dark:text-gray-300">
|
|
341
|
-
Download your favorites for offline listening anywhere
|
|
342
|
-
</p>
|
|
343
|
-
</div>
|
|
344
|
-
|
|
345
|
-
<div className={`${glass.card} ${glass.border} text-center p-6 rounded-2xl ${animations.hover.scale} ${animations.transition.smooth} ${animations.delay.extra}">
|
|
346
|
-
<div className={"mx-auto w-12 h-12" + " " + glass.accent + " " + "rounded-xl flex items-center justify-center mb-4" + " " + animations.hover.glow}>
|
|
347
|
-
<svg className="h-6 w-6 text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
348
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
|
|
349
|
-
</svg>
|
|
350
|
-
</div>
|
|
351
|
-
<h3 className="text-lg font-semibold mb-2">Premium Plans</h3>
|
|
352
|
-
<p className="text-sm text-gray-600 dark:text-gray-300">
|
|
353
|
-
Flexible subscription options for every music lover
|
|
354
|
-
</p>
|
|
355
|
-
</div>
|
|
356
|
-
</ResponsiveGrid>
|
|
357
|
-
</MobileContainer>
|
|
358
|
-
</div>
|
|
359
|
-
</main>
|
|
360
|
-
</PullToRefresh>
|
|
361
|
-
</OfflineWrapper>
|
|
362
|
-
|
|
363
|
-
{/* Fixed Audio Player Bar with Enhanced Glassmorphism */}
|
|
364
|
-
<div className={"fixed bottom-0 left-0 right-0 z-50" + " " + glass.card + " " + glass.border + " " + "border-t backdrop-blur-xl"}>
|
|
365
|
-
<FixedAudioBar
|
|
366
|
-
track={currentTrack || demoPlaylist[0]}
|
|
367
|
-
isPlaying={isPlaying}
|
|
368
|
-
onPlayPause={() => setIsPlaying(!isPlaying)}
|
|
369
|
-
onNext={() => {
|
|
370
|
-
const currentIndex = demoPlaylist.findIndex(track => track.id === (currentTrack?.id || demoPlaylist[0].id))
|
|
371
|
-
const nextIndex = (currentIndex + 1) % demoPlaylist.length
|
|
372
|
-
setCurrentTrack(demoPlaylist[nextIndex])
|
|
373
|
-
}}
|
|
374
|
-
onPrevious={() => {
|
|
375
|
-
const currentIndex = demoPlaylist.findIndex(track => track.id === (currentTrack?.id || demoPlaylist[0].id))
|
|
376
|
-
const prevIndex = (currentIndex - 1 + demoPlaylist.length) % demoPlaylist.length
|
|
377
|
-
setCurrentTrack(demoPlaylist[prevIndex])
|
|
378
|
-
}}
|
|
379
|
-
showWaveform={true}
|
|
380
|
-
showVolumeControl={true}
|
|
381
|
-
showTimeProgress={true}
|
|
382
|
-
showLikeButton={true}
|
|
383
|
-
showShareButton={true}
|
|
384
|
-
showShuffleRepeat={true}
|
|
385
|
-
allowMinimize={true}
|
|
386
|
-
className="bg-transparent"
|
|
387
|
-
/>
|
|
388
|
-
</div>
|
|
389
|
-
</PageTransition>
|
|
390
|
-
)
|
|
391
|
-
}
|