Files
dashboard/components/shared/LocationSelector.tsx
T
Alberto-Audrix 32a36cceff
CI / lint-and-test (push) Canceled after 0s
first commit
2026-07-28 08:55:05 +07:00

120 lines
3.9 KiB
TypeScript

import React, { useState, useEffect, useMemo } from 'react';
import { Location, Coop, Floor } from '../../types';
interface LocationSelectorProps {
locations: Location[];
coops: Coop[];
floors: Floor[];
initialFloorId: string | null;
onFloorChange: (floorId: string | null) => void;
}
const LocationSelector: React.FC<LocationSelectorProps> = ({
locations,
coops,
floors,
initialFloorId,
onFloorChange,
}) => {
const [selectedLocationId, setSelectedLocationId] = useState<string>('');
const [selectedCoopId, setSelectedCoopId] = useState<string>('');
useEffect(() => {
if (initialFloorId) {
const floor = floors.find((f) => f.id === initialFloorId);
const coop = floor ? coops.find((c) => c.id === floor.coopId) : undefined;
const location = coop ? locations.find((l) => l.id === coop.locationId) : undefined;
if (location) setSelectedLocationId(location.id);
if (coop) setSelectedCoopId(coop.id);
} else {
setSelectedLocationId(locations[0]?.id || '');
}
}, [initialFloorId, locations, coops, floors]);
useEffect(() => {
if (!initialFloorId) {
const firstCoop = coops.find((c) => c.locationId === selectedLocationId);
setSelectedCoopId(firstCoop?.id || '');
}
}, [selectedLocationId, coops, initialFloorId]);
useEffect(() => {
if (!initialFloorId) {
const firstFloor = floors.find((f) => f.coopId === selectedCoopId);
onFloorChange(firstFloor?.id || null);
}
// We only want this to run when the coop changes, not when the parent's floor changes.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedCoopId, floors, initialFloorId]);
const availableCoops = useMemo(
() => coops.filter((c) => c.locationId === selectedLocationId),
[coops, selectedLocationId]
);
const availableFloors = useMemo(
() => floors.filter((f) => f.coopId === selectedCoopId),
[floors, selectedCoopId]
);
return (
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div>
<label htmlFor="location" className="block text-sm font-medium text-gray-700 mb-1">
Lokasi
</label>
<select
id="location"
value={selectedLocationId}
onChange={(e) => setSelectedLocationId(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-red-500 focus:border-red-500 bg-white"
>
{locations.map((l) => (
<option key={l.id} value={l.id}>
{l.name}
</option>
))}
</select>
</div>
<div>
<label htmlFor="coop" className="block text-sm font-medium text-gray-700 mb-1">
Kandang
</label>
<select
id="coop"
value={selectedCoopId}
onChange={(e) => setSelectedCoopId(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-red-500 focus:border-red-500 bg-white"
disabled={!selectedLocationId}
>
{availableCoops.map((c) => (
<option key={c.id} value={c.id}>
{c.name}
</option>
))}
</select>
</div>
<div>
<label htmlFor="floor" className="block text-sm font-medium text-gray-700 mb-1">
Lantai
</label>
<select
id="floor"
value={initialFloorId || ''}
onChange={(e) => onFloorChange(e.target.value || null)}
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-red-500 focus:border-red-500 bg-white"
disabled={!selectedCoopId}
>
<option value="">-- Pilih Lantai --</option>
{availableFloors.map((f) => (
<option key={f.id} value={f.id}>
{f.name}
</option>
))}
</select>
</div>
</div>
);
};
export default LocationSelector;