chore(env): update application version to 2.2.4 in production environment

feat(multi-select): enhance MultiSelect component with dropdown positioning and portal rendering

- Added dynamic dropdown positioning to ensure it appears correctly relative to the trigger element.
- Implemented portal rendering for the dropdown to improve performance and prevent overflow issues.
- Refactored MultiSelect state management for better clarity and maintainability.

feat(switch): improve Switch component with GSAP animations and enhanced styling

- Integrated GSAP animations for thumb transitions and glow effects to enhance user interaction.
- Updated styling for the Switch component to improve visual feedback and responsiveness.

feat(companies-table): add currency and language metadata display in CompaniesTable

- Introduced currency and language metadata for better representation of company details.
- Enhanced UI for displaying company languages and currencies with tooltips for additional context.

feat(assign-to-company-modal): refactor AssignToCompanyModalContent to use MultiSelect

- Replaced Select component with MultiSelect for improved user experience in selecting companies.
- Streamlined state management and data handling for company assignments.

feat(customers-table): enhance customer company display with tooltips and improved layout

- Updated customer company display to show a maximum of two companies with a tooltip for additional companies.
- Improved styling for better visual representation of customer associations with companies.

feat(confirmation-modal): enhance ConfirmationModal with animations and improved accessibility

- Added GSAP animations for modal entrance and exit to improve user experience.
- Implemented accessibility features for better keyboard navigation and focus management.

feat(status): extend Status component with pulse and shimmer effects for enhanced visual feedback

- Introduced new visual effects for status indicators to improve user engagement and clarity.
- Updated styles for better integration with existing UI components.

feat(tooltip): enhance tooltip styling and functionality with new palettes

- Implemented a new tooltip design with gradient backgrounds and shadows for improved visibility.
- Updated tooltip parameters to support new styling options and enhance user experience.
This commit is contained in:
AmirReza Jamali
2026-05-24 13:07:07 +03:30
parent 48f0b3ce2e
commit 36334119bd
13 changed files with 829 additions and 165 deletions
@@ -1,18 +1,12 @@
import {
ChangeEvent,
Dispatch,
FC,
SetStateAction,
useEffect,
useState,
} from "react";
import { Dispatch, FC, SetStateAction, useCallback, useMemo, useState } from "react";
import { Select } from "@/components/FormElements/select";
import { Building } from "@/components/Layouts/sidebar/icons";
import { ApiResponse, TAssignCustomerToCompanyCredentials, TCompaniesResponse } from "@/lib/api";
import { ILabelValue } from "@/types/shared";
import MultiSelect from "@/components/FormElements/MultiSelect";
import {
ApiResponse,
TAssignCustomerToCompanyCredentials,
TCompaniesResponse,
} from "@/lib/api";
import { UseQueryResult } from "@tanstack/react-query";
import { useForm } from "react-hook-form";
interface IProps {
companiesQuery: UseQueryResult<ApiResponse<TCompaniesResponse>, Error>;
@@ -21,66 +15,52 @@ interface IProps {
>;
defaultValues?: TAssignCustomerToCompanyCredentials;
}
const AssignToCompanyModalContent: FC<IProps> = ({
companiesQuery,
setCompanies,
defaultValues,
}) => {
const [options, setOptions] = useState<ILabelValue[]>([]);
const { data, isSuccess } = companiesQuery;
const [selected, setSelected] = useState<string[]>(
defaultValues?.companies ?? [],
);
const { data, status, isSuccess } = companiesQuery;
const { handleSubmit, watch, setValue } =
useForm<TAssignCustomerToCompanyCredentials>({
mode: "onChange",
defaultValues,
});
const options = useMemo(() => {
if (!isSuccess) return [];
return (
data?.data.companies?.map((item) => ({
label: item.name,
value: item.id,
})) ?? []
);
}, [isSuccess, data?.data.companies]);
const selectedCompanyId = watch("company_ids")?.[0] || "";
const handleChange = useCallback(
(event: { target: { value: string[] } }) => {
const next = event.target.value;
setSelected(next);
setCompanies({ companies: next });
},
[setCompanies],
);
useEffect(() => {
if (isSuccess) {
setOptions(
data.data.companies
? data.data.companies?.map((item) => ({
label: item.name,
value: item.id,
}))
: [],
);
}
}, [status, isSuccess, data?.data.companies]);
const noop = useCallback(() => {}, []);
useEffect(() => {
if (defaultValues?.company_ids?.[0]) {
setValue("company_ids", defaultValues.company_ids);
}
}, [defaultValues, setValue]);
const assignCompany = (data: TAssignCustomerToCompanyCredentials) => {
setCompanies(data);
};
return (
<form className="mt-5" onSubmit={handleSubmit(assignCompany)}>
<Select
name="company_ids"
clearable
<div className="mt-5">
<MultiSelect
name="companies"
label="Companies"
items={options}
prefixIcon={<Building />}
placeholder="Please Select company"
value={selectedCompanyId}
onChange={
((e: ChangeEvent<HTMLSelectElement>) => {
const value = e.target.value;
setValue("company_ids", [value]);
setCompanies({
company_ids: [value],
});
}) as any
}
value={selected}
placeholder="Please select companies"
required
onChange={handleChange as any}
onBlur={noop as any}
ref={noop as any}
/>
</form>
</div>
);
};
+48 -8
View File
@@ -120,11 +120,47 @@ const CustomersTable = () => {
</TableCell>
<TableCell colSpan={100}>
{customer?.companies?.length ? (
customer?.companies.map((c) => (
<span key={c.id}>{c.name}, </span>
))
<div className="flex max-w-[260px] flex-wrap items-center gap-1.5">
{customer.companies.slice(0, 2).map((c) => (
<span
key={c.id}
data-tooltip-id={`company-${customer.id}-${c.id}`}
data-tooltip-content={c.name}
className="inline-flex max-w-[140px] items-center gap-1.5 rounded-full border border-primary/20 bg-primary/10 px-2.5 py-1 text-xs font-medium text-primary transition-colors hover:bg-primary/20 dark:border-primary/30 dark:bg-primary/20 dark:text-white"
>
<Building className="h-3 w-3 shrink-0" />
<span className="truncate">{c.name}</span>
<Tooltip
{..._TooltipDefaultParams({
id: `company-${customer.id}-${c.id}`,
})}
/>
</span>
))}
{customer.companies.length > 2 && (
<>
<span
data-tooltip-id={`company-more-${customer.id}`}
data-tooltip-content={customer.companies
.slice(2)
.map((c) => c.name)
.join(", ")}
className="inline-flex cursor-default items-center rounded-full border border-stroke bg-gray-2 px-2.5 py-1 text-xs font-semibold text-dark transition-colors hover:bg-gray-3 dark:border-dark-3 dark:bg-dark-3 dark:text-white"
>
+{customer.companies.length - 2}
</span>
<Tooltip
{..._TooltipDefaultParams({
id: `company-more-${customer.id}`,
})}
/>
</>
)}
</div>
) : (
<span>None</span>
<span className="inline-flex items-center gap-1 rounded-full border border-dashed border-stroke px-2.5 py-1 text-xs font-medium text-dark-5 dark:border-dark-3 dark:text-dark-6">
None
</span>
)}
</TableCell>
<TableCell colSpan={100} className="uppercase">
@@ -168,7 +204,8 @@ const CustomersTable = () => {
setCurrentCustomer(customer);
setIsAssignCompanyModalOpen(true);
setSelectedCompanies({
company_ids: [customer?.companies?.[0]?.id ?? ""],
companies:
customer?.companies?.map((c) => c.id) ?? [],
});
}}
>
@@ -210,12 +247,15 @@ const CustomersTable = () => {
<Modal
classNames="w-full xl:w-1/2"
onConfirm={() => {
if (!selectedCompanies || !currentCustomer) {
toast.error("Invalid credentials");
if (
!currentCustomer ||
!selectedCompanies?.companies?.length
) {
toast.error("Please select at least one company");
return;
}
assignSelectedCompanies({
credentials: selectedCompanies,
credentials: { companies: selectedCompanies.companies },
id: currentCustomer?.id ?? "",
});
}}