fix(koja): default to fa (no browser locale guess); guard null discoverProfile
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 && (
|
||||
<div className="mt-2 flex flex-wrap gap-1">
|
||||
{cafe.discoverProfile.themes.slice(0, 3).map((tag) => (
|
||||
{themes.slice(0, 3).map((tag) => (
|
||||
<span
|
||||
key={tag}
|
||||
className="rounded-full bg-brand-50 px-2 py-0.5 text-[10px] font-medium text-brand-700"
|
||||
|
||||
@@ -46,11 +46,11 @@ export function CafeJsonLd({ cafe, locale, baseUrl }: Props) {
|
||||
worstRating: "1",
|
||||
},
|
||||
} : {}),
|
||||
...(cafe.discoverProfile.themes.length ? {
|
||||
...(cafe.discoverProfile?.themes?.length ? {
|
||||
servesCuisine: cafe.discoverProfile.themes,
|
||||
} : {}),
|
||||
priceRange: (() => {
|
||||
const tier = cafe.discoverProfile.priceTier;
|
||||
const tier = cafe.discoverProfile?.priceTier;
|
||||
if (tier === "budget") return "﷼";
|
||||
if (tier === "moderate") return "﷼﷼";
|
||||
if (tier === "upscale") return "﷼﷼﷼";
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user