mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 00:52:50 +00:00
147 lines
5.0 KiB
TypeScript
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>
|
|
);
|
|
};
|