diff --git a/src/interfaces/topic.ts b/src/interfaces/topic.ts index 26fe244..4852517 100644 --- a/src/interfaces/topic.ts +++ b/src/interfaces/topic.ts @@ -13,3 +13,7 @@ export interface ITopicCreate { title: string; sectionId: number; } + +export interface IReorderTopicContent { + topicContentIds: number[]; +} diff --git a/src/pages/topics/TopicDetails.tsx b/src/pages/topics/TopicDetails.tsx index c2ee9d1..af57a2c 100644 --- a/src/pages/topics/TopicDetails.tsx +++ b/src/pages/topics/TopicDetails.tsx @@ -11,6 +11,7 @@ import { ITopicCreate } from "@/interfaces/topic"; import { useSectionsQuery } from "@/queries/sections"; import { useTopicContent, + useTopicContentReorder, useTopicDeletion, useTopicDetailsQuery, useTopicMutation, @@ -27,11 +28,13 @@ import AddContentCard from "./components/AddContentCard"; interface TopicForm { title: string; sectionId: number; + topicContentIds: number[]; } const initialValues: TopicForm = { title: "", sectionId: -1, + topicContentIds: [], }; function TopicDetails() { @@ -69,6 +72,11 @@ function TopicDetails() { value: sections?.[0].id.toString(), }); + const topicContentIds = useMemo( + () => topicContentDisplay.map((content) => content.id), + [topicContentDisplay] + ); + const sectionOptions = useMemo( () => sections?.map((section) => ({ @@ -114,6 +122,9 @@ function TopicDetails() { } ); + const { mutate: reorderTopicContent, isPending: isReordering } = + useTopicContentReorder({ id: +id! }); + const topicForm = useForm({ defaultValues: initialValues, mode: "onBlur", @@ -122,10 +133,14 @@ function TopicDetails() { const isValid = Object.values(topicForm.formState.errors).length === 0; const onSubmit: SubmitHandler = (data: ITopicCreate) => { - mutate(data); + mutate({ sectionId: data.sectionId, title: data.title }); + reorderTopicContent({ topicContentIds }); }; const updateTopicContentOrderNumbers = () => { + topicForm.setValue("topicContentIds", topicContentIds, { + shouldDirty: true, + }); setTopicContentDisplay((topicContent) => { return topicContent.map((content, index) => ({ ...content, @@ -135,8 +150,12 @@ function TopicDetails() { }; useEffect(() => { - if (topicContent) setTopicContentDisplay(topicContent); - }, [topicContent]); + if (topicContent) { + setTopicContentDisplay(topicContent); + } + }, [topicContent, topicForm]); + + useEffect(() => {}, [topicContentDisplay, topicForm, topicContentIds]); useEffect(() => { if (existingTopic && id) { @@ -170,7 +189,7 @@ function TopicDetails() { isExisting={!!id} isLoading={isLoading || isTopicContentLoading} isSaveDisabled={!isValid || !topicForm.formState.isDirty} - isSaveButtonLoading={isPending} + isSaveButtonLoading={isPending || isReordering} onDeleteClick={deleteTopic} isDeleting={isDeleting} onSaveClick={() => onSubmit(topicForm.getValues())} diff --git a/src/queries/topics.ts b/src/queries/topics.ts index 461ca61..0b9f894 100644 --- a/src/queries/topics.ts +++ b/src/queries/topics.ts @@ -1,11 +1,12 @@ import { QUERY_KEYS } from "@/constants/queryKeys"; -import { ITopic, ITopicCreate } from "@/interfaces/topic"; +import { IReorderTopicContent, ITopic, ITopicCreate } from "@/interfaces/topic"; import { createTopic, getTopicContent, getTopicDetails, getTopics, removeTopic, + reorderTopicContent, updateTopic, } from "@/requests/topics"; import { useMutation, useQuery } from "@tanstack/react-query"; @@ -93,3 +94,20 @@ export const useTopicContent = (id: number, { enabled }: QueryParams) => { isLoading, }; }; + +export const useTopicContentReorder = ({ + onError, + onSuccess, + id, +}: MutationQuery) => { + const { mutate, isPending } = useMutation({ + mutationFn: (data: IReorderTopicContent) => reorderTopicContent(id!, data), + onSuccess, + onError, + }); + + return { + mutate, + isPending, + }; +}; diff --git a/src/requests/topics.ts b/src/requests/topics.ts index 3464939..5e5899e 100644 --- a/src/requests/topics.ts +++ b/src/requests/topics.ts @@ -1,4 +1,8 @@ -import { ITopic, ITopicCreate } from "../interfaces/topic"; +import { + IReorderTopicContent, + ITopic, + ITopicCreate, +} from "../interfaces/topic"; import { API_TOPICS } from "../constants/apiConstants"; import { request } from "./request"; import { ITopicContent } from "@/interfaces/topicContent"; @@ -37,3 +41,12 @@ export async function getTopicContent(id: number): Promise { .get(`${API_TOPICS}${id}/get-content/`) .then(({ data }) => data); } + +export async function reorderTopicContent( + id: number, + data: IReorderTopicContent +) { + return request + .post(`${API_TOPICS}${id}/update_content_order/`, data) + .then(({ data }) => data); +}