From e839db7331d6e73a8bda4d6b9a4bcb38d369d27b Mon Sep 17 00:00:00 2001 From: "soroush.asadi" Date: Tue, 2 Jun 2026 01:51:50 +0330 Subject: [PATCH] fix(koja): default to fa (no browser locale guess); guard null discoverProfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Koja auto-detected locale from the browser Accept-Language (en for many Persian users); set localeDetection:false so locale-less URLs default to fa. Also guarded cafe.discoverProfile across the cafe page, cafe card, and JSON-LD — a café without a discover profile crashed the page (500). The cafe page now resolves the café first and notFound()s an unknown slug before fetching menu/reviews. Co-Authored-By: Claude Opus 4.8 --- .../src/app/[locale]/cafe/[slug]/page.tsx | 23 +++++++++++++++---- web/koja/src/components/cafe/cafe-card.tsx | 7 +++--- web/koja/src/components/seo/cafe-json-ld.tsx | 4 ++-- web/koja/src/i18n/routing.ts | 3 +++ 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/web/koja/src/app/[locale]/cafe/[slug]/page.tsx b/web/koja/src/app/[locale]/cafe/[slug]/page.tsx index a3a3542..4bd2038 100644 --- a/web/koja/src/app/[locale]/cafe/[slug]/page.tsx +++ b/web/koja/src/app/[locale]/cafe/[slug]/page.tsx @@ -70,16 +70,29 @@ export default async function CafePage({ const t = await getTranslations({ locale, namespace: "cafe" }); const isFa = locale === "fa"; - const [cafe, menu, reviews] = await Promise.all([ - getCafe(slug), + // Resolve the café first so an unknown slug 404s cleanly instead of doing + // (and potentially erroring on) the menu/review fetches. + const cafe = await getCafe(slug); + if (!cafe) notFound(); + + const [menu, reviews] = await Promise.all([ getCafeMenu(slug), getCafeReviews(slug), ]); - if (!cafe) notFound(); - const name = isFa ? cafe.name : (cafe.nameEn ?? cafe.name); - const profile = cafe.discoverProfile; + // discoverProfile may be absent for cafés that never filled it in — fall back + // to an empty profile so the page renders instead of throwing a 500. + const profile = cafe.discoverProfile ?? { + themes: [], + size: null, + floors: null, + vibes: [], + occasions: [], + spaceFeatures: [], + noiseLevel: null, + priceTier: null, + }; const priceTier = profile.priceTier; // Similar cafes diff --git a/web/koja/src/components/cafe/cafe-card.tsx b/web/koja/src/components/cafe/cafe-card.tsx index 7063517..8ff568f 100644 --- a/web/koja/src/components/cafe/cafe-card.tsx +++ b/web/koja/src/components/cafe/cafe-card.tsx @@ -11,7 +11,8 @@ interface Props { export function CafeCard({ cafe, locale, href }: Props) { const isFa = locale === "fa"; const name = isFa ? cafe.name : (cafe.name); - const priceTier = cafe.discoverProfile.priceTier; + const priceTier = cafe.discoverProfile?.priceTier ?? null; + const themes = cafe.discoverProfile?.themes ?? []; const priceLabel = priceTier ? (PRICE_TIER_LABELS[priceTier]?.[isFa ? "fa" : "en"] ?? priceTier) : null; return ( @@ -72,9 +73,9 @@ export function CafeCard({ cafe, locale, href }: Props) { )} {/* Tags */} - {cafe.discoverProfile.themes.length > 0 && ( + {themes.length > 0 && (
- {cafe.discoverProfile.themes.slice(0, 3).map((tag) => ( + {themes.slice(0, 3).map((tag) => ( { - const tier = cafe.discoverProfile.priceTier; + const tier = cafe.discoverProfile?.priceTier; if (tier === "budget") return "﷼"; if (tier === "moderate") return "﷼﷼"; if (tier === "upscale") return "﷼﷼﷼"; diff --git a/web/koja/src/i18n/routing.ts b/web/koja/src/i18n/routing.ts index a538685..7f77335 100644 --- a/web/koja/src/i18n/routing.ts +++ b/web/koja/src/i18n/routing.ts @@ -3,4 +3,7 @@ import { defineRouting } from "next-intl/routing"; export const routing = defineRouting({ locales: ["fa", "en"], defaultLocale: "fa", + // Iran-first: don't pick the locale from the browser's Accept-Language + // (Persian users often have an en-US browser). Locale-less URLs default to fa. + localeDetection: false, });