satupeta-main/app/(modules)/admin/mapset-upload/_context/upload-context.tsx

111 lines
3.3 KiB
TypeScript
Raw Normal View History

2026-01-28 05:48:46 +00:00
"use client";
import React, { createContext, useContext, useState, useEffect, Suspense } from "react";
import { useRouter, useSearchParams, usePathname } from "next/navigation";
export type UploadStepType = "UPLOAD" | "PDF_VIEWER" | "TABLE_PICKER" | "VALIDATE" | "SUCCESS";
type UploadState = {
step: UploadStepType;
file: File | null;
fileDesc: string;
result: any;
selectedPages: number[];
validatedData: any;
sheetNames: string[];
selectedSheet: string | null;
pdfPageCount: number | null;
};
type UploadContextType = {
state: UploadState;
setState: React.Dispatch<React.SetStateAction<UploadState>>;
reset: () => void;
// 🔥 Update Signature: Tambah parameter options
goToStep: (step: UploadStepType, options?: { replace?: boolean }) => void;
};
const UploadContext = createContext<UploadContextType | undefined>(undefined);
function UploadProviderContent({ children }: { children: React.ReactNode }) {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const initialState: UploadState = {
step: "UPLOAD",
file: null,
fileDesc: "",
result: null,
selectedPages: [],
validatedData: null,
sheetNames: [],
selectedSheet: null,
pdfPageCount: null
};
const [state, setState] = useState<UploadState>(initialState);
// 1. SYNC URL -> STATE (Handle Browser Back)
useEffect(() => {
const stepParam = searchParams.get("step") as UploadStepType;
const validSteps: UploadStepType[] = ["UPLOAD", "PDF_VIEWER", "TABLE_PICKER", "VALIDATE", "SUCCESS"];
if (stepParam && validSteps.includes(stepParam)) {
if (stepParam !== "UPLOAD" && !state.file) {
router.replace(pathname);
setState(prev => ({ ...prev, step: "UPLOAD" }));
} else {
setState(prev => ({ ...prev, step: stepParam }));
}
} else {
setState(prev => ({ ...prev, step: "UPLOAD" }));
}
}, [searchParams, state.file, pathname, router]);
const reset = () => {
setState(initialState);
router.push(pathname);
};
// 2. STATE -> URL (Handle Navigation)
// 🔥 Update Logic Navigation
const goToStep = (newStep: UploadStepType, options?: { replace?: boolean }) => {
if (newStep === "UPLOAD") {
router.push(pathname);
} else {
const params = new URLSearchParams(searchParams.toString());
params.set("step", newStep);
const url = `${pathname}?${params.toString()}`;
// Jika replace = true, timpa history saat ini (Step 3 ditimpa Step 4)
if (options?.replace) {
router.replace(url);
} else {
router.push(url);
}
}
// Update state immediate agar UI responsif
setState((prev) => ({ ...prev, step: newStep }));
};
return (
<UploadContext.Provider value={{ state, setState, reset, goToStep }}>
{children}
</UploadContext.Provider>
);
}
export function UploadProvider({ children }: { children: React.ReactNode }) {
return (
<Suspense fallback={<div>Loading app...</div>}>
<UploadProviderContent>{children}</UploadProviderContent>
</Suspense>
);
}
export const useUploadContext = () => {
const context = useContext(UploadContext);
if (!context) throw new Error("useUploadContext must be used within UploadProvider");
return context;
};