120 lines
3.9 KiB
TypeScript
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;
|