Arrange priority

This commit is contained in:
myrmidex 2025-12-29 23:35:57 +01:00
parent 74583a1c73
commit c907f40508
2 changed files with 82 additions and 17 deletions

View file

@ -7,6 +7,7 @@
use App\Models\Scenario; use App\Models\Scenario;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException; use InvalidArgumentException;
class BucketController extends Controller class BucketController extends Controller
@ -198,20 +199,28 @@ private function updateBucketPriority(Bucket $bucket, int $newPriority): void
return; return;
} }
if ($newPriority < $oldPriority) { // Use database transaction to handle constraint conflicts
// Moving up - shift others down DB::transaction(function () use ($bucket, $scenario, $oldPriority, $newPriority) {
$scenario->buckets() // Temporarily set the moving bucket to a high priority to avoid conflicts
->where('id', '!=', $bucket->id) $tempPriority = $scenario->buckets()->max('priority') + 100;
->whereBetween('priority', [$newPriority, $oldPriority - 1]) $bucket->update(['priority' => $tempPriority]);
->increment('priority');
} else {
// Moving down - shift others up
$scenario->buckets()
->where('id', '!=', $bucket->id)
->whereBetween('priority', [$oldPriority + 1, $newPriority])
->decrement('priority');
}
$bucket->update(['priority' => $newPriority]); if ($newPriority < $oldPriority) {
// Moving up - shift others down
$scenario->buckets()
->where('id', '!=', $bucket->id)
->whereBetween('priority', [$newPriority, $oldPriority - 1])
->increment('priority');
} else {
// Moving down - shift others up
$scenario->buckets()
->where('id', '!=', $bucket->id)
->whereBetween('priority', [$oldPriority + 1, $newPriority])
->decrement('priority');
}
// Finally, set the bucket to its new priority
$bucket->update(['priority' => $newPriority]);
});
} }
} }

View file

@ -69,6 +69,40 @@ export default function Show({ scenario, buckets }: Props) {
} }
}; };
const handlePriorityChange = async (bucketId: number, direction: 'up' | 'down') => {
const bucket = buckets.find(b => b.id === bucketId);
if (!bucket) return;
const newPriority = direction === 'up' ? bucket.priority - 1 : bucket.priority + 1;
// Don't allow moving beyond bounds
if (newPriority < 1 || newPriority > buckets.length) return;
try {
const response = await fetch(`/buckets/${bucketId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
},
body: JSON.stringify({
name: bucket.name,
allocation_type: bucket.allocation_type,
allocation_value: bucket.allocation_value,
priority: newPriority
}),
});
if (response.ok) {
router.reload({ only: ['buckets'] });
} else {
console.error('Failed to update bucket priority');
}
} catch (error) {
console.error('Error updating bucket priority:', error);
}
};
return ( return (
<> <>
<Head title={scenario.name} /> <Head title={scenario.name} />
@ -123,9 +157,31 @@ export default function Show({ scenario, buckets }: Props) {
Priority {bucket.priority} {bucket.allocation_type_label} Priority {bucket.priority} {bucket.allocation_type_label}
</p> </p>
</div> </div>
<span className="rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800"> <div className="flex items-center gap-1">
#{bucket.priority} <button
</span> onClick={() => handlePriorityChange(bucket.id, 'up')}
disabled={bucket.priority === 1}
className="p-1 rounded hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed"
title="Move up in priority"
>
<svg className="w-3 h-3 text-gray-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
<button
onClick={() => handlePriorityChange(bucket.id, 'down')}
disabled={bucket.priority === buckets.length}
className="p-1 rounded hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed"
title="Move down in priority"
>
<svg className="w-3 h-3 text-gray-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
<span className="rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800">
#{bucket.priority}
</span>
</div>
</div> </div>
<div className="mt-4"> <div className="mt-4">