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:
parent
8b6ddb91f8
commit
d99aef9d11
@ -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',
|
||||||
|
@ -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';
|
||||||
|
Loading…
Reference in New Issue
Block a user