117 lines
3.4 KiB
TypeScript
117 lines
3.4 KiB
TypeScript
"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 (state.step === "SUCCESS" && stepParam !== "SUCCESS") {
|
|
// reset();
|
|
// return;
|
|
// }
|
|
|
|
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]);
|
|
|
|
// 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 }));
|
|
};
|
|
|
|
|
|
const reset = () => {
|
|
setState(initialState);
|
|
router.push(pathname);
|
|
};
|
|
|
|
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;
|
|
}; |