Add PasswordForDownload component for secure file access with password protection

This commit is contained in:
Atharva Ombase
2025-08-03 19:27:00 +05:30
parent 7597f52b47
commit dff2de5ddd
@@ -0,0 +1,94 @@
import { useState } from "react";
import PropTypes from "prop-types";
const API_URL = import.meta.env.VITE_API_URL;
const PasswordForDownload = ({ filename, onDownload, onClose }) => {
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const handleDownload = async () => {
if (!password) {
setError("Password is required");
return;
}
setLoading(true);
setError("");
try {
const response = await fetch(`${API_URL}/api/files/download`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
body: JSON.stringify({ filename, password }),
});
if (!response.ok) {
const msg = await response.text();
throw new Error(msg);
}
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
onDownload();
onClose();
} catch (err) {
console.error(err);
setError(`Download failed: ${err.message}`);
} finally {
setLoading(false);
}
};
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
<div className="bg-white p-6 rounded-lg w-80">
<h3 className="text-lg font-semibold mb-4">Enter Password</h3>
<input
type="password"
className="w-full border border-gray-300 rounded px-3 py-2 mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
{error && <p className="text-red-500 text-sm mb-2">{error}</p>}
<div className="flex justify-end space-x-2">
<button
onClick={onClose}
disabled={loading}
className="px-4 py-2 bg-gray-200 rounded hover:bg-gray-300"
>
Cancel
</button>
<button
onClick={handleDownload}
disabled={loading}
className={`px-4 py-2 text-white rounded ${
loading ? "bg-gray-400" : "bg-blue-600 hover:bg-blue-700"
}`}
>
{loading ? "Downloading..." : "Download"}
</button>
</div>
</div>
</div>
);
};
PasswordForDownload.propTypes = {
filename: PropTypes.string.isRequired,
onDownload: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
};
export default PasswordForDownload;