mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-11-10 00:45:39 +00:00
fix(frontend): use useId() for input IDs
This commit is contained in:
@@ -14,6 +14,12 @@ import { useAuth } from "../contexts/AuthContext";
|
||||
import { authAPI } from "../utils/api";
|
||||
|
||||
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 [formData, setFormData] = useState({
|
||||
username: "",
|
||||
@@ -212,14 +218,14 @@ const Login = () => {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label
|
||||
htmlFor="username"
|
||||
htmlFor={usernameId}
|
||||
className="block text-sm font-medium text-secondary-700"
|
||||
>
|
||||
{isSignupMode ? "Username" : "Username or Email"}
|
||||
</label>
|
||||
<div className="mt-1 relative">
|
||||
<input
|
||||
id="username"
|
||||
id={usernameId}
|
||||
name="username"
|
||||
type="text"
|
||||
required
|
||||
@@ -243,7 +249,7 @@ const Login = () => {
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label
|
||||
htmlFor="firstName"
|
||||
htmlFor={firstNameId}
|
||||
className="block text-sm font-medium text-secondary-700"
|
||||
>
|
||||
First Name
|
||||
@@ -253,7 +259,7 @@ const Login = () => {
|
||||
<User className="h-5 w-5 text-secondary-400" />
|
||||
</div>
|
||||
<input
|
||||
id="firstName"
|
||||
id={firstNameId}
|
||||
name="firstName"
|
||||
type="text"
|
||||
required
|
||||
@@ -266,7 +272,7 @@ const Login = () => {
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
htmlFor="lastName"
|
||||
htmlFor={lastNameId}
|
||||
className="block text-sm font-medium text-secondary-700"
|
||||
>
|
||||
Last Name
|
||||
@@ -276,7 +282,7 @@ const Login = () => {
|
||||
<User className="h-5 w-5 text-secondary-400" />
|
||||
</div>
|
||||
<input
|
||||
id="lastName"
|
||||
id={lastNameId}
|
||||
name="lastName"
|
||||
type="text"
|
||||
required
|
||||
@@ -290,14 +296,14 @@ const Login = () => {
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
htmlFor={emailId}
|
||||
className="block text-sm font-medium text-secondary-700"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<div className="mt-1 relative">
|
||||
<input
|
||||
id="email"
|
||||
id={emailId}
|
||||
name="email"
|
||||
type="email"
|
||||
required
|
||||
@@ -316,14 +322,14 @@ const Login = () => {
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="password"
|
||||
htmlFor={passwordId}
|
||||
className="block text-sm font-medium text-secondary-700"
|
||||
>
|
||||
Password
|
||||
</label>
|
||||
<div className="mt-1 relative">
|
||||
<input
|
||||
id="password"
|
||||
id={passwordId}
|
||||
name="password"
|
||||
type={showPassword ? "text" : "password"}
|
||||
required
|
||||
@@ -415,14 +421,14 @@ const Login = () => {
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="token"
|
||||
htmlFor={tokenId}
|
||||
className="block text-sm font-medium text-secondary-700"
|
||||
>
|
||||
Verification Code
|
||||
</label>
|
||||
<div className="mt-1">
|
||||
<input
|
||||
id="token"
|
||||
id={tokenId}
|
||||
name="token"
|
||||
type="text"
|
||||
required
|
||||
|
||||
@@ -25,6 +25,13 @@ import { useTheme } from "../contexts/ThemeContext";
|
||||
import { tfaAPI } from "../utils/api";
|
||||
|
||||
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 { theme, toggleTheme, isDark } = useTheme();
|
||||
const [activeTab, setActiveTab] = useState("profile");
|
||||
@@ -250,7 +257,7 @@ const Profile = () => {
|
||||
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
||||
<div>
|
||||
<label
|
||||
htmlFor="username"
|
||||
htmlFor={usernameId}
|
||||
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
Username
|
||||
@@ -259,7 +266,7 @@ const Profile = () => {
|
||||
<input
|
||||
type="text"
|
||||
name="username"
|
||||
id="username"
|
||||
id={usernameId}
|
||||
value={profileData.username}
|
||||
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"
|
||||
@@ -271,7 +278,7 @@ const Profile = () => {
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
htmlFor={emailId}
|
||||
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
Email Address
|
||||
@@ -280,7 +287,7 @@ const Profile = () => {
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
id={emailId}
|
||||
value={profileData.email}
|
||||
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"
|
||||
@@ -292,7 +299,7 @@ const Profile = () => {
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="first_name"
|
||||
htmlFor={firstNameId}
|
||||
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
First Name
|
||||
@@ -301,7 +308,7 @@ const Profile = () => {
|
||||
<input
|
||||
type="text"
|
||||
name="first_name"
|
||||
id="first_name"
|
||||
id={firstNameId}
|
||||
value={profileData.first_name}
|
||||
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"
|
||||
@@ -311,7 +318,7 @@ const Profile = () => {
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="last_name"
|
||||
htmlFor={lastNameId}
|
||||
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
Last Name
|
||||
@@ -320,7 +327,7 @@ const Profile = () => {
|
||||
<input
|
||||
type="text"
|
||||
name="last_name"
|
||||
id="last_name"
|
||||
id={lastNameId}
|
||||
value={profileData.last_name}
|
||||
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"
|
||||
@@ -353,7 +360,7 @@ const Profile = () => {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label
|
||||
htmlFor="currentPassword"
|
||||
htmlFor={currentPasswordId}
|
||||
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
Current Password
|
||||
@@ -362,7 +369,7 @@ const Profile = () => {
|
||||
<input
|
||||
type={showPasswords.current ? "text" : "password"}
|
||||
name="currentPassword"
|
||||
id="currentPassword"
|
||||
id={currentPasswordId}
|
||||
value={passwordData.currentPassword}
|
||||
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"
|
||||
@@ -385,7 +392,7 @@ const Profile = () => {
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="newPassword"
|
||||
htmlFor={newPasswordId}
|
||||
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
New Password
|
||||
@@ -394,7 +401,7 @@ const Profile = () => {
|
||||
<input
|
||||
type={showPasswords.new ? "text" : "password"}
|
||||
name="newPassword"
|
||||
id="newPassword"
|
||||
id={newPasswordId}
|
||||
value={passwordData.newPassword}
|
||||
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"
|
||||
@@ -421,7 +428,7 @@ const Profile = () => {
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="confirmPassword"
|
||||
htmlFor={confirmPasswordId}
|
||||
className="block text-sm font-medium text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
Confirm New Password
|
||||
@@ -430,7 +437,7 @@ const Profile = () => {
|
||||
<input
|
||||
type={showPasswords.confirm ? "text" : "password"}
|
||||
name="confirmPassword"
|
||||
id="confirmPassword"
|
||||
id={confirmPasswordId}
|
||||
value={passwordData.confirmPassword}
|
||||
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"
|
||||
@@ -986,7 +993,11 @@ const TfaTab = () => {
|
||||
</div>
|
||||
</div>
|
||||
<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 Codes
|
||||
</button>
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Link, useParams } from "react-router-dom";
|
||||
import { repositoryAPI } from "../utils/api";
|
||||
|
||||
const RepositoryDetail = () => {
|
||||
const isActiveId = useId();
|
||||
const { repositoryId } = useParams();
|
||||
const queryClient = useQueryClient();
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
@@ -241,7 +242,7 @@ const RepositoryDetail = () => {
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="is_active"
|
||||
id={isActiveId}
|
||||
checked={formData.is_active}
|
||||
onChange={(e) =>
|
||||
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"
|
||||
/>
|
||||
<label
|
||||
htmlFor="is_active"
|
||||
htmlFor={isActiveId}
|
||||
className="ml-2 block text-sm text-secondary-900 dark:text-white"
|
||||
>
|
||||
Repository is active
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import {
|
||||
AlertCircle,
|
||||
CheckCircle,
|
||||
@@ -14,6 +15,7 @@ import {
|
||||
Trash2,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import UpgradeNotificationIcon from "../components/UpgradeNotificationIcon";
|
||||
import { useUpdateNotification } from "../contexts/UpdateNotificationContext";
|
||||
@@ -25,6 +27,10 @@ import {
|
||||
} from "../utils/api";
|
||||
|
||||
const Settings = () => {
|
||||
const repoPublicId = useId();
|
||||
const repoPrivateId = useId();
|
||||
const useCustomSshKeyId = useId();
|
||||
const isDefaultId = useId();
|
||||
const [formData, setFormData] = useState({
|
||||
serverProtocol: "http",
|
||||
serverHost: "localhost",
|
||||
@@ -992,7 +998,7 @@ const Settings = () => {
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="radio"
|
||||
id="repo-public"
|
||||
id={repoPublicId}
|
||||
name="repositoryType"
|
||||
value="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"
|
||||
/>
|
||||
<label
|
||||
htmlFor="repo-public"
|
||||
htmlFor={repoPublicId}
|
||||
className="ml-2 text-sm text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
Public Repository (uses GitHub API - no authentication
|
||||
@@ -1012,7 +1018,7 @@ const Settings = () => {
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="radio"
|
||||
id="repo-private"
|
||||
id={repoPrivateId}
|
||||
name="repositoryType"
|
||||
value="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"
|
||||
/>
|
||||
<label
|
||||
htmlFor="repo-private"
|
||||
htmlFor={repoPrivateId}
|
||||
className="ml-2 text-sm text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
Private Repository (uses SSH with deploy key)
|
||||
@@ -1058,7 +1064,7 @@ const Settings = () => {
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="useCustomSshKey"
|
||||
id={useCustomSshKeyId}
|
||||
checked={formData.useCustomSshKey}
|
||||
onChange={(e) => {
|
||||
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"
|
||||
/>
|
||||
<label
|
||||
htmlFor="useCustomSshKey"
|
||||
htmlFor={useCustomSshKeyId}
|
||||
className="text-sm font-medium text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
Set custom SSH key path
|
||||
@@ -1458,7 +1464,7 @@ const AgentVersionModal = ({ isOpen, onClose, onSubmit, isLoading }) => {
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="isDefault"
|
||||
id={isDefaultId}
|
||||
checked={formData.isDefault}
|
||||
onChange={(e) =>
|
||||
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"
|
||||
/>
|
||||
<label
|
||||
htmlFor="isDefault"
|
||||
htmlFor={isDefaultId}
|
||||
className="ml-2 block text-sm text-secondary-700 dark:text-secondary-200"
|
||||
>
|
||||
Set as default version for new installations
|
||||
|
||||
Reference in New Issue
Block a user