Files
edr-platform/apps/edr-freight-web/backoffice/src/user-management/userManagement/components/UnitSelectionModal.tsx
natib21 22cf8eabd1 fix ui
2026-07-14 07:59:17 +00:00

147 lines
5.0 KiB
TypeScript

import React, { useState } from "react";
import { Button } from "@/shared/common/ui/button";
import { X, ChevronLeft, ChevronRight } from "lucide-react";
import { t } from "i18next";
interface UnitSelectionModalProps {
units: unknown[];
isLoading: boolean;
onSelectUnit: (unitId: string) => void;
onClose: () => void;
}
const UNITS_PER_PAGE = 10;
export const UnitSelectionModal: React.FC<UnitSelectionModalProps> = ({
units,
isLoading,
onSelectUnit,
onClose,
}) => {
const [currentPage, setCurrentPage] = useState(0);
const typedUnits = units
.filter(
(unit): unit is { id: string; name: any; description?: string } =>
typeof unit === "object" &&
unit !== null &&
"id" in unit &&
"name" in unit
);
const totalPages = Math.ceil(typedUnits.length / UNITS_PER_PAGE);
const startIndex = currentPage * UNITS_PER_PAGE;
const endIndex = startIndex + UNITS_PER_PAGE;
const currentUnits = typedUnits.slice(startIndex, endIndex);
const handleNext = () => {
if (currentPage < totalPages - 1) {
setCurrentPage(currentPage + 1);
}
};
const handlePrevious = () => {
if (currentPage > 0) {
setCurrentPage(currentPage - 1);
}
};
return (
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 max-w-2xl w-full mx-4 shadow-xl">
{/* Header */}
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold dark:text-white">
{t("selectUnit")}
</h3>
<button
onClick={onClose}
className="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 focus:outline-none dark:hover:bg-gray-700 rounded"
aria-label="Close"
>
<X className="h-5 w-5" />
</button>
</div>
{/* Content */}
{isLoading ? (
<div className="text-center py-12">
<div className="flex flex-col items-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary-600 mx-auto"></div>
<p className="mt-2 dark:text-gray-400">{t("loadingUnits")}</p>
</div>
</div>
) : (
<>
{/* Units List */}
<div className="space-y-2 mb-4">
{currentUnits.length > 0 ? (
currentUnits.map((unit) => (
<button
key={unit.id}
onClick={() => onSelectUnit(unit.id)}
className="w-full text-left p-4 rounded border border-gray-200 hover:bg-gray-100 hover:shadow-sm transition-all focus:outline-none focus:ring-2 focus:ring-primary-500 cursor-pointer dark:border-gray-600 dark:hover:bg-gray-700 dark:focus:ring-primary-400"
>
<div className="font-medium dark:text-gray-200 truncate">
{unit.name?.en || unit.name}
</div>
{unit.description && (
<div className="text-sm text-gray-500 dark:text-gray-400 truncate mt-1">
{unit.description}
</div>
)}
</button>
))
) : (
<div className="text-center py-8 text-gray-500 dark:text-gray-400">
<p>{t("noUnitsFound")}</p>
</div>
)}
</div>
{/* Pagination Info */}
{totalPages > 1 && (
<div className="text-center text-sm text-gray-600 dark:text-gray-400 mb-4">
{t("page", {
current: currentPage + 1,
total: totalPages,
defaultValue: `Page ${currentPage + 1} of ${totalPages}`,
})}
</div>
)}
{/* Footer with Pagination */}
<div className="flex items-center justify-between pt-4 border-t border-gray-200 dark:border-gray-700">
<Button
variant="outline"
size="sm"
onClick={handlePrevious}
disabled={currentPage === 0}
className="dark:border-gray-600 dark:text-gray-200 dark:hover:bg-gray-700"
>
<ChevronLeft className="h-4 w-4 mr-1" />
{t("previous")}
</Button>
<span className="text-sm text-gray-600 dark:text-gray-400">
{typedUnits.length > 0
? `${startIndex + 1} - ${Math.min(endIndex, typedUnits.length)} of ${typedUnits.length}`
: "0"}
</span>
<Button
variant="outline"
size="sm"
onClick={handleNext}
disabled={currentPage >= totalPages - 1}
className="dark:border-gray-600 dark:text-gray-200 dark:hover:bg-gray-700"
>
{t("next")}
<ChevronRight className="h-4 w-4 ml-1" />
</Button>
</div>
</>
)}
</div>
);
};