運搬計画: グループ一括割り当て機能を追加
各回の追加ドロップダウンに「+ グループを追加...」を追加。 グループ内の全圃場の未割り当て分を一括で回に追加できるようにした。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -433,6 +433,32 @@ export default function DeliveryEditPage({ planId }: Props) {
|
||||
]);
|
||||
};
|
||||
|
||||
// グループの全圃場をtripに一括割り当て
|
||||
const assignGroupToTrip = (groupTempId: string, tripTempId: string) => {
|
||||
const group = groups.find(g => g.tempId === groupTempId);
|
||||
if (!group) return;
|
||||
setTrips(prev => prev.map(t => {
|
||||
if (t.tempId !== tripTempId) return t;
|
||||
const newItems = [...t.items];
|
||||
for (const fieldId of group.fieldIds) {
|
||||
for (const fert of selectedFertilizers) {
|
||||
const remaining = getUnassignedBags(fieldId, fert.id);
|
||||
if (remaining > 0) {
|
||||
const existing = newItems.find(
|
||||
item => item.fieldId === fieldId && item.fertilizerId === fert.id
|
||||
);
|
||||
if (existing) {
|
||||
existing.bags += remaining;
|
||||
} else {
|
||||
newItems.push({ fieldId, fertilizerId: fert.id, bags: remaining });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return { ...t, items: newItems };
|
||||
}));
|
||||
};
|
||||
|
||||
// tripの中の圃場IDを取得(表示用・重複なし)
|
||||
const getTripFieldIds = useCallback((trip: LocalTrip): number[] => {
|
||||
const seen = new Set<number>();
|
||||
@@ -989,9 +1015,31 @@ export default function DeliveryEditPage({ planId }: Props) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* このtripに圃場を追加 */}
|
||||
{/* このtripに追加 */}
|
||||
{hasUnassignedBags && (
|
||||
<div className="mt-2 pt-2 border-t border-gray-100">
|
||||
<div className="mt-2 pt-2 border-t border-gray-100 flex gap-2 flex-wrap">
|
||||
{/* グループ一括追加 */}
|
||||
<select
|
||||
value=""
|
||||
onChange={e => {
|
||||
if (e.target.value) {
|
||||
assignGroupToTrip(e.target.value, trip.tempId);
|
||||
}
|
||||
}}
|
||||
className="border border-gray-300 rounded px-2 py-1 text-xs focus:outline-none focus:ring-1 focus:ring-green-500"
|
||||
>
|
||||
<option value="">+ グループを追加...</option>
|
||||
{groups.map(g => {
|
||||
const hasRemaining = g.fieldIds.some(fId =>
|
||||
selectedFertilizers.some(f => getUnassignedBags(fId, f.id) > 0)
|
||||
);
|
||||
if (!hasRemaining) return null;
|
||||
return (
|
||||
<option key={g.tempId} value={g.tempId}>★ {g.name}({g.fieldIds.length}圃場)</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
{/* 圃場単体追加 */}
|
||||
<select
|
||||
value=""
|
||||
onChange={e => {
|
||||
@@ -1002,7 +1050,6 @@ export default function DeliveryEditPage({ planId }: Props) {
|
||||
className="border border-gray-300 rounded px-2 py-1 text-xs focus:outline-none focus:ring-1 focus:ring-green-500"
|
||||
>
|
||||
<option value="">+ 圃場を追加...</option>
|
||||
{/* グループごとにまとめて表示 */}
|
||||
{groups.map(g => {
|
||||
const fieldsWithRemaining = g.fieldIds.filter(fId =>
|
||||
selectedFertilizers.some(f => getUnassignedBags(fId, f.id) > 0)
|
||||
@@ -1016,7 +1063,6 @@ export default function DeliveryEditPage({ planId }: Props) {
|
||||
</optgroup>
|
||||
);
|
||||
})}
|
||||
{/* 未グループ */}
|
||||
{unassignedFields.filter(fi =>
|
||||
selectedFertilizers.some(f => getUnassignedBags(fi.id, f.id) > 0)
|
||||
).length > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user