Initial commit: CI Agent competitive-intelligence monitoring app

FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring,
source collection, LLM-based change analysis, enrichment, and account
security (Turnstile, escalating lockout, email verification).
This commit is contained in:
2026-08-05 10:48:20 -04:00
commit 1a4c80958f
365 changed files with 43541 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
"use client";
import { type InputHTMLAttributes, forwardRef, useState } from "react";
import { Eye, EyeOff } from "lucide-react";
import clsx from "clsx";
interface PasswordFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
label: string;
error?: string;
hint?: string;
}
/** Same visual language as `FormField`, plus a show/hide toggle - same
* crossfade-icon-swap technique as `ApiKeyRow`'s Show/Hide button. */
export const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
({ label, error, hint, id, className, ...props }, ref) => {
const [revealed, setRevealed] = useState(false);
const fieldId = id ?? props.name;
return (
<div>
<label htmlFor={fieldId} className="block text-sm font-medium text-slate-700">
{label}
</label>
<div className="relative mt-1">
<input
ref={ref}
id={fieldId}
type={revealed ? "text" : "password"}
className={clsx(
"focus-ring block w-full rounded-md border border-slate-300 px-3 py-2 pr-10 text-sm shadow-sm transition-colors duration-150",
error && "border-red-400",
className,
)}
aria-invalid={error ? "true" : "false"}
aria-describedby={error ? `${fieldId}-error` : hint ? `${fieldId}-hint` : undefined}
{...props}
/>
<button
type="button"
onClick={() => setRevealed((r) => !r)}
title={revealed ? "Hide password" : "Show password"}
tabIndex={-1}
className="focus-ring absolute inset-y-0 right-0 flex w-9 items-center justify-center text-slate-400 transition-colors duration-150 hover:text-slate-600"
>
<span className="relative block h-4 w-4">
<Eye
className={`absolute inset-0 h-4 w-4 transition-opacity duration-200 ${revealed ? "opacity-0" : "opacity-100"}`}
aria-hidden
/>
<EyeOff
className={`absolute inset-0 h-4 w-4 transition-opacity duration-200 ${revealed ? "opacity-100" : "opacity-0"}`}
aria-hidden
/>
</span>
</button>
</div>
{hint && !error && (
<p id={`${fieldId}-hint`} className="mt-1 text-xs text-slate-500">
{hint}
</p>
)}
{error && (
<p
id={`${fieldId}-error`}
className="mt-1 animate-fade-in text-xs text-red-600"
role="alert"
>
{error}
</p>
)}
</div>
);
},
);
PasswordField.displayName = "PasswordField";