Rename public discovery app from "finder" to "koja"
Rebrand the public café-discovery app: directories web/finder→web/koja and docker/finder→docker/koja, plus all service wiring (docker-compose, Caddy subdomain koja.meezi.ir, env vars KOJA_PORT / NEXT_PUBLIC_KOJA_URL, CI workflows) and the app's display name (Koja / کجا). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import type { CafePublicDto } from "@/lib/types";
|
||||
|
||||
interface Props {
|
||||
cafe: CafePublicDto;
|
||||
locale: string;
|
||||
baseUrl: string;
|
||||
}
|
||||
|
||||
export function CafeJsonLd({ cafe, locale, baseUrl }: Props) {
|
||||
const name = locale === "en" && cafe.nameEn ? cafe.nameEn : cafe.name;
|
||||
|
||||
const openingHours: string[] = [];
|
||||
if (cafe.workingHours) {
|
||||
const days = cafe.workingHours;
|
||||
const dayMap: [string, keyof typeof days][] = [
|
||||
["Sa", "sat"], ["Su", "sun"], ["Mo", "mon"],
|
||||
["Tu", "tue"], ["We", "wed"], ["Th", "thu"], ["Fr", "fri"],
|
||||
];
|
||||
for (const [abbr, key] of dayMap) {
|
||||
const d = days[key];
|
||||
if (d?.isOpen && d.open && d.close) {
|
||||
openingHours.push(`${abbr} ${d.open}-${d.close}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schema: Record<string, unknown> = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "CafeOrCoffeeShop",
|
||||
name,
|
||||
description: cafe.description ?? undefined,
|
||||
url: `${baseUrl}/${locale}/cafe/${cafe.slug}`,
|
||||
...(cafe.logoUrl ? { logo: cafe.logoUrl } : {}),
|
||||
...(cafe.coverImageUrl ? { image: [cafe.coverImageUrl, ...(cafe.galleryUrls ?? [])] } : {}),
|
||||
...(cafe.address ? { address: { "@type": "PostalAddress", streetAddress: cafe.address, addressLocality: cafe.city ?? undefined, addressCountry: "IR" } } : {}),
|
||||
...(cafe.phone ? { telephone: cafe.phone } : {}),
|
||||
...(openingHours.length ? { openingHours } : {}),
|
||||
...(cafe.instagramHandle ? { sameAs: [`https://instagram.com/${cafe.instagramHandle}`] } : {}),
|
||||
...(cafe.websiteUrl ? { url: cafe.websiteUrl } : {}),
|
||||
...(cafe.reviewCount > 0 ? {
|
||||
aggregateRating: {
|
||||
"@type": "AggregateRating",
|
||||
ratingValue: cafe.averageRating.toFixed(1),
|
||||
reviewCount: cafe.reviewCount,
|
||||
bestRating: "5",
|
||||
worstRating: "1",
|
||||
},
|
||||
} : {}),
|
||||
...(cafe.discoverProfile.themes.length ? {
|
||||
servesCuisine: cafe.discoverProfile.themes,
|
||||
} : {}),
|
||||
priceRange: (() => {
|
||||
const tier = cafe.discoverProfile.priceTier;
|
||||
if (tier === "budget") return "﷼";
|
||||
if (tier === "moderate") return "﷼﷼";
|
||||
if (tier === "upscale") return "﷼﷼﷼";
|
||||
if (tier === "luxury") return "﷼﷼﷼﷼";
|
||||
return undefined;
|
||||
})(),
|
||||
};
|
||||
|
||||
// BreadcrumbList
|
||||
const breadcrumb = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
itemListElement: [
|
||||
{ "@type": "ListItem", position: 1, name: locale === "fa" ? "خانه" : "Home", item: `${baseUrl}/${locale}` },
|
||||
{ "@type": "ListItem", position: 2, name: locale === "fa" ? "جستجو" : "Search", item: `${baseUrl}/${locale}/search` },
|
||||
...(cafe.city ? [{ "@type": "ListItem", position: 3, name: cafe.city, item: `${baseUrl}/${locale}/city/${cafe.city.toLowerCase()}` }] : []),
|
||||
{ "@type": "ListItem", position: cafe.city ? 4 : 3, name, item: `${baseUrl}/${locale}/cafe/${cafe.slug}` },
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
||||
/>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumb) }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user