Skip to content

Commit 1a2d09a

Browse files
committed
feat(update): finishing update events, and update image
1 parent 234e80f commit 1a2d09a

File tree

7 files changed

+130
-8
lines changed

7 files changed

+130
-8
lines changed

src/domains/Events.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export const createEventFormSchema = (t: (key: string) => string) =>
125125

126126
export type EventFormType = z.infer<ReturnType<typeof createEventFormSchema>>;
127127

128-
export type CreateEventPayload = Omit<EventFormType, "image"> & { file_name: string };
128+
export type CreateEventPayload = Omit<EventFormType, "image"> & { file_name?: string };
129129

130130
export type AdminEventResponseType = Omit<EventFormType, "image"> & {
131131
id: number;

src/features/events/hooks/useEvent.ts

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
"use client";
22

33
import React from "react";
4-
import { useQuery, useMutation } from "@tanstack/react-query";
4+
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
55
import { eventsService } from "@/services/events";
66
import { uploadsService } from "@/services/uploads";
77
import { EventFormType, CreateEventPayload } from "@/domains/Events";
88
import DialogSuccess from "@/components/common/DialogGlobal/DialogSuccess";
99
import { useRouter } from "@/lib/navigation";
1010
import { useDialog } from "@/contexts";
1111
import DialogError from "@/components/common/DialogGlobal/DialogError";
12+
import { getFileNameFromUrl } from "@/lib/image";
1213

1314
export const useEventById = (eventId: string) => {
1415
return useQuery({
@@ -54,11 +55,14 @@ export const useEventsAdmin = (page: number, limit: number, search?: string) =>
5455
export const useCreateEvent = (t: (key: string) => string) => {
5556
const router = useRouter();
5657
const { openDialog, closeDialog } = useDialog();
58+
const queryClient = useQueryClient();
5759

5860
const submitMutation = useMutation({
5961
mutationKey: ["createEvent"],
6062
mutationFn: (payload: CreateEventPayload) => eventsService.createEventAdmin(payload),
6163
onSuccess: () => {
64+
queryClient.invalidateQueries({ queryKey: ["eventsAdmin"] });
65+
6266
openDialog({
6367
content: React.createElement(DialogSuccess, {
6468
title: t("EventForm.create-success-title"),
@@ -123,3 +127,90 @@ export const useGetDetailEventAdmin = (id: string) => {
123127
queryFn: async () => eventsService.getDetailEventAdmin(id),
124128
});
125129
};
130+
131+
export const useUpdateEvent = (t: (key: string) => string, id: string) => {
132+
const router = useRouter();
133+
const { openDialog, closeDialog } = useDialog();
134+
const queryClient = useQueryClient();
135+
136+
const { mutate: mutateUpdateEvent, isPending: loadingCreateEvent } = useMutation({
137+
mutationKey: ["updateEvent"],
138+
mutationFn: (payload: CreateEventPayload) => eventsService.updateEventAdmin(id, payload),
139+
onSuccess: () => {
140+
queryClient.invalidateQueries({ queryKey: ["getDetailEventAdmin", id] });
141+
queryClient.invalidateQueries({ queryKey: ["eventsAdmin"] });
142+
143+
openDialog({
144+
content: React.createElement(DialogSuccess, {
145+
title: t("EventForm.update-success-title"),
146+
description: t("EventForm.update-success-description"),
147+
}),
148+
confirmText: t("EventForm.back-to-list"),
149+
onConfirm: () => {
150+
router.push("/admin/events");
151+
closeDialog();
152+
},
153+
classAction: "sm:justify-center",
154+
});
155+
},
156+
onError: () => {
157+
openDialog({
158+
content: React.createElement(DialogError, {
159+
title: t("EventForm.update-error-title"),
160+
description: t("EventForm.update-error-description"),
161+
}),
162+
cancelText: "OK",
163+
classAction: "sm:justify-center",
164+
});
165+
},
166+
});
167+
168+
const { mutate: mutateUpdateImage, isPending: loadingCreateImage } = useMutation({
169+
mutationFn: (payload: EventFormType) =>
170+
uploadsService.updateImageAdmin(payload.image, "events", getFileNameFromUrl(payload?.file_name as string)),
171+
onSuccess: (data, variables) => {
172+
const filename = data.data.file_name;
173+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
174+
const { image, ...rest } = variables;
175+
mutateUpdateEvent({
176+
...rest,
177+
file_name: filename,
178+
});
179+
},
180+
onError: () => {
181+
openDialog({
182+
content: React.createElement(DialogError, {
183+
title: t("EventForm.upload-error-title"),
184+
description: t("EventForm.upload-error-description"),
185+
}),
186+
onConfirm: () => {
187+
closeDialog();
188+
},
189+
confirmText: "OK",
190+
classAction: "sm:justify-center",
191+
});
192+
},
193+
});
194+
195+
const updateEvent = (payload: EventFormType) => {
196+
if (payload.image instanceof File) {
197+
return mutateUpdateImage(payload);
198+
} else if (payload.file_name) {
199+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
200+
const { image, ...rest } = payload;
201+
return mutateUpdateEvent({
202+
...rest,
203+
file_name: getFileNameFromUrl(payload.file_name),
204+
});
205+
} else {
206+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
207+
const { image, file_name, ...rest } = payload;
208+
return mutateUpdateEvent(rest);
209+
}
210+
};
211+
212+
return {
213+
updateEvent,
214+
isLoading: loadingCreateEvent || loadingCreateImage,
215+
};
216+
};

src/features/events/pages/AdminEventUpdatePage.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22

33
import { EventFormType } from "@/domains/Events";
44
import EventForm from "../components/EventForm";
5-
import { useGetDetailEventAdmin } from "../hooks/useEvent";
5+
import { useGetDetailEventAdmin, useUpdateEvent } from "../hooks/useEvent";
66
import Loader from "@/components/common/Loader";
7+
import { useTranslations } from "next-intl";
78

89
const AdminEventUpdatePage = ({ eventId }: { eventId: string }) => {
910
console.log("eventsss id", eventId);
11+
const t = useTranslations();
1012
const { data, isLoading } = useGetDetailEventAdmin(eventId);
13+
const { updateEvent, isLoading: loadingUpdate } = useUpdateEvent(t, eventId);
1114

12-
console.log("dataaa", data);
1315
const handleSubmit = (data: EventFormType) => {
14-
// createMutation.mutate(data);
16+
updateEvent(data);
1517
console.log(data);
1618
};
1719

@@ -25,7 +27,7 @@ const AdminEventUpdatePage = ({ eventId }: { eventId: string }) => {
2527
{isLoading ? (
2628
<Loader />
2729
) : (
28-
<EventForm onSubmit={handleSubmit} mode="edit" isLoading={false} initialData={data?.data} />
30+
<EventForm onSubmit={handleSubmit} mode="edit" isLoading={loadingUpdate} initialData={data?.data} />
2931
)}
3032
</section>
3133
);

src/lib/image.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const getFileNameFromUrl = (url: string): string => {
2+
return url.substring(url.lastIndexOf("/") + 1);
3+
};

src/locales/en.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,13 @@
309309
"create-success": "Event created successfully!",
310310
"create-success-title": "Success!",
311311
"create-success-description": "You can now view it in your event list or continue managing other events",
312+
"update-success": "Event updated successfully!",
313+
"update-success-title": "Success!",
314+
"update-success-description": "Your event has been updated successfully",
312315
"create-error-title": "Error",
313316
"create-error-description": "Failed to create event. Please try again.",
317+
"update-error-title": "Error",
318+
"update-error-description": "Failed to update event. Please try again.",
314319
"upload-error-title": "Upload Error",
315320
"upload-error-description": "Failed to upload image. Please try again.",
316321
"back-to-list": "Back to List",

src/locales/id.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,13 @@
309309
"create-success": "Event berhasil dibuat!",
310310
"create-success-title": "Berhasil!",
311311
"create-success-description": "Anda sekarang dapat melihatnya di daftar event atau melanjutkan mengelola event lainnya",
312+
"update-success": "Event berhasil diperbarui!",
313+
"update-success-title": "Berhasil!",
314+
"update-success-description": "Event Anda telah berhasil diperbarui",
312315
"create-error-title": "Error",
313316
"create-error-description": "Gagal membuat event. Silakan coba lagi.",
317+
"update-error-title": "Error",
318+
"update-error-description": "Gagal memperbarui event. Silakan coba lagi.",
314319
"upload-error-title": "Error Upload",
315320
"upload-error-description": "Gagal mengupload gambar. Silakan coba lagi.",
316321
"back-to-list": "Kembali ke Daftar",

src/services/uploads/index.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export const uploadsService = {
55
/**
66
* API to Uploads an image file to the server
77
* @param image - The image file to upload
8-
* @param type - The type of the image
98
* @param category - The category for the image
109
*/
1110
uploadImage(image: string | File, category: string): Promise<HttpResponse<{ file_name: string }>> {
@@ -19,7 +18,6 @@ export const uploadsService = {
1918
/**
2019
* API to Uploads an image file to the server
2120
* @param image - The image file to upload
22-
* @param type - The type of the image
2321
* @param category - The category for the image
2422
*/
2523
uploadImageAdmin(image: string | File | undefined, category: string): Promise<HttpResponse<{ file_name: string }>> {
@@ -30,4 +28,22 @@ export const uploadsService = {
3028
headers: { "Content-Type": "multipart/form-data" },
3129
});
3230
},
31+
/**
32+
* API to update an image file to the server
33+
* @param image - The image file to upload
34+
* @param file_name - The file name of the image
35+
* @param category - The category for the image
36+
*/
37+
updateImageAdmin(
38+
image: string | File | undefined,
39+
category: string,
40+
file_name: string
41+
): Promise<HttpResponse<{ file_name: string }>> {
42+
const data = new FormData();
43+
data.append("image", image as File);
44+
data.append("category", category);
45+
return fetcher.put(`/admin/images/${file_name}`, data, {
46+
headers: { "Content-Type": "multipart/form-data" },
47+
});
48+
},
3349
};

0 commit comments

Comments
 (0)