fix(frontend): use useId() for input IDs

This commit is contained in:
tigattack
2025-09-24 22:54:28 +01:00
parent a11f180d23
commit 15902da87c
4 changed files with 61 additions and 37 deletions

View File

@@ -14,6 +14,12 @@ import { useAuth } from "../contexts/AuthContext";
import { authAPI } from "../utils/api"; import { authAPI } from "../utils/api";
const Login = () => { const Login = () => {
const usernameId = useId();
const firstNameId = useId();
const lastNameId = useId();
const emailId = useId();
const passwordId = useId();
const tokenId = useId();
const [isSignupMode, setIsSignupMode] = useState(false); const [isSignupMode, setIsSignupMode] = useState(false);
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
username: "", username: "",
@@ -212,14 +218,14 @@ const Login = () => {
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<label <label
htmlFor="username" htmlFor={usernameId}
className="block text-sm font-medium text-secondary-700" className="block text-sm font-medium text-secondary-700"
> >
{isSignupMode ? "Username" : "Username or Email"} {isSignupMode ? "Username" : "Username or Email"}
</label> </label>
<div className="mt-1 relative"> <div className="mt-1 relative">
<input <input
id="username" id={usernameId}
name="username" name="username"
type="text" type="text"
required required
@@ -243,7 +249,7 @@ const Login = () => {
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<label <label
htmlFor="firstName" htmlFor={firstNameId}
className="block text-sm font-medium text-secondary-700" className="block text-sm font-medium text-secondary-700"
> >
First Name First Name
@@ -253,7 +259,7 @@ const Login = () => {
<User className="h-5 w-5 text-secondary-400" /> <User className="h-5 w-5 text-secondary-400" />
</div> </div>
<input <input
id="firstName" id={firstNameId}
name="firstName" name="firstName"
type="text" type="text"
required required
@@ -266,7 +272,7 @@ const Login = () => {
</div> </div>
<div> <div>
<label <label
htmlFor="lastName" htmlFor={lastNameId}
className="block text-sm font-medium text-secondary-700" className="block text-sm font-medium text-secondary-700"
> >
Last Name Last Name
@@ -276,7 +282,7 @@ const Login = () => {
<User className="h-5 w-5 text-secondary-400" /> <User className="h-5 w-5 text-secondary-400" />
</div> </div>
<input <input
id="lastName" id={lastNameId}
name="lastName" name="lastName"
type="text" type="text"
required required
@@ -290,14 +296,14 @@ const Login = () => {
</div> </div>
<div> <div>
<label <label
htmlFor="email" htmlFor={emailId}
className="block text-sm font-medium text-secondary-700" className="block text-sm font-medium text-secondary-700"
> >
Email Email
</label> </label>
<div className="mt-1 relative"> <div className="mt-1 relative">
<input <input
id="email" id={emailId}
name="email" name="email"
type="email" type="email"
required required
@@ -316,14 +322,14 @@ const Login = () => {
<div> <div>
<label <label
htmlFor="password" htmlFor={passwordId}
className="block text-sm font-medium text-secondary-700" className="block text-sm font-medium text-secondary-700"
> >
Password Password
</label> </label>
<div className="mt-1 relative"> <div className="mt-1 relative">
<input <input
id="password" id={passwordId}
name="password" name="password"
type={showPassword ? "text" : "password"} type={showPassword ? "text" : "password"}
required required
@@ -415,14 +421,14 @@ const Login = () => {
<div> <div>
<label <label
htmlFor="token" htmlFor={tokenId}
className="block text-sm font-medium text-secondary-700" className="block text-sm font-medium text-secondary-700"
> >
Verification Code Verification Code
</label> </label>
<div className="mt-1"> <div className="mt-1">
<input <input
id="token" id={tokenId}
name="token" name="token"
type="text" type="text"
required required

View File

@@ -25,6 +25,13 @@ import { useTheme } from "../contexts/ThemeContext";
import { tfaAPI } from "../utils/api"; import { tfaAPI } from "../utils/api";
const Profile = () => { const Profile = () => {
const usernameId = useId();
const emailId = useId();
const firstNameId = useId();
const lastNameId = useId();
const currentPasswordId = useId();
const newPasswordId = useId();
const confirmPasswordId = useId();
const { user, updateProfile, changePassword } = useAuth(); const { user, updateProfile, changePassword } = useAuth();
const { theme, toggleTheme, isDark } = useTheme(); const { theme, toggleTheme, isDark } = useTheme();
const [activeTab, setActiveTab] = useState("profile"); const [activeTab, setActiveTab] = useState("profile");
@@ -250,7 +257,7 @@ const Profile = () => {
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2"> <div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div> <div>
<label <label
htmlFor="username" htmlFor={usernameId}
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200" className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
> >
Username Username
@@ -259,7 +266,7 @@ const Profile = () => {
<input <input
type="text" type="text"
name="username" name="username"
id="username" id={usernameId}
value={profileData.username} value={profileData.username}
onChange={handleInputChange} onChange={handleInputChange}
className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 pl-10 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white" className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 pl-10 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white"
@@ -271,7 +278,7 @@ const Profile = () => {
<div> <div>
<label <label
htmlFor="email" htmlFor={emailId}
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200" className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
> >
Email Address Email Address
@@ -280,7 +287,7 @@ const Profile = () => {
<input <input
type="email" type="email"
name="email" name="email"
id="email" id={emailId}
value={profileData.email} value={profileData.email}
onChange={handleInputChange} onChange={handleInputChange}
className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 pl-10 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white" className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 pl-10 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white"
@@ -292,7 +299,7 @@ const Profile = () => {
<div> <div>
<label <label
htmlFor="first_name" htmlFor={firstNameId}
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200" className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
> >
First Name First Name
@@ -301,7 +308,7 @@ const Profile = () => {
<input <input
type="text" type="text"
name="first_name" name="first_name"
id="first_name" id={firstNameId}
value={profileData.first_name} value={profileData.first_name}
onChange={handleInputChange} onChange={handleInputChange}
className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white" className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white"
@@ -311,7 +318,7 @@ const Profile = () => {
<div> <div>
<label <label
htmlFor="last_name" htmlFor={lastNameId}
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200" className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
> >
Last Name Last Name
@@ -320,7 +327,7 @@ const Profile = () => {
<input <input
type="text" type="text"
name="last_name" name="last_name"
id="last_name" id={lastNameId}
value={profileData.last_name} value={profileData.last_name}
onChange={handleInputChange} onChange={handleInputChange}
className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white" className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white"
@@ -353,7 +360,7 @@ const Profile = () => {
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<label <label
htmlFor="currentPassword" htmlFor={currentPasswordId}
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200" className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
> >
Current Password Current Password
@@ -362,7 +369,7 @@ const Profile = () => {
<input <input
type={showPasswords.current ? "text" : "password"} type={showPasswords.current ? "text" : "password"}
name="currentPassword" name="currentPassword"
id="currentPassword" id={currentPasswordId}
value={passwordData.currentPassword} value={passwordData.currentPassword}
onChange={handleInputChange} onChange={handleInputChange}
className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 pl-10 pr-10 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white" className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 pl-10 pr-10 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white"
@@ -385,7 +392,7 @@ const Profile = () => {
<div> <div>
<label <label
htmlFor="newPassword" htmlFor={newPasswordId}
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200" className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
> >
New Password New Password
@@ -394,7 +401,7 @@ const Profile = () => {
<input <input
type={showPasswords.new ? "text" : "password"} type={showPasswords.new ? "text" : "password"}
name="newPassword" name="newPassword"
id="newPassword" id={newPasswordId}
value={passwordData.newPassword} value={passwordData.newPassword}
onChange={handleInputChange} onChange={handleInputChange}
className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 pl-10 pr-10 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white" className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 pl-10 pr-10 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white"
@@ -421,7 +428,7 @@ const Profile = () => {
<div> <div>
<label <label
htmlFor="confirmPassword" htmlFor={confirmPasswordId}
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200" className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
> >
Confirm New Password Confirm New Password
@@ -430,7 +437,7 @@ const Profile = () => {
<input <input
type={showPasswords.confirm ? "text" : "password"} type={showPasswords.confirm ? "text" : "password"}
name="confirmPassword" name="confirmPassword"
id="confirmPassword" id={confirmPasswordId}
value={passwordData.confirmPassword} value={passwordData.confirmPassword}
onChange={handleInputChange} onChange={handleInputChange}
className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 pl-10 pr-10 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white" className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 pl-10 pr-10 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white"
@@ -986,7 +993,11 @@ const TfaTab = () => {
</div> </div>
</div> </div>
<div className="flex space-x-3"> <div className="flex space-x-3">
<button type="button" onClick={downloadBackupCodes} className="btn-outline"> <button
type="button"
onClick={downloadBackupCodes}
className="btn-outline"
>
<Download className="h-4 w-4 mr-2" /> <Download className="h-4 w-4 mr-2" />
Download Codes Download Codes
</button> </button>

View File

@@ -18,6 +18,7 @@ import { Link, useParams } from "react-router-dom";
import { repositoryAPI } from "../utils/api"; import { repositoryAPI } from "../utils/api";
const RepositoryDetail = () => { const RepositoryDetail = () => {
const isActiveId = useId();
const { repositoryId } = useParams(); const { repositoryId } = useParams();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [editMode, setEditMode] = useState(false); const [editMode, setEditMode] = useState(false);
@@ -241,7 +242,7 @@ const RepositoryDetail = () => {
<div className="flex items-center"> <div className="flex items-center">
<input <input
type="checkbox" type="checkbox"
id="is_active" id={isActiveId}
checked={formData.is_active} checked={formData.is_active}
onChange={(e) => onChange={(e) =>
setFormData({ ...formData, is_active: e.target.checked }) setFormData({ ...formData, is_active: e.target.checked })
@@ -249,7 +250,7 @@ const RepositoryDetail = () => {
className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-secondary-300 rounded" className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-secondary-300 rounded"
/> />
<label <label
htmlFor="is_active" htmlFor={isActiveId}
className="ml-2 block text-sm text-secondary-900 dark:text-white" className="ml-2 block text-sm text-secondary-900 dark:text-white"
> >
Repository is active Repository is active

View File

@@ -1,4 +1,5 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { import {
AlertCircle, AlertCircle,
CheckCircle, CheckCircle,
@@ -14,6 +15,7 @@ import {
Trash2, Trash2,
X, X,
} from "lucide-react"; } from "lucide-react";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import UpgradeNotificationIcon from "../components/UpgradeNotificationIcon"; import UpgradeNotificationIcon from "../components/UpgradeNotificationIcon";
import { useUpdateNotification } from "../contexts/UpdateNotificationContext"; import { useUpdateNotification } from "../contexts/UpdateNotificationContext";
@@ -25,6 +27,10 @@ import {
} from "../utils/api"; } from "../utils/api";
const Settings = () => { const Settings = () => {
const repoPublicId = useId();
const repoPrivateId = useId();
const useCustomSshKeyId = useId();
const isDefaultId = useId();
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
serverProtocol: "http", serverProtocol: "http",
serverHost: "localhost", serverHost: "localhost",
@@ -992,7 +998,7 @@ const Settings = () => {
<div className="flex items-center"> <div className="flex items-center">
<input <input
type="radio" type="radio"
id="repo-public" id={repoPublicId}
name="repositoryType" name="repositoryType"
value="public" value="public"
checked={formData.repositoryType === "public"} checked={formData.repositoryType === "public"}
@@ -1002,7 +1008,7 @@ const Settings = () => {
className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300" className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300"
/> />
<label <label
htmlFor="repo-public" htmlFor={repoPublicId}
className="ml-2 text-sm text-secondary-700 dark:text-secondary-200" className="ml-2 text-sm text-secondary-700 dark:text-secondary-200"
> >
Public Repository (uses GitHub API - no authentication Public Repository (uses GitHub API - no authentication
@@ -1012,7 +1018,7 @@ const Settings = () => {
<div className="flex items-center"> <div className="flex items-center">
<input <input
type="radio" type="radio"
id="repo-private" id={repoPrivateId}
name="repositoryType" name="repositoryType"
value="private" value="private"
checked={formData.repositoryType === "private"} checked={formData.repositoryType === "private"}
@@ -1022,7 +1028,7 @@ const Settings = () => {
className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300" className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300"
/> />
<label <label
htmlFor="repo-private" htmlFor={repoPrivateId}
className="ml-2 text-sm text-secondary-700 dark:text-secondary-200" className="ml-2 text-sm text-secondary-700 dark:text-secondary-200"
> >
Private Repository (uses SSH with deploy key) Private Repository (uses SSH with deploy key)
@@ -1058,7 +1064,7 @@ const Settings = () => {
<div className="flex items-center gap-3 mb-3"> <div className="flex items-center gap-3 mb-3">
<input <input
type="checkbox" type="checkbox"
id="useCustomSshKey" id={useCustomSshKeyId}
checked={formData.useCustomSshKey} checked={formData.useCustomSshKey}
onChange={(e) => { onChange={(e) => {
const checked = e.target.checked; const checked = e.target.checked;
@@ -1070,7 +1076,7 @@ const Settings = () => {
className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded" className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded"
/> />
<label <label
htmlFor="useCustomSshKey" htmlFor={useCustomSshKeyId}
className="text-sm font-medium text-secondary-700 dark:text-secondary-200" className="text-sm font-medium text-secondary-700 dark:text-secondary-200"
> >
Set custom SSH key path Set custom SSH key path
@@ -1458,7 +1464,7 @@ const AgentVersionModal = ({ isOpen, onClose, onSubmit, isLoading }) => {
<div className="flex items-center"> <div className="flex items-center">
<input <input
type="checkbox" type="checkbox"
id="isDefault" id={isDefaultId}
checked={formData.isDefault} checked={formData.isDefault}
onChange={(e) => onChange={(e) =>
setFormData((prev) => ({ setFormData((prev) => ({
@@ -1469,7 +1475,7 @@ const AgentVersionModal = ({ isOpen, onClose, onSubmit, isLoading }) => {
className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-secondary-300 dark:border-secondary-600 rounded" className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-secondary-300 dark:border-secondary-600 rounded"
/> />
<label <label
htmlFor="isDefault" htmlFor={isDefaultId}
className="ml-2 block text-sm text-secondary-700 dark:text-secondary-200" className="ml-2 block text-sm text-secondary-700 dark:text-secondary-200"
> >
Set as default version for new installations Set as default version for new installations