Skip to content

Commit 471ec18

Browse files
committed
imp todo
1 parent 71b481b commit 471ec18

File tree

3 files changed

+65
-23
lines changed

3 files changed

+65
-23
lines changed

ios/MusclogLiftLogRepeat.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
13B07F8E1A680F5B00A75B9A /* Resources */,
107107
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
108108
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
109-
D3B95386B6854396851A4A8D /* Upload Debug Symbols to Sentry */,
109+
3749F639D9B4478EAC2D4EA7 /* Upload Debug Symbols to Sentry */,
110110
);
111111
buildRules = (
112112
);
@@ -223,7 +223,7 @@
223223
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MusclogLiftLogRepeat/Pods-MusclogLiftLogRepeat-resources.sh\"\n";
224224
showEnvVarsInLog = 0;
225225
};
226-
D3B95386B6854396851A4A8D /* Upload Debug Symbols to Sentry */ = {
226+
3749F639D9B4478EAC2D4EA7 /* Upload Debug Symbols to Sentry */ = {
227227
isa = PBXShellScriptBuildPhase;
228228
buildActionMask = 2147483647;
229229
files = (

types/openFoodFacts.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,27 @@ export type { ProductStateV3 as ProductState, ProductV2, ProductV3, V2SearchResu
1212
// Type for search results (using V2 types from the library)
1313
export type SearchResultProduct = ProductV2;
1414

15+
/**
16+
* OFF product name fields used by getProductName (aligned with OFF Data fields / API).
17+
* @see https://wiki.openfoodfacts.org/Data_fields
18+
* @see https://openfoodfacts.github.io/openfoodfacts-server/api/ref-v2/
19+
* Localized: product_name_LANG, generic_name_LANG (e.g. product_name_en, generic_name_fr).
20+
*/
21+
export interface ProductNameFields {
22+
product_name?: string;
23+
product_name_en?: string;
24+
product_name_nl?: string;
25+
product_name_fr?: string;
26+
product_name_de?: string;
27+
abbreviated_product_name?: string;
28+
generic_name?: string;
29+
generic_name_en?: string;
30+
brands?: string;
31+
categories?: string;
32+
lang?: string;
33+
[key: string]: string | undefined;
34+
}
35+
1536
// Structured nutriments shape built by mapOpenFoodFactsProduct (not the raw API shape)
1637
export interface MappedNutriments {
1738
macronutrients?: {

utils/openFoodFactsMapper.ts

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { UnifiedFoodResult } from '../hooks/useUnifiedFoodSearch';
22
import i18n from '../lang/lang';
3-
import { SearchResultProduct, SuccessFoodProductState } from '../types/openFoodFacts';
3+
import {
4+
ProductNameFields,
5+
ProductV3,
6+
SearchResultProduct,
7+
SuccessFoodProductState,
8+
} from '../types/openFoodFacts';
49

510
// All possible Open Food Facts nutriment properties
611
const NUTRIMENT_PROPERTIES = [
@@ -438,41 +443,57 @@ export function mapOpenFoodFactsProduct(product: SearchResultProduct): UnifiedFo
438443
};
439444
}
440445

441-
// TODO: instead of any, use the possible types passed to this function (by scanning the codebase)
442-
export function getProductName(data: any): string {
443-
// Handle search results (array) vs single product (object)
446+
/**
447+
* All possible types passed to getProductName across the codebase:
448+
* - SearchResultProduct (V2 search result item)
449+
* - ProductV3 (V3 product, e.g. from FoodService.createFromV3Product)
450+
* - SuccessFoodProductState (V3 barcode-detail response with .product)
451+
* - Wrapper shapes from API: { product } or { products: [...] }
452+
*/
453+
export type GetProductNameInput =
454+
| SearchResultProduct
455+
| ProductV3
456+
| SuccessFoodProductState
457+
| { product?: SearchResultProduct | ProductV3 }
458+
| { products?: (SearchResultProduct | ProductV3)[] };
459+
460+
export function getProductName(data: GetProductNameInput | null | undefined): string {
461+
// OFF API: single product has .product, search has .products[], or payload is the product itself
462+
type WithOptional = { product?: unknown; products?: unknown[] };
444463
const product =
445-
data?.product || (Array.isArray(data?.products) ? data.products[0] : data);
464+
(data as WithOptional)?.product ||
465+
(Array.isArray((data as WithOptional)?.products) ? (data as WithOptional).products?.[0] : data);
446466

447467
if (!product) {
448468
return i18n.t('food.unknownFood');
449469
}
450470

451-
// 1. Try the standard name fields
452-
let name =
453-
product.product_name ||
454-
product[`product_name_${product.lang}`] || // Dynamic lookup based on product's main lang
455-
product.product_name_en ||
456-
product.product_name_nl ||
457-
product.product_name_fr ||
458-
product.product_name_de;
471+
const p = product as ProductNameFields;
459472

460-
// 2. Fallback to Abbreviated Name (Receipt/Small UI names)
473+
// 1. Try the standard name fields (OFF: product_name, product_name_LANG)
474+
let name: string | undefined =
475+
p.product_name ||
476+
p[`product_name_${p.lang}`] || // Dynamic lookup based on product's main lang
477+
p.product_name_en ||
478+
p.product_name_nl ||
479+
p.product_name_fr ||
480+
p.product_name_de;
481+
482+
// 2. Fallback to Abbreviated Name (OFF: abbreviated_product_name, receipt/small UI names)
461483
if (!name) {
462-
name = product.abbreviated_product_name;
484+
name = p.abbreviated_product_name;
463485
}
464486

465-
// 3. Fallback to Generic Names (Common names)
487+
// 3. Fallback to Generic Names (OFF: generic_name, generic_name_LANG)
466488
if (!name) {
467-
name =
468-
product.generic_name || product[`generic_name_${product.lang}`] || product.generic_name_en;
489+
name = p.generic_name || p[`generic_name_${p.lang}`] || p.generic_name_en;
469490
}
470491

471492
// 4. Ultimate Fallback: Brand + Category
472493
// Returns something like "Milbona (Yogurts)" instead of "Unknown"
473-
if (!name && product.brands) {
474-
const category = product.categories?.split(',')[0]; // Take the first category
475-
name = category ? `${product.brands} (${category})` : product.brands;
494+
if (!name && p.brands) {
495+
const category = p.categories?.split(',')[0]; // Take the first category
496+
name = category ? `${p.brands} (${category})` : p.brands;
476497
}
477498

478499
return name?.trim() || i18n.t('food.unknownFood');

0 commit comments

Comments
 (0)