diff --git a/src/components/LocationChip.vue b/src/components/LocationChip.vue
new file mode 100644
index 0000000000..dd9b82a4d1
--- /dev/null
+++ b/src/components/LocationChip.vue
@@ -0,0 +1,50 @@
+
+
+
+ {{ locationTitle }}
+ {{ locationEmoji }}
+
+
+
+
diff --git a/src/components/LocationInputRow.vue b/src/components/LocationInputRow.vue
index 2e9a2a1a95..2eb2e57ebe 100644
--- a/src/components/LocationInputRow.vue
+++ b/src/components/LocationInputRow.vue
@@ -47,22 +47,34 @@ export default {
type: Object,
default: () => ({ location_osm_id: null, location_osm_type: null })
},
+ maxRecentLocations: {
+ type: Number,
+ default: 3
+ }
},
+ emits: ['location'],
data() {
return {
locationSelectorDialog: false,
+ locationObject: null,
+ loading: false,
}
},
computed: {
...mapStores(useAppStore),
recentLocations() {
- return this.appStore.getRecentLocations(3)
+ return this.appStore.getRecentLocations(this.maxRecentLocations)
},
locationFormFilled() {
let keys = ['location_osm_id', 'location_osm_type']
return Object.keys(this.locationForm).filter(k => keys.includes(k)).every(k => !!this.locationForm[k])
},
},
+ watch: {
+ locationObject(newLocationObject, oldLocationObject) { // eslint-disable-line no-unused-vars
+ this.$emit('location', newLocationObject)
+ }
+ },
mounted() {
this.initLocationForm()
},
@@ -83,11 +95,14 @@ export default {
},
setLocationData(location) {
this.appStore.addRecentLocation(location)
+ // update locationForm
this.locationForm.location_osm_id = utils.getLocationID(location)
this.locationForm.location_osm_type = utils.getLocationType(location)
+ // set locationObject
+ this.locationObject = location
},
isSelectedLocation(location) {
- return (this.locationForm.location_osm_id === utils.getLocationID(location)) && (this.locationForm.location_osm_type === utils.getLocationType(location))
+ return utils.buildLocationUniqueId(this.locationForm.location_osm_id, this.locationForm.location_osm_type) === utils.getLocationUniqueID(location)
},
}
}
diff --git a/src/components/PriceFooterRow.vue b/src/components/PriceFooterRow.vue
index 49b36e7ebe..49d6643b40 100644
--- a/src/components/PriceFooterRow.vue
+++ b/src/components/PriceFooterRow.vue
@@ -1,7 +1,7 @@
-
+
@@ -18,7 +18,7 @@ import { useAppStore } from '../store'
export default {
components: {
- PriceLocationChip: defineAsyncComponent(() => import('../components/PriceLocationChip.vue')),
+ LocationChip: defineAsyncComponent(() => import('../components/LocationChip.vue')),
PriceOwnerChip: defineAsyncComponent(() => import('../components/PriceOwnerChip.vue')),
RelativeDateTimeChip: defineAsyncComponent(() => import('../components/RelativeDateTimeChip.vue')),
PriceProof: defineAsyncComponent(() => import('../components/PriceProof.vue')),
diff --git a/src/components/PriceLocationChip.vue b/src/components/PriceLocationChip.vue
deleted file mode 100644
index aa2c5de624..0000000000
--- a/src/components/PriceLocationChip.vue
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
- {{ priceLocationTitle }}
- {{ priceLocationEmoji }}
-
-
-
-
diff --git a/src/components/ProofCard.vue b/src/components/ProofCard.vue
index b97dcc55f9..1c09b43dfd 100644
--- a/src/components/ProofCard.vue
+++ b/src/components/ProofCard.vue
@@ -68,8 +68,8 @@ export default {
}
},
getProofUrl(proof) {
- // return 'https://prices.openfoodfacts.org/img/0002/qU59gK8PQw.webp'
- // return 'https://prices.openfoodfacts.net/img/0001/lZGFga9ZOT.webp'
+ // return 'https://prices.openfoodfacts.org/img/0002/qU59gK8PQw.webp' // PRICE_TAG
+ // return 'https://prices.openfoodfacts.net/img/0001/lZGFga9ZOT.webp' // RECEIPT
return `${import.meta.env.VITE_OPEN_PRICES_APP_URL}/img/${proof.file_path}`
},
close() {
diff --git a/src/components/ProofFooter.vue b/src/components/ProofFooter.vue
index 56b64b79a7..24a0f046e0 100644
--- a/src/components/ProofFooter.vue
+++ b/src/components/ProofFooter.vue
@@ -3,6 +3,7 @@
+
@@ -22,6 +23,7 @@ export default {
components: {
ProofTypeChip: defineAsyncComponent(() => import('../components/ProofTypeChip.vue')),
ProofPrivateChip: defineAsyncComponent(() => import('../components/ProofPrivateChip.vue')),
+ LocationChip: defineAsyncComponent(() => import('../components/LocationChip.vue')),
PriceCountChip: defineAsyncComponent(() => import('../components/PriceCountChip.vue')),
ProofDateChip: defineAsyncComponent(() => import('../components/ProofDateChip.vue')),
CurrencyChip: defineAsyncComponent(() => import('../components/CurrencyChip.vue')),
diff --git a/src/components/ProofInputRow.vue b/src/components/ProofInputRow.vue
index 7c788834cd..a4ad1f6e56 100644
--- a/src/components/ProofInputRow.vue
+++ b/src/components/ProofInputRow.vue
@@ -52,6 +52,8 @@
+
+
@@ -137,7 +139,8 @@ Compressor.setDefaults({
export default {
components: {
UserRecentProofsDialog: defineAsyncComponent(() => import('../components/UserRecentProofsDialog.vue')),
- ProofCard: defineAsyncComponent(() => import('../components/ProofCard.vue'))
+ ProofCard: defineAsyncComponent(() => import('../components/ProofCard.vue')),
+ LocationInputRow: defineAsyncComponent(() => import('../components/LocationInputRow.vue')),
},
props: {
proofType: {
@@ -146,13 +149,14 @@ export default {
},
proofForm: {
type: Object,
- default: () => ({ proof_id: null, date: utils.currentDate(), currency: null })
+ default: () => ({ proof_id: null, location_osm_id: null, location_osm_type: null, date: utils.currentDate(), currency: null })
},
hideRecentProofChoice: {
type: Boolean,
default: false
},
},
+ emits: ['proof'],
data() {
return {
proofFormImage: null,
@@ -162,6 +166,7 @@ export default {
userRecentProofsDialog: false,
proofSelectedSuccessMessage: false,
proofObject: null,
+ locationObject: null,
loading: false,
}
},
@@ -178,6 +183,11 @@ export default {
return this.appStore.getUserFavoriteCurrencies
}
},
+ watch: {
+ proofObject(newProofObject, oldProofObject) { // eslint-disable-line no-unused-vars
+ this.$emit('proof', newProofObject)
+ }
+ },
mounted() {
if (this.$route.query.proof_id) {
this.getProofById(this.$route.query.proof_id)
@@ -231,14 +241,14 @@ export default {
})
.then((proofFormImageCompressed) => {
api
- .createProof(proofFormImageCompressed, this.proofType, this.proofForm.date, this.proofForm.currency)
+ .createProof(proofFormImageCompressed, this.proofType, this.proofForm.location_osm_id, this.proofForm.location_osm_type, this.proofForm.date, this.proofForm.currency)
.then((data) => {
this.loading = false
if (data.id) {
const store = useAppStore()
store.addProof(data)
this.proofForm.proof_id = data.id
- this.proofObject = data
+ this.proofObject = {...data, ...{location: this.locationObject}}
this.proofSuccessMessage = true
} else {
alert('Error: server error when creating proof')
@@ -266,7 +276,8 @@ export default {
this.proofObject = null
},
getLocalProofUrl(blob) {
- // return 'https://prices.openfoodfacts.org/img/0002/qU59gK8PQw.webp'
+ // return 'https://prices.openfoodfacts.org/img/0002/qU59gK8PQw.webp' // PRICE_TAG
+ // return 'https://prices.openfoodfacts.net/img/0001/lZGFga9ZOT.webp' // RECEIPT
return URL.createObjectURL(blob)
}
}
diff --git a/src/services/api.js b/src/services/api.js
index 2228258945..9609715452 100644
--- a/src/services/api.js
+++ b/src/services/api.js
@@ -49,12 +49,13 @@ export default {
.then((response) => response.json())
},
- createProof(proofImage, type='PRICE_TAG', date=null, currency=null) {
- console.log('createProof', proofImage, type, date, currency)
+ createProof(proofImage, type='PRICE_TAG', location_osm_id=null, location_osm_type=null, date=null, currency=null) {
const store = useAppStore()
let formData = new FormData()
formData.append('file', proofImage, proofImage.name)
formData.append('type', type)
+ formData.append('location_osm_id', location_osm_id ? location_osm_id : '')
+ formData.append('location_osm_type', location_osm_type ? location_osm_type : '')
formData.append('date', date ? date : '')
formData.append('currency', currency ? currency : '')
const url = `${import.meta.env.VITE_OPEN_PRICES_API_URL}/proofs/upload?${buildURLParams()}`
diff --git a/src/utils.js b/src/utils.js
index 229ce63a79..2ed1d27a7a 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -231,9 +231,16 @@ function getLocationType(locationObject) {
return locationObject.osm_type.toUpperCase()
}
+function buildLocationUniqueId(locationId, locationType) {
+ // examples: N12345, W12345, R12345
+ if (locationId && locationType) {
+ return `${locationType[0]}${locationId.toString()}`
+ }
+ return null
+}
+
function getLocationUniqueID(locationObject) {
- // examples: N12345
- return `${getLocationType(locationObject)[0]}${getLocationID(locationObject).toString()}`
+ return buildLocationUniqueId(getLocationID(locationObject), getLocationType(locationObject))
}
function getLocationTag(locationObject) {
@@ -297,6 +304,7 @@ export default {
getLocationTitle,
getLocationID,
getLocationType,
+ buildLocationUniqueId,
getLocationUniqueID,
getLocationTag,
getLocationLatLng,
diff --git a/src/views/AddPriceMultiple.vue b/src/views/AddPriceMultiple.vue
index f69b718954..416239150e 100644
--- a/src/views/AddPriceMultiple.vue
+++ b/src/views/AddPriceMultiple.vue
@@ -4,8 +4,8 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
{{ $t('AddPriceMultiple.ProductPriceDetails.Add') }}
@@ -131,7 +112,7 @@
{{ $t('AddPriceMultiple.Done') }}
@@ -165,7 +146,6 @@ import utils from '../utils.js'
export default {
components: {
ProofInputRow: defineAsyncComponent(() => import('../components/ProofInputRow.vue')),
- LocationInputRow: defineAsyncComponent(() => import('../components/LocationInputRow.vue')),
ProductInputRow: defineAsyncComponent(() => import('../components/ProductInputRow.vue')),
PriceInputRow: defineAsyncComponent(() => import('../components/PriceInputRow.vue')),
PriceCard: defineAsyncComponent(() => import('../components/PriceCard.vue')),
@@ -212,16 +192,9 @@ export default {
computed: {
...mapStores(useAppStore),
proofFormFilled() {
- let keys = ['proof_id', 'date', 'currency']
+ let keys = ['proof_id', 'location_osm_id', 'location_osm_type', 'date', 'currency']
return Object.keys(this.addPriceMultipleForm).filter(k => keys.includes(k)).every(k => !!this.addPriceMultipleForm[k])
},
- locationFormFilled() {
- let keys = ['location_osm_id', 'location_osm_type']
- return Object.keys(this.addPriceMultipleForm).filter(k => keys.includes(k)).every(k => !!this.addPriceMultipleForm[k])
- },
- proofLocationFormFilled() {
- return this.proofFormFilled && this.locationFormFilled
- },
pricePerFormFilled() {
let keys = ['price_per']
return Object.keys(this.addPriceMultipleForm).filter(k => keys.includes(k)).every(k => !!this.addPriceMultipleForm[k])
@@ -233,14 +206,11 @@ export default {
return this.productFormFilled && this.priceFormFilled
},
formFilled() {
- return this.proofLocationFormFilled && !!this.productPriceUploadedList.length && !Object.keys(this.productPriceForm).length
+ return this.proofFormFilled && !!this.productPriceUploadedList.length && !Object.keys(this.productPriceForm).length
},
disableProofForm() {
return this.proofFormFilled
},
- disableLocationForm() {
- return !this.proofFormFilled || (this.proofLocationFormFilled && !!this.productPriceUploadedList.length)
- },
disablePriceAlreadyUploadedCard() {
// return !!this.productPriceUploadedList.length
return true
diff --git a/src/views/AddPriceSingle.vue b/src/views/AddPriceSingle.vue
index 096e181267..b6a886459a 100644
--- a/src/views/AddPriceSingle.vue
+++ b/src/views/AddPriceSingle.vue
@@ -23,15 +23,33 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -50,38 +68,6 @@
{{ $t('AddPriceSingle.PriceDetails.Proof') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ $t('AddPriceSingle.WhereWhen.Date') }}
-
-
-
-
-
-
@@ -120,9 +106,8 @@ import utils from '../utils.js'
export default {
components: {
ProductInputRow: defineAsyncComponent(() => import('../components/ProductInputRow.vue')),
- PriceInputRow: defineAsyncComponent(() => import('../components/PriceInputRow.vue')),
ProofInputRow: defineAsyncComponent(() => import('../components/ProofInputRow.vue')),
- LocationInputRow: defineAsyncComponent(() => import('../components/LocationInputRow.vue')),
+ PriceInputRow: defineAsyncComponent(() => import('../components/PriceInputRow.vue')),
},
data() {
return {
@@ -158,6 +143,10 @@ export default {
},
computed: {
...mapStores(useAppStore),
+ proofFormFilled() {
+ let keys = ['proof_id', 'location_osm_id', 'location_osm_type', 'date', 'currency']
+ return Object.keys(this.addPriceSingleForm).filter(k => keys.includes(k)).every(k => !!this.addPriceSingleForm[k])
+ },
pricePerFormFilled() {
let keys = ['price_per']
return Object.keys(this.addPriceSingleForm).filter(k => keys.includes(k)).every(k => !!this.addPriceSingleForm[k])
@@ -165,23 +154,8 @@ export default {
priceFormFilled() {
return this.pricePerFormFilled && this.pricePriceFormFilled
},
- proofFormFilled() {
- let keys = ['proof_id']
- return Object.keys(this.addPriceSingleForm).filter(k => keys.includes(k)).every(k => !!this.addPriceSingleForm[k])
- },
- priceProofFormFilled() {
- return this.priceFormFilled && this.proofFormFilled
- },
- locationFormFilled() {
- let keys = ['location_osm_id', 'location_osm_type']
- return Object.keys(this.addPriceSingleForm).filter(k => keys.includes(k)).every(k => !!this.addPriceSingleForm[k])
- },
- locationDateFormFilled() {
- let keys = ['location_osm_id', 'location_osm_type', 'date']
- return Object.keys(this.addPriceSingleForm).filter(k => keys.includes(k)).every(k => !!this.addPriceSingleForm[k])
- },
formFilled() {
- return this.productFormFilled && this.priceProofFormFilled && this.locationDateFormFilled
+ return this.productFormFilled && this.proofFormFilled && this.priceFormFilled
},
},
mounted() {