mirror of
https://github.com/hanzoai/dataroom.git
synced 2026-10-30 18:41:07 +00:00
hanzo-build-linux-amd64 is the only ARC runner pool installed on hanzo-k8s today (arm64 pool is paused until DigitalOcean ships arm64 droplets, per ~/work/hanzo/.github/RUNNERS.md). The arm64 job was waiting on spark-hanzoai-arm64 — not provisioned in this cluster — so every build sat in queue forever and the amd64 leg got cancelled. Set platforms: linux/amd64 on the reusable build call to skip arm64 entirely. Re-add arm64 if/when DO ships arm64 droplets and the spark runner pool comes back online.
204 lines
5.3 KiB
TypeScript
204 lines
5.3 KiB
TypeScript
import { useState } from "react";
|
|
|
|
import NotFound from "@/pages/404";
|
|
import { Brand, DataroomBrand } from "@prisma/client";
|
|
import { toast } from "sonner";
|
|
|
|
import AccessForm, {
|
|
DEFAULT_ACCESS_FORM_TYPE,
|
|
} from "@/components/view/access-form";
|
|
import EmailVerificationMessage from "@/components/view/access-form/email-verification-form";
|
|
|
|
interface WorkflowAccessViewProps {
|
|
entryLinkId: string;
|
|
domain?: string;
|
|
slug?: string;
|
|
brand?: Partial<Brand> | Partial<DataroomBrand> | null;
|
|
}
|
|
|
|
export default function WorkflowAccessView({
|
|
entryLinkId,
|
|
domain,
|
|
slug,
|
|
brand,
|
|
}: WorkflowAccessViewProps) {
|
|
const [data, setData] = useState<DEFAULT_ACCESS_FORM_TYPE>({
|
|
email: "",
|
|
password: "",
|
|
});
|
|
const [code, setCode] = useState<string | null>(null);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [showVerification, setShowVerification] = useState(false);
|
|
const [isInvalidCode, setIsInvalidCode] = useState(false);
|
|
const [showNotFound, setShowNotFound] = useState(false);
|
|
|
|
// Build API endpoints based on whether we have domain/slug or just linkId
|
|
const verifyEndpoint =
|
|
domain && slug
|
|
? `/api/workflow-entry/domains/${domain}/${slug}/verify`
|
|
: `/api/workflow-entry/link/${entryLinkId}/verify`;
|
|
|
|
const accessEndpoint =
|
|
domain && slug
|
|
? `/api/workflow-entry/domains/${domain}/${slug}/access`
|
|
: `/api/workflow-entry/link/${entryLinkId}/access`;
|
|
|
|
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
e.preventDefault();
|
|
|
|
if (!data.email) {
|
|
toast.error("Email is required");
|
|
return;
|
|
}
|
|
|
|
// If we're in verification mode, verify the code
|
|
if (showVerification && code) {
|
|
await handleVerifyCode();
|
|
return;
|
|
}
|
|
|
|
// Otherwise, request OTP
|
|
await handleRequestOTP();
|
|
};
|
|
|
|
const handleRequestOTP = async () => {
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
const response = await fetch(verifyEndpoint, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
email: data.email,
|
|
}),
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (!response.ok) {
|
|
// Show 404 for inactive/deleted workflows
|
|
if (response.status === 403 && result.error?.includes("inactive")) {
|
|
setShowNotFound(true);
|
|
return;
|
|
}
|
|
if (response.status === 404) {
|
|
setShowNotFound(true);
|
|
return;
|
|
}
|
|
throw new Error(result.error || "Failed to send verification code");
|
|
}
|
|
|
|
setShowVerification(true);
|
|
toast.success("Verification code sent to your email");
|
|
} catch (error) {
|
|
console.error("Error requesting OTP:", error);
|
|
toast.error(
|
|
error instanceof Error
|
|
? error.message
|
|
: "Failed to send verification code",
|
|
);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleVerifyCode = async () => {
|
|
if (!code || code.length !== 6) {
|
|
setIsInvalidCode(true);
|
|
return;
|
|
}
|
|
|
|
setIsLoading(true);
|
|
setIsInvalidCode(false);
|
|
|
|
try {
|
|
const response = await fetch(accessEndpoint, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
email: data.email,
|
|
code: code,
|
|
}),
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
console.log("--------------------------------");
|
|
console.log("result", result);
|
|
console.log("--------------------------------");
|
|
|
|
if (!response.ok) {
|
|
// Show 404 for inactive/deleted workflows
|
|
if (response.status === 403 && result.error?.includes("inactive")) {
|
|
setShowNotFound(true);
|
|
return;
|
|
}
|
|
if (response.status === 404) {
|
|
setShowNotFound(true);
|
|
return;
|
|
}
|
|
if (result.resetVerification) {
|
|
// Reset to email entry if verification expired/invalid
|
|
setShowVerification(false);
|
|
setCode(null);
|
|
}
|
|
throw new Error(result.error || "Failed to verify code");
|
|
}
|
|
|
|
// Redirect to target URL
|
|
if (result.targetUrl) {
|
|
window.location.href = result.targetUrl;
|
|
} else {
|
|
throw new Error("No target URL provided");
|
|
}
|
|
} catch (error) {
|
|
console.error("Error verifying code:", error);
|
|
setIsInvalidCode(true);
|
|
toast.error(
|
|
error instanceof Error ? error.message : "Failed to verify code",
|
|
);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
if (showNotFound) {
|
|
return <NotFound message="Sorry, this workflow is no longer available." />;
|
|
}
|
|
|
|
if (showVerification) {
|
|
return (
|
|
<EmailVerificationMessage
|
|
onSubmitHandler={handleSubmit}
|
|
data={data}
|
|
isLoading={isLoading}
|
|
code={code}
|
|
setCode={setCode}
|
|
isInvalidCode={isInvalidCode}
|
|
setIsInvalidCode={setIsInvalidCode}
|
|
brand={brand}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<AccessForm
|
|
data={data}
|
|
email={data.email}
|
|
setData={setData}
|
|
onSubmitHandler={handleSubmit}
|
|
brand={brand}
|
|
requireEmail={true}
|
|
requirePassword={false}
|
|
isLoading={isLoading}
|
|
linkId={entryLinkId}
|
|
disableEditEmail={false}
|
|
linkWelcomeMessage="Enter your email to access the workflow"
|
|
/>
|
|
);
|
|
}
|