@@ -6,12 +6,20 @@ import Footer from "@/components/Footer"
6
6
import { Snippet } from "fake-snippets-api/lib/db/schema"
7
7
import { Link } from "wouter"
8
8
import { CreateNewSnippetWithAiHero } from "@/components/CreateNewSnippetWithAiHero"
9
- import { Edit2 , Star , ChevronDown , ChevronUp } from "lucide-react"
9
+ import {
10
+ Edit2 ,
11
+ Star ,
12
+ ChevronDown ,
13
+ ChevronUp ,
14
+ Key ,
15
+ KeyRound ,
16
+ } from "lucide-react"
10
17
import { Button } from "@/components/ui/button"
11
18
import { useGlobalStore } from "@/hooks/use-global-store"
12
19
import { PrefetchPageLink } from "@/components/PrefetchPageLink"
13
20
import { SnippetList } from "@/components/SnippetList"
14
21
import { Helmet } from "react-helmet-async"
22
+ import { useSignIn } from "@/hooks/use-sign-in"
15
23
import { SnippetCard } from "@/components/SnippetCard"
16
24
import { useSnippetsBaseApiUrl } from "@/hooks/use-snippets-base-api-url"
17
25
import { useConfirmDeletePackageDialog } from "@/components/dialogs/confirm-delete-package-dialog"
@@ -20,6 +28,9 @@ export const DashboardPage = () => {
20
28
const axios = useAxios ( )
21
29
22
30
const currentUser = useGlobalStore ( ( s ) => s . session ?. github_username )
31
+ const isLoggedIn = Boolean ( currentUser )
32
+ const signIn = useSignIn ( )
33
+
23
34
const [ showAllTrending , setShowAllTrending ] = useState ( false )
24
35
const [ showAllLatest , setShowAllLatest ] = useState ( false )
25
36
const [ snippetToDelete , setSnippetToDelete ] = useState < Snippet | null > ( null )
@@ -30,14 +41,22 @@ export const DashboardPage = () => {
30
41
data : mySnippets ,
31
42
isLoading,
32
43
error,
33
- } = useQuery < Snippet [ ] > ( "userSnippets" , async ( ) => {
34
- const response = await axios . get ( `/snippets/list?owner_name=${ currentUser } ` )
35
- return response . data . snippets . sort (
36
- ( a : any , b : any ) =>
37
- new Date ( b . updated_at || b . created_at ) . getTime ( ) -
38
- new Date ( a . updated_at || a . created_at ) . getTime ( ) ,
39
- )
40
- } )
44
+ } = useQuery < Snippet [ ] > (
45
+ "userSnippets" ,
46
+ async ( ) => {
47
+ const response = await axios . get (
48
+ `/snippets/list?owner_name=${ currentUser } ` ,
49
+ )
50
+ return response . data . snippets . sort (
51
+ ( a : any , b : any ) =>
52
+ new Date ( b . updated_at || b . created_at ) . getTime ( ) -
53
+ new Date ( a . updated_at || a . created_at ) . getTime ( ) ,
54
+ )
55
+ } ,
56
+ {
57
+ enabled : isLoggedIn ,
58
+ } ,
59
+ )
41
60
42
61
const { data : trendingSnippets } = useQuery < Snippet [ ] > (
43
62
"trendingSnippets" ,
@@ -72,107 +91,133 @@ export const DashboardPage = () => {
72
91
< h1 className = "text-3xl font-bold mb-6" > Dashboard</ h1 >
73
92
< div className = "flex md:flex-row flex-col" >
74
93
< div className = "md:w-3/4 p-0 md:pr-6" >
75
- < div className = "mt-6 mb-4" >
76
- < div className = "flex items-center" >
77
- < h2 className = "text-sm text-gray-600 whitespace-nowrap" >
78
- Edit Recent
79
- </ h2 >
80
- < div className = "flex gap-2 items-center overflow-x-scroll md:overflow-hidden " >
81
- { mySnippets &&
82
- mySnippets . slice ( 0 , 3 ) . map ( ( snippet ) => (
83
- < div key = { snippet . snippet_id } >
84
- < PrefetchPageLink
85
- href = { `/editor?snippet_id=${ snippet . snippet_id } ` }
86
- className = "text-blue-600 hover:underline"
87
- >
88
- < Button
89
- variant = "ghost"
90
- size = "sm"
91
- className = "font-medium"
92
- >
93
- { snippet . unscoped_name }
94
- < Edit2 className = "w-3 h-3 ml-2" />
95
- </ Button >
96
- </ PrefetchPageLink >
97
- </ div >
98
- ) ) }
94
+ { ! isLoggedIn ? (
95
+ < div className = "flex flex-col items-center justify-center h-64 rounded-md p-4 mt-[40px] mb-2 sm:mb-4" >
96
+ < div className = "p-4 mb-4 rounded-full bg-blue-50 border border-blue-100 shadow-sm" >
97
+ < KeyRound className = "text-blue-500" size = { 32 } />
99
98
</ div >
99
+ < h2 className = "text-xl sm:text-2xl font-bold text-gray-800 mb-3" >
100
+ You're not logged in
101
+ </ h2 >
102
+
103
+ < p className = "text-gray-600 mb-6 text-center max-w-md text-sm sm:text-base" >
104
+ Log in to access your dashboard and manage your snippets.
105
+ </ p >
106
+ < Button onClick = { ( ) => signIn ( ) } variant = "outline" >
107
+ Log in
108
+ </ Button >
100
109
</ div >
101
- </ div >
102
- { /* <CreateNewSnippetWithAiHero /> */ }
103
- < h2 className = "text-sm font-bold mb-2 text-gray-700 border-b border-gray-200" >
104
- Your Recent Snippets
105
- </ h2 >
106
- { isLoading && (
107
- < div className = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4" >
108
- { [ ...Array ( 6 ) ] . map ( ( _ , i ) => (
109
- < div key = { i } className = "border p-4 rounded-md animate-pulse" >
110
- < div className = "flex items-start gap-4" >
111
- < div className = "h-16 w-16 flex-shrink-0 rounded-md bg-slate-200" > </ div >
112
- < div className = "flex-1" >
113
- < div className = "h-5 bg-slate-200 rounded w-3/4 mb-2" > </ div >
114
- < div className = "h-4 bg-slate-200 rounded w-1/2 mb-2" > </ div >
115
- < div className = "flex gap-2" >
116
- < div className = "h-3 bg-slate-200 rounded w-16" > </ div >
117
- < div className = "h-3 bg-slate-200 rounded w-16" > </ div >
110
+ ) : (
111
+ < >
112
+ < div className = "mt-6 mb-4" >
113
+ < div className = "flex items-center" >
114
+ < h2 className = "text-sm text-gray-600 whitespace-nowrap" >
115
+ Edit Recent
116
+ </ h2 >
117
+ < div className = "flex gap-2 items-center overflow-x-scroll md:overflow-hidden" >
118
+ { mySnippets &&
119
+ mySnippets . slice ( 0 , 3 ) . map ( ( snippet ) => (
120
+ < div key = { snippet . snippet_id } >
121
+ < PrefetchPageLink
122
+ href = { `/editor?snippet_id=${ snippet . snippet_id } ` }
123
+ className = "text-blue-600 hover:underline"
124
+ >
125
+ < Button
126
+ variant = "ghost"
127
+ size = "sm"
128
+ className = "font-medium"
129
+ >
130
+ { snippet . unscoped_name }
131
+ < Edit2 className = "w-3 h-3 ml-2" />
132
+ </ Button >
133
+ </ PrefetchPageLink >
134
+ </ div >
135
+ ) ) }
136
+ </ div >
137
+ </ div >
138
+ </ div >
139
+ { /* <CreateNewSnippetWithAiHero/> */ }
140
+ < h2 className = "text-sm font-bold mb-2 text-gray-700 border-b border-gray-200" >
141
+ Your Recent Packages
142
+ </ h2 >
143
+ { isLoading && (
144
+ < div className = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4" >
145
+ { [ ...Array ( 6 ) ] . map ( ( _ , i ) => (
146
+ < div
147
+ key = { i }
148
+ className = "border p-4 rounded-md animate-pulse"
149
+ >
150
+ < div className = "flex items-start gap-4" >
151
+ < div className = "h-16 w-16 flex-shrink-0 rounded-md bg-slate-200" > </ div >
152
+ < div className = "flex-1" >
153
+ < div className = "h-5 bg-slate-200 rounded w-3/4 mb-2" > </ div >
154
+ < div className = "h-4 bg-slate-200 rounded w-1/2 mb-2" > </ div >
155
+ < div className = "flex gap-2" >
156
+ < div className = "h-3 bg-slate-200 rounded w-16" > </ div >
157
+ < div className = "h-3 bg-slate-200 rounded w-16" > </ div >
158
+ </ div >
159
+ </ div >
118
160
</ div >
119
161
</ div >
120
- </ div >
162
+ ) ) }
121
163
</ div >
122
- ) ) }
123
- </ div >
124
- ) }
125
- { mySnippets && mySnippets . length > 0 ? (
126
- < div className = "grid grid-cols-1 lg:grid-cols-2 gap-4" >
127
- { mySnippets . slice ( 0 , 10 ) . map ( ( snippet ) => (
128
- < SnippetCard
129
- key = { snippet . snippet_id }
130
- snippet = { snippet }
131
- baseUrl = { baseUrl }
132
- isCurrentUserSnippet = { snippet . owner_name === currentUser }
133
- onDeleteClick = { handleDeleteClick }
134
- />
135
- ) ) }
136
- </ div >
137
- ) : (
138
- ! isLoading && (
139
- < span className = "font-medium text-sm text-gray-500" >
140
- No snippets found
141
- </ span >
142
- )
143
- ) }
144
- { mySnippets && mySnippets . length > 10 && (
145
- < Link
146
- href = { `/${ currentUser } ` }
147
- className = "text-sm text-blue-600 hover:underline mt-2 inline-block"
148
- >
149
- View all snippets
150
- </ Link >
164
+ ) }
165
+ { mySnippets && mySnippets . length > 0 ? (
166
+ < div className = "grid grid-cols-1 lg:grid-cols-2 gap-4" >
167
+ { mySnippets . slice ( 0 , 10 ) . map ( ( snippet ) => (
168
+ < SnippetCard
169
+ key = { snippet . snippet_id }
170
+ snippet = { snippet }
171
+ baseUrl = { baseUrl }
172
+ isCurrentUserSnippet = {
173
+ snippet . owner_name === currentUser
174
+ }
175
+ onDeleteClick = { handleDeleteClick }
176
+ />
177
+ ) ) }
178
+ </ div >
179
+ ) : (
180
+ ! isLoading &&
181
+ mySnippets ?. length === 0 && (
182
+ < span className = "font-medium text-sm text-gray-500" >
183
+ No packages found
184
+ </ span >
185
+ )
186
+ ) }
187
+ { mySnippets && mySnippets . length > 10 && (
188
+ < Link
189
+ href = { `/${ currentUser } ` }
190
+ className = "text-sm text-blue-600 hover:underline mt-2 inline-block"
191
+ >
192
+ View all packages
193
+ </ Link >
194
+ ) }
195
+ </ >
151
196
) }
152
197
</ div >
153
198
< div className = "md:w-1/4" >
154
199
< SnippetList
155
- title = "Trending Snippets "
200
+ title = "Trending Packages "
156
201
snippets = { trendingSnippets }
157
202
showAll = { showAllTrending }
158
203
onToggleShowAll = { ( ) => setShowAllTrending ( ! showAllTrending ) }
159
204
/>
160
205
< div className = "mt-8" >
161
206
< SnippetList
162
- title = "Latest Snippets "
207
+ title = "Latest Packages "
163
208
snippets = { latestSnippets }
164
209
showAll = { showAllLatest }
165
210
onToggleShowAll = { ( ) => setShowAllLatest ( ! showAllLatest ) }
166
211
/>
167
212
</ div >
168
213
</ div >
169
- { snippetToDelete && (
170
- < DeleteDialog
171
- packageId = { snippetToDelete . snippet_id }
172
- packageName = { snippetToDelete . unscoped_name }
173
- />
174
- ) }
175
214
</ div >
215
+ { snippetToDelete && (
216
+ < DeleteDialog
217
+ packageId = { snippetToDelete . snippet_id }
218
+ packageName = { snippetToDelete . unscoped_name }
219
+ />
220
+ ) }
176
221
</ div >
177
222
< Footer />
178
223
</ div >
0 commit comments