← back to kyle94024__Science-Simplified

Function bodies 169 total

All specs Real LLM only Function bodies
GET function · javascript · L7-L39 (33 LOC)
src/app/api/editors/route.js
export async function GET() {
    try {
        // Join the `email_credentials` and `profile` tables on the `user_id` column
        const result = await query(
            `
            SELECT
                ec.id,
                ec.email,
                p.name,
                p.photo,
                p.title,
                p.degree,
                p.university
            FROM
                email_credentials ec
            LEFT JOIN
                profile p
            ON
                ec.id = p.user_id
            WHERE
                ec.role = 'editor'
            `
        );

        return NextResponse.json(result.rows);
    } catch (error) {
        console.error("Error fetching editors:", error);
        return NextResponse.json(
            { message: "Error fetching editors" },
            { status: 500 }
        );
    }
}
DELETE function · javascript · L10-L51 (42 LOC)
src/app/api/images/delete-image/route.js
export async function DELETE(req) {
    try {
        // Parse the request to get the public ID of the image to delete
        const { public_id } = await req.json();

        if (!public_id) {
            return new Response(
                JSON.stringify({ error: "Public ID is required" }),
                { status: 400 }
            );
        }

        // Call Cloudinary to delete the image by its public ID
        const result = await new Promise((resolve, reject) => {
            cloudinary.uploader.destroy(public_id, (error, result) => {
                if (error) {
                    console.error("Error deleting from Cloudinary:", error);
                    reject(
                        new Response(
                            JSON.stringify({
                                error: "Failed to delete image from Cloudinary",
                            }),
                            { status: 500 }
                        )
                    );
                } else {
uploadBufferToCloudinary function · javascript · L13-L31 (19 LOC)
src/app/api/images/generate/route.js
async function uploadBufferToCloudinary(base64, publicId) {
  // base64 should be like "data:image/png;base64,AAAA..."
  return new Promise((resolve, reject) => {
    cloudinary.uploader.upload(
      base64,
      {
        resource_type: "image",
        public_id: publicId,
        folder: "ai_generated",
        overwrite: true,
        quality: "auto:good",
      },
      (err, result) => {
        if (err) return reject(err);
        resolve(result);
      }
    );
  });
}
POST function · javascript · L33-L89 (57 LOC)
src/app/api/images/generate/route.js
export async function POST(req) {
  try {
    const { text, articleId } = await req.json();

    if (!text) {
      return NextResponse.json({ error: "Missing text" }, { status: 400 });
    }

    if (!process.env.OPENAI_API_KEY) {
      return NextResponse.json({ error: "OpenAI API key not configured" }, { status: 500 });
    }

    // Build prompt — keep it clear, instruct "no text"
    const prompt = `${text}\n\nCreate a clean scientific illustration (no text on the image) that visually represents the simplified article above. Minimalistic, clear, high-quality, suitable as a magazine-style cover image.`;

    // Call OpenAI Images (gpt-image-1) - returns base64
    const openaiResp = await fetch("https://api.openai.com/v1/images/generations", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
      },
      body: JSON.stringify({
        model: "gpt-image-1",
        prompt,
        si
POST function · javascript · L18-L78 (61 LOC)
src/app/api/images/upload-image/route.js
export async function POST(req) {
    // Parse the incoming form data
    const formData = await req.formData();
    const file = formData.get("file"); // Get the file from the form data

    if (!file) {
        return new Response(JSON.stringify({ error: "No file uploaded" }), {
            status: 400,
        });
    }

    // Convert the buffer to a Node.js readable stream
    const buffer = await file.arrayBuffer(); // Get the file buffer
    const readableStream = new Readable({
        read() {
            this.push(Buffer.from(buffer)); // Push the buffer to the stream
            this.push(null); // Signal the end of the stream
        },
    });

    try {
        // Upload the image buffer to Cloudinary
        const uploadResult = await new Promise((resolve, reject) => {
            const uploadStream = cloudinary.uploader.upload_stream(
                {
                    resource_type: "auto", // Automatically detect resource type
                    upload_preset: pro
POST function · javascript · L27-L98 (72 LOC)
src/app/api/magic-link/create/route.js
export async function POST(req) {
  const adminCheck = requireAdmin(req);
  if (adminCheck instanceof NextResponse) return adminCheck;

  try {
    const body = await req.json();

    const tenant = defaultTenant.shortName; // Force tenant to current panel

    const email = (body?.email || "").toLowerCase();

    if (!tenant || !email) {
      return NextResponse.json({ error: "Missing tenant or email" }, { status: 400 });
    }

    // Load tenant env
    getTenantPool(tenant);

    const redirectUrl = "/assigned-articles";

    // Generate raw + hashed token
    const rawToken = crypto.randomBytes(32).toString("hex");
    const tokenHash = crypto.createHash("sha256").update(rawToken).digest("hex");

    // 30 days from now
    const expiresAt = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);

    // Store into tenant DB with expiration
    const insertSQL = `
      INSERT INTO magic_links (email, token_hash, redirect_url, expires_at)
      VALUES ($1, $2, $3, $4)
      RETURNING id
DELETE function · javascript · L6-L39 (34 LOC)
src/app/api/magic-link/delete/route.js
export async function DELETE(req) {
  const adminCheck = requireAdmin(req);
  if (adminCheck instanceof NextResponse) return adminCheck;

  try {
    const url = new URL(req.url);
    const id = url.searchParams.get("id");

    if (!id) {
      return NextResponse.json(
        { error: "Missing id" },
        { status: 400 }
      );
    }

    // 🔒 Use backend tenant only — prevent cross-tenant deletion
    const tenant = defaultTenant.shortName;

    // Perform deletion
    await tenantQuery(
      tenant,
      "DELETE FROM magic_links WHERE id = $1",
      [id]
    );

    return NextResponse.json({ success: true });
  } catch (error) {
    console.error("Delete magic link error:", error);
    return NextResponse.json(
      { error: "Server error" },
      { status: 500 }
    );
  }
}
Repobility · code-quality intelligence · https://repobility.com
GET function · javascript · L7-L58 (52 LOC)
src/app/api/magic-link/list/route.js
export async function GET(req) {

    const adminCheck = requireAdmin(req);
    if (adminCheck instanceof NextResponse) return adminCheck;

    // const TENANT_DOMAINS = {
    //     NF: "https://nfsimplified.com",
    //     EB: "https://sseb.vercel.app",
    //     Vitiligo: "https://ssvitiligo.vercel.app",
    //     CF: "https://sscf-coral.vercel.app",
    //     ALS: "https://ssals-ten.vercel.app",
    //     HS: "https://science-simplified-mu.vercel.app/",
    //     Ashermans: "https://ssashermans.vercel.app",
    //     RYR1: "https://ssryr1.vercel.app",
    //     Aicardi: "https://ssaicardi.vercel.app",
    //     Progeria: "https://ssprogeria.vercel.app",
    //     RETT: "https://ssrett.vercel.app",
    //     Canavan: "https://sscanavan.vercel.app",
    //     HUNTINGTONS: "https://sshuntingtons.vercel.app", 
    //   };
    const tenant_domain = tenant.domain;

    try {
        const allLinks = [];

        // Loop over all tenant keys (NF, EB, CF, HS, etc)
        const
GET function · javascript · L31-L123 (93 LOC)
src/app/api/magic-link/verify/route.js
export async function GET(req) {


  try {
    const { searchParams } = new URL(req.url);
    const tenant = defaultTenant.shortName; // Force tenant to current panel
    const token = searchParams.get("token");

    if (!tenant || !token) {
      return NextResponse.json({ error: "Missing tenant or token" }, { status: 400 });
    }

    // Hash token
    const tokenHash = crypto.createHash("sha256").update(token).digest("hex");

    // Get magic link row
    const sql = `
      SELECT * 
      FROM magic_links 
      WHERE token_hash = $1
    `;
    const { rows } = await tenantQuery(tenant, sql, [tokenHash]);

    if (rows.length === 0) {
      return NextResponse.json({ error: "Invalid or used token" }, { status: 400 });
    }

    const magicLink = rows[0];

    // Check expiration
    if (magicLink.expires_at && new Date() > new Date(magicLink.expires_at)) {
      return NextResponse.json({ error: "Token expired" }, { status: 400 });
    }

    // Mark token as used
    await tena
POST function · javascript · L4-L32 (29 LOC)
src/app/api/pdfToText/route.js
export async function POST(req) {
  try {
    // Parse the FormData from the request
    const formData = await req.formData();
    const file = formData.get("file");

    if (!file) {
      return NextResponse.json({ error: "No file provided" }, { status: 400 });
    }

    // Convert file to Buffer
    const arrayBuffer = await file.arrayBuffer();
    const buffer = Buffer.from(arrayBuffer);

    // Parse the PDF file
    const pdfData = await pdfParse(buffer);

    return NextResponse.json(
      { message: "File uploaded successfully", text: pdfData.text },
      { status: 200 }
    );
  } catch (error) {
    console.error("File upload error:", error);
    return NextResponse.json(
      { error: "Error processing the file" },
      { status: 500 }
    );
  }
}
DELETE function · javascript · L10-L54 (45 LOC)
src/app/api/profile/delete-image/route.js
export async function DELETE(req) {
    try {
        // Parse the request to get the public ID of the image to delete
        const { public_id } = await req.json();

        if (!public_id) {
            return new Response(
                JSON.stringify({ error: "Public ID is required" }),
                { status: 400 }
            );
        }

        // Ensure the public_id corresponds to the 'profiles' folder
        const fullPublicId = `profiles/${public_id}`;

        // Call Cloudinary to delete the image by its public ID
        const result = await new Promise((resolve, reject) => {
            cloudinary.uploader.destroy(fullPublicId, (error, result) => {
                if (error) {
                    console.error("Error deleting from Cloudinary:", error);
                    reject(
                        new Response(
                            JSON.stringify({
                                error: "Failed to delete image from Cloudinary",
                      
POST function · javascript · L5-L55 (51 LOC)
src/app/api/profile/update/route.js
export async function POST(req) {
    try {
        const {
            userId,
            name,
            photo,
            bio,
            degree,
            title,
            university,
            linkedin,
            labLink,
        } = await req.json();

        if (!userId) {
            return NextResponse.json(
                { message: "User ID is required." },
                { status: 400 }
            );
        }

        // Update the profile
        await query(
            `UPDATE profile
             SET name = $1, photo = $2, bio = $3, degree = $4, title = $5, university = $6, linkedin = $7, lablink = $8
             WHERE user_id = $9`,
            [
                name,
                photo,
                bio,
                degree,
                title,
                university,
                linkedin,
                labLink,
                userId,
            ]
        );

        return NextResponse.json(
            { message: "Profile up
POST function · javascript · L18-L79 (62 LOC)
src/app/api/profile/upload-image/route.js
export async function POST(req) {
    // Parse the incoming form data
    const formData = await req.formData();
    const file = formData.get("file"); // Get the file from the form data

    if (!file) {
        return new Response(JSON.stringify({ error: "No file uploaded" }), {
            status: 400,
        });
    }

    // Convert the buffer to a Node.js readable stream
    const buffer = await file.arrayBuffer(); // Get the file buffer
    const readableStream = new Readable({
        read() {
            this.push(Buffer.from(buffer)); // Push the buffer to the stream
            this.push(null); // Signal the end of the stream
        },
    });

    try {
        // Upload the image buffer to Cloudinary in the 'profiles' folder
        const uploadResult = await new Promise((resolve, reject) => {
            const uploadStream = cloudinary.uploader.upload_stream(
                {
                    resource_type: "auto", // Automatically detect resource type
             
GET function · javascript · L6-L34 (29 LOC)
src/app/api/profile/[userId]/route.js
export async function GET(request, { params }) {
    const { userId } = params; // Extract the userId from the URL parameters

    try {
        // Fetch the profile from the database using the provided userId
        const profileResult = await query(
            `SELECT user_id, name, email, photo, bio, degree, title, university, linkedin, lablink
             FROM profile
             WHERE user_id = $1`,
            [userId]
        );

        // Check if the profile exists
        if (profileResult.rows.length > 0) {
            return NextResponse.json(profileResult.rows[0]); // Send the profile as a JSON response
        } else {
            return NextResponse.json(
                { message: "Profile not found" },
                { status: 404 }
            ); // Profile not found
        }
    } catch (error) {
        console.error("Error fetching profile:", error);
        return NextResponse.json(
            { message: "Error fetching profile" },
            { status: 50
POST function · javascript · L418-L663 (246 LOC)
src/app/api/pubmed/route.js
export async function POST(req) {
    try {
        const { url } = await req.json();

        const validPattern =
            /(pubmed\.ncbi\.nlm\.nih\.gov\/\d+)|(pmc\.ncbi\.nlm\.nih\.gov\/articles\/PMC\d+)/i;
        if (!url || !validPattern.test(url)) {
            return NextResponse.json(
                { error: "Invalid PubMed or PubMed Central URL" },
                { status: 400 }
            );
        }

        // Detect DB & ID
        let db = "pubmed";
        let id = null;
        if (/pubmed\.ncbi\.nlm\.nih\.gov/i.test(url)) {
            id = url.match(/pubmed\.ncbi\.nlm\.nih\.gov\/(\d+)/i)?.[1];
        } else if (/pmc\.ncbi\.nlm\.nih\.gov/i.test(url)) {
            id = url.match(/PMC(\d+)/i)?.[1];
            db = "pmc";
        }
        if (!id) {
            return NextResponse.json({ error: "Could not extract ID" }, { status: 400 });
        }

        // Fetch from correct db
        const efetchUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.f
Powered by Repobility — scan your code at https://repobility.com
ArticleCard function · javascript · L171-L225 (55 LOC)
src/app/(editor)/assigned-articles/page.jsx
function ArticleCard({ article }) {
    const isPublished = article.status === "published";

    return (
        <Link
            href={`/assigned-articles/${article.id}`}
            className="admin-card admin-card-interactive block"
        >
            <div className="p-5 flex gap-5">
                {/* Thumbnail */}
                <div className="flex-shrink-0">
                    <img
                        src={article.image_url || "/default-article-image.png"}
                        alt=""
                        className="w-24 h-24 object-cover rounded-lg bg-gray-100"
                    />
                </div>

                {/* Content */}
                <div className="flex-1 min-w-0">
                    <div className="flex items-start justify-between gap-4 mb-2">
                        <h3 className="text-[1.6rem] font-semibold text-gray-900 line-clamp-2">
                            {article.title}
                        </h3>
                        <St
RootLayout function · javascript · L23-L45 (23 LOC)
src/app/layout.js
export default function RootLayout({ children }) {
    return (
        <html lang="en">
            <body className={`${outfitFont.variable} antialiased`}>

                <Analytics />

                <ThemeProvider>
                    <ToastContainer
                        position="top-right"
                        autoClose={2000}
                        hideProgressBar={true}
                        closeOnClick
                        pauseOnHover
                        draggable
                    />

                    {children}
                </ThemeProvider>
            </body>
        </html>
    );
}
MagicSuccess function · javascript · L1-L8 (8 LOC)
src/app/magic-success/page.js
export default function MagicSuccess() {
    return (
        <div style={{ padding: 40, textAlign: "center" }}>
            <h1>Login Successful</h1>
            <p>You will be redirected shortly...</p>
        </div>
    );
}
HomeContent function · javascript · L25-L140 (116 LOC)
src/app/page.jsx
function HomeContent() {
    const router = useRouter();
    const searchParams = useSearchParams();

    const { role } = useAuthStore();
    console.log("User: ", role);

    const handleSearchSubmit = (query) => {
        // Navigate to the article search page with the query
        router.push(`/articles}`);
    };

    // Handle HSF redirect (e.g., ?hsf-id=100941 -> /articles/126)
    // Only active for HS (Hidradenitis Suppurativa) tenant
    useEffect(() => {
        if (tenant.shortName !== "HS") return; // Only for HS Foundation links

        const hsfId = searchParams.get("hsf-id");
        if (hsfId) {
            const articleId = getArticleIdFromHsfId(hsfId);
            if (articleId) {
                router.replace(`/articles/${articleId}`);
                return;
            }
        }
    }, [searchParams, router]);

    // Check if tenant opts into full-width banner background
    const useFullWidthBg = tenant.homeBG_full === true;

    useEffect(() => {
        c
Home function · javascript · L143-L149 (7 LOC)
src/app/page.jsx
export default function Home() {
    return (
        <Suspense fallback={<div>Loading...</div>}>
            <HomeContent />
        </Suspense>
    );
}
fetchEditors function · javascript · L23-L40 (18 LOC)
src/app/(public)/about/page.jsx
async function fetchEditors() {
    const result = await query(`
      SELECT DISTINCT
        p.user_id AS id,
        p.name,
        p.photo,
        p.title,
        p.degree,
        p.university
      FROM article a
      JOIN profile p
        ON (a.certifiedby->>'userId')::INT = p.user_id
      WHERE a.certifiedby IS NOT NULL
      ORDER BY p.name
    `);

    return result.rows;
}
getInitial function · javascript · L43-L45 (3 LOC)
src/app/(public)/about/page.jsx
function getInitial(name) {
    return name && name.length > 0 ? name[0].toUpperCase() : "N/A";
}
getTrialIcon function · javascript · L12-L54 (43 LOC)
src/app/(public)/clinical-trials/[nctId]/page.jsx
function getTrialIcon(trial) {
  const protocol = trial.raw_data?.protocolSection;
  if (!protocol) return "/trial-icons/observational.png";

  const studyType = protocol.designModule?.studyType?.toLowerCase() || "";

  // Expanded access
  if (studyType.includes("expanded")) {
    return "/trial-icons/expandedaccess.png";
  }

  // Observational
  if (studyType.includes("observational")) {
    return "/trial-icons/observational.png";
  }

  // Interventional
  if (studyType.includes("interventional")) {
    const phasesRaw = protocol.designModule?.phases;

    const phases = Array.isArray(phasesRaw)
      ? phasesRaw.map((p) => p.toLowerCase())
      : typeof phasesRaw === "string"
      ? [phasesRaw.toLowerCase()]
      : [];

    if (phases.some((p) => p.includes("phase 1"))) {
      return "/trial-icons/phase1.png";
    }

    if (phases.some((p) => p.includes("phase 2"))) {
      return "/trial-icons/phase2.png";
    }

    if (phases.some((p) => p.includes("phase 3") || p.include
All rows above produced by Repobility · https://repobility.com
TrialDetailPage function · javascript · L56-L173 (118 LOC)
src/app/(public)/clinical-trials/[nctId]/page.jsx
export default function TrialDetailPage() {
  const { nctId } = useParams();
  const [trial, setTrial] = useState(null);
  const [loading, setLoading] = useState(true);
  const [showAllLocations, setShowAllLocations] = useState(false);

  useEffect(() => {
    const fetchTrial = async () => {
      const res = await fetch(`/api/clinical-trials/${nctId}`, {
        cache: "no-store",
      });
      const data = await res.json();
      setTrial(data.trial);
      setLoading(false);
    };

    fetchTrial();
  }, [nctId]);

  if (loading) return <p className="page-loading">Loading…</p>;
  if (!trial) return <p className="page-error">Trial not found</p>;

  const protocol = trial.raw_data?.protocolSection;

  const locations =
    protocol?.contactsLocationsModule?.locations
      ?.map((l) => [l.city, l.state, l.country].filter(Boolean).join(", "))
      .filter(Boolean) || [];

  const minAge = protocol?.eligibilityModule?.minimumAge;
  const maxAge = protocol?.eligibilityModule?.maximu
ContactPage function · javascript · L18-L341 (324 LOC)
src/app/(public)/contact/page.jsx
export default function ContactPage() {
    const [articleLink, setArticleLink] = useState("");
    const [sendArticleAnonymously, setSendArticleAnonymously] = useState(false);
    const [bugName, setBugName] = useState("");
    const [bugEmail, setBugEmail] = useState("");
    const [bugDescription, setBugDescription] = useState("");
    const [bugImage, setBugImage] = useState(null);
    const [sendBugAnonymously, setSendBugAnonymously] = useState(false);
    const [isArticleLoading, setIsArticleLoading] = useState(false);
    const [isBugLoading, setIsBugLoading] = useState(false);

    const handleArticleSubmit = async (e) => {
        e.preventDefault();
        setIsArticleLoading(true);

        const user = useAuthStore.getState().user; // Access user from Zustand store

        try {
            console.log(articleLink, sendArticleAnonymously, user?.userId);
            const response = await fetch("/api/contact/article-request", {
                method: "POST",
             
LoginForm function · javascript · L15-L132 (118 LOC)
src/app/(public)/login/page.jsx
export default function LoginForm() {
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const [showPassword, setShowPassword] = useState(false);
    const [isLoading, setIsLoading] = useState(false);
    const { login, error } = useAuth();
    const router = useRouter();

    const handleSubmit = async (e) => {
        e.preventDefault();
        setIsLoading(true);
        try {
            await login({ email, password });
            toast.success("Login successful!");
            router.push("/");
        } catch (err) {
            console.error("Login failed", err);
            toast.error(error || "Login failed!");
        } finally {
            setIsLoading(false);
        }
    };

    useEffect(() => {
        document.documentElement.style.setProperty('--auth-bg-top', `url(/assets/${tenant.pathName}/${tenant.loginBGTop})`);
        document.documentElement.style.setProperty('--auth-bg-bottom', `url(/assets/${tenant.pathName}/$
CreateAccountForm function · javascript · L13-L244 (232 LOC)
src/app/(public)/signup/page.jsx
export default function CreateAccountForm() {
    const [formData, setFormData] = useState({
        firstName: "",
        lastName: "",
        email: "",
        password: "",
        confirmPassword: "",
    });
    const [showPassword, setShowPassword] = useState(false);
    const [showConfirmPassword, setShowConfirmPassword] = useState(false);
    const [isLoading, setIsLoading] = useState(false); // Add isLoading state
    const router = useRouter();

    const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData((prevState) => ({
            ...prevState,
            [name]: value,
        }));
    };

    const handleSubmit = async (e) => {
        e.preventDefault();

        if (formData.password !== formData.confirmPassword) {
            toast.error("Passwords do not match.");
            return;
        }

        setIsLoading(true); // Set loading to true

        try {
            const response = await fetch("/api/auth/signup", {
      
ConfirmDialog function · javascript · L28-L82 (55 LOC)
src/components/admin/ConfirmDialog.jsx
export default function ConfirmDialog({
    open,
    onOpenChange,
    title,
    description,
    confirmLabel = "Confirm",
    cancelLabel = "Cancel",
    variant = "default",
    onConfirm,
    loading = false
}) {
    return (
        <AlertDialog open={open} onOpenChange={onOpenChange}>
            <AlertDialogContent className="max-w-[400px]">
                <AlertDialogHeader>
                    <AlertDialogTitle className="text-[1.8rem]">
                        {title}
                    </AlertDialogTitle>
                    <AlertDialogDescription className="text-[1.4rem]">
                        {description}
                    </AlertDialogDescription>
                </AlertDialogHeader>
                <AlertDialogFooter>
                    <AlertDialogCancel
                        className="text-[1.4rem] px-6 py-3"
                        disabled={loading}
                    >
                        {cancelLabel}
                    </AlertDialogCancel>
   
EmptyState function · javascript · L21-L39 (19 LOC)
src/components/admin/EmptyState.jsx
export default function EmptyState({
    icon = "inbox",
    title,
    description,
    action
}) {
    const Icon = iconMap[icon] || Inbox;

    return (
        <div className="empty-state">
            <Icon className="empty-state-icon" strokeWidth={1.5} />
            <h3 className="empty-state-title">{title}</h3>
            {description && (
                <p className="empty-state-description">{description}</p>
            )}
            {action && <div className="mt-2">{action}</div>}
        </div>
    );
}
PageHeader function · javascript · L16-L51 (36 LOC)
src/components/admin/PageHeader.jsx
export default function PageHeader({
    title,
    subtitle,
    backHref,
    backLabel = "Back",
    actions,
    children
}) {
    return (
        <div className="page-header">
            {backHref && (
                <Link
                    href={backHref}
                    className="flex items-center gap-2 text-gray-600 hover:text-gray-900 transition-colors mb-2 w-fit"
                >
                    <ArrowLeft size={18} />
                    <span className="text-[1.4rem] font-medium">{backLabel}</span>
                </Link>
            )}
            <div className="page-header-row">
                <div>
                    <h1 className="page-header-title">{title}</h1>
                    {subtitle && (
                        <p className="page-header-subtitle">{subtitle}</p>
                    )}
                </div>
                {actions && (
                    <div className="page-header-actions">
                        {actions}
                 
SearchInput function · javascript · L15-L67 (53 LOC)
src/components/admin/SearchInput.jsx
export default function SearchInput({
    value,
    onChange,
    placeholder = "Search...",
    debounceMs = 300,
    className = ""
}) {
    const [localValue, setLocalValue] = useState(value);

    // Sync with external value
    useEffect(() => {
        setLocalValue(value);
    }, [value]);

    // Debounced change handler
    useEffect(() => {
        const timer = setTimeout(() => {
            if (localValue !== value) {
                onChange(localValue);
            }
        }, debounceMs);

        return () => clearTimeout(timer);
    }, [localValue, debounceMs, onChange, value]);

    const handleClear = useCallback(() => {
        setLocalValue("");
        onChange("");
    }, [onChange]);

    return (
        <div className={`search-input-wrapper ${className}`}>
            <Search size={18} className="search-input-icon" />
            <input
                type="text"
                value={localValue}
                onChange={(e) => setLocalValue(e.target.valu
Repobility · MCP-ready · https://repobility.com
StatsCard function · javascript · L15-L51 (37 LOC)
src/components/admin/StatsCard.jsx
export default function StatsCard({
    label,
    value,
    change,
    changeType = "neutral",
    icon: Icon,
    className = ""
}) {
    return (
        <div className={`stats-card ${className}`}>
            <div className="flex items-center justify-between">
                <span className="stats-card-label">{label}</span>
                {Icon && (
                    <div className="text-gray-400">
                        <Icon size={20} />
                    </div>
                )}
            </div>
            <div className="stats-card-value">{value}</div>
            {change && (
                <div
                    className={`stats-card-change ${
                        changeType === "positive"
                            ? "stats-card-change-positive"
                            : changeType === "negative"
                            ? "stats-card-change-negative"
                            : "text-gray-500"
                    }`}
                >
         
StatusBadge function · javascript · L56-L78 (23 LOC)
src/components/admin/StatusBadge.jsx
export default function StatusBadge({
    variant = "neutral",
    label,
    showIcon = true,
    size = "md"
}) {
    const config = variants[variant] || variants.neutral;
    const Icon = config.icon;

    const sizeClass = size === "sm" ? "badge-sm" : size === "lg" ? "badge-lg" : "";

    return (
        <span className={`${config.className} ${sizeClass}`}>
            {showIcon && Icon && (
                <Icon
                    size={size === "sm" ? 10 : size === "lg" ? 16 : 12}
                    className={variant === "loading" ? "animate-spin" : ""}
                />
            )}
            {label}
        </span>
    );
}
ArticleCard function · javascript · L28-L194 (167 LOC)
src/components/ArticleCard/ArticleCard.jsx
function ArticleCard({
    id,
    imageUrl,
    date,
    title,
    summary,
    authorImageUrl,
    authorName,
    authorCreds,
    authorInstitution,
    pageType,
}) {
    const router = useRouter();
    const [isLoading, setIsLoading] = useState(false);

    const displayName =
        authorName && authorName.trim() ? authorName : "Anonymous";

    const showDegree =
        authorCreds && authorCreds.trim() && authorCreds !== "No Degree";

    const articleUrl =
        pageType === "pending"
            ? `/pending-articles/${id}`
            : pageType === "assigned"
            ? `/assigned-articles/${id}`
            : `/articles/${id}`;

    const handleCardClick = () => {
        router.push(articleUrl);
    };

    const handleFeatureStatus = async (shouldBeFeatured) => {
        setIsLoading(true);
        try {
            const response = await fetch("/api/articles/actions/feature", {
                method: "POST",
                headers: { "Content-Type": "applica
ArticleCardSkeleton function · javascript · L3-L22 (20 LOC)
src/components/ArticleCardSkeleton/ArticleCardSkeleton.jsx
export function ArticleCardSkeleton() {
    return (
        <div className="flex flex-col w-full gap-8">
            <Skeleton className="h-[250px] w-full rounded-xl" />
            <div className="space-y-4">
                <Skeleton className="h-6 w-[100px]" />
                <Skeleton className="h-8 w-full" />
                <Skeleton className="h-8 w-full" />
                <Skeleton className="h-8 w-[90%]" />
            </div>
            <div className="flex items-center space-x-4">
                <Skeleton className="h-20 w-20 rounded-full" />
                <div className="space-y-4">
                    <Skeleton className="h-6 w-[250px]" />
                    <Skeleton className="h-6 w-[200px]" />
                </div>
            </div>
        </div>
    );
}
ArticlesListPaginated function · javascript · L18-L229 (212 LOC)
src/components/ArticlesListPaginated/ArticlesListPaginated.jsx
export default function ArticlesListPaginated({
  articles = [],
  articlesPerPage = 6,
  loading = false,
  error = false,
  pageType = "",
}) {
  const [currentPage, setCurrentPage] = useState(1);
  const [isMobile, setIsMobile] = useState(false);
  const isHS = tenant.shortName === "HS"; // ✅ key flag

  useEffect(() => {
    const handleResize = () => setIsMobile(window.innerWidth <= 768);
    handleResize();
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  const totalPages = Math.max(1, Math.ceil(articles.length / articlesPerPage));

  useEffect(() => {
    if (currentPage > totalPages) {
      setCurrentPage(totalPages);
    }
  }, [articles.length, totalPages, currentPage]);

  const selectedArticles = articles.slice(
    (currentPage - 1) * articlesPerPage,
    currentPage * articlesPerPage
  );

  const handlePageChange = (page) => {
    if (page >= 1 && page <= totalPages) {
      setCurrent
getActiveNode function · javascript · L19-L33 (15 LOC)
src/components/ContentEditor/HeadingSelector.jsx
	function getActiveNode() {
		let pos = null;

		HEADINGS.forEach((_, idx) => {
			if (idx == 0 && isActive('paragraph')) {
				pos = 0;
			} 

			if (idx > 0 && isActive('heading', {level: idx })) {
				pos = idx;
			}
		})

		return pos;
	}
onValueChange function · javascript · L35-L41 (7 LOC)
src/components/ContentEditor/HeadingSelector.jsx
	function onValueChange(value) {
		if (value == 0) {
			setNode('paragraph');
		} else {
			setNode('heading', { level: value });
		}
	}
onInputChange function · javascript · L9-L17 (9 LOC)
src/components/ContentEditor/ImageInputButton.jsx
	function onInputChange() {
		const file = input.current.files[0];
		const reader = new FileReader()
		reader.readAsDataURL(file)
		reader.onload = () => {
			onChange(reader.result);
			input.current.value = null;
		}
	}
Repobility · code-quality intelligence · https://repobility.com
GenerateAIImageButton function · javascript · L4-L55 (52 LOC)
src/components/GenerateAIImageButtton.jsx
export default function GenerateAIImageButton({ articleId, simplifiedText, onImageGenerated }) {
    const [loading, setLoading] = useState(false);

    async function handleGenerate() {
        if (!simplifiedText || simplifiedText.trim().length < 10) {
            alert("Simplified text is required before generating an image.");
            return;
        }

        setLoading(true);

        try {
            const res = await fetch("/api/articles/generate-ai-image", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({
                    articleId,
                    simplifiedText,
                }),
            });

            const data = await res.json();

            if (!data.success) {
                alert("Failed to generate AI image.");
                setLoading(false);
                return;
            }

            // Call parent function → update UI
            onImageGenerated
handleGenerate function · javascript · L7-L42 (36 LOC)
src/components/GenerateAIImageButtton.jsx
    async function handleGenerate() {
        if (!simplifiedText || simplifiedText.trim().length < 10) {
            alert("Simplified text is required before generating an image.");
            return;
        }

        setLoading(true);

        try {
            const res = await fetch("/api/articles/generate-ai-image", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({
                    articleId,
                    simplifiedText,
                }),
            });

            const data = await res.json();

            if (!data.success) {
                alert("Failed to generate AI image.");
                setLoading(false);
                return;
            }

            // Call parent function → update UI
            onImageGenerated(data.imageUrl);

        } catch (err) {
            console.error("Error generating AI image:", err);
            alert("An error occurred.");
    
HomeServiceBanner function · javascript · L6-L26 (21 LOC)
src/components/HomeServiceBanner/HomeServiceBanner.jsx
function HomeServiceBanner() {
    useEffect(() => {
        document.documentElement.style.setProperty('--cta-background', `url(/assets/${tenant.pathName}/home/${tenant.homeExploreAllBG})`);
    }, []);

    return (
        <div className={`service-banner ${tenant.shortName === "HS" || tenant.shortName === "CF" || tenant.shortName === "Vitiligo" || tenant.shortName === "Canavan" || tenant.shortName === "Progeria" || tenant.shortName === "Huntington's" || tenant.shortName === "Rett" || tenant.shortName === "RYR1" || tenant.shortName === "ALS" || tenant.shortName === "NF" || tenant.shortName === "Asherman's" || tenant.shortName === "Aicardi" || tenant.shortName === "TS" || tenant.shortName === "RUNX1" ? "background-alt" : ""}`}>
            <div className="service-banner__content">
                <h2 className={`heading-quaternary ${tenant.shortName === "ALS" ? "invisible" : ""}`}>
                    {tenant.text_exploreAllTitle}{" "}
                </h2>
                <p classNam
Navbar function · javascript · L11-L203 (193 LOC)
src/components/Navbar/Navbar.jsx
export default function Navbar() {
    const { user, isAdmin, role } = useAuthStore();
    const { logout } = useAuth();
    const [navbarOpen, setNavbarOpen] = useState(false);

    const toggleNavbar = () => setNavbarOpen(!navbarOpen);
    const navbrand = `/assets/${tenant.pathName}/${tenant.logoWithText}`;

    return (
        <nav className={`navbar ${tenant.shortName === "HS" ? "hs-mode" : tenant.shortName === "RUNX1" ? "runx1-mode" : ""}`}>
            <div className="navbar-inner boxed padding">
                {/* Left logo */}
                <Link href="/" className="navbrand">
                    <Image
                        width={100}
                        height={50}
                        src={navbrand}
                        alt="Logo"
                        className="navbrand-img"
                    />
                </Link>

                {/* Main nav */}
                <ul className="nav-links">
                    <li>
                        <Link hr
ThemeProvider function · javascript · L6-L20 (15 LOC)
src/components/ThemeProvider/ThemeProvider.jsx
export default function ThemeProvider({ children }) {
    useEffect(() => {
        // Set CSS variables based on tenant theme
        document.documentElement.style.setProperty('--color-primary', tenant.theme.primary);
        document.documentElement.style.setProperty('--color-primary-dark', tenant.theme.primaryDark);
        document.documentElement.style.setProperty('--color-light-grey', tenant.theme.lightGrey);
        document.documentElement.style.setProperty('--color-text', tenant.theme.text);
        document.documentElement.style.setProperty('--color-background', tenant.theme.background);
        document.documentElement.style.setProperty('--color-contactUsColor', tenant.theme.contactUsColor);
        document.documentElement.style.setProperty('--color-author-text-color', tenant.theme.authorTextColor);
        document.documentElement.style.setProperty('--color-footer-bg', tenant.theme.footerBGColor);
    }, []);

    return children;
} 
TrialCard function · javascript · L22-L75 (54 LOC)
src/components/TrialCard/TrialCard.jsx
export default function TrialCard({ trial }) {
  const ageLabel = formatAge(trial.min_age, trial.max_age);

  return (
    <article className="trial-card article-card">
      <div className="trial-card__content">
        {/* TITLE */}
        <h3 className="trial-card__title">
          {trial.short_title || "Clinical Trial"}
        </h3>

        {/* LOCATION */}
        {Array.isArray(trial.locations) && trial.locations.length > 0 && (
          <div className="trial-card__location">
            <MapPin size={14} />
            <span>
              {trial.locations.length > 1
                ? "Multiple Locations"
                : [trial.locations[0]?.city, trial.locations[0]?.state]
                    .filter(Boolean)
                    .join(", ")}
            </span>
          </div>
        )}

        {/* SUMMARY */}
        <p className="trial-card__summary">{truncate(trial.ai_summary)}</p>

        {/* TRIAL DETAILS LABEL */}
        <div className="trial-card__details-lab
isBadAIText function · javascript · L8-L24 (17 LOC)
src/components/TrialDetailQuestions/TrialDetailQuestions.jsx
function isBadAIText(text) {
  if (!text || !text.trim()) return true;

  const normalized = text.toLowerCase().trim();

  // ONLY truly broken AI responses
  const hardFailures = [
    "please paste",
    "if you share",
    "i can explain",
    "i can summarize",
    "not enough information provided",
    "the text you shared",
  ];

  return hardFailures.some((p) => normalized.includes(p));
}
renderContent function · javascript · L28-L86 (59 LOC)
src/components/TrialDetailQuestions/TrialDetailQuestions.jsx
function renderContent(text, fallback, isManual = false) {
  if (!isManual && isBadAIText(text)) {
    return <p className="trial-paragraph">{fallback}</p>;
  }

  const cleaned = text
    .replace(/###/g, "")
    .replace(/##/g, "")
    .replace(/\*\*/g, "")
    .replace(/---/g, "")
    .trim();

  const lines = cleaned
    .split(/\n{1,}/)
    .map((l) => l.trim())
    .filter(Boolean);
  const items = [];

  lines.forEach((line, i) => {
    const lower = line.toLowerCase();

    if (
      lower.includes("who may") ||
      lower.includes("who may be able") ||
      lower.includes("who cannot") ||
      lower.includes("who may not")
    ) {
      items.push(
        <h4 key={`h-${i}`} className="trial-subheading">
          {line}
        </h4>,
      );
      return;
    }

    if (line.startsWith("- ") || line.startsWith("• ")) {
      items.push(
        <li key={`li-${i}`} className="trial-list-item">
          {line.replace(/^[-•]\s*/, "")}
        </li>,
      );
      return;
Powered by Repobility — scan your code at https://repobility.com
TrialDetailQuestions function · javascript · L90-L183 (94 LOC)
src/components/TrialDetailQuestions/TrialDetailQuestions.jsx
export default function TrialDetailQuestions({ trial }) {
  const [openIndex, setOpenIndex] = useState(null);
  if (!trial) return null;

  const sections = [
    {
      title: "What is the purpose of this study?",
      text: trial.ai_purpose_manual || trial.ai_purpose,
      isManual: !!trial.ai_purpose_manual,
      fallback:
        "The purpose of this study is being reviewed by the research team.",
    },
    {
      title: "What treatments are being tested?",
      text: trial.ai_treatments_manual || trial.ai_treatments,
      isManual: !!trial.ai_treatments_manual,
      fallback:
        "The study team will explain what treatment or approach is being studied.",
    },
    {
      title: "Is there past research on this treatment?",
      text: trial.ai_prior_research_manual || trial.ai_prior_research,
      isManual: !!trial.ai_prior_research_manual,
      fallback:
        "There is limited publicly available information about prior research for this treatment.",
    },
    
TrialsListPaginated function · javascript · L16-L193 (178 LOC)
src/components/TrialsListPaginated/TrialsListPaginated.jsx
export default function TrialsListPaginated({
  trials = [],
  trialsPerPage = 6,
  loading = false,
  error = false,
}) {
  const [currentPage, setCurrentPage] = useState(1);
  const [isMobile, setIsMobile] = useState(false);

  /* ---------- RESPONSIVE ---------- */
  useEffect(() => {
    const handleResize = () => setIsMobile(window.innerWidth <= 768);
    handleResize();
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  const totalPages = Math.max(1, Math.ceil(trials.length / trialsPerPage));

  useEffect(() => {
    if (currentPage > totalPages) setCurrentPage(totalPages);
  }, [trials.length, totalPages, currentPage]);

  const selectedTrials = trials.slice(
    (currentPage - 1) * trialsPerPage,
    currentPage * trialsPerPage
  );

  const handlePageChange = (page) => {
    if (page >= 1 && page <= totalPages) {
      setCurrentPage(page);
      window.scrollTo({ top: 0, behavior: "smooth" });
Skeleton function · javascript · L3-L15 (13 LOC)
src/components/ui/skeleton.jsx
function Skeleton({
  className,
  ...props
}) {
  return (
    (<div
      className={cn(
        "animate-pulse rounded-md bg-neutral-900/10 dark:bg-neutral-50/10",
        className
      )}
      {...props} />)
  );
}
‹ prevpage 3 / 4next ›