diff --git a/src/components/ContributionAssistantCropImageList.vue b/src/components/ContributionAssistantCropImageList.vue new file mode 100644 index 00000000000..3e43368404c --- /dev/null +++ b/src/components/ContributionAssistantCropImageList.vue @@ -0,0 +1,38 @@ + + + diff --git a/src/components/ContributionAssistantDrawCanvas.vue b/src/components/ContributionAssistantDrawCanvas.vue new file mode 100644 index 00000000000..4b738a4e1f8 --- /dev/null +++ b/src/components/ContributionAssistantDrawCanvas.vue @@ -0,0 +1,148 @@ + + + diff --git a/src/components/ContributionAssistantPriceFormCard.vue b/src/components/ContributionAssistantPriceFormCard.vue new file mode 100644 index 00000000000..73b002abbd4 --- /dev/null +++ b/src/components/ContributionAssistantPriceFormCard.vue @@ -0,0 +1,84 @@ + + + + + \ No newline at end of file diff --git a/src/components/ProductInputRow.vue b/src/components/ProductInputRow.vue index 50cbeb13db5..64e48ee6ec7 100644 --- a/src/components/ProductInputRow.vue +++ b/src/components/ProductInputRow.vue @@ -96,6 +96,10 @@ export default { productForm: { type: Object, default: () => ({ mode: '', product: null, product_code: '', category_tag: null, origins_tags: '', labels_tags: [] }) + }, + disableInitWhenSwitchingModes : { + type: Boolean, + default: () => false } }, emits: ['filled'], @@ -172,7 +176,9 @@ export default { }, setMode(mode) { this.productForm.mode = mode - this.initProductForm() + if (!this.disableInitWhenSwitchingModes) { + this.initProductForm() + } }, setProductCode(code) { this.productForm.product_code = code diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 4b84891177b..f4311466238 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -511,6 +511,9 @@ }, "TopProducts": { "Title": "Top products" + }, + "ContributionAssistant": { + "Title": "Contribution Assistant" } }, "Search": { diff --git a/src/router.js b/src/router.js index 8ff6a935e2c..355d1ab14f4 100644 --- a/src/router.js +++ b/src/router.js @@ -33,6 +33,7 @@ const routes = [ { path: '/users', name: 'users', component: () => import('./views/UserList.vue'), meta: { title: 'TopContributors', icon: 'mdi-account-star-outline', drawerMenu: true, breadcrumbs: [{title: 'TopContributors', disabled: true }] }}, { path: '/users/:username', name: 'user-detail', component: () => import('./views/UserDetail.vue'), meta: { title: 'User detail' }}, { path: '/experiments', name: 'experiments', component: () => import('./views/Experiments.vue'), meta: { title: 'Experiments', icon: 'mdi-test-tube', drawerMenu: true, drawerMenuConditionalDisplay: 'drawer_display_experiments', breadcrumbs: [{title: 'Experiments', disabled: true }] }}, + { path: '/experiments/contribution-assistant', name: 'contribution-assistant', component: () => import('./views/ContributionAssistant.vue'), meta: { title: 'ContributionAssistant', icon: 'mdi-test-tube', requiresAuth: true, breadcrumbs: [{title: 'Experiments', disabled: false, to: '/experiments' }, {title: 'ContributionAssistant', disabled: true }] }}, { path: '/reuses', name: 'reuses', component: () => import('./views/Reuses.vue'), meta: { title: 'Reuses', icon: 'mdi-account-group', drawerMenu: true, breadcrumbs: [{title: 'Reuses', disabled: true }] }}, { path: '/stats', name: 'stats', component: () => import('./views/Stats.vue'), meta: { title: 'Stats', icon: 'mdi-chart-box-outline', drawerMenu: true, breadcrumbs: [{title: 'Stats', disabled: true }] }}, { path: '/settings', name: 'settings', component: () => import('./views/Settings.vue'), meta: { title: 'Settings', icon: 'mdi-cog-outline', drawerMenu: true, breadcrumbs: [{title: 'Settings', disabled: true }] }}, diff --git a/src/services/api.js b/src/services/api.js index 8fdf49ddb97..e5b9ff964d4 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -329,5 +329,23 @@ export default { // default to nominatim return this.openstreetmapNominatimSearch(q) } + }, + processWithGemini(croppedBlobs) { + const store = useAppStore() + const url = `${import.meta.env.VITE_OPEN_PRICES_API_URL}/proofs/process_with_gemini` + const formData = new FormData() + + croppedBlobs.forEach((blob) => { + formData.append('files', blob) + }); + + return fetch(url, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${store.user.token}`, + }, + body: formData, + }) + .then((response) => response.json()) } } diff --git a/src/views/ContributionAssistant.vue b/src/views/ContributionAssistant.vue new file mode 100644 index 00000000000..3154b56ed1c --- /dev/null +++ b/src/views/ContributionAssistant.vue @@ -0,0 +1,267 @@ + + + diff --git a/src/views/Experiments.vue b/src/views/Experiments.vue index 18266e4f5e3..d3117fb2ccc 100644 --- a/src/views/Experiments.vue +++ b/src/views/Experiments.vue @@ -14,6 +14,13 @@ to="/proofs/add/single" /> + + +