Skip to content

Commit 45ce568

Browse files
Fetch favorites feed and show them in my books
1 parent ba4c3e2 commit 45ce568

File tree

5 files changed

+62
-11
lines changed

5 files changed

+62
-11
lines changed

src/components/MyBooks.tsx

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ function compareTitles(a: AnyBook, b: AnyBook): 0 | -1 | 1 {
4141
}
4242

4343
export const MyBooks: React.FC = () => {
44-
const { loans, isLoading } = useUser();
44+
const { loans, selected, isLoading } = useUser();
4545
const sortedBooks = loans ? sortBooksByLoanExpirationDate(loans) : [];
46+
const selectedBooks = selected ? selected : [];
4647
const noBooks = sortedBooks.length === 0;
4748

4849
return (
@@ -57,11 +58,21 @@ export const MyBooks: React.FC = () => {
5758
{noBooks && isLoading ? (
5859
<PageLoader />
5960
) : noBooks ? (
60-
<Empty />
61+
<EmptyLoansAndHolds />
6162
) : (
6263
<LoansContent books={sortedBooks} />
6364
)}
6465
</div>
66+
<div sx={{ flex: 1, pb: 4 }}>
67+
<PageTitle>Favorites</PageTitle>
68+
{noBooks && isLoading ? (
69+
<PageLoader />
70+
) : noBooks ? (
71+
<EmptySelected />
72+
) : (
73+
<LoansContent books={selectedBooks} />
74+
)}
75+
</div>
6576
</AuthProtectedRoute>
6677
);
6778
};
@@ -74,7 +85,7 @@ const LoansContent: React.FC<{ books: AnyBook[] }> = ({ books }) => {
7485
);
7586
};
7687

77-
const Empty = () => {
88+
const EmptyLoansAndHolds = () => {
7889
return (
7990
<>
8091
<div
@@ -89,7 +100,26 @@ const Empty = () => {
89100
<H3>
90101
Your books will show up here when you have any loaned or on hold.
91102
</H3>
92-
<SignOut />
103+
</div>
104+
</>
105+
);
106+
};
107+
108+
const EmptySelected = () => {
109+
return (
110+
<>
111+
<div
112+
sx={{
113+
display: "flex",
114+
alignItems: "center",
115+
justifyContent: "center",
116+
flexDirection: "column",
117+
px: [3, 5]
118+
}}
119+
>
120+
<H3>
121+
No books in favorites.
122+
</H3>
93123
</div>
94124
</>
95125
);

src/components/context/UserContext.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { addHours, isBefore } from "date-fns";
1212
type Status = "authenticated" | "loading" | "unauthenticated";
1313
export type UserState = {
1414
loans: AnyBook[] | undefined;
15+
selected: AnyBook[] | undefined;
1516
status: Status;
1617
isAuthenticated: boolean;
1718
isLoading: boolean;
@@ -44,7 +45,7 @@ interface UserProviderProps {
4445
* those change it will cause a refetch.
4546
*/
4647
export const UserProvider = ({ children }: UserProviderProps) => {
47-
const { shelfUrl, slug, authMethods } = useLibraryContext();
48+
const { shelfUrl, selectedUrl, slug, authMethods } = useLibraryContext();
4849
const { credentials, setCredentials, clearCredentials } = useCredentials(
4950
slug,
5051
authMethods
@@ -64,9 +65,15 @@ export const UserProvider = ({ children }: UserProviderProps) => {
6465
};
6566

6667
const token = stringifyToken(credentials);
67-
const { data, mutate, isValidating } = useSWR(
68+
const { data : loansData, mutate, isValidating } = fetchFeed(shelfUrl)
69+
const { data : selectedData } = fetchFeed(selectedUrl)
70+
71+
function fetchFeed (
72+
fetchableUrl: string | null
73+
) {
74+
return useSWR(
6875
// pass null if there are no credentials or shelfUrl to tell SWR not to fetch at all.
69-
credentials && shelfUrl ? [shelfUrl, token, credentials?.methodType] : null,
76+
credentials && fetchableUrl ? [fetchableUrl, token, credentials?.methodType] : null,
7077
fetchLoans,
7178
{
7279
shouldRetryOnError: credentials?.methodType === BasicTokenAuthType,
@@ -115,7 +122,8 @@ export const UserProvider = ({ children }: UserProviderProps) => {
115122
}
116123
}
117124
}
118-
);
125+
)
126+
}
119127

120128
function signIn(
121129
token: string | Token,
@@ -132,7 +140,7 @@ export const UserProvider = ({ children }: UserProviderProps) => {
132140
}
133141

134142
function setBook(book: AnyBook, id?: string) {
135-
const existing = data ?? [];
143+
const existing = loansData ?? [];
136144

137145
// if the id exists, remove that book and set the new one
138146
const withoutOldBook = existing.filter(book => book.id !== id);
@@ -144,7 +152,7 @@ export const UserProvider = ({ children }: UserProviderProps) => {
144152
* We should only ever be in one of these three states.
145153
*/
146154
const status: Status =
147-
data && credentials
155+
loansData && credentials
148156
? "authenticated"
149157
: credentials && isValidating
150158
? "loading"
@@ -156,7 +164,8 @@ export const UserProvider = ({ children }: UserProviderProps) => {
156164
status,
157165
isAuthenticated,
158166
isLoading,
159-
loans: isAuthenticated ? data ?? [] : undefined,
167+
loans: isAuthenticated ? loansData ?? [] : undefined,
168+
selected: isAuthenticated ? selectedData ?? [] : undefined,
160169
refetchLoans: mutate,
161170
signIn,
162171
signOut,

src/dataflow/getLibraryData.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ function getShelfUrl(authDoc: OPDS1.AuthDocument): string | null {
4646
);
4747
}
4848

49+
function getSelectedUrl(authDoc: OPDS1.AuthDocument): string | null {
50+
return (
51+
authDoc.links?.find(link => {
52+
return link.rel === OPDS1.SelectedLinkRel;
53+
})?.href ?? null
54+
);
55+
}
4956
/**
5057
* Extracts the catalog root url from an auth document
5158
*/
@@ -79,11 +86,13 @@ export function buildLibraryData(
7986
const libraryLinks = parseLinks(authDoc.links);
8087
const authMethods = flattenSamlMethod(authDoc);
8188
const shelfUrl = getShelfUrl(authDoc);
89+
const selectedUrl = getSelectedUrl(authDoc);
8290
const catalogUrl = getCatalogUrl(authDoc);
8391
return {
8492
slug: librarySlug,
8593
catalogUrl,
8694
shelfUrl: shelfUrl ?? null,
95+
selectedUrl: selectedUrl ?? null,
8796
catalogName: authDoc.title,
8897
logoUrl: logoUrl ?? null,
8998
colors:

src/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export interface LibraryData {
130130
libraryLinks: LibraryLinks;
131131
authMethods: AppAuthMethod[];
132132
shelfUrl: string | null;
133+
selectedUrl: string | null;
133134
}
134135

135136
/**

src/types/opds1.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,12 @@ export interface Link {
156156
*/
157157
export const CatalogRootRel = "start";
158158
export const ShelfLinkRel = "http://opds-spec.org/shelf";
159+
export const SelectedLinkRel = "http://opds-spec.org/shelf/selected_books";
159160
type AuthDocLinkRelations =
160161
| typeof SelfRel
161162
| typeof CatalogRootRel
162163
| typeof ShelfLinkRel
164+
| typeof SelectedLinkRel
163165
| "navigation"
164166
| "logo"
165167
| "register"

0 commit comments

Comments
 (0)