import { json, redirect, type ActionFunctionArgs, type LoaderFunctionArgs } from "@remix-run/node"; import { Form, useActionData, useLoaderData, useNavigation, Link } from "@remix-run/react"; import { useEffect, useState } from "react"; import { Card, CardContent, CardHeader } from "~/components/ui/card"; import { Button } from "~/components/ui/button"; import { Alert, AlertDescription } from "~/components/ui/alert"; import { Progress } from "~/components/ui/progress"; import { Clock, CheckCircle, RefreshCw, Loader2, AlertCircle, UserCheck, ArrowLeft, ArrowRight, MessageCircle, FileCheck } from "lucide-react"; import pengelolaAuthService from "~/services/auth/pengelola.service"; import { getUserSession, createUserSession } from "~/sessions.server"; // Progress Indicator Component const ProgressIndicator = ({ currentStep = 4, totalSteps = 5 }) => { return (
{Array.from({ length: totalSteps }, (_, index) => { const stepNumber = index + 1; const isActive = stepNumber === currentStep; const isCompleted = stepNumber < currentStep; return (
{isCompleted ? : stepNumber}
{stepNumber < totalSteps && (
)}
); })}
); }; // Interfaces interface LoaderData { userSession: any; lastChecked: string; } interface CheckApprovalActionData { success?: boolean; approved?: boolean; message?: string; errors?: { general?: string; }; } export const loader = async ({ request }: LoaderFunctionArgs): Promise => { const userSession = await getUserSession(request); // Check if user is authenticated and has pengelola role if (!userSession || userSession.role !== "pengelola") { return redirect("/authpengelola"); } // Check if user should be on this step if (userSession.registrationStatus !== "awaiting_approval") { // Redirect based on current status switch (userSession.registrationStatus) { case "uncomplete": return redirect("/authpengelola/completingcompanyprofile"); case "approved": return redirect("/authpengelola/createanewpin"); case "complete": return redirect("/pengelola/dashboard"); default: break; } } return json({ userSession, lastChecked: new Date().toISOString() }); }; export const action = async ({ request }: ActionFunctionArgs): Promise => { const userSession = await getUserSession(request); if (!userSession || userSession.role !== "pengelola") { return redirect("/authpengelola"); } try { // Call API untuk check approval status const response = await pengelolaAuthService.checkApproval(); if (response.meta.status === 200 && response.data) { if (response.data.registration_status === "approved") { // User sudah di-approve, update session dan redirect return createUserSession({ request, sessionData: { ...userSession, ...(response.data.access_token && { accessToken: response.data.access_token }), ...(response.data.refresh_token && { refreshToken: response.data.refresh_token }), ...(response.data.session_id && { sessionId: response.data.session_id }), tokenType: response.data.token_type, registrationStatus: response.data.registration_status, nextStep: response.data.next_step }, redirectTo: "/authpengelola/createanewpin" }); } else { // Masih awaiting approval return json({ success: true, approved: false, message: response.data.message || "Masih menunggu persetujuan administrator" }); } } else { return json( { errors: { general: response.meta.message || "Gagal mengecek status persetujuan" } }, { status: 400 } ); } } catch (error: any) { console.error("Check approval error:", error); // Handle specific API errors if (error.response?.data?.meta?.message) { return json( { errors: { general: error.response.data.meta.message } }, { status: error.response.status || 500 } ); } return json( { errors: { general: "Gagal mengecek status persetujuan. Silakan coba lagi." } }, { status: 500 } ); } }; export default function WaitingApprovalFromAdministrator() { const { userSession, lastChecked } = useLoaderData(); const actionData = useActionData(); const navigation = useNavigation(); const [timeWaiting, setTimeWaiting] = useState(""); const [autoRefresh, setAutoRefresh] = useState(true); const isSubmitting = navigation.state === "submitting"; // Calculate time waiting useEffect(() => { const updateTimeWaiting = () => { const now = new Date(); const submitted = new Date(lastChecked); const diffMs = now.getTime() - submitted.getTime(); const hours = Math.floor(diffMs / (1000 * 60 * 60)); const minutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60)); if (hours > 0) { setTimeWaiting(`${hours} jam ${minutes} menit`); } else { setTimeWaiting(`${minutes} menit`); } }; updateTimeWaiting(); const interval = setInterval(updateTimeWaiting, 60000); // Update every minute return () => clearInterval(interval); }, [lastChecked]); // Auto refresh every 30 seconds useEffect(() => { if (!autoRefresh) return; const interval = setInterval(() => { // Trigger form submission to check approval const form = document.getElementById( "check-approval-form" ) as HTMLFormElement; if (form && !isSubmitting) { form.requestSubmit(); } }, 30000); // 30 seconds return () => clearInterval(interval); }, [autoRefresh, isSubmitting]); return (
{/* Progress Indicator */} {/* Main Card */}

Menunggu Persetujuan

Profil perusahaan Anda sedang ditinjau oleh administrator

{/* Status Alert */} {actionData?.success && !actionData.approved && ( {actionData.message} )} {/* Error Alert */} {actionData?.errors?.general && ( {actionData.errors.general} )} {/* Waiting Status */}
{/* Progress Animation */}
Data Dikirim
Verifikasi Admin
Approved
{/* Time Waiting */}

Telah menunggu:

{timeWaiting}

{/* Information Cards */}

Proses Verifikasi

Administrator sedang memverifikasi dokumen dan informasi perusahaan yang Anda berikan. Proses ini biasanya memakan waktu 1-24 jam.

Yang Diverifikasi

• Kebenaran informasi perusahaan

• Validitas dokumen NPWP/Tax ID

• Kesesuaian bidang usaha

• Kelengkapan data kontak

{/* Check Status Form */}
{/* Auto Refresh Toggle */}
{/* Contact Support */}

Sudah lebih dari 24 jam? Hubungi administrator

{/* Back Link */}
Edit profil perusahaan
{/* Tips Card */}

💡 Tips: Pastikan informasi yang diberikan akurat

Jika ada kesalahan data, admin akan menghubungi Anda untuk revisi

); }