Skip to content

Commit fd8557a

Browse files
committed
feat: Add bookmark functionality with toggle action and repository integration
1 parent 0260cc4 commit fd8557a

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

src/backend/models/domain-models.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,10 @@ export interface ArticleTag {
113113
article?: Article;
114114
tag?: Tag;
115115
}
116+
117+
export interface Bookmark {
118+
id: string;
119+
resource_id: string;
120+
resource_type: "ARTICLE" | "COMMENT";
121+
user_id: string;
122+
}

src/backend/persistence/persistence-contracts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export enum DatabaseTableName {
55
user_sessions = "user_sessions",
66
series = "series",
77
series_items = "series_items",
8+
bookmarks = "bookmarks",
89
tags = "tags",
910
article_tag = "article_tag",
1011
}

src/backend/persistence/persistence-repositories.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Repository } from "sqlkit";
22
import {
33
Article,
44
ArticleTag,
5+
Bookmark,
56
Series,
67
SeriesItem,
78
Tag,
@@ -59,11 +60,18 @@ const seriesItemsRepository = new Repository<SeriesItem>(
5960
repositoryConfig
6061
);
6162

63+
const bookmarkRepository = new Repository<Bookmark>(
64+
DatabaseTableName.bookmarks,
65+
pgClient,
66+
repositoryConfig
67+
);
68+
6269
export const persistenceRepository = {
6370
user: userRepository,
6471
userSocial: userSocialRepository,
6572
userSession: userSessionRepository,
6673
article: articleRepository,
74+
bookmark: bookmarkRepository,
6775
articleTagPivot: articleTagRepository,
6876
tags: tagRepository,
6977
series: seriesRepository,
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import z from "zod";
2+
import { BookmarkActionInput } from "./inputs/bookmark.input";
3+
import { authID } from "./session.actions";
4+
import { ActionException, handleActionException } from "./RepositoryException";
5+
import { persistenceRepository } from "../persistence/persistence-repositories";
6+
import { and, eq } from "sqlkit";
7+
8+
export async function toggleResourceBookmark(
9+
_input: z.infer<typeof BookmarkActionInput.toggleBookmarkInput>
10+
) {
11+
try {
12+
const sessionUserId = await authID();
13+
if (!sessionUserId) {
14+
throw new ActionException("Unauthorized");
15+
}
16+
const input =
17+
await BookmarkActionInput.toggleBookmarkInput.parseAsync(_input);
18+
19+
// -----------
20+
const [existingBookmark] = await persistenceRepository.bookmark.find({
21+
limit: 1,
22+
where: and(
23+
eq("resource_id", input.resource_id),
24+
eq("resource_type", input.resource_type),
25+
eq("user_id", sessionUserId)
26+
),
27+
});
28+
29+
if (existingBookmark) {
30+
// If bookmark exists, delete it
31+
await persistenceRepository.bookmark.delete({
32+
where: and(
33+
eq("resource_id", input.resource_id),
34+
eq("resource_type", input.resource_type),
35+
eq("user_id", sessionUserId)
36+
),
37+
});
38+
return { bookmarked: false };
39+
}
40+
41+
// If bookmark does not exist, create it
42+
await persistenceRepository.bookmark.insert([
43+
{
44+
resource_id: input.resource_id,
45+
resource_type: input.resource_type,
46+
user_id: sessionUserId,
47+
},
48+
]);
49+
return { bookmarked: true };
50+
} catch (error) {
51+
handleActionException(error);
52+
}
53+
}

0 commit comments

Comments
 (0)