Skip to content

Commit 3cde2a4

Browse files
committed
add the ability to switch order status
1 parent 0ed991b commit 3cde2a4

File tree

2 files changed

+79
-51
lines changed

2 files changed

+79
-51
lines changed

app/models/shop_order.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ class ShopOrder < ApplicationRecord
22
belongs_to :user
33
belongs_to :shop_item
44

5-
after_create :sync_to_airtable
5+
after_save :sync_to_airtable
66

77
private
88

app/views/admin/shop.html.erb

Lines changed: 78 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,11 @@
115115
<%= order.name %>
116116
</td>
117117
<td style="padding: 1rem;">
118-
<% status_color = case order.status
119-
when 'pending' then '#fff3cd'
120-
when 'completed' then '#d4edda'
121-
when 'cancelled' then '#f8d7da'
122-
else '#e2e3e5'
123-
end %>
124-
<span style="background: <%= status_color %>; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem; font-weight: 600; text-transform: capitalize;"><%= order.status %></span>
118+
<select class="order-status" data-order-id="<%= order.id %>" style="padding: 4px 8px; border-radius: 4px; font-size: 0.85rem; font-weight: 600; border: 1px solid #ddd;">
119+
<option value="pending" <%= 'selected' if order.status == 'pending' %>>Pending</option>
120+
<option value="completed" <%= 'selected' if order.status == 'completed' %>>Completed</option>
121+
<option value="cancelled" <%= 'selected' if order.status == 'cancelled' %>>Cancelled</option>
122+
</select>
125123
</td>
126124
<td style="padding: 1rem; color: #999; font-size: 0.9rem;">
127125
<%= order.created_at.strftime('%b %d, %Y') %>
@@ -135,49 +133,79 @@
135133
</main>
136134

137135
<script>
138-
const addItemForm = document.getElementById('add-item-form');
139-
const addItemBtn = document.getElementById('add-item-btn');
136+
const addItemForm = document.getElementById('add-item-form');
137+
const addItemBtn = document.getElementById('add-item-btn');
140138

141-
addItemForm?.addEventListener('submit', async (e) => {
142-
e.preventDefault();
143-
144-
addItemBtn.disabled = true;
145-
addItemBtn.textContent = 'Adding...';
146-
147-
const data = {
148-
shop_item: {
149-
name: document.getElementById('item_name').value,
150-
description: document.getElementById('item_description').value,
151-
cost: parseFloat(document.getElementById('item_cost').value),
152-
status: document.getElementById('item_status').value,
153-
image_url: document.getElementById('item_image_url').value
154-
}
155-
};
156-
157-
try {
158-
const response = await fetch('/api/v1/admin/shop_items', {
159-
method: 'POST',
160-
headers: {
161-
'Content-Type': 'application/json',
162-
'Accept': 'application/json',
163-
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content
164-
},
165-
credentials: 'same-origin',
166-
body: JSON.stringify(data)
139+
addItemForm?.addEventListener('submit', async (e) => {
140+
e.preventDefault();
141+
142+
addItemBtn.disabled = true;
143+
addItemBtn.textContent = 'Adding...';
144+
145+
const data = {
146+
shop_item: {
147+
name: document.getElementById('item_name').value,
148+
description: document.getElementById('item_description').value,
149+
cost: parseFloat(document.getElementById('item_cost').value),
150+
status: document.getElementById('item_status').value,
151+
image_url: document.getElementById('item_image_url').value
152+
}
153+
};
154+
155+
try {
156+
const response = await fetch('/api/v1/admin/shop_items', {
157+
method: 'POST',
158+
headers: {
159+
'Content-Type': 'application/json',
160+
'Accept': 'application/json',
161+
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content
162+
},
163+
credentials: 'same-origin',
164+
body: JSON.stringify(data)
165+
});
166+
167+
if (response.ok) {
168+
window.location.reload();
169+
} else {
170+
const result = await response.json();
171+
alert(result.errors?.join(', ') || 'Failed to create item.');
172+
}
173+
} catch (error) {
174+
console.error('Failed to create shop item:', error);
175+
alert('Failed to create item. Please try again.');
176+
} finally {
177+
addItemBtn.disabled = false;
178+
addItemBtn.textContent = 'Add Item';
179+
}
167180
});
168181

169-
if (response.ok) {
170-
window.location.reload();
171-
} else {
172-
const result = await response.json();
173-
alert(result.errors?.join(', ') || 'Failed to create item.');
174-
}
175-
} catch (error) {
176-
console.error('Failed to create shop item:', error);
177-
alert('Failed to create item. Please try again.');
178-
} finally {
179-
addItemBtn.disabled = false;
180-
addItemBtn.textContent = 'Add Item';
181-
}
182-
});
183-
</script>
182+
document.querySelectorAll('.order-status').forEach(select => {
183+
select.addEventListener('change', async (e) => {
184+
const orderId = select.dataset.orderId;
185+
const newStatus = select.value;
186+
187+
try {
188+
const response = await fetch(`/api/v1/admin/shop_orders/${orderId}`, {
189+
method: 'PATCH',
190+
headers: {
191+
'Content-Type': 'application/json',
192+
'Accept': 'application/json',
193+
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content
194+
},
195+
credentials: 'same-origin',
196+
body: JSON.stringify({ order: { status: newStatus } })
197+
});
198+
199+
if (!response.ok) {
200+
const result = await response.json();
201+
alert(result.errors?.join(', ') || 'Failed to update order.');
202+
window.location.reload();
203+
}
204+
} catch (error) {
205+
console.error('Failed to update order status:', error);
206+
alert('Failed to update order. Please try again.');
207+
window.location.reload();
208+
}
209+
});
210+
});
211+
</script>

0 commit comments

Comments
 (0)