merge
This commit is contained in:
commit
6b10fedabf
|
|
@ -30,9 +30,6 @@ yarn-debug.log*
|
|||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env*
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ COPY package.json ./
|
|||
# Menyalin direktori ckeditor5 jika diperlukan
|
||||
COPY vendor/ckeditor5 ./vendor/ckeditor5
|
||||
|
||||
# Menyalin env
|
||||
COPY .env .env
|
||||
|
||||
# Install dependencies
|
||||
RUN pnpm install
|
||||
# RUN pnpm install --frozen-lockfile
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
import Author from "@/components/landing-page/author";
|
||||
import Footer from "@/components/landing-page/footer";
|
||||
import Header from "@/components/landing-page/header";
|
||||
import Latest from "@/components/landing-page/latest";
|
||||
import LatestandPopular from "@/components/landing-page/latest-and-popular";
|
||||
import Navbar from "@/components/landing-page/navbar";
|
||||
import News from "@/components/landing-page/news";
|
||||
import Image from "next/image";
|
||||
|
||||
export default function Home() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import type { Metadata } from "next";
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import ChunkErrorBoundary from "@/components/layout/chunk-error-boundary";
|
||||
import "@/utils/chunk-error-handler";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
|
|
@ -25,7 +27,9 @@ export default function RootLayout({
|
|||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`} suppressHydrationWarning>
|
||||
{children}
|
||||
<ChunkErrorBoundary>
|
||||
{children}
|
||||
</ChunkErrorBoundary>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import {
|
|||
saveManualContext,
|
||||
updateManualArticle,
|
||||
} from "@/service/generate-article";
|
||||
import { getUserLevels } from "@/service/user-levels/user-levels-service";
|
||||
import { getUserLevels } from "@/service/user-levels-service";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { getCategoryById } from "@/service/master-categories";
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { z } from "zod";
|
|||
import ReactSelect from "react-select";
|
||||
import makeAnimated from "react-select/animated";
|
||||
import { editMasterUsers, getDetailMasterUsers } from "@/service/master-user";
|
||||
import { getAllUserLevels } from "@/service/user-levels/user-levels-service";
|
||||
import { getAllUserLevels } from "@/service/user-levels-service";
|
||||
import { listUserRole } from "@/service/master-user-role";
|
||||
import { Card } from "../ui/card";
|
||||
import { Label } from "../ui/label";
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import ReactSelect from "react-select";
|
|||
import makeAnimated from "react-select/animated";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { createMasterUser } from "@/service/master-user";
|
||||
import { getAllUserLevels } from "@/service/user-levels/user-levels-service";
|
||||
import { getAllUserLevels } from "@/service/user-levels-service";
|
||||
import { listUserRole } from "@/service/master-user-role";
|
||||
import { Card } from "../ui/card";
|
||||
import { Input } from "../ui/input";
|
||||
|
|
|
|||
|
|
@ -78,13 +78,13 @@ export default function Login() {
|
|||
secure: true,
|
||||
sameSite: "strict",
|
||||
});
|
||||
const resActivity = await saveActivity(
|
||||
await saveActivity(
|
||||
{
|
||||
activityTypeId: 1,
|
||||
url: "https://dev.mikulnews.com/auth",
|
||||
userId: profile?.data?.data?.id,
|
||||
},
|
||||
accessData?.id_token
|
||||
response?.data?.data?.access_token
|
||||
);
|
||||
Cookies.set("profile_picture", profile?.data?.data?.profilePictureUrl, {
|
||||
expires: 1,
|
||||
|
|
|
|||
|
|
@ -250,7 +250,11 @@ export default function LatestandPopular() {
|
|||
<div key={index}>
|
||||
<div className="relative w-full aspect-video mb-3">
|
||||
<Image
|
||||
src={article.thumbnailUrl}
|
||||
src={
|
||||
articles[0]?.thumbnailUrl ||
|
||||
articles[0]?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={"article.title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
|
|
@ -407,7 +411,11 @@ export default function LatestandPopular() {
|
|||
<div key={index} className="flex gap-3">
|
||||
<div className="relative w-[120px] h-[86px] shrink-0">
|
||||
<Image
|
||||
src={article?.thumbnailUrl}
|
||||
src={
|
||||
articles[0]?.thumbnailUrl ||
|
||||
articles[0]?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={"article?.title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,104 @@
|
|||
"use client";
|
||||
|
||||
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { RefreshCw } from 'lucide-react';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
fallback?: ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
class ChunkErrorBoundary extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error): State {
|
||||
// Check if it's a chunk loading error
|
||||
if (error.name === 'ChunkLoadError' || error.message.includes('Loading chunk')) {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
return { hasError: false };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
console.error('Chunk loading error:', error, errorInfo);
|
||||
|
||||
// If it's a chunk loading error, try to reload the page
|
||||
if (error.name === 'ChunkLoadError' || error.message.includes('Loading chunk')) {
|
||||
this.setState({ hasError: true, error });
|
||||
}
|
||||
}
|
||||
|
||||
handleRetry = () => {
|
||||
// Clear the error state and reload the page
|
||||
this.setState({ hasError: false, error: undefined });
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
if (this.props.fallback) {
|
||||
return this.props.fallback;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-50 via-white to-slate-50">
|
||||
<div className="text-center p-8 max-w-md">
|
||||
<div className="mb-6">
|
||||
<div className="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<RefreshCw className="w-8 h-8 text-red-600" />
|
||||
</div>
|
||||
<h2 className="text-xl font-semibold text-gray-900 mb-2">
|
||||
Chunk Loading Error
|
||||
</h2>
|
||||
<p className="text-gray-600 mb-6">
|
||||
There was an issue loading a part of the application. This usually happens when the application has been updated.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<Button
|
||||
onClick={this.handleRetry}
|
||||
className="w-full bg-blue-600 hover:bg-blue-700 text-white"
|
||||
>
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
Reload Application
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => window.location.href = '/'}
|
||||
variant="outline"
|
||||
className="w-full"
|
||||
>
|
||||
Go to Homepage
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{process.env.NODE_ENV === 'development' && this.state.error && (
|
||||
<details className="mt-6 text-left">
|
||||
<summary className="cursor-pointer text-sm text-gray-500 hover:text-gray-700">
|
||||
Error Details (Development)
|
||||
</summary>
|
||||
<pre className="mt-2 p-3 bg-gray-100 rounded text-xs overflow-auto">
|
||||
{this.state.error.message}
|
||||
</pre>
|
||||
</details>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export default ChunkErrorBoundary;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
import { getStatisticMonthly } from "@/service/article";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { SafeReactApexChart } from "@/utils/dynamic-import";
|
||||
|
||||
type WeekData = {
|
||||
week: number;
|
||||
|
|
@ -53,9 +53,6 @@ const ApexChartColumn = (props: {
|
|||
const [seriesComment, setSeriesComment] = useState<number[]>([]);
|
||||
const [seriesView, setSeriesView] = useState<number[]>([]);
|
||||
const [seriesShare, setSeriesShare] = useState<number[]>([]);
|
||||
const ReactApexChart = dynamic(() => import("react-apexcharts"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
initFetch();
|
||||
|
|
@ -132,7 +129,7 @@ const ApexChartColumn = (props: {
|
|||
return (
|
||||
<div className="h-full">
|
||||
<div id="chart" className="h-full">
|
||||
<ReactApexChart
|
||||
<SafeReactApexChart
|
||||
options={{
|
||||
chart: {
|
||||
height: "100%",
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@ import Image from "next/image";
|
|||
import { Switch } from "@/components/ui/switch";
|
||||
import useDisclosure from "@/components/useDisclosure";
|
||||
import {
|
||||
createAdvertiseById,
|
||||
createMediaFileAdvertise,
|
||||
deleteAdvertise,
|
||||
editAdvertise,
|
||||
editAdvertiseIsActive,
|
||||
getAdvertise,
|
||||
getAdvertiseById,
|
||||
} from "@/service/advertisement";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
|
@ -226,7 +226,7 @@ export default function AdvertiseTable(props: { triggerRefresh: boolean }) {
|
|||
};
|
||||
|
||||
const openModal = async (id: number) => {
|
||||
const res = await createAdvertiseById(Number(id));
|
||||
const res = await getAdvertiseById(Number(id));
|
||||
const data = res?.data?.data;
|
||||
setValue("id", String(data?.id));
|
||||
setValue("title", data?.title);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import Cookies from "js-cookie";
|
|||
import {
|
||||
deleteArticle,
|
||||
getArticleByCategory,
|
||||
getListArticle,
|
||||
getArticlePagination,
|
||||
updateIsBannerArticle,
|
||||
} from "@/service/article";
|
||||
import {
|
||||
|
|
@ -91,9 +91,6 @@ export default function ArticleTable() {
|
|||
|
||||
useEffect(() => {
|
||||
initState();
|
||||
}, [page, showData, startDateValue, selectedCategories]);
|
||||
|
||||
useEffect(() => {
|
||||
getCategories();
|
||||
}, []);
|
||||
|
||||
|
|
@ -103,7 +100,7 @@ export default function ArticleTable() {
|
|||
setCategories(data);
|
||||
}
|
||||
|
||||
async function initState() {
|
||||
const initState = useCallback(async () => {
|
||||
loading();
|
||||
const req = {
|
||||
limit: showData,
|
||||
|
|
@ -116,11 +113,11 @@ export default function ArticleTable() {
|
|||
sort: "desc",
|
||||
sortBy: "created_at",
|
||||
};
|
||||
const res = await getListArticle(req);
|
||||
const res = await getArticlePagination(req);
|
||||
await getTableNumber(parseInt(showData), res.data?.data);
|
||||
setTotalPage(res?.data?.meta?.totalPage);
|
||||
close();
|
||||
}
|
||||
}, [page]);
|
||||
|
||||
const getTableNumber = async (limit: number, data: Article[]) => {
|
||||
if (data) {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
env: {
|
||||
MEDOLS_CLIENT_KEY: process.env.MEDOLS_CLIENT_KEY,
|
||||
},
|
||||
images: {
|
||||
domains: ["mikulnews.com", "dev.mikulnews.com"],
|
||||
},
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
// Add experimental features for better chunk handling
|
||||
experimental: {
|
||||
optimizePackageImports: ['@ckeditor/ckeditor5-react', 'react-apexcharts'],
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 154 KiB |
|
|
@ -1,5 +1,4 @@
|
|||
import { PaginationRequest } from "@/types/globals";
|
||||
import { httpGet, httpPost, httpPut } from "./http-config/axios-base-service";
|
||||
import { httpGet, httpPost } from "./http-config/http-base-services";
|
||||
|
||||
export async function saveActivity(data: any, token?: string) {
|
||||
const headers = token
|
||||
|
|
@ -11,11 +10,10 @@ export async function saveActivity(data: any, token?: string) {
|
|||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/activity-logs`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPost(pathUrl, data, headers);
|
||||
}
|
||||
|
||||
export async function getActivity() {
|
||||
const headers = { "content-type": "application/json" };
|
||||
const pathUrl = `/activity-logs/statistics`;
|
||||
return await httpGet(pathUrl, headers);
|
||||
return await httpGet(pathUrl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,68 +1,42 @@
|
|||
import {
|
||||
httpDeleteInterceptor,
|
||||
httpGet,
|
||||
httpPost,
|
||||
httpPut,
|
||||
} from "./http-config/axios-base-service";
|
||||
import Cookies from "js-cookie";
|
||||
import { httpDeleteInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services";
|
||||
import { httpGet } from "./http-config/http-base-services";
|
||||
|
||||
const token = Cookies.get("access_token");
|
||||
|
||||
export async function createAdvertise(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
const pathUrl = `/advertisement`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPostInterceptor(pathUrl, data);
|
||||
}
|
||||
export async function createMediaFileAdvertise(id: string | number, data: any) {
|
||||
const headers = {
|
||||
"content-type": "multipart/form-data",
|
||||
};
|
||||
const pathUrl = `/advertisement/upload/${id}`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPostInterceptor(pathUrl, data, headers);
|
||||
}
|
||||
|
||||
export async function getAdvertise(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/advertisement?page=${data?.page || 1}&limit=${
|
||||
data?.limit || ""
|
||||
}&placement=${data?.placement || ""}&isPublish=${data.isPublish || ""}`;
|
||||
return await httpGet(pathUrl, headers);
|
||||
const pathUrl = `/advertisement?page=${data?.page || 1}&limit=${data?.limit || ""}&placement=${data?.placement || ""}&isPublish=${data.isPublish || ""}`;
|
||||
return await httpGet(pathUrl);
|
||||
}
|
||||
|
||||
export async function createAdvertiseById(id: number) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
export async function getAdvertiseById(id: number) {
|
||||
const pathUrl = `/advertisement/${id}`;
|
||||
return await httpGet(pathUrl, headers);
|
||||
return await httpGet(pathUrl);
|
||||
}
|
||||
|
||||
export async function editAdvertise(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/advertisement/${data?.id}`;
|
||||
return await httpPut(pathUrl, headers, data);
|
||||
return await httpPutInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function editAdvertiseIsActive(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
const pathUrl = `/advertisement/publish/${data?.id}?isPublish=${data?.isActive}`;
|
||||
return await httpPut(pathUrl, headers);
|
||||
return await httpPutInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function deleteAdvertise(id: number) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/advertisement/${id}`;
|
||||
return await httpDeleteInterceptor(pathUrl, headers);
|
||||
return await httpDeleteInterceptor(pathUrl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { PaginationRequest } from "@/types/globals";
|
||||
import Cookies from "js-cookie";
|
||||
import { httpGet } from "./http-config/http-base-services";
|
||||
import { httpDeleteInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services";
|
||||
import { httpDeleteInterceptor, httpGetInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services";
|
||||
|
||||
export async function getListArticle(props: PaginationRequest) {
|
||||
const {
|
||||
|
|
@ -29,6 +28,28 @@ export async function getListArticle(props: PaginationRequest) {
|
|||
);
|
||||
}
|
||||
|
||||
export async function getArticlePagination(props: PaginationRequest) {
|
||||
const {
|
||||
page,
|
||||
limit,
|
||||
search,
|
||||
startDate,
|
||||
endDate,
|
||||
category,
|
||||
sortBy,
|
||||
sort,
|
||||
categorySlug,
|
||||
isBanner,
|
||||
} = props;
|
||||
return await httpGetInterceptor(
|
||||
`/articles?limit=${limit}&page=${page}&title=${search}&startDate=${startDate || ""}&endDate=${
|
||||
endDate || ""
|
||||
}&categoryId=${category || ""}&sortBy=${sortBy || "created_at"}&sort=${
|
||||
sort || "asc"
|
||||
}&category=${categorySlug || ""}&isBanner=${isBanner || ""}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function getTopArticles(props: PaginationRequest) {
|
||||
const { page, limit, search, startDate, endDate, isPublish, category } =
|
||||
props;
|
||||
|
|
@ -75,7 +96,7 @@ export async function deleteArticle(id: string) {
|
|||
}
|
||||
|
||||
export async function getArticleByCategory() {
|
||||
return await httpGet(`/article-categories?limit=1000`);
|
||||
return await httpGetInterceptor(`/article-categories?limit=1000`);
|
||||
}
|
||||
export async function getCategoryPagination(data: any) {
|
||||
return await httpGet(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ const baseURL = "https://dev.mikulnews.com/api";
|
|||
const axiosBaseInstance = axios.create({
|
||||
baseURL,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"X-Client-Key": "bb65b1ad-e954-4a1a-b4d0-74df5bb0b640"
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,154 +0,0 @@
|
|||
import { getCsrfToken } from "../master-user";
|
||||
import axiosInterceptorInstance from "./axios-interceptor-instance";
|
||||
import axiosBaseInstance from "./http-base-instance";
|
||||
import mediahubBaseInstance from "./mediahub-base-service";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
const defaultHeaders = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
|
||||
export async function httpPost(pathUrl: any, headers: any, data?: any) {
|
||||
const resCsrf = await getCsrfToken();
|
||||
const csrfToken = resCsrf?.data?.csrf_token;
|
||||
|
||||
const mergedHeaders = {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
...(csrfToken ? { "X-CSRF-TOKEN": csrfToken } : {}),
|
||||
};
|
||||
|
||||
const response = await axiosBaseInstance
|
||||
.post(pathUrl, data, { headers: mergedHeaders })
|
||||
.catch(function (error: any) {
|
||||
console.log(error);
|
||||
return error.response;
|
||||
});
|
||||
console.log("Response base svc : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
return {
|
||||
error: false,
|
||||
message: "success",
|
||||
data: response?.data,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
error: true,
|
||||
message: response?.data?.message || response?.data || null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function httpGet(pathUrl: any, headers: any) {
|
||||
const response = await axiosInterceptorInstance
|
||||
.get(pathUrl, { headers })
|
||||
.catch(function (error: any) {
|
||||
console.log(error);
|
||||
return error.response;
|
||||
});
|
||||
console.log("Response base svc : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
return {
|
||||
error: false,
|
||||
message: "success",
|
||||
data: response?.data,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
error: true,
|
||||
message: response?.data?.message || response?.data || null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function httpPut(pathUrl: any, headers: any, data?: any) {
|
||||
const resCsrf = await getCsrfToken();
|
||||
const csrfToken = resCsrf?.data?.csrf_token;
|
||||
|
||||
const defaultHeaders = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const mergedHeaders = {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
...(csrfToken ? { "X-CSRF-TOKEN": csrfToken } : {}),
|
||||
};
|
||||
|
||||
const response = await axiosBaseInstance
|
||||
.put(pathUrl, data, { headers: mergedHeaders })
|
||||
.catch(function (error: any) {
|
||||
console.log(error);
|
||||
return error.response;
|
||||
});
|
||||
console.log("Response base svc : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
return {
|
||||
error: false,
|
||||
message: "success",
|
||||
data: response?.data,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
error: true,
|
||||
message: response?.data?.message || response?.data || null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function httpDeleteInterceptor(pathUrl: any, headers: any) {
|
||||
const resCsrf = await getCsrfToken();
|
||||
const csrfToken = resCsrf?.data?.csrf_token;
|
||||
|
||||
const defaultHeaders = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const mergedHeaders = {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
...(csrfToken ? { "X-CSRF-TOKEN": csrfToken } : {}),
|
||||
};
|
||||
|
||||
const response = await axiosBaseInstance
|
||||
.delete(pathUrl, { headers: mergedHeaders })
|
||||
.catch((error) => error.response);
|
||||
console.log("Response interceptor : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
return {
|
||||
error: false,
|
||||
message: "success",
|
||||
data: response?.data,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
error: true,
|
||||
message: response?.data?.message || response?.data || null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function mediahubGet(pathUrl: any, headers: any) {
|
||||
const response = await mediahubBaseInstance
|
||||
.get(pathUrl, { headers })
|
||||
.catch(function (error: any) {
|
||||
console.log(error);
|
||||
return error.response;
|
||||
});
|
||||
console.log("Response base svc : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
return {
|
||||
error: false,
|
||||
message: "success",
|
||||
data: response?.data,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
error: true,
|
||||
message: response?.data?.message || response?.data || null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ const axiosInterceptorInstance = axios.create({
|
|||
baseURL,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Client-Key": process.env.MEDOLS_CLIENT_KEY
|
||||
"X-Client-Key": "bb65b1ad-e954-4a1a-b4d0-74df5bb0b640"
|
||||
},
|
||||
withCredentials: true,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
import axios from "axios";
|
||||
|
||||
const baseURL = "https://dev.mikulnews.com/api";
|
||||
|
||||
const axiosBaseInstance = axios.create({
|
||||
baseURL,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
"X-Client-Key": process.env.MEDOLS_CLIENT_KEY
|
||||
},
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
export default axiosBaseInstance;
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
import axiosBaseInstance from "./http-base-instance";
|
||||
import axiosBaseInstance from "./axios-base-instance";
|
||||
|
||||
const defaultHeaders = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Client-Key": process.env.MEDOLS_CLIENT_KEY
|
||||
"X-Client-Key": "bb65b1ad-e954-4a1a-b4d0-74df5bb0b640"
|
||||
};
|
||||
|
||||
export async function httpGet(pathUrl: any, headers?: any) {
|
||||
|
||||
export async function httpGet(pathUrl: any, headers?: any) {
|
||||
console.log("X-HEADERS : ", defaultHeaders)
|
||||
const mergedHeaders = {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
|
|
@ -33,9 +33,13 @@ export async function httpGet(pathUrl: any, headers?: any) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function httpPost(pathUrl: any, headers: any, data: any) {
|
||||
export async function httpPost(pathUrl: any, data: any, headers?: any) {
|
||||
const mergedHeaders = {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
};
|
||||
const response = await axiosBaseInstance
|
||||
.post(pathUrl, data, { headers })
|
||||
.post(pathUrl, data, { headers: mergedHeaders })
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
return error.response;
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ import { getCsrfToken } from "../master-user";
|
|||
|
||||
const defaultHeaders = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Client-Key": process.env.MEDOLS_CLIENT_KEY
|
||||
"X-Client-Key": "bb65b1ad-e954-4a1a-b4d0-74df5bb0b640"
|
||||
};
|
||||
|
||||
export async function httpGetInterceptor(pathUrl: any) {
|
||||
console.log("X-HEADERS : ", defaultHeaders)
|
||||
const response = await axiosInterceptorInstance
|
||||
.get(pathUrl)
|
||||
.get(pathUrl, { headers: defaultHeaders })
|
||||
.catch((error) => error.response);
|
||||
console.log("Response interceptor : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
|
|
@ -97,7 +98,7 @@ export async function httpPutInterceptor(pathUrl: any, data: any, headers?: any)
|
|||
}
|
||||
}
|
||||
|
||||
export async function httpDeleteInterceptor(pathUrl: any, headers: any) {
|
||||
export async function httpDeleteInterceptor(pathUrl: any, headers?: any) {
|
||||
const resCsrf = await getCsrfToken();
|
||||
const csrfToken = resCsrf?.data?.csrf_token;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
import axios from "axios";
|
||||
|
||||
const baseURL = "https://mediahub.polri.go.id/api";
|
||||
|
||||
const mediahubBaseInstance = axios.create({
|
||||
baseURL,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
export default mediahubBaseInstance;
|
||||
|
|
@ -1,75 +1,50 @@
|
|||
import { PaginationRequest } from "@/types/globals";
|
||||
import {
|
||||
httpDeleteInterceptor,
|
||||
httpGet,
|
||||
httpPost,
|
||||
httpPut,
|
||||
} from "./http-config/axios-base-service";
|
||||
import Cookies from "js-cookie";
|
||||
import { httpDeleteInterceptor, httpGetInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services";
|
||||
|
||||
const token = Cookies.get("access_token");
|
||||
|
||||
export async function createMagazine(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
const pathUrl = `/magazines`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPostInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function getListMagazine(props: PaginationRequest) {
|
||||
const { page, limit, search, startDate, endDate } = props;
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(
|
||||
return await httpGetInterceptor(
|
||||
`/magazines?limit=${limit}&page=${page}&title=${search}&startDate=${
|
||||
startDate || ""
|
||||
}&endDate=${endDate || ""}`,
|
||||
headers
|
||||
}&endDate=${endDate || ""}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function updateMagazine(id: string, data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/magazines/${id}`;
|
||||
return await httpPut(pathUrl, headers, data);
|
||||
return await httpPutInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function getMagazineById(id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`/magazines/${id}`, headers);
|
||||
return await httpGetInterceptor(`/magazines/${id}`);
|
||||
}
|
||||
|
||||
export async function deleteMagazine(id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpDeleteInterceptor(`magazines/${id}`, headers);
|
||||
return await httpDeleteInterceptor(`magazines/${id}`);
|
||||
}
|
||||
|
||||
export async function uploadMagazineFile(id: string, data: any) {
|
||||
const headers = {
|
||||
"content-type": "multipart/form-data",
|
||||
};
|
||||
return await httpPost(`/magazine-files/${id}`, headers, data);
|
||||
return await httpPostInterceptor(`/magazine-files/${id}`, data, headers);
|
||||
}
|
||||
|
||||
export async function uploadMagazineThumbnail(id: string, data: any) {
|
||||
const headers = {
|
||||
"content-type": "multipart/form-data",
|
||||
};
|
||||
return await httpPost(`/magazines/thumbnail/${id}`, headers, data);
|
||||
return await httpPostInterceptor(`/magazines/thumbnail/${id}`, data, headers);
|
||||
}
|
||||
|
||||
export async function deleteMagazineFiles(id: number) {
|
||||
const headers = {
|
||||
"content-type": "multipart/form-data",
|
||||
};
|
||||
return await httpDeleteInterceptor(`magazine-files/${id}`, headers);
|
||||
return await httpDeleteInterceptor(`magazine-files/${id}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,29 @@
|
|||
import {
|
||||
httpDeleteInterceptor,
|
||||
httpGet,
|
||||
httpPost,
|
||||
httpPut,
|
||||
} from "./http-config/axios-base-service";
|
||||
import Cookies from "js-cookie";
|
||||
import { httpDeleteInterceptor, httpGetInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services";
|
||||
|
||||
const token = Cookies.get("access_token");
|
||||
|
||||
export async function createCategory(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
const pathUrl = `/article-categories`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPostInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function updateCategory(id: string, data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/article-categories/${id}`;
|
||||
return await httpPut(pathUrl, headers, data);
|
||||
return await httpPutInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function getCategoryById(id: number) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`/article-categories/${id}`, headers);
|
||||
return await httpGetInterceptor(`/article-categories/${id}`);
|
||||
}
|
||||
|
||||
export async function deleteCategory(id: number) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpDeleteInterceptor(`article-categories/${id}`, headers);
|
||||
return await httpDeleteInterceptor(`article-categories/${id}`);
|
||||
}
|
||||
|
||||
export async function uploadCategoryThumbnail(id: string, data: any) {
|
||||
const headers = {
|
||||
"content-type": "multipart/form-data",
|
||||
};
|
||||
return await httpPost(`/article-categories/thumbnail/${id}`, headers, data);
|
||||
return await httpPostInterceptor(`/article-categories/thumbnail/${id}`, data, headers);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,42 +1,29 @@
|
|||
import {
|
||||
httpDeleteInterceptor,
|
||||
httpGet,
|
||||
httpPost,
|
||||
} from "./http-config/axios-base-service";
|
||||
|
||||
import Cookies from "js-cookie";
|
||||
import { httpDeleteInterceptor, httpGetInterceptor, httpPostInterceptor } from "./http-config/http-interceptor-services";
|
||||
|
||||
const token = Cookies.get("access_token");
|
||||
|
||||
export async function listUserRole(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(
|
||||
`/user-roles?limit=${data.limit}&page=${data.page}`,
|
||||
headers
|
||||
return await httpGetInterceptor(
|
||||
`/user-roles?limit=${data.limit}&page=${data.page}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function createMasterUserRole(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
const pathUrl = `/user-roles`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPostInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function getMasterUserRoleById(id: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`/user-roles/${id}`, headers);
|
||||
return await httpGetInterceptor(`/user-roles/${id}`);
|
||||
}
|
||||
|
||||
export async function deleteMasterUserRole(id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpDeleteInterceptor(`/user-roles/${id}`, headers);
|
||||
return await httpDeleteInterceptor(`/user-roles/${id}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { httpDeleteInterceptor, httpGet, httpPost, httpPut } from "./http-config/axios-base-service";
|
||||
import Cookies from "js-cookie";
|
||||
import axiosBaseInstance from "./http-config/http-base-instance";
|
||||
import { httpGet, httpPost } from "./http-config/http-base-services";
|
||||
import { httpDeleteInterceptor, httpGetInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services";
|
||||
|
||||
const token = Cookies.get("access_token");
|
||||
const id = Cookies.get("uie");
|
||||
|
|
@ -13,78 +13,55 @@ export async function listMasterUsers(data: any) {
|
|||
}
|
||||
|
||||
export async function createMasterUser(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/users`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPostInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function emailValidation(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/users/email-validation`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPost(pathUrl, data);
|
||||
}
|
||||
export async function setupEmail(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/users/setup-email`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPost(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function getDetailMasterUsers(id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`/users/detail/${id}`, headers);
|
||||
const pathUrl = `/users/detail/${id}`;
|
||||
return await httpGetInterceptor(pathUrl);
|
||||
}
|
||||
|
||||
export async function editMasterUsers(data: any, id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpPut(`/users/${id}`, headers, data);
|
||||
const pathUrl = `/users/${id}`
|
||||
return await httpPutInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function deleteMasterUser(id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpDeleteInterceptor(`/users/${id}`, headers);
|
||||
const pathUrl = `/users/${id}`
|
||||
return await httpDeleteInterceptor(pathUrl);
|
||||
}
|
||||
|
||||
export async function postSignIn(data: any) {
|
||||
const headers = {
|
||||
accept: "application/json",
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/users/login`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPost(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function getProfile(code?: string) {
|
||||
export async function getProfile(token?: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${code || token}`,
|
||||
"Authorization": `Bearer ${token}`,
|
||||
};
|
||||
return await httpGet(`/users/info`, headers);
|
||||
const pathUrl = `/users/info`;
|
||||
return await httpGet(pathUrl, headers);
|
||||
}
|
||||
|
||||
export async function updateProfile(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
return await httpPut(`/users/${id}`, headers, data);
|
||||
const pathUrl = `/users/${id}`;
|
||||
return await httpPutInterceptor(pathUrl, data);
|
||||
}
|
||||
export async function savePassword(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
return await httpPost(`/users/save-password`, headers, data);
|
||||
const pathUrl = `/users/save-password`
|
||||
return await httpPostInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function resetPassword(data: any) {
|
||||
|
|
@ -102,23 +79,13 @@ export async function checkUsernames(username: string) {
|
|||
}
|
||||
|
||||
export async function otpRequest(email: string, name: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpPost(`/users/otp-request`, headers, { email, name });
|
||||
const pathUrl = `/users/otp-request`;
|
||||
return await httpPost(pathUrl, { email, name });
|
||||
}
|
||||
|
||||
export async function otpValidation(email: string, otpCode: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpPost(`/users/otp-validation`, headers, { email, otpCode });
|
||||
}
|
||||
export async function otpValidationLogin(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpPost(`/users/otp-validation`, headers, data);
|
||||
const pathUrl = `/users/otp-validation`
|
||||
return await httpPost(pathUrl, { email, otpCode });
|
||||
}
|
||||
|
||||
export async function postArticleComment(data: any) {
|
||||
|
|
@ -134,31 +101,21 @@ export async function postArticleComment(data: any) {
|
|||
}
|
||||
|
||||
export async function editArticleComment(data: any, id: number) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
return await httpPut(`/article-comments/${id}`, headers, data);
|
||||
const pathUrl = `/article-comments/${id}`;
|
||||
return await httpPutInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function getArticleComment(id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`/article-comments?isPublic=true&articleId=${id}`, headers);
|
||||
const pathUrl = `/article-comments?isPublic=true&articleId=${id}`;
|
||||
return await httpGet(pathUrl);
|
||||
}
|
||||
|
||||
export async function deleteArticleComment(id: number) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpDeleteInterceptor(`/article-comments/${id}`, headers);
|
||||
const pathUrl = `/article-comments/${id}`
|
||||
return await httpDeleteInterceptor(pathUrl);
|
||||
}
|
||||
|
||||
export async function getCsrfToken() {
|
||||
const pathUrl = "csrf-token";
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return httpGet(pathUrl, headers);
|
||||
return httpGet(pathUrl);
|
||||
}
|
||||
|
|
@ -1,47 +1,28 @@
|
|||
import { PaginationRequest } from "@/types/globals";
|
||||
import {
|
||||
httpDeleteInterceptor,
|
||||
httpGet,
|
||||
httpPost,
|
||||
httpPut,
|
||||
} from "./http-config/axios-base-service";
|
||||
import { httpGetInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services";
|
||||
import { httpGet } from "./http-config/http-base-services";
|
||||
|
||||
export async function createCustomStaticPage(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/custom-static-pages`;
|
||||
return await httpPost(pathUrl, headers, data);
|
||||
return await httpPostInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function editCustomStaticPage(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
const pathUrl = `/custom-static-pages/${data.id}`;
|
||||
return await httpPut(pathUrl, headers, data);
|
||||
return await httpPutInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function getCustomStaticPage(props: PaginationRequest) {
|
||||
const { page, limit, search } = props;
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(
|
||||
`/custom-static-pages?limit=${limit}&page=${page}&title=${search}`,
|
||||
headers
|
||||
);
|
||||
const pathUrl = `/custom-static-pages?limit=${limit}&page=${page}&title=${search}`;
|
||||
return await httpGetInterceptor(pathUrl);
|
||||
}
|
||||
|
||||
export async function getCustomStaticDetail(id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`/custom-static-pages/${id}`, headers);
|
||||
return await httpGetInterceptor(`/custom-static-pages/${id}`);
|
||||
}
|
||||
|
||||
export async function getCustomStaticDetailBySlug(slug: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`/custom-static-pages/slug/${slug}`, headers);
|
||||
const pathUrl = `/custom-static-pages/slug/${slug}`;
|
||||
return await httpGet(pathUrl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
import Cookies from "js-cookie";
|
||||
import { httpGetInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services";
|
||||
const token = Cookies.get("access_token");
|
||||
|
||||
export async function getAllUserLevels(data?: any) {
|
||||
const pathUrl = `user-levels?limit=${data?.limit || ""}&levelNumber=${
|
||||
data?.levelNumber || ""
|
||||
}&name=${data?.search || ""}&page=${data?.page || "1"}`
|
||||
return await httpGetInterceptor(pathUrl);
|
||||
}
|
||||
export async function getUserLevels(id: string) {
|
||||
return await httpGetInterceptor(`user-levels/${id}`);
|
||||
}
|
||||
|
||||
export async function getAccountById(id: string) {
|
||||
return await httpGetInterceptor(`user-account/findById/${id}`);
|
||||
}
|
||||
|
||||
export async function createUserLevels(data: any) {
|
||||
return await httpPostInterceptor(`user-levels`, data);
|
||||
}
|
||||
|
||||
export async function editUserLevels(id: string, data: any) {
|
||||
return await httpPutInterceptor(`user-levels/${id}`, data);
|
||||
}
|
||||
|
||||
export async function changeIsApproval(data: any) {
|
||||
return await httpPutInterceptor(`user-levels/enable-approval`, data);
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
|
||||
import Cookies from "js-cookie";
|
||||
import { httpGet, httpPost, httpPut } from "../http-config/axios-base-service";
|
||||
|
||||
const token = Cookies.get("access_token");
|
||||
|
||||
export async function getAllUserLevels(data?: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(
|
||||
`user-levels?limit=${data?.limit || ""}&levelNumber=${
|
||||
data?.levelNumber || ""
|
||||
}&name=${data?.search || ""}&page=${data?.page || "1"}`,
|
||||
headers
|
||||
);
|
||||
}
|
||||
export async function getUserLevels(id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`user-levels/${id}`, headers);
|
||||
}
|
||||
|
||||
export async function getAccountById(id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`user-account/findById/${id}`, headers);
|
||||
}
|
||||
|
||||
export async function createUserLevels(request: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpPost(`user-levels`, headers, request);
|
||||
}
|
||||
|
||||
export async function editUserLevels(id: string, request: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpPut(`user-levels/${id}`, headers, request);
|
||||
}
|
||||
|
||||
export async function changeIsApproval(request: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
return await httpPut(`user-levels/enable-approval`, headers, request);
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
// Global chunk loading error handler
|
||||
export function setupChunkErrorHandler() {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
// Handle chunk loading errors
|
||||
window.addEventListener('error', (event) => {
|
||||
const error = event.error;
|
||||
|
||||
// Check if it's a chunk loading error
|
||||
if (
|
||||
error?.name === 'ChunkLoadError' ||
|
||||
error?.message?.includes('Loading chunk') ||
|
||||
error?.message?.includes('Failed to fetch')
|
||||
) {
|
||||
console.warn('Chunk loading error detected:', error);
|
||||
|
||||
// Prevent the error from being logged to console
|
||||
event.preventDefault();
|
||||
|
||||
// Show a user-friendly message
|
||||
const message = document.createElement('div');
|
||||
message.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: #fef2f2;
|
||||
border: 1px solid #fecaca;
|
||||
color: #dc2626;
|
||||
padding: 12px 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
z-index: 9999;
|
||||
max-width: 300px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
`;
|
||||
message.innerHTML = `
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<span>⚠️</span>
|
||||
<span>Application update detected. Please refresh the page.</span>
|
||||
</div>
|
||||
<button onclick="window.location.reload()" style="
|
||||
margin-top: 8px;
|
||||
background: #dc2626;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
">Refresh</button>
|
||||
`;
|
||||
|
||||
document.body.appendChild(message);
|
||||
|
||||
// Auto-remove after 10 seconds
|
||||
setTimeout(() => {
|
||||
if (message.parentNode) {
|
||||
message.parentNode.removeChild(message);
|
||||
}
|
||||
}, 10000);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle unhandled promise rejections (which might include chunk loading errors)
|
||||
window.addEventListener('unhandledrejection', (event) => {
|
||||
const error = event.reason;
|
||||
|
||||
if (
|
||||
error?.name === 'ChunkLoadError' ||
|
||||
error?.message?.includes('Loading chunk') ||
|
||||
error?.message?.includes('Failed to fetch')
|
||||
) {
|
||||
console.warn('Unhandled chunk loading rejection:', error);
|
||||
event.preventDefault();
|
||||
|
||||
// Reload the page after a short delay
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Auto-setup when this module is imported
|
||||
if (typeof window !== 'undefined') {
|
||||
setupChunkErrorHandler();
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
import dynamic from 'next/dynamic';
|
||||
import { ComponentType } from 'react';
|
||||
|
||||
interface DynamicImportOptions {
|
||||
ssr?: boolean;
|
||||
loading?: () => React.ReactElement;
|
||||
retries?: number;
|
||||
retryDelay?: number;
|
||||
}
|
||||
|
||||
export function createSafeDynamicImport<T extends ComponentType<any>>(
|
||||
importFn: () => Promise<{ default: T }>,
|
||||
options: DynamicImportOptions = {}
|
||||
) {
|
||||
const { ssr = false, loading, retries = 3, retryDelay = 1000 } = options;
|
||||
|
||||
return dynamic(
|
||||
() => {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
let attempts = 0;
|
||||
|
||||
const attemptImport = async () => {
|
||||
try {
|
||||
const module = await importFn();
|
||||
resolve(module.default);
|
||||
} catch (error) {
|
||||
attempts++;
|
||||
|
||||
// Check if it's a chunk loading error
|
||||
if (
|
||||
(error as any)?.name === 'ChunkLoadError' ||
|
||||
(error as any)?.message?.includes('Loading chunk') ||
|
||||
(error as any)?.message?.includes('Failed to fetch')
|
||||
) {
|
||||
if (attempts < retries) {
|
||||
console.warn(`Chunk loading failed, retrying... (${attempts}/${retries})`);
|
||||
setTimeout(attemptImport, retryDelay);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
reject(error);
|
||||
}
|
||||
};
|
||||
|
||||
attemptImport();
|
||||
});
|
||||
},
|
||||
{
|
||||
ssr,
|
||||
loading,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Predefined safe dynamic imports for common components
|
||||
export const SafeCustomEditor = createSafeDynamicImport(
|
||||
() => import('@/components/editor/custom-editor'),
|
||||
{ ssr: false }
|
||||
);
|
||||
|
||||
export const SafeViewEditor = createSafeDynamicImport(
|
||||
() => import('@/components/editor/view-editor'),
|
||||
{ ssr: false }
|
||||
);
|
||||
|
||||
export const SafeReactApexChart = createSafeDynamicImport(
|
||||
() => import('react-apexcharts'),
|
||||
{ ssr: false }
|
||||
);
|
||||
Loading…
Reference in New Issue