Compare commits
2 Commits
ced0236ca7
...
db5dbd8b31
| Author | SHA1 | Date | |
|---|---|---|---|
| db5dbd8b31 | |||
| dd718d4e81 |
@@ -26,7 +26,29 @@
|
||||
* correct; the data has to catch up.
|
||||
*/
|
||||
|
||||
const NUTRITION_BASE = 'https://mcp.nearle.ai.in/api';
|
||||
/*
|
||||
* Through this console's OWN origin, not the service's.
|
||||
*
|
||||
* `/ingest` is proxied to mcp.nearle.ai.in by nginx in production and by vite in
|
||||
* development, so this is same-origin either way and CORS does not enter into
|
||||
* it.
|
||||
*
|
||||
* It used to be the absolute `https://mcp.nearle.ai.in/api`, and that works only
|
||||
* where the service's allowlist names the calling origin. Measured 30 Sep 2026:
|
||||
* a request carrying `Origin: https://app.nearledaily.com` comes back with
|
||||
* `Access-Control-Allow-Origin` and one carrying
|
||||
* `Origin: https://platform.nearledaily.com` comes back without it. So the
|
||||
* browser dropped every response here, `forProduct` returned null, and the panel
|
||||
* showed "No health score available for this product yet" for every product —
|
||||
* the same product that renders fine in the merchant console.
|
||||
*
|
||||
* `vite.config.ts` called this exactly: "it works on every developer machine and
|
||||
* fails the moment it is deployed, which is the worst order to find out."
|
||||
*
|
||||
* The proxy also attaches the ingest API key, which this endpoint does not need
|
||||
* and does not mind.
|
||||
*/
|
||||
const NUTRITION_BASE = '/ingest/api';
|
||||
|
||||
/** How confident the service is that it matched the right source record. */
|
||||
export const LOW_CONFIDENCE = 0.7;
|
||||
|
||||
@@ -56,14 +56,25 @@ export function HealthScorePanel({
|
||||
populated for both, so nothing in the response separates them. Our own
|
||||
category does, so the decision is made here until they publish theirs.
|
||||
|
||||
Before the network call, deliberately: there is nothing to ask about.
|
||||
Still no network call for one — see `enabled` below — but the EARLY RETURN
|
||||
that used to sit here has moved past the hook.
|
||||
|
||||
It read `if (!isEdible(category)) return null` on the line above `useQuery`,
|
||||
which made the hook conditional. React counts hooks per component instance, so
|
||||
one drawer reused for two products — a soap and then a biscuit, which is
|
||||
ordinary browsing in the global catalogue — went 0 hooks then 1, and React
|
||||
threw "rendered more hooks than during the previous render". That does not
|
||||
degrade the panel, it unmounts the tree: the health score then disappears for
|
||||
EVERY product until the page is reloaded, which reads exactly like the feature
|
||||
being switched off.
|
||||
*/
|
||||
if (!isEdible(category)) return null;
|
||||
const isFood = isEdible(category);
|
||||
|
||||
const query = useQuery({
|
||||
queryKey: ['nutrition', brand, imageId],
|
||||
queryFn: () => nutritionApi.forProduct(brand, imageId),
|
||||
enabled: Boolean(brand && imageId),
|
||||
// Non-food asks nothing, which is what the early return was protecting.
|
||||
enabled: Boolean(brand && imageId && isFood),
|
||||
// Nutrition for a packaged product does not change during a trading day.
|
||||
staleTime: 60 * 60_000,
|
||||
refetchOnWindowFocus: false,
|
||||
@@ -72,6 +83,9 @@ export function HealthScorePanel({
|
||||
retry: false,
|
||||
});
|
||||
|
||||
// Past the hook, so the count is the same on every render.
|
||||
if (!isFood) return null;
|
||||
|
||||
/*
|
||||
* No catalogue link, so there is nothing to look up.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user