Skip to content

Commit 5901983

Browse files
committed
feat: add delete article functionality with scheduling and authorization checks
1 parent 30e5783 commit 5901983

File tree

2 files changed

+49
-38
lines changed

2 files changed

+49
-38
lines changed

src/app/dashboard/_components/ArticleList.tsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
} from "@radix-ui/react-icons";
2323

2424
import { useInfiniteQuery } from "@tanstack/react-query";
25+
import { TrashIcon } from "lucide-react";
2526
import Link from "next/link";
2627

2728
const ArticleList = () => {
@@ -82,17 +83,17 @@ const ArticleList = () => {
8283

8384
<div className="flex items-center gap-10 justify-between">
8485
<div className="flex gap-4 items-center">
85-
{!article.approved_at && (
86+
{/* {!article.approved_at && (
8687
<p className="bg-yellow-400/30 rounded-sm px-2 py-1 text-sm">
8788
🚧 {_t("অনুমোদনাধীন")}
8889
</p>
89-
)}
90+
)} */}
9091

91-
{article.approved_at && (
92+
{/* {article.approved_at && (
9293
<p className="bg-green-400/30 rounded-sm px-2 py-1 text-sm">
9394
✅ {_t("অনুমোদিত")}
9495
</p>
95-
)}
96+
)} */}
9697

9798
{!article.is_published && (
9899
<p className="bg-yellow-400/30 rounded-sm px-2 py-1 text-sm">
@@ -167,6 +168,19 @@ const ArticleList = () => {
167168
</span>
168169
</button>
169170
</DropdownMenuItem>
171+
<DropdownMenuItem
172+
onClick={() => {
173+
appConfirm.show({
174+
title: _t("Sure to delete?"),
175+
labels: {
176+
confirm: _t("Delete"),
177+
},
178+
});
179+
}}
180+
>
181+
<TrashIcon />
182+
{_t("Delete")}
183+
</DropdownMenuItem>
170184
</DropdownMenuContent>
171185
</DropdownMenu>
172186
</div>

src/backend/services/article.actions.ts

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { handleActionException, ActionException } from "./RepositoryException";
1515
import { ArticleRepositoryInput } from "./inputs/article.input";
1616
import { authID } from "./session.actions";
1717
import { syncTagsWithArticles } from "./tag.action";
18+
import { addDays } from "date-fns";
1819

1920
export async function createMyArticle(
2021
_input: z.infer<typeof ArticleRepositoryInput.createMyArticleInput>
@@ -144,40 +145,6 @@ export const getUniqueArticleHandle = async (
144145
}
145146
};
146147

147-
/**
148-
* Updates an existing article in the database.
149-
*
150-
* @param _input - The article update data, validated against ArticleRepositoryInput.updateArticleInput schema
151-
* @returns Promise<Article> - The updated article
152-
* @throws {ActionException} If article update fails, article not found, or validation fails
153-
*/
154-
export async function updateArticle(
155-
_input: z.infer<typeof ArticleRepositoryInput.updateArticleInput>
156-
) {
157-
try {
158-
const input =
159-
await ArticleRepositoryInput.updateArticleInput.parseAsync(_input);
160-
const article = await persistenceRepository.article.update({
161-
where: eq("id", input.article_id),
162-
data: {
163-
title: input.title,
164-
handle: input.handle
165-
? await getUniqueArticleHandle(input.handle, input.article_id)
166-
: undefined,
167-
excerpt: input.excerpt,
168-
body: input.body,
169-
cover_image: input.cover_image,
170-
is_published: input.is_published,
171-
published_at: input.is_published ? new Date() : null,
172-
},
173-
});
174-
175-
return article?.rows?.[0];
176-
} catch (error) {
177-
handleActionException(error);
178-
}
179-
}
180-
181148
export async function updateMyArticle(
182149
_input: z.infer<typeof ArticleRepositoryInput.updateMyArticleInput>
183150
) {
@@ -217,6 +184,36 @@ export async function updateMyArticle(
217184
}
218185
}
219186

187+
export const scheduleArticleDelete = async (article_id: string) => {
188+
try {
189+
const session_userID = await authID();
190+
if (!session_userID) {
191+
throw new ActionException("Unauthorized");
192+
}
193+
194+
const [permissibleArticle] = await persistenceRepository.article.find({
195+
where: and(eq("id", article_id), eq("author_id", session_userID)),
196+
});
197+
198+
if (!permissibleArticle) {
199+
throw new ActionException("Unauthorized");
200+
}
201+
202+
const updated = await persistenceRepository.article.update({
203+
where: and(eq("id", article_id), eq("author_id", session_userID)),
204+
data: {
205+
delete_scheduled_at: addDays(new Date(), 7),
206+
},
207+
});
208+
return {
209+
success: true as const,
210+
data: updated.rows[0],
211+
};
212+
} catch (error) {
213+
return handleActionException(error);
214+
}
215+
};
216+
220217
/**
221218
* Deletes an article from the database.
222219
*

0 commit comments

Comments
 (0)