CtrlK
BlogDocsLog inGet started
Tessl Logo

base/typescript-engineering

Use this skill whenever the user asks you to write, edit, review, refactor, debug, or design TypeScript or TSX code. It is especially relevant for application code, backend routes, React/UI work, schemas, runtime boundaries, persistence, async workflows, API contracts, tests, lint/typecheck fixes, and code review. Apply it even when the user does not explicitly mention "TypeScript" if the files or project are TypeScript-based.

89

1.26x
Quality

85%

Does it follow best practices?

Impact

95%

1.26x

Average score across 5 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

task.mdevals/scenario-2/

Stabilize Bulk Invites

Problem/Feature Description

Support keeps getting reports that the bulk-invite panel shows stale counts and confusing success or error messages after a failed request. The component grew quickly during a launch and now mixes rendering, request state, recipient rules, and form handling in one place.

Refactor this feature so the user experience is reliable and the code is easier to reason about. Keep the public component props compatible with the existing call site.

Output Specification

Produce a TypeScript React project in the current directory. Include updated source files and focused tests for the invite panel behavior.

Input Files

The following files are provided as inputs. Extract them before beginning.

=============== FILE: AGENTS.md ===============

Project Instructions

  • React components live under src/features/<feature>/.
  • Application modules use named exports.
  • Tests use Vitest and React Testing Library.
  • Avoid snapshot-only tests for UI behavior.

=============== FILE: package.json =============== { "type": "module", "scripts": { "test": "vitest run", "typecheck": "tsc --noEmit" }, "dependencies": { "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.5.2", "jsdom": "^24.1.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, "devDependencies": { "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.1", "typescript": "^5.5.3", "vite": "^5.3.4", "vitest": "^2.0.4" } }

=============== FILE: tsconfig.json =============== { "compilerOptions": { "jsx": "react-jsx", "target": "ES2022", "module": "ESNext", "moduleResolution": "Bundler", "strict": true, "exactOptionalPropertyTypes": true, "skipLibCheck": true }, "include": ["src//*.ts", "src//*.tsx"] }

=============== FILE: src/test/setup.ts =============== import "@testing-library/jest-dom/vitest";

=============== FILE: src/features/invites/BulkInvitePanel.tsx =============== import { useEffect, useState } from "react";

type Member = { id: string; email: string; role: "owner" | "admin" | "member"; invitedAt: string | null; };

type Props = { teamName: string; members: Member[]; sendInvites: (emails: string[]) => Promise<{ sent: string[]; skipped: string[] }>; };

export default function BulkInvitePanel({ teamName, members, sendInvites }: Props) { const [localMembers, setLocalMembers] = useState(members); const [rawEmails, setRawEmails] = useState(""); const [selectedCount, setSelectedCount] = useState(0); const [isLoading, setIsLoading] = useState(false); const [isSuccess, setIsSuccess] = useState(false); const [isError, setIsError] = useState(false); const [message, setMessage] = useState<string | null>(null);

useEffect(() => { setLocalMembers(members); setSelectedCount(rawEmails.split(",").filter(Boolean).length); }, [members, rawEmails]);

async function handleClick() { setIsLoading(true); setIsSuccess(false); setIsError(false); setMessage(null); const emails = rawEmails .split(",") .map((email) => email.trim().toLowerCase()) .filter((email) => email && !localMembers.some((member) => member.email === email || member.invitedAt));

try {
  const result = await sendInvites(emails);
  setIsSuccess(true);
  setMessage("Sent " + result.sent.length + " invites");
  setSelectedCount(0);
  setRawEmails("");
} catch (error) {
  setIsError(true);
  setMessage((error as Error).message);
} finally {
  setIsLoading(false);
}

}

return ( <section> <h2>Invite people to {teamName}</h2> <div contentEditable onInput={(event) => setRawEmails(event.currentTarget.textContent || "")} /> <div onClick={handleClick}>Send {selectedCount} invites</div> {isLoading && <p>Sending...</p>} {isSuccess && <p>{message}</p>} {isError && <p>{message}</p>} </section> ); }

evals

SKILL.md

tile.json