feat: Add loading states and improve form handling

This commit introduces several enhancements to form components and user experience across the application.

- **Sign-in Form:**
  - Implemented a loading state using `useIsMutating` from TanStack Query.
  - The username and password fields are now disabled during the login process to prevent concurrent submissions.
  - The "Sign in" button displays a spinner while the mutation is pending, providing clear visual feedback.

- **Assign to Company Modal:**
  - Refactored the modal to use `react-hook-form` for more robust state management and validation.
  - The form submission button is now disabled while the assignment request is in progress.

- **Tag Input Component:**
  - Added a new `shouldAddWithSpace` prop to allow creating tags by pressing the space bar, increasing the component's flexibility.

- **Header:**
  - Corrected the image path for the mobile header logo to display the correct icon.
This commit is contained in:
AmirReza Jamali
2025-09-24 10:45:45 +03:30
parent 708f35cf02
commit 3801073fd7
10 changed files with 58 additions and 33 deletions
@@ -1,31 +1,31 @@
import {
Dispatch,
FC,
RefObject,
SetStateAction,
useEffect,
useState,
} from "react";
import { Dispatch, FC, SetStateAction, useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { TAssignCustomerToCompanyCredentials } from "@/lib/api";
import { useCompanyFullList } from "@/hooks/queries";
import { ILabelValue } from "@/types/shared";
import { Select } from "@/components/FormElements/select";
import { Building } from "@/components/Layouts/sidebar/icons";
import { FormErrorMessages } from "@/constants/Texts";
import { useCompanyFullList } from "@/hooks/queries";
import { TAssignCustomerToCompanyCredentials } from "@/lib/api";
import { ILabelValue } from "@/types/shared";
import { useForm } from "react-hook-form";
interface IProps {
setCompanies: Dispatch<
SetStateAction<TAssignCustomerToCompanyCredentials | null>
SetStateAction<TAssignCustomerToCompanyCredentials | undefined>
>;
defaultValues?: TAssignCustomerToCompanyCredentials;
}
const AssignToCompanyModalContent: FC<IProps> = ({ setCompanies }) => {
const AssignToCompanyModalContent: FC<IProps> = ({
setCompanies,
defaultValues,
}) => {
const [options, setOptions] = useState<ILabelValue[]>([]);
const { data, status, isSuccess } = useCompanyFullList();
const { handleSubmit, register } =
useForm<TAssignCustomerToCompanyCredentials>();
useForm<TAssignCustomerToCompanyCredentials>({
mode: "onChange",
defaultValues,
});
useEffect(() => {
if (isSuccess) {
+7 -1
View File
@@ -112,6 +112,9 @@ const CustomersTable = () => {
onClick={() => {
setCurrentCustomer(customer);
setIsAssignCompanyModalOpen(true);
setSelectedCompanies({
company_ids: [customer?.companies?.[0]?.id ?? ""],
});
}}
>
<span className="sr-only">Assign To Company </span>
@@ -145,7 +148,10 @@ const CustomersTable = () => {
isOpen={isAssignCompanyModalOpen}
onClose={() => setIsAssignCompanyModalOpen(false)}
>
<AssignToCompanyModalContent setCompanies={setSelectedCompanies} />
<AssignToCompanyModalContent
setCompanies={setSelectedCompanies}
defaultValues={selectedCompanies}
/>
</Modal>
{isModalOpen && (
<ConfirmationModal
@@ -12,8 +12,9 @@ import { useState } from "react";
const useCustomerListPresenter = () => {
const [isAssignCompanyModalOpen, setIsAssignCompanyModalOpen] =
useState(false);
const [selectedCompanies, setSelectedCompanies] =
useState<TAssignCustomerToCompanyCredentials | null>(null);
const [selectedCompanies, setSelectedCompanies] = useState<
TAssignCustomerToCompanyCredentials | undefined
>();
const [currentCustomer, setCurrentCustomer] = useState<TCustomer | null>(
null,
);
@@ -50,6 +51,7 @@ const useCustomerListPresenter = () => {
deleteCustomer(currentCustomer.id);
}
};
const customers = data?.pages.flatMap((page) => page.data.customers) ?? [];
return {
allCustomers: customers,