From e21ff675a9198edf726bc61df9fbb0550dcb7fbf Mon Sep 17 00:00:00 2001 From: Sabda Yagra Date: Fri, 10 Oct 2025 23:30:17 +0700 Subject: [PATCH] fix: list tenant in register and add api save and bookmark --- components/form/sign-up.tsx | 99 +++--- components/landing-page/header.tsx | 357 ++++++-------------- components/landing-page/media-update.tsx | 402 ++++++++++++++++++++--- components/main/for-you-card.tsx | 209 +++++++++--- service/auth.ts | 2 + service/content.ts | 34 +- service/landing/landing.ts | 32 +- service/tenant.ts | 4 + 8 files changed, 748 insertions(+), 391 deletions(-) diff --git a/components/form/sign-up.tsx b/components/form/sign-up.tsx index 65fb26f..a0e44dd 100644 --- a/components/form/sign-up.tsx +++ b/components/form/sign-up.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import Link from "next/link"; import Cookies from "js-cookie"; // import { close, error, loading } from "@/config/swal"; @@ -9,6 +9,13 @@ import withReactContent from "sweetalert2-react-content"; import { Input } from "../ui/input"; import { Button } from "../ui/button"; import { Label } from "../ui/label"; +import { + Select, + SelectTrigger, + SelectValue, + SelectContent, + SelectItem, +} from "@/components/ui/select"; // import { saveActivity } from "@/service/activity-log"; @@ -17,47 +24,25 @@ import { error } from "console"; import { EyeFilledIcon, EyeSlashFilledIcon } from "../icons"; import { RadioGroup, RadioGroupItem } from "../ui/radio-group"; import { createUser, registerTenant } from "@/service/auth"; +import { getTenantList } from "@/service/tenant"; + +interface Tenant { + id: string; + name: string; +} export default function SignUp() { const router = useRouter(); const [isVisible, setIsVisible] = useState(false); const [isVisibleSetup, setIsVisibleSetup] = useState([false, false]); - const [oldEmail, setOldEmail] = useState(""); - const [newEmail, setNewEmail] = useState(""); - const [passwordSetup, setPasswordSetup] = useState(""); - const [confPasswordSetup, setConfPasswordSetup] = useState(""); - const toggleVisibility = () => setIsVisible(!isVisible); - const [needOtp, setNeedOtp] = useState(false); - const [isFirstLogin, setFirstLogin] = useState(false); const [otpValue, setOtpValue] = useState(""); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); - const [accessData, setAccessData] = useState(); - const [profile, setProfile] = useState(); - const [isValidEmail, setIsValidEmail] = useState(false); - const [isResetPassword, setIsResetPassword] = useState(false); - const [checkUsernameValue, setCheckUsernameValue] = useState(""); const MySwal = withReactContent(Swal); const [fullname, setFullname] = useState(""); const [userLevelId, setUserLevelId] = useState(""); const [userRoleId, setUserRoleId] = useState(""); - const setValUsername = (e: any) => { - const uname = e.replaceAll(/[^\w.-]/g, ""); - setUsername(uname.toLowerCase()); - }; - - const onSubmit = () => { - // Simpan userId dummy ke cookie - Cookies.set("userId", "3"); - - // (Opsional) Simpan juga data lainnya jika dibutuhkan - // Cookies.set("username", username); - - // Redirect ke halaman dashboard atau homepage - router.push("/"); // Ganti dengan path sesuai kebutuhan - }; - const [step, setStep] = useState<"login" | "otp">("login"); const [email, setEmail] = useState(""); const [role, setRole] = useState("umum"); @@ -82,7 +67,16 @@ export default function SignUp() { useState(""); const [isLoading, setIsLoading] = useState(false); const [formErrors, setFormErrors] = useState({}); + const [tenantList, setTenantList] = useState([]); + useEffect(() => { + getTenant(); + }, []); + const getTenant = async () => { + const res = await getTenantList(); + setTenantList(res.data.data); + console.log("LLLLLL", res.data.data); + }; const handleSendOtp = async (e: React.FormEvent) => { e.preventDefault(); @@ -178,8 +172,8 @@ export default function SignUp() { lastEducation: "", password, phoneNumber: "", - userLevelId: parseInt(userLevelId), - userRoleId: 3, + userLevelId: 1, + userRoleId: 4, username: autoUsername, workType: "", }; @@ -296,7 +290,6 @@ export default function SignUp() { icon: "success", confirmButtonText: "OK", }).then(() => { - // Redirect to login page or dashboard router.push("/auth"); }); } @@ -416,13 +409,13 @@ export default function SignUp() { /> {/* Email */} - setEmail(e.target.value)} - /> + /> */} {/* Password */}
@@ -448,7 +441,7 @@ export default function SignUp() {
{/* Level dan Role */} - + */} - + */} )} @@ -697,6 +690,34 @@ export default function SignUp() {
+ + + {formErrors.namaTenant && ( +

+ {formErrors.namaTenant} +

+ )} +
+ + {/*
)} -
+ */}
([]); + const [bookmarkedIds, setBookmarkedIds] = useState>(new Set()); useEffect(() => { const fetchData = async () => { try { - // 🔹 Gunakan API artikel baru + // 🔹 Ambil artikel const response = await listArticles( 1, 5, @@ -27,6 +28,8 @@ export default function Header() { "createdAt" ); + let articlesData: any[] = []; + if (response?.error) { // fallback ke API lama const fallbackResponse = await listData( @@ -40,13 +43,13 @@ export default function Header() { "", "" ); - const content = fallbackResponse?.data?.data?.content || []; - setData(content); - return; + articlesData = fallbackResponse?.data?.data?.content || []; + } else { + articlesData = response?.data?.data || []; } - const articlesData = response?.data?.data || []; - const transformedData = articlesData.map((article: any) => ({ + // 🔹 Transform agar seragam + const transformed = articlesData.map((article: any) => ({ id: article.id, title: article.title, categoryName: @@ -70,40 +73,79 @@ export default function Header() { : "", })); - setData(transformedData); + setData(transformed); + + const roleId = Number(getCookiesDecrypt("urie")); + if (roleId && !isNaN(roleId)) { + const saved = localStorage.getItem("bookmarkedIds"); + let localSet = new Set(); + if (saved) { + localSet = new Set(JSON.parse(saved)); + setBookmarkedIds(localSet); + } + + const res = await getBookmarkSummaryForUser(); + const bookmarks = + res?.data?.data?.recentBookmarks || + res?.data?.data?.bookmarks || + res?.data?.data || + []; + + const ids = new Set( + (Array.isArray(bookmarks) ? bookmarks : []) + .map((b: any) => Number(b.articleId ?? b.id ?? b.article?.id)) + .filter((x) => !isNaN(x)) + ); + + const merged = new Set([...localSet, ...ids]); + setBookmarkedIds(merged); + localStorage.setItem( + "bookmarkedIds", + JSON.stringify(Array.from(merged)) + ); + } } catch (error) { console.error("Gagal memuat data:", error); - try { - const fallbackResponse = await listData( - "", - "", - "", - 5, - 0, - "createdAt", - "", - "", - "" - ); - const content = fallbackResponse?.data?.data?.content || []; - setData(content); - } catch (fallbackError) { - console.error("Fallback API juga gagal:", fallbackError); - } } }; fetchData(); }, []); + // Simpan setiap kali state berubah + useEffect(() => { + if (bookmarkedIds.size > 0) { + localStorage.setItem( + "bookmarkedIds", + JSON.stringify(Array.from(bookmarkedIds)) + ); + } + }, [bookmarkedIds]); + return (
- {data.length > 0 && } + {data.length > 0 && ( + + setBookmarkedIds((prev) => new Set([...prev, Number(id)])) + } + /> + )}
{data.slice(1, 5).map((item) => ( - + + setBookmarkedIds((prev) => new Set([...prev, Number(id)])) + } + /> ))}
@@ -120,14 +162,25 @@ export default function Header() { ); } -// ======================== -// 🔹 CARD COMPONENT -// ======================== -function Card({ item, isBig = false }: { item: any; isBig?: boolean }) { +function Card({ + item, + isBig = false, + isInitiallyBookmarked = false, + onSaved, +}: { + item: any; + isBig?: boolean; + isInitiallyBookmarked?: boolean; + onSaved?: (id: number) => void; +}) { const router = useRouter(); const MySwal = withReactContent(Swal); const [isSaving, setIsSaving] = useState(false); - const [isBookmarked, setIsBookmarked] = useState(false); + const [isBookmarked, setIsBookmarked] = useState(isInitiallyBookmarked); + + useEffect(() => { + setIsBookmarked(isInitiallyBookmarked); + }, [isInitiallyBookmarked]); const getLink = () => { switch (item?.fileTypeId) { @@ -144,28 +197,23 @@ function Card({ item, isBig = false }: { item: any; isBig?: boolean }) { } }; - // ✅ Fungsi simpan bookmark const handleSave = async () => { const roleId = Number(getCookiesDecrypt("urie")); - // 🔸 Cek apakah user login (roleId ada & valid) - if (!roleId || roleId === 0 || isNaN(roleId)) { + if (!roleId || isNaN(roleId)) { MySwal.fire({ icon: "warning", title: "Login diperlukan", text: "Silakan login terlebih dahulu untuk menyimpan artikel.", confirmButtonText: "Login Sekarang", confirmButtonColor: "#d33", - }).then(() => { - router.push("/auth"); - }); + }).then(() => router.push("/auth")); return; } try { setIsSaving(true); const res = await toggleBookmark(item.id); - console.log("Toggle Bookmark Response:", res); if (res?.error) { MySwal.fire({ @@ -176,6 +224,17 @@ function Card({ item, isBig = false }: { item: any; isBig?: boolean }) { }); } else { setIsBookmarked(true); + onSaved?.(item.id); + + // 🔹 Simpan ke localStorage + const saved = localStorage.getItem("bookmarkedIds"); + const newSet = new Set(saved ? JSON.parse(saved) : []); + newSet.add(Number(item.id)); + localStorage.setItem( + "bookmarkedIds", + JSON.stringify(Array.from(newSet)) + ); + MySwal.fire({ icon: "success", title: "Berhasil", @@ -265,11 +324,10 @@ function Card({ item, isBig = false }: { item: any; isBig?: boolean }) { />
- {/* ✅ Tombol Save/Disable */} -// -// -// -// -// ); -// } diff --git a/components/landing-page/media-update.tsx b/components/landing-page/media-update.tsx index f76d8a0..ee2b6e1 100644 --- a/components/landing-page/media-update.tsx +++ b/components/landing-page/media-update.tsx @@ -7,10 +7,14 @@ import { ThumbsUp, ThumbsDown } from "lucide-react"; import { Card } from "../ui/card"; import Link from "next/link"; import { listData, listArticles } from "@/service/landing/landing"; +import { toggleBookmark, getBookmarkSummaryForUser } from "@/service/content"; +import { getCookiesDecrypt } from "@/lib/utils"; import { Swiper, SwiperSlide } from "swiper/react"; import "swiper/css"; import "swiper/css/navigation"; import { Navigation } from "swiper/modules"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; // Format tanggal function formatTanggal(dateString: string) { @@ -33,7 +37,9 @@ function formatTanggal(dateString: string) { export default function MediaUpdate() { const [tab, setTab] = useState<"latest" | "popular">("latest"); const [dataToRender, setDataToRender] = useState([]); + const [bookmarkedIds, setBookmarkedIds] = useState>(new Set()); const [loading, setLoading] = useState(true); + const MySwal = withReactContent(Swal); useEffect(() => { fetchData(tab); @@ -42,22 +48,21 @@ export default function MediaUpdate() { async function fetchData(section: "latest" | "popular") { try { setLoading(true); - - // Use new Articles API + + // 🔹 Ambil data artikel const response = await listArticles( - 1, - 20, - 1, // typeId for images - undefined, - undefined, + 1, + 20, + 1, // typeId = image + undefined, + undefined, section === "latest" ? "createdAt" : "viewCount" ); - - console.log("Media Update Articles API response:", response); - + + let articlesData: any[] = []; + if (response?.error) { - console.error("Articles API failed, falling back to old API"); - // Fallback to old API + console.error("Articles API failed, fallback ke old API"); const fallbackRes = await listData( "1", "", @@ -69,49 +74,132 @@ export default function MediaUpdate() { "", "" ); - setDataToRender(fallbackRes?.data?.data?.content || []); - return; + articlesData = fallbackRes?.data?.data?.content || []; + } else { + articlesData = response?.data?.data || []; } - // Handle new API response structure - const articlesData = response?.data?.data || []; - - // Transform articles data to match old structure for backward compatibility + // 🔹 Normalisasi struktur data const transformedData = articlesData.map((article: any) => ({ id: article.id, title: article.title, - category: article.categoryName || (article.categories && article.categories[0]?.title) || "Tanpa Kategori", + category: + article.categoryName || + (article.categories && article.categories[0]?.title) || + "Tanpa Kategori", createdAt: article.createdAt, smallThumbnailLink: article.thumbnailUrl, - label: article.typeId === 1 ? "Image" : article.typeId === 2 ? "Video" : article.typeId === 3 ? "Text" : article.typeId === 4 ? "Audio" : "", - ...article + label: + article.typeId === 1 + ? "Image" + : article.typeId === 2 + ? "Video" + : article.typeId === 3 + ? "Text" + : article.typeId === 4 + ? "Audio" + : "", + ...article, })); - + setDataToRender(transformedData); + + // 🔹 Sinkronisasi bookmark + const roleId = Number(getCookiesDecrypt("urie")); + if (roleId && !isNaN(roleId)) { + const savedLocal = localStorage.getItem("bookmarkedIds"); + let localSet = new Set(); + if (savedLocal) { + localSet = new Set(JSON.parse(savedLocal)); + setBookmarkedIds(localSet); + } + + const res = await getBookmarkSummaryForUser(); + const bookmarks = + res?.data?.data?.recentBookmarks || + res?.data?.data?.bookmarks || + res?.data?.data || + []; + + const ids = new Set( + (Array.isArray(bookmarks) ? bookmarks : []) + .map((b: any) => Number(b.articleId ?? b.id ?? b.article?.id)) + .filter((x) => !isNaN(x)) + ); + + const merged = new Set([...localSet, ...ids]); + setBookmarkedIds(merged); + localStorage.setItem( + "bookmarkedIds", + JSON.stringify(Array.from(merged)) + ); + } } catch (err) { console.error("Gagal memuat data:", err); - // Try fallback to old API if new API fails - try { - const fallbackRes = await listData( - "1", - "", - "", - 20, - 0, - section === "latest" ? "createdAt" : "clickCount", - "", - "", - "" - ); - setDataToRender(fallbackRes?.data?.data?.content || []); - } catch (fallbackError) { - console.error("Fallback API also failed:", fallbackError); - } } finally { setLoading(false); } } + // 🔹 Simpan perubahan bookmark ke localStorage + useEffect(() => { + if (bookmarkedIds.size > 0) { + localStorage.setItem( + "bookmarkedIds", + JSON.stringify(Array.from(bookmarkedIds)) + ); + } + }, [bookmarkedIds]); + + const handleSave = async (id: number) => { + const roleId = Number(getCookiesDecrypt("urie")); + if (!roleId || isNaN(roleId)) { + MySwal.fire({ + icon: "warning", + title: "Login diperlukan", + text: "Silakan login terlebih dahulu untuk menyimpan artikel.", + confirmButtonText: "Login Sekarang", + confirmButtonColor: "#d33", + }); + return; + } + + try { + const res = await toggleBookmark(id); + if (res?.error) { + MySwal.fire({ + icon: "error", + title: "Gagal", + text: "Gagal menyimpan artikel.", + confirmButtonColor: "#d33", + }); + } else { + const updated = new Set(bookmarkedIds); + updated.add(Number(id)); + setBookmarkedIds(updated); + localStorage.setItem( + "bookmarkedIds", + JSON.stringify(Array.from(updated)) + ); + + MySwal.fire({ + icon: "success", + title: "Berhasil", + text: "Artikel berhasil disimpan ke bookmark.", + timer: 1500, + showConfirmButton: false, + }); + } + } catch (err) { + console.error("Error saving bookmark:", err); + MySwal.fire({ + icon: "error", + title: "Kesalahan", + text: "Terjadi kesalahan saat menyimpan artikel.", + }); + } + }; + return (
@@ -188,11 +276,17 @@ export default function MediaUpdate() {
@@ -223,3 +317,229 @@ export default function MediaUpdate() {
); } + +// "use client"; + +// import { useState, useEffect } from "react"; +// import Image from "next/image"; +// import { Button } from "@/components/ui/button"; +// import { ThumbsUp, ThumbsDown } from "lucide-react"; +// import { Card } from "../ui/card"; +// import Link from "next/link"; +// import { listData, listArticles } from "@/service/landing/landing"; +// import { Swiper, SwiperSlide } from "swiper/react"; +// import "swiper/css"; +// import "swiper/css/navigation"; +// import { Navigation } from "swiper/modules"; + +// // Format tanggal +// function formatTanggal(dateString: string) { +// if (!dateString) return ""; +// return ( +// new Date(dateString) +// .toLocaleString("id-ID", { +// day: "2-digit", +// month: "short", +// year: "numeric", +// hour: "2-digit", +// minute: "2-digit", +// hour12: false, +// timeZone: "Asia/Jakarta", +// }) +// .replace(/\./g, ":") + " WIB" +// ); +// } + +// export default function MediaUpdate() { +// const [tab, setTab] = useState<"latest" | "popular">("latest"); +// const [dataToRender, setDataToRender] = useState([]); +// const [loading, setLoading] = useState(true); + +// useEffect(() => { +// fetchData(tab); +// }, [tab]); + +// async function fetchData(section: "latest" | "popular") { +// try { +// setLoading(true); + +// // Use new Articles API +// const response = await listArticles( +// 1, +// 20, +// 1, // typeId for images +// undefined, +// undefined, +// section === "latest" ? "createdAt" : "viewCount" +// ); + +// console.log("Media Update Articles API response:", response); + +// if (response?.error) { +// console.error("Articles API failed, falling back to old API"); +// // Fallback to old API +// const fallbackRes = await listData( +// "1", +// "", +// "", +// 20, +// 0, +// section === "latest" ? "createdAt" : "clickCount", +// "", +// "", +// "" +// ); +// setDataToRender(fallbackRes?.data?.data?.content || []); +// return; +// } + +// // Handle new API response structure +// const articlesData = response?.data?.data || []; + +// // Transform articles data to match old structure for backward compatibility +// const transformedData = articlesData.map((article: any) => ({ +// id: article.id, +// title: article.title, +// category: article.categoryName || (article.categories && article.categories[0]?.title) || "Tanpa Kategori", +// createdAt: article.createdAt, +// smallThumbnailLink: article.thumbnailUrl, +// label: article.typeId === 1 ? "Image" : article.typeId === 2 ? "Video" : article.typeId === 3 ? "Text" : article.typeId === 4 ? "Audio" : "", +// ...article +// })); + +// setDataToRender(transformedData); +// } catch (err) { +// console.error("Gagal memuat data:", err); +// // Try fallback to old API if new API fails +// try { +// const fallbackRes = await listData( +// "1", +// "", +// "", +// 20, +// 0, +// section === "latest" ? "createdAt" : "clickCount", +// "", +// "", +// "" +// ); +// setDataToRender(fallbackRes?.data?.data?.content || []); +// } catch (fallbackError) { +// console.error("Fallback API also failed:", fallbackError); +// } +// } finally { +// setLoading(false); +// } +// } + +// return ( +//
+//
+//

+// Media Update +//

+ +// {/* Tab */} +//
+// +// +// +// +//
+ +// {/* Slider */} +// {loading ? ( +//

Loading...

+// ) : ( +// +// {dataToRender.map((item) => ( +// +//
+//
+// {item.title +//
+//
+//
+// +// {item.category || "Tanpa Kategori"} +// +// +// {item.label || ""} +// +//
+//

+// {formatTanggal(item.createdAt)} +//

+//

+// {item.title} +//

+ +//
+//
+// +// +//
+// +//
+//
+//
+//
+// ))} +//
+// )} + +// {/* Lihat lebih banyak */} +//
+// +// +// +//
+//
+//
+// ); +// } diff --git a/components/main/for-you-card.tsx b/components/main/for-you-card.tsx index 54f6c1b..fedf13a 100644 --- a/components/main/for-you-card.tsx +++ b/components/main/for-you-card.tsx @@ -3,7 +3,8 @@ import { useEffect, useState } from "react"; import PublicationKlFilter from "./publication-filter"; import { Button } from "@/components/ui/button"; -import { mediaWishlist } from "@/service/landing/landing"; +import { getCookiesDecrypt } from "@/lib/utils"; +import { getBookmarksByUserId, getBookmarksForUser } from "@/service/landing/landing"; const itemsPerPage = 9; @@ -22,43 +23,37 @@ export default function ForYouCardGrid({ selectedCategory, title, refresh, - isInstitute = false, instituteId = "", }: PublicationCardGridProps) { - const [currentPage, setCurrentPage] = useState(0); - const [contentImage, setContentImage] = useState([]); + const [currentPage, setCurrentPage] = useState(1); + const [contentImage, setContentImage] = useState([]); const [totalPages, setTotalPages] = useState(1); - const [categoryFilter] = useState([]); - const [formatFilter] = useState([]); - const [sortBy] = useState(); + const [categoryFilter] = useState([]); + const [formatFilter] = useState([]); + const [sortBy] = useState("createdAt"); useEffect(() => { - getDataImage(); + getDataBookmark(); }, [currentPage, selectedCategory, title, refresh]); - async function getDataImage() { - const filter = - categoryFilter?.length > 0 - ? categoryFilter?.sort().join(",") - : selectedCategory || ""; + async function getDataBookmark() { + console.log("📡 Fetching bookmark list..."); - const name = title ?? ""; - const format = formatFilter?.join(",") ?? ""; + try { + const response = await getBookmarksForUser(1, 12, "desc", "createdAt"); + console.log("✅ Bookmark response:", response); - const response = await mediaWishlist( - "1", - isInstitute ? instituteId : "", - name, - filter, - "12", - currentPage, - sortBy, - format - ); + const bookmarks = + response?.data?.data?.content || response?.data?.data || []; + const totalPage = response?.data?.data?.totalPages || 1; - setTotalPages(response?.data?.data?.totalPages || 1); - setContentImage(response?.data?.data?.content || []); + setContentImage(bookmarks); + setTotalPages(totalPage); + } catch (error) { + console.error("❌ Gagal memuat bookmark:", error); + setContentImage([]); + } } const goToPage = (page: number) => { @@ -71,31 +66,39 @@ export default function ForYouCardGrid({
{contentImage.length === 0 ? (
- Tidak ada konten ditemukan. + Tidak ada artikel tersimpan.
) : ( - contentImage.map((item: any, idx: number) => ( - { + const article = item.article || item; // jaga-jaga kalau API return nested + return ( + c.title).join(", ") || + article.tags || + "-" + } + date={new Date(article.createdAt).toLocaleString("id-ID", { day: "2-digit", month: "short", year: "numeric", hour: "2-digit", minute: "2-digit", timeZoneName: "short", - } - )} - title={item?.mediaUpload?.title} - description={""} // Optional: Tambahkan jika tersedia dari API - /> - )) + })} + title={article.title} + description={article.description || ""} + /> + ); + }) )}
@@ -115,3 +118,121 @@ export default function ForYouCardGrid({ ); } + +// "use client"; + +// import { useEffect, useState } from "react"; +// import PublicationKlFilter from "./publication-filter"; +// import { Button } from "@/components/ui/button"; +// import { mediaWishlist } from "@/service/landing/landing"; + +// const itemsPerPage = 9; + +// type PublicationCardGridProps = { +// selectedCategory: string; +// title?: string; +// refresh?: boolean; +// categoryFilter?: string[]; +// formatFilter?: string[]; +// isInstitute?: boolean; +// instituteId?: string; +// sortBy?: string; +// }; + +// export default function ForYouCardGrid({ +// selectedCategory, +// title, +// refresh, + +// isInstitute = false, +// instituteId = "", +// }: PublicationCardGridProps) { +// const [currentPage, setCurrentPage] = useState(0); +// const [contentImage, setContentImage] = useState([]); +// const [totalPages, setTotalPages] = useState(1); +// const [categoryFilter] = useState([]); +// const [formatFilter] = useState([]); +// const [sortBy] = useState(); + +// useEffect(() => { +// getDataImage(); +// }, [currentPage, selectedCategory, title, refresh]); + +// async function getDataImage() { +// const filter = +// categoryFilter?.length > 0 +// ? categoryFilter?.sort().join(",") +// : selectedCategory || ""; + +// const name = title ?? ""; +// const format = formatFilter?.join(",") ?? ""; + +// const response = await mediaWishlist( +// "1", +// isInstitute ? instituteId : "", +// name, +// filter, +// "12", +// currentPage, +// sortBy, +// format +// ); + +// setTotalPages(response?.data?.data?.totalPages || 1); +// setContentImage(response?.data?.data?.content || []); +// } + +// const goToPage = (page: number) => { +// setCurrentPage(page); +// }; + +// return ( +//
+// {/* Grid Card */} +//
+// {contentImage.length === 0 ? ( +//
+// Tidak ada konten ditemukan. +//
+// ) : ( +// contentImage.map((item: any, idx: number) => ( +// +// )) +// )} +//
+ +// {/* Pagination */} +//
+// {Array.from({ length: totalPages }, (_, i) => ( +// +// ))} +//
+//
+// ); +// } diff --git a/service/auth.ts b/service/auth.ts index 3d43738..a36e8d3 100644 --- a/service/auth.ts +++ b/service/auth.ts @@ -214,3 +214,5 @@ export async function registerTenant(data: any) { const url = "clients/with-user"; return httpPost(url, data); } + + diff --git a/service/content.ts b/service/content.ts index 607bc1d..bb87f81 100644 --- a/service/content.ts +++ b/service/content.ts @@ -219,7 +219,10 @@ export async function uploadThumbnail(id: any, data: any) { } // New Articles API - Upload Article Files -export async function uploadArticleFiles(articleId: string | number, files: FormData) { +export async function uploadArticleFiles( + articleId: string | number, + files: FormData +) { const url = `article-files/${articleId}`; const headers = { "Content-Type": "multipart/form-data", @@ -228,7 +231,10 @@ export async function uploadArticleFiles(articleId: string | number, files: Form } // New Articles API - Upload Article Thumbnail -export async function uploadArticleThumbnail(articleId: string | number, thumbnail: FormData) { +export async function uploadArticleThumbnail( + articleId: string | number, + thumbnail: FormData +) { const url = `articles/thumbnail/${articleId}`; const headers = { "Content-Type": "multipart/form-data", @@ -237,7 +243,10 @@ export async function uploadArticleThumbnail(articleId: string | number, thumbna } // New Articles API - Get Article Categories -export async function listArticleCategories(page: number = 1, limit: number = 100) { +export async function listArticleCategories( + page: number = 1, + limit: number = 100 +) { const url = `article-categories?page=${page}&limit=${limit}`; return httpGetInterceptor(url); } @@ -315,7 +324,7 @@ export async function listArticles( endDate?: string ) { let url = `articles?page=${page}&totalPage=${totalPage}`; - + // Add optional query parameters based on available filters if (title) url += `&title=${encodeURIComponent(title)}`; if (description) url += `&description=${encodeURIComponent(description)}`; @@ -330,7 +339,7 @@ export async function listArticles( if (isDraft !== undefined) url += `&isDraft=${isDraft}`; if (startDate) url += `&startDate=${startDate}`; if (endDate) url += `&endDate=${endDate}`; - + return await httpGetInterceptor(url); } @@ -373,8 +382,9 @@ export async function listDataTeksNew( ) { // Convert old parameters to new API format const categoryId = categoryFilter ? Number(categoryFilter) : undefined; - const statusId = statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined; - + const statusId = + statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined; + return await listArticles( page + 1, // API expects 1-based page Number(size), @@ -397,4 +407,14 @@ export async function listDataTeksNew( export async function toggleBookmark(articleId: string | number) { const url = `/bookmarks/toggle/${articleId}`; return httpPostInterceptor(url); +} + +export async function getBookmarkSummaryForUser() { + const url = "/bookmarks/summary"; + return await httpGetInterceptor(url); +} + +export async function deleteBookmark(id: string | number) { + const url = `/bookmarks/${id}`; + return await httpDeleteInterceptor(url); } \ No newline at end of file diff --git a/service/landing/landing.ts b/service/landing/landing.ts index e7a3055..ed6cf7b 100644 --- a/service/landing/landing.ts +++ b/service/landing/landing.ts @@ -177,12 +177,12 @@ export async function listArticles( sortBy = "createdAt" ) { let url = `articles?page=${page}&totalPage=${totalPage}&isPublish=true`; - + if (typeId !== undefined) url += `&typeId=${typeId}`; if (search) url += `&title=${encodeURIComponent(search)}`; if (categoryId) url += `&categoryId=${categoryId}`; // if (sortBy) url += `&sortBy=${sortBy}`; - + return await httpGetInterceptor(url); } @@ -241,6 +241,34 @@ export async function mediaWishlist( ); } +export async function getBookmarksByUserId( + userId: number, + articleId = "", + count = "", + limit = 10, + nextPage = "", + page = 1, + previousPage = "", + sort = "desc", + sortBy = "createdAt", + totalPage = 10 +) { + return await httpGetInterceptor( + `bookmarks/user?userId=${userId}&articleId=${articleId}&count=${count}&limit=${limit}&nextPage=${nextPage}&page=${page}&previousPage=${previousPage}&sort=${sort}&sortBy=${sortBy}&totalPage=${totalPage}` + ); +} + +export async function getBookmarksForUser( + page = 1, + limit = 10, + sort = "desc", + sortBy = "createdAt", + totalPage = 10 +) { + const url = `bookmarks/user?page=${page}&limit=${limit}&sort=${sort}&sortBy=${sortBy}&totalPage=${totalPage}`; + return await httpGetInterceptor(url); +} + export async function checkWishlistStatus(mediaId: any) { return await httpGetInterceptor(`/media/wishlist/status?mediaId=${mediaId}`); } diff --git a/service/tenant.ts b/service/tenant.ts index 2fe18b4..71fe6bd 100644 --- a/service/tenant.ts +++ b/service/tenant.ts @@ -14,5 +14,9 @@ export async function getUserLevelDetail(id: number) { const url = `user-levels/${id}`; return httpGetInterceptor(url); } +export async function getTenantList() { + const url = `clients?limit=1000`; + return httpGetInterceptor(url); +}