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

feat(image-upload): introduce ImageUploadField component for enhanced image uploads

- Added ImageUploadField component to streamline image uploads with improved UI and functionality.
- Integrated file upload handling with a new file service for better management of image uploads.
- Updated SectionStep component to utilize ImageUploadField for icon uploads, enhancing user experience.
- Refactored TenderListFilters to use isDateRangeActive utility for improved date range filtering logic.
This commit is contained in:
AmirReza Jamali
2026-06-06 09:51:32 +03:30
parent a99f86b2f9
commit 5d01d66ea3
11 changed files with 436 additions and 56 deletions
@@ -9,6 +9,7 @@ import {
buildQueryString,
deleteEmptyKeys,
getPaginatedRowNumber,
isDateRangeActive,
unixToDate,
} from "@/utils/shared";
import gsap from "gsap";
@@ -293,6 +294,40 @@ const TENDER_FILTER_MODAL_KEYS = new Set<string>([
...TENDER_RANGE_PARAM_KEYS,
]);
/**
* Applying a date-range filter retargets the table sort to that same field, so the
* results lead with the dates the user just narrowed to. Ordered by precedence — the
* first active range wins when several are applied at once. `sortOrder` mirrors each
* column's default click direction (see `columnDefaultOrder`).
*/
const SORT_TARGET_BY_RANGE_KEY: Array<{
rangeKey: string;
sortBy: string;
sortOrder: SortDirection;
}> = [
{
rangeKey: "publication_date_range",
sortBy: "publication_date",
sortOrder: "desc",
},
{
rangeKey: "submission_deadline_range",
sortBy: "submission_deadline",
sortOrder: "asc",
},
{
rangeKey: "tender_deadline_range",
sortBy: "tender_deadline",
sortOrder: "asc",
},
{ rangeKey: "created_at_range", sortBy: "created_at", sortOrder: "desc" },
];
const resolveSortFromActiveDateFilters = (formData: Record<string, any>) =>
SORT_TARGET_BY_RANGE_KEY.find((target) =>
isDateRangeActive(formData[target.rangeKey]),
) ?? null;
const useTenderListPresenter = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [currentTender, setCurrentTender] = useState<TCustomer | null>(null);
@@ -482,7 +517,22 @@ const useTenderListPresenter = () => {
delete merged[key];
}
}
const newParams = buildFirstPageParams({ ...merged, ...normalizedData });
// Retarget the sort to a freshly applied date filter, but only while the user is
// on the implicit default sort — never clobber a column they sorted on by hand.
const sortTarget = resolveSortFromActiveDateFilters(data);
const currentSortBy = params.sort_by as string | undefined;
const isDefaultSort = !currentSortBy || currentSortBy === "created_at";
const sortOverride =
sortTarget && isDefaultSort
? { sort_by: sortTarget.sortBy, sort_order: sortTarget.sortOrder }
: {};
const newParams = buildFirstPageParams({
...merged,
...normalizedData,
...sortOverride,
});
const cleanedParams = deleteEmptyKeys(newParams);
const queryString = buildQueryString(cleanedParams);
router.push(`${pathName}?${queryString}`);