fix: list tenant in register and add api save and bookmark
This commit is contained in:
parent
0029826927
commit
e21ff675a9
|
|
@ -1,5 +1,5 @@
|
||||||
"use client";
|
"use client";
|
||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
// import { close, error, loading } from "@/config/swal";
|
// import { close, error, loading } from "@/config/swal";
|
||||||
|
|
@ -9,6 +9,13 @@ import withReactContent from "sweetalert2-react-content";
|
||||||
import { Input } from "../ui/input";
|
import { Input } from "../ui/input";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import { Label } from "../ui/label";
|
import { Label } from "../ui/label";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
|
||||||
// import { saveActivity } from "@/service/activity-log";
|
// import { saveActivity } from "@/service/activity-log";
|
||||||
|
|
||||||
|
|
@ -17,47 +24,25 @@ import { error } from "console";
|
||||||
import { EyeFilledIcon, EyeSlashFilledIcon } from "../icons";
|
import { EyeFilledIcon, EyeSlashFilledIcon } from "../icons";
|
||||||
import { RadioGroup, RadioGroupItem } from "../ui/radio-group";
|
import { RadioGroup, RadioGroupItem } from "../ui/radio-group";
|
||||||
import { createUser, registerTenant } from "@/service/auth";
|
import { createUser, registerTenant } from "@/service/auth";
|
||||||
|
import { getTenantList } from "@/service/tenant";
|
||||||
|
|
||||||
|
interface Tenant {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default function SignUp() {
|
export default function SignUp() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
const [isVisibleSetup, setIsVisibleSetup] = useState([false, 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 toggleVisibility = () => setIsVisible(!isVisible);
|
||||||
const [needOtp, setNeedOtp] = useState(false);
|
|
||||||
const [isFirstLogin, setFirstLogin] = useState(false);
|
|
||||||
const [otpValue, setOtpValue] = useState("");
|
const [otpValue, setOtpValue] = useState("");
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [accessData, setAccessData] = useState<any>();
|
|
||||||
const [profile, setProfile] = useState<any>();
|
|
||||||
const [isValidEmail, setIsValidEmail] = useState(false);
|
|
||||||
const [isResetPassword, setIsResetPassword] = useState(false);
|
|
||||||
const [checkUsernameValue, setCheckUsernameValue] = useState("");
|
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const [fullname, setFullname] = useState("");
|
const [fullname, setFullname] = useState("");
|
||||||
const [userLevelId, setUserLevelId] = useState("");
|
const [userLevelId, setUserLevelId] = useState("");
|
||||||
const [userRoleId, setUserRoleId] = 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 [step, setStep] = useState<"login" | "otp">("login");
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [role, setRole] = useState("umum");
|
const [role, setRole] = useState("umum");
|
||||||
|
|
@ -82,7 +67,16 @@ export default function SignUp() {
|
||||||
useState("");
|
useState("");
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [formErrors, setFormErrors] = useState<any>({});
|
const [formErrors, setFormErrors] = useState<any>({});
|
||||||
|
const [tenantList, setTenantList] = useState<Tenant[]>([]);
|
||||||
|
|
||||||
|
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) => {
|
const handleSendOtp = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
|
@ -178,8 +172,8 @@ export default function SignUp() {
|
||||||
lastEducation: "",
|
lastEducation: "",
|
||||||
password,
|
password,
|
||||||
phoneNumber: "",
|
phoneNumber: "",
|
||||||
userLevelId: parseInt(userLevelId),
|
userLevelId: 1,
|
||||||
userRoleId: 3,
|
userRoleId: 4,
|
||||||
username: autoUsername,
|
username: autoUsername,
|
||||||
workType: "",
|
workType: "",
|
||||||
};
|
};
|
||||||
|
|
@ -296,7 +290,6 @@ export default function SignUp() {
|
||||||
icon: "success",
|
icon: "success",
|
||||||
confirmButtonText: "OK",
|
confirmButtonText: "OK",
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// Redirect to login page or dashboard
|
|
||||||
router.push("/auth");
|
router.push("/auth");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -416,13 +409,13 @@ export default function SignUp() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Email */}
|
{/* Email */}
|
||||||
<Input
|
{/* <Input
|
||||||
type="email"
|
type="email"
|
||||||
required
|
required
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
value={email}
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
/>
|
/> */}
|
||||||
|
|
||||||
{/* Password */}
|
{/* Password */}
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|
@ -448,7 +441,7 @@ export default function SignUp() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Level dan Role */}
|
{/* Level dan Role */}
|
||||||
<select
|
{/* <select
|
||||||
required
|
required
|
||||||
className="w-full border border-gray-300 rounded-md p-2 text-sm"
|
className="w-full border border-gray-300 rounded-md p-2 text-sm"
|
||||||
value={userLevelId}
|
value={userLevelId}
|
||||||
|
|
@ -460,9 +453,9 @@ export default function SignUp() {
|
||||||
<option value="3">Satker</option>
|
<option value="3">Satker</option>
|
||||||
<option value="4">Polres</option>
|
<option value="4">Polres</option>
|
||||||
<option value="5">Polsek</option>
|
<option value="5">Polsek</option>
|
||||||
</select>
|
</select> */}
|
||||||
|
|
||||||
<select
|
{/* <select
|
||||||
required
|
required
|
||||||
className="w-full border border-gray-300 rounded-md p-2 text-sm"
|
className="w-full border border-gray-300 rounded-md p-2 text-sm"
|
||||||
value={userRoleId}
|
value={userRoleId}
|
||||||
|
|
@ -472,7 +465,7 @@ export default function SignUp() {
|
||||||
<option value="1">Admin</option>
|
<option value="1">Admin</option>
|
||||||
<option value="2">Editor</option>
|
<option value="2">Editor</option>
|
||||||
<option value="3">User</option>
|
<option value="3">User</option>
|
||||||
</select>
|
</select> */}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -697,6 +690,34 @@ export default function SignUp() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
<Select
|
||||||
|
value={namaTenant}
|
||||||
|
onValueChange={(value) => setNamaTenant(value)}
|
||||||
|
>
|
||||||
|
<SelectTrigger
|
||||||
|
className={`w-full ${
|
||||||
|
formErrors.namaTenant ? "border-red-500" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<SelectValue placeholder="Pilih Tenant" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{tenantList.map((tenant) => (
|
||||||
|
<SelectItem key={tenant.id} value={tenant.id}>
|
||||||
|
{tenant.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
{formErrors.namaTenant && (
|
||||||
|
<p className="text-red-500 text-xs mt-1">
|
||||||
|
{formErrors.namaTenant}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
required
|
required
|
||||||
|
|
@ -712,7 +733,7 @@ export default function SignUp() {
|
||||||
{formErrors.namaTenant}
|
{formErrors.namaTenant}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Input
|
<Input
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,16 @@ import Swal from "sweetalert2";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import { listData, listArticles } from "@/service/landing/landing";
|
import { listData, listArticles } from "@/service/landing/landing";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
import { toggleBookmark } from "@/service/content";
|
import { toggleBookmark, getBookmarkSummaryForUser } from "@/service/content";
|
||||||
|
|
||||||
export default function Header() {
|
export default function Header() {
|
||||||
const [data, setData] = useState<any[]>([]);
|
const [data, setData] = useState<any[]>([]);
|
||||||
|
const [bookmarkedIds, setBookmarkedIds] = useState<Set<number>>(new Set());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
// 🔹 Gunakan API artikel baru
|
// 🔹 Ambil artikel
|
||||||
const response = await listArticles(
|
const response = await listArticles(
|
||||||
1,
|
1,
|
||||||
5,
|
5,
|
||||||
|
|
@ -27,6 +28,8 @@ export default function Header() {
|
||||||
"createdAt"
|
"createdAt"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let articlesData: any[] = [];
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
// fallback ke API lama
|
// fallback ke API lama
|
||||||
const fallbackResponse = await listData(
|
const fallbackResponse = await listData(
|
||||||
|
|
@ -40,13 +43,13 @@ export default function Header() {
|
||||||
"",
|
"",
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
const content = fallbackResponse?.data?.data?.content || [];
|
articlesData = fallbackResponse?.data?.data?.content || [];
|
||||||
setData(content);
|
} else {
|
||||||
return;
|
articlesData = response?.data?.data || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const articlesData = response?.data?.data || [];
|
// 🔹 Transform agar seragam
|
||||||
const transformedData = articlesData.map((article: any) => ({
|
const transformed = articlesData.map((article: any) => ({
|
||||||
id: article.id,
|
id: article.id,
|
||||||
title: article.title,
|
title: article.title,
|
||||||
categoryName:
|
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<number>();
|
||||||
|
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<number>(
|
||||||
|
(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) {
|
} catch (error) {
|
||||||
console.error("Gagal memuat data:", 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();
|
fetchData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Simpan setiap kali state berubah
|
||||||
|
useEffect(() => {
|
||||||
|
if (bookmarkedIds.size > 0) {
|
||||||
|
localStorage.setItem(
|
||||||
|
"bookmarkedIds",
|
||||||
|
JSON.stringify(Array.from(bookmarkedIds))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [bookmarkedIds]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="max-w-[1350px] mx-auto px-4">
|
<section className="max-w-[1350px] mx-auto px-4">
|
||||||
<div className="flex flex-col lg:flex-row gap-6 py-6">
|
<div className="flex flex-col lg:flex-row gap-6 py-6">
|
||||||
{data.length > 0 && <Card item={data[0]} isBig />}
|
{data.length > 0 && (
|
||||||
|
<Card
|
||||||
|
item={data[0]}
|
||||||
|
isBig
|
||||||
|
isInitiallyBookmarked={bookmarkedIds.has(Number(data[0].id))}
|
||||||
|
onSaved={(id) =>
|
||||||
|
setBookmarkedIds((prev) => new Set([...prev, Number(id)]))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 w-full">
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 w-full">
|
||||||
{data.slice(1, 5).map((item) => (
|
{data.slice(1, 5).map((item) => (
|
||||||
<Card key={item.id} item={item} />
|
<Card
|
||||||
|
key={item.id}
|
||||||
|
item={item}
|
||||||
|
isInitiallyBookmarked={bookmarkedIds.has(Number(item.id))}
|
||||||
|
onSaved={(id) =>
|
||||||
|
setBookmarkedIds((prev) => new Set([...prev, Number(id)]))
|
||||||
|
}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -120,14 +162,25 @@ export default function Header() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================
|
function Card({
|
||||||
// 🔹 CARD COMPONENT
|
item,
|
||||||
// ========================
|
isBig = false,
|
||||||
function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
isInitiallyBookmarked = false,
|
||||||
|
onSaved,
|
||||||
|
}: {
|
||||||
|
item: any;
|
||||||
|
isBig?: boolean;
|
||||||
|
isInitiallyBookmarked?: boolean;
|
||||||
|
onSaved?: (id: number) => void;
|
||||||
|
}) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
const [isBookmarked, setIsBookmarked] = useState(false);
|
const [isBookmarked, setIsBookmarked] = useState(isInitiallyBookmarked);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsBookmarked(isInitiallyBookmarked);
|
||||||
|
}, [isInitiallyBookmarked]);
|
||||||
|
|
||||||
const getLink = () => {
|
const getLink = () => {
|
||||||
switch (item?.fileTypeId) {
|
switch (item?.fileTypeId) {
|
||||||
|
|
@ -144,28 +197,23 @@ function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ✅ Fungsi simpan bookmark
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
const roleId = Number(getCookiesDecrypt("urie"));
|
const roleId = Number(getCookiesDecrypt("urie"));
|
||||||
|
|
||||||
// 🔸 Cek apakah user login (roleId ada & valid)
|
if (!roleId || isNaN(roleId)) {
|
||||||
if (!roleId || roleId === 0 || isNaN(roleId)) {
|
|
||||||
MySwal.fire({
|
MySwal.fire({
|
||||||
icon: "warning",
|
icon: "warning",
|
||||||
title: "Login diperlukan",
|
title: "Login diperlukan",
|
||||||
text: "Silakan login terlebih dahulu untuk menyimpan artikel.",
|
text: "Silakan login terlebih dahulu untuk menyimpan artikel.",
|
||||||
confirmButtonText: "Login Sekarang",
|
confirmButtonText: "Login Sekarang",
|
||||||
confirmButtonColor: "#d33",
|
confirmButtonColor: "#d33",
|
||||||
}).then(() => {
|
}).then(() => router.push("/auth"));
|
||||||
router.push("/auth");
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsSaving(true);
|
setIsSaving(true);
|
||||||
const res = await toggleBookmark(item.id);
|
const res = await toggleBookmark(item.id);
|
||||||
console.log("Toggle Bookmark Response:", res);
|
|
||||||
|
|
||||||
if (res?.error) {
|
if (res?.error) {
|
||||||
MySwal.fire({
|
MySwal.fire({
|
||||||
|
|
@ -176,6 +224,17 @@ function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setIsBookmarked(true);
|
setIsBookmarked(true);
|
||||||
|
onSaved?.(item.id);
|
||||||
|
|
||||||
|
// 🔹 Simpan ke localStorage
|
||||||
|
const saved = localStorage.getItem("bookmarkedIds");
|
||||||
|
const newSet = new Set<number>(saved ? JSON.parse(saved) : []);
|
||||||
|
newSet.add(Number(item.id));
|
||||||
|
localStorage.setItem(
|
||||||
|
"bookmarkedIds",
|
||||||
|
JSON.stringify(Array.from(newSet))
|
||||||
|
);
|
||||||
|
|
||||||
MySwal.fire({
|
MySwal.fire({
|
||||||
icon: "success",
|
icon: "success",
|
||||||
title: "Berhasil",
|
title: "Berhasil",
|
||||||
|
|
@ -265,11 +324,10 @@ function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ✅ Tombol Save/Disable */}
|
|
||||||
<button
|
<button
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
disabled={isSaving || isBookmarked}
|
disabled={isSaving || isBookmarked}
|
||||||
className={`text-sm px-3 py-1 rounded-md transition-all duration-200 cursor-pointer ${
|
className={`text-sm px-3 py-1 rounded-md transition-all duration-200 ${
|
||||||
isBookmarked
|
isBookmarked
|
||||||
? "bg-gray-400 text-white cursor-not-allowed"
|
? "bg-gray-400 text-white cursor-not-allowed"
|
||||||
: "bg-[#F60100] text-white hover:bg-[#c90000]"
|
: "bg-[#F60100] text-white hover:bg-[#c90000]"
|
||||||
|
|
@ -283,220 +341,3 @@ function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// "use client";
|
|
||||||
// import Image from "next/image";
|
|
||||||
// import Link from "next/link";
|
|
||||||
// import { ThumbsUp, ThumbsDown } from "lucide-react";
|
|
||||||
// import { useEffect, useState } from "react";
|
|
||||||
// import {
|
|
||||||
// listData,
|
|
||||||
// listArticles,
|
|
||||||
// } from "@/service/landing/landing";
|
|
||||||
|
|
||||||
// export default function Header() {
|
|
||||||
// const [data, setData] = useState<any[]>([]);
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// const fetchData = async () => {
|
|
||||||
// try {
|
|
||||||
// // Use new Articles API
|
|
||||||
// const response = await listArticles(
|
|
||||||
// 1,
|
|
||||||
// 5,
|
|
||||||
// undefined,
|
|
||||||
// undefined,
|
|
||||||
// undefined,
|
|
||||||
// "createdAt"
|
|
||||||
// );
|
|
||||||
// console.log("Articles API response:", response);
|
|
||||||
|
|
||||||
// if (response?.error) {
|
|
||||||
// console.error("Articles API failed, falling back to old API");
|
|
||||||
// // Fallback to old API
|
|
||||||
// const fallbackResponse = await listData(
|
|
||||||
// "",
|
|
||||||
// "",
|
|
||||||
// "",
|
|
||||||
// 5,
|
|
||||||
// 0,
|
|
||||||
// "createdAt",
|
|
||||||
// "",
|
|
||||||
// "",
|
|
||||||
// ""
|
|
||||||
// );
|
|
||||||
// const content = fallbackResponse?.data?.data?.content || [];
|
|
||||||
// setData(content);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Handle new API response structure
|
|
||||||
// const articlesData = response?.data?.data || [];
|
|
||||||
// console.log("Articles data:", articlesData);
|
|
||||||
|
|
||||||
// // Transform articles data to match old structure for backward compatibility
|
|
||||||
// const transformedData = articlesData.map((article: any) => ({
|
|
||||||
// id: article.id,
|
|
||||||
// title: article.title,
|
|
||||||
// categoryName:
|
|
||||||
// article.categoryName ||
|
|
||||||
// (article.categories && article.categories[0]?.title) ||
|
|
||||||
// "",
|
|
||||||
// createdAt: article.createdAt,
|
|
||||||
// smallThumbnailLink: article.thumbnailUrl,
|
|
||||||
// fileTypeId: article.typeId,
|
|
||||||
// label:
|
|
||||||
// article.typeId === 1
|
|
||||||
// ? "Image"
|
|
||||||
// : article.typeId === 2
|
|
||||||
// ? "Video"
|
|
||||||
// : article.typeId === 3
|
|
||||||
// ? "Text"
|
|
||||||
// : article.typeId === 4
|
|
||||||
// ? "Audio"
|
|
||||||
// : "",
|
|
||||||
// ...article,
|
|
||||||
// }));
|
|
||||||
|
|
||||||
// setData(transformedData);
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Gagal memuat data:", error);
|
|
||||||
// // Try fallback to old API if new API fails
|
|
||||||
// try {
|
|
||||||
// const fallbackResponse = await listData(
|
|
||||||
// "",
|
|
||||||
// "",
|
|
||||||
// "",
|
|
||||||
// 5,
|
|
||||||
// 0,
|
|
||||||
// "createdAt",
|
|
||||||
// "",
|
|
||||||
// "",
|
|
||||||
// ""
|
|
||||||
// );
|
|
||||||
// const content = fallbackResponse?.data?.data?.content || [];
|
|
||||||
// setData(content);
|
|
||||||
// } catch (fallbackError) {
|
|
||||||
// console.error("Fallback API also failed:", fallbackError);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// fetchData();
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <section className="max-w-[1350px] mx-auto px-4">
|
|
||||||
// <div className="flex flex-col lg:flex-row gap-6 py-6">
|
|
||||||
// {data.length > 0 && <Card item={data[0]} isBig />}
|
|
||||||
|
|
||||||
// <div className="grid grid-cols-1 sm:grid-cols-2 gap-4 w-full">
|
|
||||||
// {data.slice(1, 5).map((item) => (
|
|
||||||
// <Card key={item.id} item={item} />
|
|
||||||
// ))}
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div className="relative w-full h-48 sm:h-64 md:h-80 lg:h-[460px] mt-4 rounded-xl">
|
|
||||||
// <Image
|
|
||||||
// src={"/PPS.png"}
|
|
||||||
// alt={"pps"}
|
|
||||||
// fill
|
|
||||||
// className="object-cover rounded-xl"
|
|
||||||
// />
|
|
||||||
// </div>
|
|
||||||
// </section>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
|
||||||
// const getLink = () => {
|
|
||||||
// switch (item?.fileTypeId) {
|
|
||||||
// case 1:
|
|
||||||
// return `/content/image/detail/${item?.id}`;
|
|
||||||
// case 2:
|
|
||||||
// return `/content/video/detail/${item?.id}`;
|
|
||||||
// case 3:
|
|
||||||
// return `/content/text/detail/${item?.id}`;
|
|
||||||
// case 4:
|
|
||||||
// return `/content/audio/detail/${item?.id}`;
|
|
||||||
// default:
|
|
||||||
// return "#"; // fallback kalau type tidak dikenali
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// return (
|
|
||||||
// <div>
|
|
||||||
// <div
|
|
||||||
// className={`rounded-xl overflow-hidden shadow hover:shadow-lg transition-all bg-white ${
|
|
||||||
// isBig
|
|
||||||
// ? "w-full lg:max-w-[670px] lg:min-h-[680px]"
|
|
||||||
// : "w-full h-[350px] md:h-[330px]"
|
|
||||||
// }`}
|
|
||||||
// >
|
|
||||||
// <div
|
|
||||||
// className={`relative ${
|
|
||||||
// isBig ? "aspect-[3/2] lg:h-[525px]" : "aspect-video"
|
|
||||||
// } w-full`}
|
|
||||||
// >
|
|
||||||
// <Link href={getLink()}>
|
|
||||||
// {" "}
|
|
||||||
// <Image
|
|
||||||
// src={item.smallThumbnailLink || "/contributor.png"}
|
|
||||||
// alt={item.title}
|
|
||||||
// fill
|
|
||||||
// className="object-cover"
|
|
||||||
// />
|
|
||||||
// </Link>
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div className="p-4 space-y-2">
|
|
||||||
// <div className="flex items-center gap-2 text-xs font-semibold flex-wrap">
|
|
||||||
// <span className="bg-emerald-600 text-white px-2 py-0.5 rounded">
|
|
||||||
// {item.tenantName}
|
|
||||||
// </span>
|
|
||||||
// <span className="text-orange-600">
|
|
||||||
// {" "}
|
|
||||||
// {item.categories?.map((cat: any) => cat.title).join(", ")}
|
|
||||||
// </span>
|
|
||||||
// </div>
|
|
||||||
// <div className="text-xs text-gray-500">
|
|
||||||
// {new Date(item.createdAt)
|
|
||||||
// .toLocaleString("id-ID", {
|
|
||||||
// day: "2-digit",
|
|
||||||
// month: "short",
|
|
||||||
// year: "numeric",
|
|
||||||
// hour: "2-digit",
|
|
||||||
// minute: "2-digit",
|
|
||||||
// hour12: false,
|
|
||||||
// timeZone: "Asia/Jakarta",
|
|
||||||
// })
|
|
||||||
// .replace(".", ":")}{" "}
|
|
||||||
// WIB
|
|
||||||
// </div>
|
|
||||||
// <Link href={getLink()}>
|
|
||||||
// {" "}
|
|
||||||
// <h3 className="text-sm font-semibold leading-snug line-clamp-2">
|
|
||||||
// {item.title}
|
|
||||||
// </h3>
|
|
||||||
// </Link>
|
|
||||||
|
|
||||||
// <div className="flex justify-between items-center pt-2">
|
|
||||||
// <div className="flex gap-2 text-gray-500">
|
|
||||||
// <ThumbsUp
|
|
||||||
// size={18}
|
|
||||||
// className="cursor-pointer hover:text-[#F60100]"
|
|
||||||
// />
|
|
||||||
// <ThumbsDown
|
|
||||||
// size={18}
|
|
||||||
// className="cursor-pointer hover:text-red-600"
|
|
||||||
// />
|
|
||||||
// </div>
|
|
||||||
// <button className="text-sm bg-[#F60100] text-white px-3 py-1 rounded-md hover:bg-[#F60100]">
|
|
||||||
// Save
|
|
||||||
// </button>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,14 @@ import { ThumbsUp, ThumbsDown } from "lucide-react";
|
||||||
import { Card } from "../ui/card";
|
import { Card } from "../ui/card";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { listData, listArticles } from "@/service/landing/landing";
|
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, SwiperSlide } from "swiper/react";
|
||||||
import "swiper/css";
|
import "swiper/css";
|
||||||
import "swiper/css/navigation";
|
import "swiper/css/navigation";
|
||||||
import { Navigation } from "swiper/modules";
|
import { Navigation } from "swiper/modules";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
import withReactContent from "sweetalert2-react-content";
|
||||||
|
|
||||||
// Format tanggal
|
// Format tanggal
|
||||||
function formatTanggal(dateString: string) {
|
function formatTanggal(dateString: string) {
|
||||||
|
|
@ -33,7 +37,9 @@ function formatTanggal(dateString: string) {
|
||||||
export default function MediaUpdate() {
|
export default function MediaUpdate() {
|
||||||
const [tab, setTab] = useState<"latest" | "popular">("latest");
|
const [tab, setTab] = useState<"latest" | "popular">("latest");
|
||||||
const [dataToRender, setDataToRender] = useState<any[]>([]);
|
const [dataToRender, setDataToRender] = useState<any[]>([]);
|
||||||
|
const [bookmarkedIds, setBookmarkedIds] = useState<Set<number>>(new Set());
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
const MySwal = withReactContent(Swal);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData(tab);
|
fetchData(tab);
|
||||||
|
|
@ -43,21 +49,20 @@ export default function MediaUpdate() {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// Use new Articles API
|
// 🔹 Ambil data artikel
|
||||||
const response = await listArticles(
|
const response = await listArticles(
|
||||||
1,
|
1,
|
||||||
20,
|
20,
|
||||||
1, // typeId for images
|
1, // typeId = image
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
section === "latest" ? "createdAt" : "viewCount"
|
section === "latest" ? "createdAt" : "viewCount"
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("Media Update Articles API response:", response);
|
let articlesData: any[] = [];
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
console.error("Articles API failed, falling back to old API");
|
console.error("Articles API failed, fallback ke old API");
|
||||||
// Fallback to old API
|
|
||||||
const fallbackRes = await listData(
|
const fallbackRes = await listData(
|
||||||
"1",
|
"1",
|
||||||
"",
|
"",
|
||||||
|
|
@ -69,49 +74,132 @@ export default function MediaUpdate() {
|
||||||
"",
|
"",
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
setDataToRender(fallbackRes?.data?.data?.content || []);
|
articlesData = fallbackRes?.data?.data?.content || [];
|
||||||
return;
|
} else {
|
||||||
|
articlesData = response?.data?.data || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle new API response structure
|
// 🔹 Normalisasi struktur data
|
||||||
const articlesData = response?.data?.data || [];
|
|
||||||
|
|
||||||
// Transform articles data to match old structure for backward compatibility
|
|
||||||
const transformedData = articlesData.map((article: any) => ({
|
const transformedData = articlesData.map((article: any) => ({
|
||||||
id: article.id,
|
id: article.id,
|
||||||
title: article.title,
|
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,
|
createdAt: article.createdAt,
|
||||||
smallThumbnailLink: article.thumbnailUrl,
|
smallThumbnailLink: article.thumbnailUrl,
|
||||||
label: article.typeId === 1 ? "Image" : article.typeId === 2 ? "Video" : article.typeId === 3 ? "Text" : article.typeId === 4 ? "Audio" : "",
|
label:
|
||||||
...article
|
article.typeId === 1
|
||||||
|
? "Image"
|
||||||
|
: article.typeId === 2
|
||||||
|
? "Video"
|
||||||
|
: article.typeId === 3
|
||||||
|
? "Text"
|
||||||
|
: article.typeId === 4
|
||||||
|
? "Audio"
|
||||||
|
: "",
|
||||||
|
...article,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setDataToRender(transformedData);
|
setDataToRender(transformedData);
|
||||||
|
|
||||||
|
// 🔹 Sinkronisasi bookmark
|
||||||
|
const roleId = Number(getCookiesDecrypt("urie"));
|
||||||
|
if (roleId && !isNaN(roleId)) {
|
||||||
|
const savedLocal = localStorage.getItem("bookmarkedIds");
|
||||||
|
let localSet = new Set<number>();
|
||||||
|
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<number>(
|
||||||
|
(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) {
|
} catch (err) {
|
||||||
console.error("Gagal memuat data:", 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 {
|
} finally {
|
||||||
setLoading(false);
|
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 (
|
return (
|
||||||
<section className="bg-white px-4 py-10 border max-w-[1350px] mx-auto rounded-md border-[#CDD5DF] my-10">
|
<section className="bg-white px-4 py-10 border max-w-[1350px] mx-auto rounded-md border-[#CDD5DF] my-10">
|
||||||
<div className="max-w-screen-xl mx-auto">
|
<div className="max-w-screen-xl mx-auto">
|
||||||
|
|
@ -188,11 +276,17 @@ export default function MediaUpdate() {
|
||||||
<ThumbsDown className="w-4 h-4 cursor-pointer" />
|
<ThumbsDown className="w-4 h-4 cursor-pointer" />
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
|
onClick={() => handleSave(item.id)}
|
||||||
|
disabled={bookmarkedIds.has(Number(item.id))}
|
||||||
variant="default"
|
variant="default"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="text-white bg-blue-600 rounded px-4"
|
className={`rounded px-4 ${
|
||||||
|
bookmarkedIds.has(Number(item.id))
|
||||||
|
? "bg-gray-400 cursor-not-allowed text-white"
|
||||||
|
: "bg-blue-600 text-white hover:bg-blue-700"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
Save
|
{bookmarkedIds.has(Number(item.id)) ? "Saved" : "Save"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -223,3 +317,229 @@ export default function MediaUpdate() {
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "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<any[]>([]);
|
||||||
|
// 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 (
|
||||||
|
// <section className="bg-white px-4 py-10 border max-w-[1350px] mx-auto rounded-md border-[#CDD5DF] my-10">
|
||||||
|
// <div className="max-w-screen-xl mx-auto">
|
||||||
|
// <h2 className="text-2xl font-semibold text-center mb-6">
|
||||||
|
// Media Update
|
||||||
|
// </h2>
|
||||||
|
|
||||||
|
// {/* Tab */}
|
||||||
|
// <div className="flex justify-center mb-8 bg-white">
|
||||||
|
// <Card className="bg-[#FFFFFF] rounded-xl flex flex-row p-3 gap-2">
|
||||||
|
// <button
|
||||||
|
// onClick={() => setTab("latest")}
|
||||||
|
// className={`px-5 py-2 rounded-lg text-sm font-medium ${
|
||||||
|
// tab === "latest" ? "bg-[#C6A455] text-white" : "text-[#C6A455]"
|
||||||
|
// }`}
|
||||||
|
// >
|
||||||
|
// Konten Terbaru
|
||||||
|
// </button>
|
||||||
|
// <button
|
||||||
|
// onClick={() => setTab("popular")}
|
||||||
|
// className={`px-5 py-2 rounded-lg text-sm font-medium ${
|
||||||
|
// tab === "popular" ? "bg-[#C6A455] text-white" : "text-[#C6A455]"
|
||||||
|
// }`}
|
||||||
|
// >
|
||||||
|
// Konten Terpopuler
|
||||||
|
// </button>
|
||||||
|
// </Card>
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// {/* Slider */}
|
||||||
|
// {loading ? (
|
||||||
|
// <p className="text-center">Loading...</p>
|
||||||
|
// ) : (
|
||||||
|
// <Swiper
|
||||||
|
// modules={[Navigation]}
|
||||||
|
// navigation
|
||||||
|
// spaceBetween={20}
|
||||||
|
// slidesPerView={1}
|
||||||
|
// breakpoints={{
|
||||||
|
// 640: { slidesPerView: 2 },
|
||||||
|
// 1024: { slidesPerView: 4 },
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// {dataToRender.map((item) => (
|
||||||
|
// <SwiperSlide key={item.id}>
|
||||||
|
// <div className="rounded-xl shadow-md overflow-hidden bg-white">
|
||||||
|
// <div className="w-full h-[204px] relative">
|
||||||
|
// <Image
|
||||||
|
// src={item.smallThumbnailLink || "/placeholder.png"}
|
||||||
|
// alt={item.title || "No Title"}
|
||||||
|
// fill
|
||||||
|
// className="object-cover"
|
||||||
|
// />
|
||||||
|
// </div>
|
||||||
|
// <div className="p-3">
|
||||||
|
// <div className="flex gap-2 mb-1">
|
||||||
|
// <span className="text-xs text-white px-2 py-0.5 rounded bg-blue-600">
|
||||||
|
// {item.category || "Tanpa Kategori"}
|
||||||
|
// </span>
|
||||||
|
// <span className="text-xs font-medium text-[#b3882e]">
|
||||||
|
// {item.label || ""}
|
||||||
|
// </span>
|
||||||
|
// </div>
|
||||||
|
// <p className="text-xs text-gray-500 mb-1">
|
||||||
|
// {formatTanggal(item.createdAt)}
|
||||||
|
// </p>
|
||||||
|
// <p className="text-sm font-semibold mb-3 line-clamp-2">
|
||||||
|
// {item.title}
|
||||||
|
// </p>
|
||||||
|
|
||||||
|
// <div className="flex items-center justify-between">
|
||||||
|
// <div className="flex gap-2 text-gray-600">
|
||||||
|
// <ThumbsUp className="w-4 h-4 cursor-pointer" />
|
||||||
|
// <ThumbsDown className="w-4 h-4 cursor-pointer" />
|
||||||
|
// </div>
|
||||||
|
// <Button
|
||||||
|
// variant="default"
|
||||||
|
// size="sm"
|
||||||
|
// className="text-white bg-blue-600 rounded px-4"
|
||||||
|
// >
|
||||||
|
// Save
|
||||||
|
// </Button>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </SwiperSlide>
|
||||||
|
// ))}
|
||||||
|
// </Swiper>
|
||||||
|
// )}
|
||||||
|
|
||||||
|
// {/* Lihat lebih banyak */}
|
||||||
|
// <div className="text-center mt-10">
|
||||||
|
// <Link
|
||||||
|
// href={
|
||||||
|
// tab === "latest"
|
||||||
|
// ? "https://mediahub.polri.go.id/"
|
||||||
|
// : "https://tribratanews.polri.go.id/"
|
||||||
|
// }
|
||||||
|
// >
|
||||||
|
// <Button
|
||||||
|
// size={"lg"}
|
||||||
|
// className="text-[#b3882e] bg-transparent border border-[#b3882e] px-6 py-2 rounded-s-sm text-sm font-medium hover:bg-[#b3882e]/10 transition"
|
||||||
|
// >
|
||||||
|
// Lihat Lebih Banyak
|
||||||
|
// </Button>
|
||||||
|
// </Link>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </section>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import PublicationKlFilter from "./publication-filter";
|
import PublicationKlFilter from "./publication-filter";
|
||||||
import { Button } from "@/components/ui/button";
|
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;
|
const itemsPerPage = 9;
|
||||||
|
|
||||||
|
|
@ -22,43 +23,37 @@ export default function ForYouCardGrid({
|
||||||
selectedCategory,
|
selectedCategory,
|
||||||
title,
|
title,
|
||||||
refresh,
|
refresh,
|
||||||
|
|
||||||
isInstitute = false,
|
isInstitute = false,
|
||||||
instituteId = "",
|
instituteId = "",
|
||||||
}: PublicationCardGridProps) {
|
}: PublicationCardGridProps) {
|
||||||
const [currentPage, setCurrentPage] = useState(0);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [contentImage, setContentImage] = useState([]);
|
const [contentImage, setContentImage] = useState<any[]>([]);
|
||||||
const [totalPages, setTotalPages] = useState(1);
|
const [totalPages, setTotalPages] = useState(1);
|
||||||
const [categoryFilter] = useState([]);
|
const [categoryFilter] = useState<string[]>([]);
|
||||||
const [formatFilter] = useState([]);
|
const [formatFilter] = useState<string[]>([]);
|
||||||
const [sortBy] = useState();
|
const [sortBy] = useState<string>("createdAt");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getDataImage();
|
getDataBookmark();
|
||||||
}, [currentPage, selectedCategory, title, refresh]);
|
}, [currentPage, selectedCategory, title, refresh]);
|
||||||
|
|
||||||
async function getDataImage() {
|
async function getDataBookmark() {
|
||||||
const filter =
|
console.log("📡 Fetching bookmark list...");
|
||||||
categoryFilter?.length > 0
|
|
||||||
? categoryFilter?.sort().join(",")
|
|
||||||
: selectedCategory || "";
|
|
||||||
|
|
||||||
const name = title ?? "";
|
try {
|
||||||
const format = formatFilter?.join(",") ?? "";
|
const response = await getBookmarksForUser(1, 12, "desc", "createdAt");
|
||||||
|
console.log("✅ Bookmark response:", response);
|
||||||
|
|
||||||
const response = await mediaWishlist(
|
const bookmarks =
|
||||||
"1",
|
response?.data?.data?.content || response?.data?.data || [];
|
||||||
isInstitute ? instituteId : "",
|
const totalPage = response?.data?.data?.totalPages || 1;
|
||||||
name,
|
|
||||||
filter,
|
|
||||||
"12",
|
|
||||||
currentPage,
|
|
||||||
sortBy,
|
|
||||||
format
|
|
||||||
);
|
|
||||||
|
|
||||||
setTotalPages(response?.data?.data?.totalPages || 1);
|
setContentImage(bookmarks);
|
||||||
setContentImage(response?.data?.data?.content || []);
|
setTotalPages(totalPage);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Gagal memuat bookmark:", error);
|
||||||
|
setContentImage([]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const goToPage = (page: number) => {
|
const goToPage = (page: number) => {
|
||||||
|
|
@ -71,31 +66,39 @@ export default function ForYouCardGrid({
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{contentImage.length === 0 ? (
|
{contentImage.length === 0 ? (
|
||||||
<div className="col-span-3 text-center text-muted-foreground">
|
<div className="col-span-3 text-center text-muted-foreground">
|
||||||
Tidak ada konten ditemukan.
|
Tidak ada artikel tersimpan.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
contentImage.map((item: any, idx: number) => (
|
contentImage.map((item: any, idx: number) => {
|
||||||
|
const article = item.article || item; // jaga-jaga kalau API return nested
|
||||||
|
return (
|
||||||
<PublicationKlFilter
|
<PublicationKlFilter
|
||||||
key={item.id}
|
key={idx}
|
||||||
id={item.id} // ✅ tambahkan ini
|
id={article.id || item.articleId}
|
||||||
image={item.mediaUpload?.smallThumbnailLink}
|
image={
|
||||||
label={item.mediaType?.name ?? "UNKNOWN"}
|
article.thumbnailUrl ||
|
||||||
category={item.tags ?? "-"}
|
article.mediaUpload?.smallThumbnailLink ||
|
||||||
date={new Date(item?.mediaUpload?.createdAt).toLocaleString(
|
"/contributor.png"
|
||||||
"id-ID",
|
}
|
||||||
{
|
label={article.typeName || article.mediaType?.name || "Artikel"}
|
||||||
|
category={
|
||||||
|
article.categories?.map((c: any) => c.title).join(", ") ||
|
||||||
|
article.tags ||
|
||||||
|
"-"
|
||||||
|
}
|
||||||
|
date={new Date(article.createdAt).toLocaleString("id-ID", {
|
||||||
day: "2-digit",
|
day: "2-digit",
|
||||||
month: "short",
|
month: "short",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
hour: "2-digit",
|
hour: "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
timeZoneName: "short",
|
timeZoneName: "short",
|
||||||
}
|
})}
|
||||||
)}
|
title={article.title}
|
||||||
title={item?.mediaUpload?.title}
|
description={article.description || ""}
|
||||||
description={""} // Optional: Tambahkan jika tersedia dari API
|
|
||||||
/>
|
/>
|
||||||
))
|
);
|
||||||
|
})
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -115,3 +118,121 @@ export default function ForYouCardGrid({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "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 (
|
||||||
|
// <div className="space-y-6">
|
||||||
|
// {/* Grid Card */}
|
||||||
|
// <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
// {contentImage.length === 0 ? (
|
||||||
|
// <div className="col-span-3 text-center text-muted-foreground">
|
||||||
|
// Tidak ada konten ditemukan.
|
||||||
|
// </div>
|
||||||
|
// ) : (
|
||||||
|
// contentImage.map((item: any, idx: number) => (
|
||||||
|
// <PublicationKlFilter
|
||||||
|
// key={item.id}
|
||||||
|
// id={item.id} // ✅ tambahkan ini
|
||||||
|
// image={item.mediaUpload?.smallThumbnailLink}
|
||||||
|
// label={item.mediaType?.name ?? "UNKNOWN"}
|
||||||
|
// category={item.tags ?? "-"}
|
||||||
|
// date={new Date(item?.mediaUpload?.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
|
||||||
|
// />
|
||||||
|
// ))
|
||||||
|
// )}
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// {/* Pagination */}
|
||||||
|
// <div className="flex justify-center gap-2">
|
||||||
|
// {Array.from({ length: totalPages }, (_, i) => (
|
||||||
|
// <Button
|
||||||
|
// key={i}
|
||||||
|
// variant={currentPage === i + 1 ? "default" : "outline"}
|
||||||
|
// size="sm"
|
||||||
|
// onClick={() => goToPage(i + 1)}
|
||||||
|
// >
|
||||||
|
// {i + 1}
|
||||||
|
// </Button>
|
||||||
|
// ))}
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
|
||||||
|
|
@ -214,3 +214,5 @@ export async function registerTenant(data: any) {
|
||||||
const url = "clients/with-user";
|
const url = "clients/with-user";
|
||||||
return httpPost(url, data);
|
return httpPost(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,10 @@ export async function uploadThumbnail(id: any, data: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New Articles API - Upload Article Files
|
// 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 url = `article-files/${articleId}`;
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "multipart/form-data",
|
"Content-Type": "multipart/form-data",
|
||||||
|
|
@ -228,7 +231,10 @@ export async function uploadArticleFiles(articleId: string | number, files: Form
|
||||||
}
|
}
|
||||||
|
|
||||||
// New Articles API - Upload Article Thumbnail
|
// 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 url = `articles/thumbnail/${articleId}`;
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "multipart/form-data",
|
"Content-Type": "multipart/form-data",
|
||||||
|
|
@ -237,7 +243,10 @@ export async function uploadArticleThumbnail(articleId: string | number, thumbna
|
||||||
}
|
}
|
||||||
|
|
||||||
// New Articles API - Get Article Categories
|
// 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}`;
|
const url = `article-categories?page=${page}&limit=${limit}`;
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
@ -373,7 +382,8 @@ export async function listDataTeksNew(
|
||||||
) {
|
) {
|
||||||
// Convert old parameters to new API format
|
// Convert old parameters to new API format
|
||||||
const categoryId = categoryFilter ? Number(categoryFilter) : undefined;
|
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(
|
return await listArticles(
|
||||||
page + 1, // API expects 1-based page
|
page + 1, // API expects 1-based page
|
||||||
|
|
@ -398,3 +408,13 @@ export async function toggleBookmark(articleId: string | number) {
|
||||||
const url = `/bookmarks/toggle/${articleId}`;
|
const url = `/bookmarks/toggle/${articleId}`;
|
||||||
return httpPostInterceptor(url);
|
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);
|
||||||
|
}
|
||||||
|
|
@ -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) {
|
export async function checkWishlistStatus(mediaId: any) {
|
||||||
return await httpGetInterceptor(`/media/wishlist/status?mediaId=${mediaId}`);
|
return await httpGetInterceptor(`/media/wishlist/status?mediaId=${mediaId}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,5 +14,9 @@ export async function getUserLevelDetail(id: number) {
|
||||||
const url = `user-levels/${id}`;
|
const url = `user-levels/${id}`;
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
export async function getTenantList() {
|
||||||
|
const url = `clients?limit=1000`;
|
||||||
|
return httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue