refactor(tender-details): enhance translation and summary features

- Integrated language selection and translation functionality in TenderDetails, allowing users to choose display language and translate tender metadata.
- Added AI summary section to display overall summary of the tender.
- Updated API service to support translation requests and handle responses effectively.
- Improved pagination handling in AdminsTable for better user experience.
- Refactored various components to ensure consistent data flow and state management.
This commit is contained in:
AmirReza Jamali
2026-05-10 08:44:03 +03:30
parent f48cb7e249
commit f01632e38d
14 changed files with 378 additions and 33 deletions
+24 -1
View File
@@ -3,9 +3,11 @@
import { PencilSquareIcon, TrashIcon, UserSettingIcon } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import ConfirmationModal from "@/components/ui/ConfirmationModal";
import IsVisible from "@/components/ui/IsVisible";
import ListHeader from "@/components/ui/ListHeader";
import ListWrapper from "@/components/ui/ListWrapper";
import Modal from "@/components/ui/modal";
import Pagination from "@/components/ui/pagination";
import Status from "@/components/ui/Status";
import {
Table,
@@ -48,6 +50,9 @@ const AdminsTable = () => {
filterRegister,
isMutating,
watch,
metadata,
setParams,
shouldShowPagination,
} = useAdminsPresenter();
return (
@@ -77,6 +82,7 @@ const AdminsTable = () => {
list={allUsers}
columns={columns}
emptyMessage="No admins were found"
isLoading={isPending}
>
{allUsers.map((item, index) => (
<TableRow
@@ -85,7 +91,11 @@ const AdminsTable = () => {
data-cy={`admins-table-row-${item?.id ?? index}`}
>
<TableCell className="text-start" colSpan={100} data-cy="admins-row-number">
{getPaginatedRowNumber({ index })}
{getPaginatedRowNumber({
index,
page: metadata?.page,
limit: metadata?.limit,
})}
</TableCell>
<TableCell className="text-start" colSpan={100} data-cy="admins-row-full-name">
{item?.full_name}
@@ -200,6 +210,19 @@ const AdminsTable = () => {
onCancel={() => setIsModalOpen(false)}
/>
)}
<IsVisible condition={shouldShowPagination}>
<Pagination
currentPage={metadata?.page ? metadata.page - 1 : 0}
totalPages={metadata?.pages ?? 1}
onPageChange={(e) => {
setParams((currentParams) => ({
...currentParams,
offset: e.selected * (metadata?.limit ?? 10),
limit: metadata?.limit ?? 10,
}));
}}
/>
</IsVisible>
</ListWrapper>
);
};
@@ -58,7 +58,9 @@ export const useAdminsPresenter = () => {
setParams(newParams);
filterFormReset(newParams);
}, [searchParams, filterFormReset]);
const { data, isPending } = useGetAdminListQuery(params);
const { data, isPending } = useGetAdminListQuery({ ...params, ...apiDefaultParams });
const shouldShowPagination =
!isPending && (data?.meta?.pages ?? 1) * (data?.meta?.limit ?? 10) > 10;
const { mutate: deleteAdmin } = useDeleteAdmin(() => {
setIsModalOpen(false);
});
@@ -121,5 +123,6 @@ export const useAdminsPresenter = () => {
handleFilterSubmit,
search,
watch,
shouldShowPagination,
};
};
@@ -3,6 +3,7 @@ import { Select } from "@/components/FormElements/select";
import { Button } from "@/components/ui-elements/button";
import { Countries } from "@/constants/countries";
import { TenderStatus } from "@/constants/enums";
import { Languages } from "@/constants/languages";
import { getEnumAsArray } from "@/utils/shared";
import {
FieldValues,
@@ -63,6 +64,16 @@ const TenderListFilters = ({
value={watch("country_code")}
onClear={() => setValue("country_code", undefined)}
/>
<Select
{...filterRegister("lang")}
items={Languages}
label="language"
name="lang"
placeholder="Language"
clearable
value={watch("lang")}
onClear={() => setValue("lang", undefined)}
/>
<div className="col-span-2 flex gap-4">
<Button
+9 -2
View File
@@ -32,6 +32,7 @@ const TendersTable = () => {
router,
pathName,
setParams,
params,
columns,
isFilterModalOpen,
setIsFilterModalOpen,
@@ -119,7 +120,10 @@ const TendersTable = () => {
data-tooltip-content="Details"
data-tooltip-place="top"
onClick={() => {
router.push(`${pathName}/${item.id}`);
const queryString = params?.lang
? `?lang=${encodeURIComponent(params.lang)}`
: "";
router.push(`${pathName}/${item.id}${queryString}`);
}}
>
<Tooltip
@@ -135,7 +139,10 @@ const TendersTable = () => {
data-tooltip-place="top"
className="text-gray-40 rounded-full bg-gray-dark bg-opacity-5 hover:text-green-dark dark:bg-gray dark:bg-opacity-5"
onClick={() => {
router.push(`${pathName}/feedback/${item.id}`);
const queryString = params?.lang
? `?lang=${encodeURIComponent(params.lang)}`
: "";
router.push(`${pathName}/feedback/${item.id}${queryString}`);
}}
>
<Tooltip {..._TooltipDefaultParams({ id: "feedback" })} />
@@ -34,6 +34,7 @@ const useTenderListPresenter = () => {
...apiDefaultParams,
offset: 0,
limit: 10,
lang: "en",
};
for (const [key, value] of searchParams.entries()) {
newParams[key] = value;
@@ -73,6 +74,7 @@ const useTenderListPresenter = () => {
error,
isPending,
setParams,
params,
data,
pathName,
isModalOpen,
@@ -23,8 +23,8 @@ const useCreateAdminPresenter = ({
id,
}: IProps) => {
const [passwordFieldInputType, setPasswordFieldInputType] = useState<
"password" | "text"
>("password");
"password" | "text"
>("password");
const isMutating = useIsMutating();
const [selectedFileName, setSelectedFileName] = useState<string>("");
const [selectedFileSize, setSelectedFileSize] = useState<number | null>(null);