11import { PageType , PageTypeToLabel } from "@changes-page/supabase/types/page" ;
22import { PlusIcon , UserGroupIcon } from "@heroicons/react/solid" ;
33import classNames from "classnames" ;
4- import { InferGetServerSidePropsType } from "next" ;
4+ import type { InferGetServerSidePropsType } from "next" ;
55import Link from "next/link" ;
66import { useRouter } from "next/router" ;
7- import { useEffect , type JSX } from "react" ;
7+ import { type JSX , useEffect } from "react" ;
88import { useHotkeys } from "react-hotkeys-hook" ;
99import { PrimaryRouterButton } from "../../components/core/buttons.component" ;
1010import { notifyError } from "../../components/core/toast.component" ;
@@ -13,6 +13,7 @@ import AuthLayout from "../../components/layout/auth-layout.component";
1313import Page from "../../components/layout/page.component" ;
1414import Changelog from "../../components/marketing/changelog" ;
1515import { ROUTES } from "../../data/routes.data" ;
16+ import { getPageScreenshotUrl } from "../../utils/capture" ;
1617import { getAppBaseURL } from "../../utils/helpers" ;
1718import { withSupabase } from "../../utils/supabase/withSupabase" ;
1819import { useUserData } from "../../utils/useUser" ;
@@ -33,16 +34,28 @@ export const getServerSideProps = withSupabase(async (_, { supabase }) => {
3334 )
3435 . order ( "updated_at" , { ascending : false } ) ;
3536
37+ const screenshots = pages . map ( ( page ) =>
38+ page
39+ ? getPageScreenshotUrl (
40+ page . page_settings ?. custom_domain
41+ ? `https://${ page . page_settings . custom_domain } `
42+ : `https://${ page . url_slug } .changes.page`
43+ )
44+ : null
45+ ) ;
46+
3647 return {
3748 props : {
3849 pages : pages ?? [ ] ,
50+ screenshots,
3951 error,
4052 } ,
4153 } ;
4254} ) ;
4355
4456export default function Pages ( {
4557 pages,
58+ screenshots,
4659 error,
4760} : InferGetServerSidePropsType < typeof getServerSideProps > ) {
4861 const { billingDetails, user } = useUserData ( ) ;
@@ -80,7 +93,7 @@ export default function Pages({
8093 message = "Get started by creating your first page."
8194 buttonLink = {
8295 billingDetails ?. has_active_subscription
83- ? ` /pages/new`
96+ ? " /pages/new"
8497 : `/api/billing/redirect-to-checkout?return_url=${ getAppBaseURL ( ) } /pages`
8598 }
8699 buttonLabel = {
@@ -107,69 +120,81 @@ export default function Pages({
107120 { pages . length ? (
108121 < div className = "overflow-hidden shadow rounded-md bg-white dark:bg-gray-900 border dark:border-gray-800" >
109122 < ul className = "divide-y divide-gray-200 dark:divide-gray-800" >
110- { pages . map ( ( page ) => (
123+ { pages . map ( ( page , idx ) => (
111124 < li
112125 key = { page . id }
113126 className = "relative group hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors duration-200"
114127 >
115128 < div className = "flex items-center justify-between p-6" >
116- < div className = "flex-1 min-w-0" >
117- < div className = "flex items-center gap-3 mb-2" >
118- < span
119- className = { classNames (
120- page . type === PageType . announcements &&
121- "bg-blue-100 dark:bg-blue-700" ,
122- page . type === PageType . changelogs &&
123- "bg-teal-100 dark:bg-teal-700" ,
124- page . type === PageType . releases &&
125- "bg-rose-100 dark:bg-rose-700" ,
126- page . type === PageType . updates &&
127- "bg-amber-100 dark:bg-amber-700" ,
128- page . type === PageType . announcements &&
129- "text-blue-500 dark:text-blue-100" ,
130- page . type === PageType . changelogs &&
131- "text-teal-500 dark:text-teal-100" ,
132- page . type === PageType . releases &&
133- "text-rose-500 dark:text-rose-100" ,
134- page . type === PageType . updates &&
135- "text-amber-500 dark:text-amber-100" ,
136- "inline-flex px-2 py-1 text-xs font-bold rounded-md"
137- ) }
138- >
139- { PageTypeToLabel [ page . type ] }
140- </ span >
141- { page . teams && page . user_id !== user ?. id && (
142- < div className = "flex items-center gap-1 text-gray-500 dark:text-gray-400" >
143- < UserGroupIcon className = "h-4 w-4" />
144- < span className = "text-xs font-medium" >
145- Editor ({ page . teams . name } )
146- </ span >
147- </ div >
148- ) }
149- </ div >
150- < div >
151- < h3 className = "text-lg font-bold tracking-tight text-gray-900 dark:text-white" >
152- < Link
153- href = { `${ ROUTES . PAGES } /${ page . id } ` }
154- className = "focus:outline-none hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors duration-200"
129+ < div className = "flex items-center gap-4" >
130+ { screenshots [ idx ] ? (
131+ < div className = "flex-shrink-0 hidden sm:block" >
132+ < img
133+ className = "w-48 h-18 object-cover rounded-md border border-gray-200 dark:border-gray-700"
134+ src = { screenshots [ idx ] }
135+ alt = { `Screenshot of ${ page . title } ` }
136+ loading = "lazy"
137+ />
138+ </ div >
139+ ) : null }
140+ < div className = "flex-1 min-w-0" >
141+ < div className = "flex items-center gap-3 mb-2" >
142+ < span
143+ className = { classNames (
144+ page . type === PageType . announcements &&
145+ "bg-blue-100 dark:bg-blue-700" ,
146+ page . type === PageType . changelogs &&
147+ "bg-teal-100 dark:bg-teal-700" ,
148+ page . type === PageType . releases &&
149+ "bg-rose-100 dark:bg-rose-700" ,
150+ page . type === PageType . updates &&
151+ "bg-amber-100 dark:bg-amber-700" ,
152+ page . type === PageType . announcements &&
153+ "text-blue-500 dark:text-blue-100" ,
154+ page . type === PageType . changelogs &&
155+ "text-teal-500 dark:text-teal-100" ,
156+ page . type === PageType . releases &&
157+ "text-rose-500 dark:text-rose-100" ,
158+ page . type === PageType . updates &&
159+ "text-amber-500 dark:text-amber-100" ,
160+ "inline-flex px-2 py-1 text-xs font-bold rounded-md"
161+ ) }
155162 >
156- < span
157- className = "absolute inset-0"
158- aria-hidden = "true"
159- />
160- { page . title }
161- </ Link >
162- </ h3 >
163- { page . description && (
164- < p className = "mt-1 text-sm text-gray-500 dark:text-gray-400 line-clamp-2" >
165- { page . description }
163+ { PageTypeToLabel [ page . type ] }
164+ </ span >
165+ { page . teams && page . user_id !== user ?. id && (
166+ < div className = "flex items-center gap-1 text-gray-500 dark:text-gray-400" >
167+ < UserGroupIcon className = "h-4 w-4" />
168+ < span className = "text-xs font-medium" >
169+ Editor ({ page . teams . name } )
170+ </ span >
171+ </ div >
172+ ) }
173+ </ div >
174+ < div >
175+ < h3 className = "text-lg font-bold tracking-tight text-gray-900 dark:text-white" >
176+ < Link
177+ href = { `${ ROUTES . PAGES } /${ page . id } ` }
178+ className = "focus:outline-none hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors duration-200"
179+ >
180+ < span
181+ className = "absolute inset-0"
182+ aria-hidden = "true"
183+ />
184+ { page . title }
185+ </ Link >
186+ </ h3 >
187+ { page . description && (
188+ < p className = "mt-1 text-sm text-gray-500 dark:text-gray-400 line-clamp-2" >
189+ { page . description }
190+ </ p >
191+ ) }
192+ < p className = "mt-2 text-xs text-gray-400 dark:text-gray-500" >
193+ { page . page_settings ?. custom_domain
194+ ? page . page_settings . custom_domain
195+ : `${ page . url_slug } .changes.page` }
166196 </ p >
167- ) }
168- < p className = "mt-2 text-xs text-gray-400 dark:text-gray-500" >
169- { page . page_settings ?. custom_domain
170- ? page . page_settings . custom_domain
171- : `${ page . url_slug } .changes.page` }
172- </ p >
197+ </ div >
173198 </ div >
174199 </ div >
175200 < div className = "ml-4 flex-shrink-0" >
@@ -178,6 +203,7 @@ export default function Pages({
178203 fill = "currentColor"
179204 viewBox = "0 0 20 20"
180205 >
206+ < title > Go to page</ title >
181207 < path
182208 fillRule = "evenodd"
183209 d = "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
0 commit comments