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', SENT: '/invites/sent',
}, },
// Items (for direct operations like update, get by ID)
ITEMS: {
BY_ID: (itemId: string) => `/items/${itemId}`,
},
// OCR // OCR
OCR: { OCR: {
PROCESS: '/ocr/extract-items', PROCESS: '/ocr/extract-items',

View File

@ -155,6 +155,20 @@
<q-item-label caption v-if="item.quantity"> <q-item-label caption v-if="item.quantity">
Quantity: {{ item.quantity }} Quantity: {{ item.quantity }}
</q-item-label> </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>
<q-item-section side> <q-item-section side>
<q-btn <q-btn
@ -200,6 +214,7 @@ interface Item {
name: string; name: string;
quantity?: string | undefined; quantity?: string | undefined;
is_complete: boolean; is_complete: boolean;
price?: number | null;
version: number; version: number;
updating?: boolean; updating?: boolean;
updated_at: string; updated_at: string;
@ -353,16 +368,24 @@ const onAddItem = async () => {
const updateItem = async (item: Item) => { const updateItem = async (item: Item) => {
item.updating = true; item.updating = true;
try { try {
// Use the new endpoint for updating a specific item
const response = await apiClient.put( 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, // Send only relevant fields for this update action
quantity: editingItemQuantity.value?.toString(), is_complete: item.is_complete,
completed: 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, version: item.version,
} }
); );
Object.assign(item, response.data as Item); 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) { } catch (err: unknown) {
if ((err as { response?: { status?: number } }).response?.status === 409) { if ((err as { response?: { status?: number } }).response?.status === 409) {
$q.notify({ $q.notify({
@ -391,7 +414,7 @@ const handleOcrUpload = async (file: File | null) => {
ocrError.value = null; ocrError.value = null;
try { try {
const formData = new FormData(); const formData = new FormData();
formData.append('file', file); formData.append('image_file', file);
const response = await apiClient.post( const response = await apiClient.post(
API_ENDPOINTS.OCR.PROCESS, 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; showOcrDialog.value = true;
} catch (err: unknown) { } catch (err: unknown) {
ocrError.value = (err as Error).message || 'Failed to process image'; ocrError.value = (err as Error).message || 'Failed to process image';