1import React, { useEffect, useState } from "react";
2import { apiFetch } from '../lib/api';
3import { useSearchParams } from "react-router-dom";
4import "./DownloadStatusCard.css";
6export default function DownloadStatus() {
7 const [searchParams] = useSearchParams();
8 const jobId = searchParams.get("job"); // <-- FIXED
9 const os = searchParams.get("os");
10 const [status, setStatus] = useState(null);
11 const [filePath, setFilePath] = useState(null);
12 const [error, setError] = useState(null);
13 const [progressPercent, setProgressPercent] = useState(0);
15 // Poll backend for job status
18 setError("No job ID provided.");
22 let timer = setInterval(async () => {
24 // Use apiFetch to include JWT
25 const res = await apiFetch(`/download-job/${jobId}/status`);
26 const response = await res.json();
27 if (!response) return;
29 setStatus(response.status);
30 setProgressPercent(parseInt(response.progressPercent) || 0);
31 if (response.filePath) {
32 setFilePath(response.filePath);
34 if (response.status === "complete") {
36 // Use a download link/button with JWT
38 window.location.href = `/api/download-job/${jobId}/download`;
41 if (response.status === "failed") {
43 setError("Build failed. Please try again.");
46 setError(err?.message || "Status check failed.");
51 return () => clearInterval(timer);
54 // Progress bar width by actual percent
55 const progressWidth = `${progressPercent}%`;
56 let statusText = "Loading…";
57 if (status === "queued") statusText = "Queued";
58 else if (status === "building") statusText = "Building";
59 else if (status === "complete") statusText = "Ready";
60 else if (status === "failed") statusText = "Failed";
63 <div className="download-status-page" style={{ display: "flex", justifyContent: "center", alignItems: "center", minHeight: "80vh" }}>
64 <div className="download-status-card">
65 <div className="download-status-title">Agent Installer Status</div>
66 <div className="download-status-progress">
67 <div className="download-status-bar" style={{ width: progressWidth }}></div>
69 <div className="download-status-step">{statusText}</div>
70 <div className="download-status-meta">
71 <span><b>Job ID:</b> {jobId}</span>
72 <span><b>Device:</b> {os ? os.toUpperCase() : "-"}</span>
74 {error && <div className="download-status-error">{error}</div>}
75 {status === "complete" && filePath && (
76 <div className="download-status-ready">
77 <a className="download-status-btn" href={filePath} download>
80 <div style={{ marginTop: "0.5rem" }}>
81 <span>Installer is ready. If your download didn't start, click above.</span>
85 {status === "failed" && (
86 <div className="download-status-error">
87 Build failed. <button className="download-status-btn" onClick={() => window.location.reload()}>Retry</button>