-
Couldn't load subscription status.
- Fork 96
fix: Add email validation to invite member form #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,12 +30,20 @@ import { | |
| SelectValue, | ||
| } from "@agentset/ui/select"; | ||
|
|
||
| // Email validation helper | ||
| const isValidEmail = (email: string): boolean => { | ||
| if (!email) return false; | ||
| const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; | ||
| return emailRegex.test(email); | ||
| }; | ||
|
|
||
| function InviteMemberDialog() { | ||
| const [open, setOpen] = useState(false); | ||
| const { id, isAdmin } = useOrganization(); | ||
|
|
||
| const [email, setEmail] = useState(""); | ||
| const [role, setRole] = useState("member"); | ||
| const [emailError, setEmailError] = useState(""); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Manual error state increases complexity. This manual error state contradicts the guideline to "Minimize client-side state." Using Zod with react-hook-form would eliminate the need for this separate state variable, as the form library manages validation state internally. As per coding guidelines 🤖 Prompt for AI Agents |
||
|
|
||
| const trpc = useTRPC(); | ||
| const queryClient = useQueryClient(); | ||
|
|
@@ -69,6 +77,12 @@ function InviteMemberDialog() { | |
| }); | ||
|
|
||
| const handleInvite = () => { | ||
|
|
||
| if (!email || !isValidEmail(email)) { | ||
| setEmailError("Please enter a valid email address"); | ||
| return; | ||
| } | ||
|
|
||
| logEvent("team_invite_member_clicked", { | ||
| organizationId: id, | ||
| email, | ||
|
|
@@ -82,8 +96,18 @@ function InviteMemberDialog() { | |
| }); | ||
| }; | ||
|
|
||
| const handleOpenChange = (isOpen: boolean) => { | ||
| setOpen(isOpen); | ||
|
|
||
| if (!isOpen) { | ||
| setEmail(""); | ||
| setEmailError(""); | ||
| setRole("member"); | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <Dialog open={open} onOpenChange={setOpen}> | ||
| <Dialog open={open} onOpenChange={handleOpenChange}> | ||
| <DialogTrigger asChild disabled={!isAdmin}> | ||
| <Button> | ||
| <PlusIcon className="size-4" /> | ||
|
|
@@ -102,10 +126,24 @@ function InviteMemberDialog() { | |
| <div className="flex flex-col gap-2"> | ||
| <Label>Email</Label> | ||
| <Input | ||
| type="email" | ||
| placeholder="Email" | ||
| value={email} | ||
| onChange={(e) => setEmail(e.target.value)} | ||
| onChange={(e) => { | ||
| const newEmail = e.target.value; | ||
| setEmail(newEmail); | ||
|
|
||
| if (newEmail && !isValidEmail(newEmail)) { | ||
| setEmailError("Please enter a valid email address"); | ||
| } else { | ||
| setEmailError(""); | ||
| } | ||
| }} | ||
| className={emailError ? "border-red-500" : ""} | ||
| /> | ||
| {emailError && ( | ||
| <p className="text-sm text-red-500">{emailError}</p> | ||
| )} | ||
| </div> | ||
|
|
||
| <div className="flex flex-col gap-2"> | ||
|
|
@@ -122,7 +160,11 @@ function InviteMemberDialog() { | |
| </div> | ||
| </div> | ||
| <DialogFooter> | ||
| <Button isLoading={isPending} onClick={handleInvite}> | ||
| <Button | ||
| isLoading={isPending} | ||
| onClick={handleInvite} | ||
| disabled={!email || !!emailError || isPending} | ||
| > | ||
| Invite | ||
| </Button> | ||
| </DialogFooter> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use Zod for validation and move static content to end of file.
This implementation violates two coding guidelines:
Form validation: The guidelines specify "Use Zod for form validation" for files matching
apps/web/**/*.{ts,tsx}. Using regex for email validation is fragile and doesn't provide the type safety and composability that Zod offers.Code organization: The guidelines require "Place static content (consts) and TypeScript interfaces at the end of the file" for files in
apps/web/**/*.{ts,tsx}.As per coding guidelines
Consider refactoring to use Zod with react-hook-form for better validation and error handling:
Then move any remaining static helpers to the end of the file, after the component definition.