Skip to content

Commit 5ea5ece

Browse files
If a user goes to /dashboard, show them an empty state that tells them to login (#955)
* Added empty state if not logged in * Fixed responsiveness * chore * changed 'snippets' to 'packages' and minor fix * Removed border and added margin top * fixed conflicts and other issues
1 parent 4633df0 commit 5ea5ece

File tree

1 file changed

+133
-88
lines changed

1 file changed

+133
-88
lines changed

src/pages/dashboard.tsx

+133-88
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,20 @@ import Footer from "@/components/Footer"
66
import { Snippet } from "fake-snippets-api/lib/db/schema"
77
import { Link } from "wouter"
88
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"
1017
import { Button } from "@/components/ui/button"
1118
import { useGlobalStore } from "@/hooks/use-global-store"
1219
import { PrefetchPageLink } from "@/components/PrefetchPageLink"
1320
import { SnippetList } from "@/components/SnippetList"
1421
import { Helmet } from "react-helmet-async"
22+
import { useSignIn } from "@/hooks/use-sign-in"
1523
import { SnippetCard } from "@/components/SnippetCard"
1624
import { useSnippetsBaseApiUrl } from "@/hooks/use-snippets-base-api-url"
1725
import { useConfirmDeletePackageDialog } from "@/components/dialogs/confirm-delete-package-dialog"
@@ -20,6 +28,9 @@ export const DashboardPage = () => {
2028
const axios = useAxios()
2129

2230
const currentUser = useGlobalStore((s) => s.session?.github_username)
31+
const isLoggedIn = Boolean(currentUser)
32+
const signIn = useSignIn()
33+
2334
const [showAllTrending, setShowAllTrending] = useState(false)
2435
const [showAllLatest, setShowAllLatest] = useState(false)
2536
const [snippetToDelete, setSnippetToDelete] = useState<Snippet | null>(null)
@@ -30,14 +41,22 @@ export const DashboardPage = () => {
3041
data: mySnippets,
3142
isLoading,
3243
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+
)
4160

4261
const { data: trendingSnippets } = useQuery<Snippet[]>(
4362
"trendingSnippets",
@@ -72,107 +91,133 @@ export const DashboardPage = () => {
7291
<h1 className="text-3xl font-bold mb-6">Dashboard</h1>
7392
<div className="flex md:flex-row flex-col">
7493
<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} />
9998
</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>
100109
</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>
118160
</div>
119161
</div>
120-
</div>
162+
))}
121163
</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+
</>
151196
)}
152197
</div>
153198
<div className="md:w-1/4">
154199
<SnippetList
155-
title="Trending Snippets"
200+
title="Trending Packages"
156201
snippets={trendingSnippets}
157202
showAll={showAllTrending}
158203
onToggleShowAll={() => setShowAllTrending(!showAllTrending)}
159204
/>
160205
<div className="mt-8">
161206
<SnippetList
162-
title="Latest Snippets"
207+
title="Latest Packages"
163208
snippets={latestSnippets}
164209
showAll={showAllLatest}
165210
onToggleShowAll={() => setShowAllLatest(!showAllLatest)}
166211
/>
167212
</div>
168213
</div>
169-
{snippetToDelete && (
170-
<DeleteDialog
171-
packageId={snippetToDelete.snippet_id}
172-
packageName={snippetToDelete.unscoped_name}
173-
/>
174-
)}
175214
</div>
215+
{snippetToDelete && (
216+
<DeleteDialog
217+
packageId={snippetToDelete.snippet_id}
218+
packageName={snippetToDelete.unscoped_name}
219+
/>
220+
)}
176221
</div>
177222
<Footer />
178223
</div>

0 commit comments

Comments
 (0)