diff --git a/packages/api/src/services/highlights.ts b/packages/api/src/services/highlights.ts
index 80a011589..327038aca 100644
--- a/packages/api/src/services/highlights.ts
+++ b/packages/api/src/services/highlights.ts
@@ -290,6 +290,11 @@ export const searchHighlights = async (
const queryBuilder = tx
.getRepository(Highlight)
.createQueryBuilder('highlight')
+ .innerJoin(
+ 'highlight.libraryItem',
+ 'libraryItem',
+ 'highlight.libraryItemId = libraryItem.id AND libraryItem.deletedAt IS NULL'
+ )
.andWhere('highlight.userId = :userId', { userId })
.orderBy('highlight.updatedAt', 'DESC')
.take(limit)
diff --git a/packages/web/components/templates/navMenu/LibraryMenu.tsx b/packages/web/components/templates/navMenu/LibraryMenu.tsx
index e39923bca..d852a2087 100644
--- a/packages/web/components/templates/navMenu/LibraryMenu.tsx
+++ b/packages/web/components/templates/navMenu/LibraryMenu.tsx
@@ -210,10 +210,10 @@ const LibraryNav = (props: LibraryFilterMenuProps): JSX.Element => {
filterTerm="in:library use:folders"
icon={}
/>
- }
/>
- highlightsError?: unknown
+ data?: Array
+ error?: unknown
isLoading: boolean
isValidating: boolean
- error: boolean
size: number
setSize: (
size: number | ((_size: number) => number)
@@ -19,7 +18,6 @@ interface HighlightsResponse {
interface HighlightsVariables {
first?: number
- after?: string
query?: string
}
@@ -46,6 +44,11 @@ export const useGetHighlights = (
edges {
node {
...HighlightFields
+ libraryItem {
+ id
+ title
+ author
+ }
}
cursor
}
@@ -67,12 +70,13 @@ export const useGetHighlights = (
const getKey = (pageIndex: number, previousPageData: any) => {
if (previousPageData && !previousPageData.highlights.edges) return null
- if (pageIndex === 0) return `${query}_${variables.first}_${variables.query}`
+ if (pageIndex === 0) return '0'
- return `${query}_${previousPageData.highlights.pageInfo.endCursor}_${variables.first}_${variables.query}`
+ return previousPageData.highlights.pageInfo.endCursor
}
- const fetcher = async () => gqlFetcher(query, variables, true)
+ const fetcher = async (cursor: string | null) =>
+ gqlFetcher(query, { ...variables, after: cursor }, true)
const { data, error, isValidating, mutate, size, setSize } = useSWRInfinite(
getKey,
@@ -99,10 +103,9 @@ export const useGetHighlights = (
return {
isValidating,
- highlightsData: responsePages || undefined,
- highlightsError: responseError,
+ data: responsePages || undefined,
+ error: responseError,
isLoading: !error && !data,
- error: !!error,
size,
setSize,
mutate,
diff --git a/packages/web/pages/highlights.tsx b/packages/web/pages/highlights.tsx
new file mode 100644
index 000000000..3a4cbd551
--- /dev/null
+++ b/packages/web/pages/highlights.tsx
@@ -0,0 +1,166 @@
+import { useRouter } from 'next/router'
+import { useCallback, useMemo, useState } from 'react'
+import ReactMarkdown from 'react-markdown'
+import remarkGfm from 'remark-gfm'
+import { LabelChip } from '../components/elements/LabelChip'
+import { Box, HStack, VStack } from '../components/elements/LayoutPrimitives'
+import { EmptyHighlights } from '../components/templates/homeFeed/EmptyHighlights'
+import { LibraryFilterMenu } from '../components/templates/navMenu/LibraryMenu'
+import { useApplyLocalTheme } from '../lib/hooks/useApplyLocalTheme'
+import { useFetchMore } from '../lib/hooks/useFetchMoreScroll'
+import { Highlight } from '../lib/networking/fragments/highlightFragment'
+import { useGetHighlights } from '../lib/networking/queries/useGetHighlights'
+import { highlightColor } from '../lib/themeUpdater'
+
+const PAGE_SIZE = 10
+
+export default function HighlightsPage(): JSX.Element {
+ const router = useRouter()
+ const [showFilterMenu, setShowFilterMenu] = useState(false)
+ const [_, setShowAddLinkModal] = useState(false)
+
+ useApplyLocalTheme()
+
+ const { isLoading, isValidating, mutate, setSize, size, data, error } =
+ useGetHighlights({
+ first: PAGE_SIZE,
+ })
+
+ const hasMore = useMemo(() => {
+ if (!data) {
+ return false
+ }
+ return data[data.length - 1].highlights.pageInfo.hasNextPage
+ }, [data])
+
+ const handleFetchMore = useCallback(() => {
+ if (isLoading || !hasMore) {
+ return
+ }
+ setSize(size + 1)
+ }, [isLoading, hasMore, setSize, size])
+
+ useFetchMore(handleFetchMore)
+
+ const highlights = useMemo(() => {
+ if (!data) {
+ return []
+ }
+ return data.flatMap((res) => res.highlights.edges.map((edge) => edge.node))
+ }, [data])
+
+ if (!highlights.length) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+ {
+ router?.push(`/home?q=${searchQuery}`)
+ }}
+ />
+
+ {highlights.map((highlight) => {
+ return
+ })}
+
+
+ )
+}
+
+interface HighlightCardProps {
+ highlight: Highlight
+}
+
+function HighlightCard(props: HighlightCardProps): JSX.Element {
+ return (
+
+
+
+ {props.highlight.quote && (
+
+ {props.highlight.quote}
+
+ )}
+ {props.highlight.labels && (
+
+ {props.highlight.labels.map((label) => {
+ return (
+
+ )
+ })}
+
+ )}
+
+ {props.highlight.libraryItem?.title}
+
+
+ {props.highlight.libraryItem?.author}
+
+
+
+ )
+}