Add price input field for completed items in ListDetailPage; update item API endpoint to use new configuration; ensure price handling is consistent and type-safe during updates.

This commit is contained in:
mohamad 2025-05-08 23:21:12 +02:00
parent 8b6ddb91f8
commit d99aef9d11
2 changed files with 35 additions and 6 deletions

View File

@ -71,6 +71,11 @@ export const API_ENDPOINTS = {
SENT: '/invites/sent',
},
// Items (for direct operations like update, get by ID)
ITEMS: {
BY_ID: (itemId: string) => `/items/${itemId}`,
},
// OCR
OCR: {
PROCESS: '/ocr/extract-items',

View File

@ -155,6 +155,20 @@
<q-item-label caption v-if="item.quantity">
Quantity: {{ item.quantity }}
</q-item-label>
<!-- Add Price Input Field when item is complete -->
<q-input
v-if="item.is_complete"
v-model.number="item.price"
type="number"
label="Price"
dense
outlined
step="0.01"
prefix="$"
class="q-mt-sm"
style="max-width: 150px"
@keydown.enter.prevent="($event.target as HTMLInputElement)?.blur()"
/>
</q-item-section>
<q-item-section side>
<q-btn
@ -200,6 +214,7 @@ interface Item {
name: string;
quantity?: string | undefined;
is_complete: boolean;
price?: number | null;
version: number;
updating?: boolean;
updated_at: string;
@ -353,16 +368,24 @@ const onAddItem = async () => {
const updateItem = async (item: Item) => {
item.updating = true;
try {
// Use the new endpoint for updating a specific item
const response = await apiClient.put(
API_ENDPOINTS.LISTS.ITEM(String(list.value.id), String(item.id)),
API_ENDPOINTS.ITEMS.BY_ID(String(item.id)),
{
name: editingItemName.value,
quantity: editingItemQuantity.value?.toString(),
completed: item.is_complete,
// Send only relevant fields for this update action
is_complete: item.is_complete,
// Ensure price is a number or null. If item.price is undefined, treat as null.
price: (item.price === undefined || item.price === null) ? null : Number(item.price),
version: item.version,
}
);
Object.assign(item, response.data as Item);
// Ensure the price is a number locally after update, or null
if (response.data.price !== null && response.data.price !== undefined) {
item.price = Number(response.data.price);
} else {
item.price = null;
}
} catch (err: unknown) {
if ((err as { response?: { status?: number } }).response?.status === 409) {
$q.notify({
@ -391,7 +414,7 @@ const handleOcrUpload = async (file: File | null) => {
ocrError.value = null;
try {
const formData = new FormData();
formData.append('file', file);
formData.append('image_file', file);
const response = await apiClient.post(
API_ENDPOINTS.OCR.PROCESS,
@ -402,7 +425,8 @@ const handleOcrUpload = async (file: File | null) => {
}
}
);
ocrItems.value = response.data.items;
// Transform the array of strings into an array of objects { name: string }
ocrItems.value = response.data.extracted_items.map((nameStr: string) => ({ name: nameStr }));
showOcrDialog.value = true;
} catch (err: unknown) {
ocrError.value = (err as Error).message || 'Failed to process image';