Files
rentall-app/frontend/src/components/BetaPasswordProtection.tsx
2025-07-31 22:06:03 -04:00

136 lines
3.6 KiB
TypeScript

import React, { useState, useEffect } from "react";
interface BetaPasswordProtectionProps {
children: React.ReactNode;
}
const BetaPasswordProtection: React.FC<BetaPasswordProtectionProps> = ({
children,
}) => {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [loading, setLoading] = useState(true);
useEffect(() => {
// Check if user already has valid beta access
const betaToken = localStorage.getItem("betaAccess");
if (betaToken) {
// Verify the stored token is still valid
verifyBetaAccess(betaToken);
} else {
setLoading(false);
}
}, []);
const verifyBetaAccess = async (token: string) => {
try {
const response = await fetch(
`${process.env.REACT_APP_API_URL}/beta/verify`,
{
headers: {
"X-Beta-Password": token,
},
}
);
if (response.ok) {
setIsAuthenticated(true);
} else {
localStorage.removeItem("betaAccess");
}
} catch (error) {
localStorage.removeItem("betaAccess");
} finally {
setLoading(false);
}
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError("");
if (!password) {
setError("Please enter a password");
return;
}
try {
const response = await fetch(
`${process.env.REACT_APP_API_URL}/beta/verify`,
{
headers: {
"X-Beta-Password": password,
},
}
);
if (response.ok) {
localStorage.setItem("betaAccess", password);
setIsAuthenticated(true);
} else {
setError("Invalid beta password");
}
} catch (error) {
setError("Failed to verify beta password");
}
};
if (loading) {
return (
<div className="min-vh-100 d-flex align-items-center justify-content-center">
<div className="spinner-border text-primary" role="status">
<span className="visually-hidden">Loading...</span>
</div>
</div>
);
}
if (!isAuthenticated) {
return (
<div className="min-vh-100 d-flex align-items-center justify-content-center bg-light">
<div
className="card shadow"
style={{ maxWidth: "400px", width: "100%" }}
>
<div className="card-body p-5">
<h2 className="text-center mb-4">Beta Access Required</h2>
<p className="text-muted text-center mb-4">
This site is currently in beta testing. Please enter the beta
password to continue.
</p>
<form onSubmit={handleSubmit}>
<div className="mb-3">
<label htmlFor="betaPassword" className="form-label">
Beta Password
</label>
<input
type="password"
className="form-control"
id="betaPassword"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Enter beta password"
autoFocus
/>
</div>
{error && (
<div className="alert alert-danger" role="alert">
{error}
</div>
)}
<button type="submit" className="btn btn-primary w-100">
Access Beta
</button>
</form>
</div>
</div>
</div>
);
}
return <>{children}</>;
};
export default BetaPasswordProtection;