From 2f51374e3a41e91a38bf13e6f83e30a7798b4cc6 Mon Sep 17 00:00:00 2001 From: myrmidex Date: Thu, 19 Mar 2026 21:35:27 +0100 Subject: [PATCH] 4 - Update frontend with bucket type support and visual distinction --- resources/js/pages/Scenarios/Show.tsx | 120 +++++++++++++++----------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/resources/js/pages/Scenarios/Show.tsx b/resources/js/pages/Scenarios/Show.tsx index a04977e..c347013 100644 --- a/resources/js/pages/Scenarios/Show.tsx +++ b/resources/js/pages/Scenarios/Show.tsx @@ -11,6 +11,8 @@ interface Scenario { interface Bucket { id: string; name: string; + type: 'need' | 'want' | 'overflow'; + type_label: string; priority: number; sort_order: number; allocation_type: string; @@ -56,20 +58,30 @@ interface Props { streamStats?: StreamStats; } +const bucketTypeBorderColor = { + need: 'border-blue-500', + want: 'border-green-500', + overflow: 'border-amber-500', +} as const; + +const defaultFormData = { + name: '', + type: 'need' as Bucket['type'], + allocation_type: 'fixed_limit', + allocation_value: '' +}; + export default function Show({ scenario, buckets, streams = { data: [] }, streamStats }: Props) { const [isModalOpen, setIsModalOpen] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const [editingBucket, setEditingBucket] = useState(null); - const [formData, setFormData] = useState({ - name: '', - allocation_type: 'fixed_limit', - allocation_value: '' - }); + const [formData, setFormData] = useState({ ...defaultFormData }); const handleEdit = (bucket: Bucket) => { setEditingBucket(bucket); setFormData({ name: bucket.name, + type: bucket.type, allocation_type: bucket.allocation_type, allocation_value: bucket.allocation_value ? bucket.allocation_value.toString() : '' }); @@ -118,6 +130,7 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream }, body: JSON.stringify({ name: formData.name, + type: formData.type, allocation_type: formData.allocation_type, allocation_value: formData.allocation_value ? parseFloat(formData.allocation_value) : null, priority: editingBucket ? editingBucket.priority : undefined @@ -126,7 +139,7 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream if (response.ok) { setIsModalOpen(false); - setFormData({ name: '', allocation_type: 'fixed_limit', allocation_value: '' }); + setFormData({ ...defaultFormData }); setEditingBucket(null); router.reload({ only: ['buckets'] }); } else { @@ -158,6 +171,7 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream }, body: JSON.stringify({ name: bucket.name, + type: bucket.type, allocation_type: bucket.allocation_type, allocation_value: bucket.allocation_value, priority: newPriority @@ -208,7 +222,7 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream - + {bucket.type !== 'overflow' && ( + + )} ))} - - {/* Virtual Overflow Bucket (placeholder for now) */} -
-
-
- - - -
-

- Overflow -

-

- Unallocated funds -

-

- $0.00 -

-
-
{/* Streams Section */} @@ -512,21 +508,41 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream /> -
- - -
+ {/* Hide type select for overflow buckets (type is fixed) */} + {!(editingBucket && editingBucket.type === 'overflow') && ( +
+ + +
+ )} + + {/* Hide allocation type select for overflow (always unlimited) */} + {formData.type !== 'overflow' && ( +
+ + +
+ )} {formData.allocation_type !== 'unlimited' && (
@@ -554,7 +570,7 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream onClick={() => { setIsModalOpen(false); setEditingBucket(null); - setFormData({ name: '', allocation_type: 'fixed_limit', allocation_value: '' }); + setFormData({ ...defaultFormData }); }} className="flex-1 px-4 py-2 text-sm font-medium text-gray-700 bg-gray-200 rounded-md hover:bg-gray-300" disabled={isSubmitting}