feat(meta): per-page titles + favicon/app icons + PWA across the panel
CI/CD / CI · API (dotnet build + test) (push) Successful in 40s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 31s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m9s
CI/CD / CI · Admin Web (tsc) (push) Successful in 39s
CI/CD / CI · Website (tsc) (push) Successful in 46s
CI/CD / CI · Koja (tsc) (push) Successful in 50s
CI/CD / Deploy · all services (push) Successful in 2m54s
CI/CD / CI · API (dotnet build + test) (push) Successful in 40s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 31s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m9s
CI/CD / CI · Admin Web (tsc) (push) Successful in 39s
CI/CD / CI · Website (tsc) (push) Successful in 46s
CI/CD / CI · Koja (tsc) (push) Successful in 50s
CI/CD / Deploy · all services (push) Successful in 2m54s
The app had no metadata anywhere — pages showed no <title> and no favicon or app icon. Added: - Root metadata in [locale]/layout: title default + "%s — میزی" template, description, icons (favicon + apple-touch-icon → /icons), manifest link, appleWebApp, themeColor viewport, noindex (private panel). - Per-page title on all 22 dashboard route pages (داشبورد, منو, گزارشها, …). - Guest menu (/q) layout: own title + icon + manifest. PWA + favicon now use the Meezi icon everywhere. Verified via SSR: titles render (e.g. "منو — میزی") and icon/manifest/apple-touch-icon links present. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
import { BranchesScreen } from "@/components/branches/branches-screen";
|
import { BranchesScreen } from "@/components/branches/branches-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "شعب" };
|
||||||
|
|
||||||
export default function BranchesPage() {
|
export default function BranchesPage() {
|
||||||
return <BranchesScreen />;
|
return <BranchesScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { CouponsScreen } from "@/components/coupons/coupons-screen";
|
import { CouponsScreen } from "@/components/coupons/coupons-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "کوپنها" };
|
||||||
|
|
||||||
export default function CouponsPage() {
|
export default function CouponsPage() {
|
||||||
return <CouponsScreen />;
|
return <CouponsScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { CrmScreen } from "@/components/crm/crm-screen";
|
import { CrmScreen } from "@/components/crm/crm-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "مشتریان" };
|
||||||
|
|
||||||
export default function CrmPage() {
|
export default function CrmPage() {
|
||||||
return <CrmScreen />;
|
return <CrmScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { ExpensesScreen } from "@/components/expenses/expenses-screen";
|
import { ExpensesScreen } from "@/components/expenses/expenses-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "هزینهها" };
|
||||||
|
|
||||||
export default function ExpensesPage() {
|
export default function ExpensesPage() {
|
||||||
return <ExpensesScreen />;
|
return <ExpensesScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { HrScreen } from "@/components/hr/hr-screen";
|
import { HrScreen } from "@/components/hr/hr-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "منابع انسانی" };
|
||||||
|
|
||||||
export default function HrPage() {
|
export default function HrPage() {
|
||||||
return <HrScreen />;
|
return <HrScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { KdsScreen } from "@/components/kds/kds-screen";
|
import { KdsScreen } from "@/components/kds/kds-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "آشپزخانه" };
|
||||||
|
|
||||||
export default function KdsPage() {
|
export default function KdsPage() {
|
||||||
return <KdsScreen />;
|
return <KdsScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { MenuAdminScreen } from "@/components/menu/menu-admin-screen";
|
import { MenuAdminScreen } from "@/components/menu/menu-admin-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "منو" };
|
||||||
|
|
||||||
export default function MenuPage() {
|
export default function MenuPage() {
|
||||||
return <MenuAdminScreen />;
|
return <MenuAdminScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { NotificationsScreen } from "@/components/notifications/notifications-screen";
|
import { NotificationsScreen } from "@/components/notifications/notifications-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "اعلانها" };
|
||||||
|
|
||||||
export default function NotificationsPage() {
|
export default function NotificationsPage() {
|
||||||
return <NotificationsScreen />;
|
return <NotificationsScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { OverviewScreen } from "@/components/overview/overview-screen";
|
import { OverviewScreen } from "@/components/overview/overview-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "داشبورد" };
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
return <OverviewScreen />;
|
return <OverviewScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { QueueScreen } from "@/components/queue/queue-screen";
|
import { QueueScreen } from "@/components/queue/queue-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "نوبتدهی" };
|
||||||
|
|
||||||
export default function QueuePage() {
|
export default function QueuePage() {
|
||||||
return <QueueScreen />;
|
return <QueueScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { ReportsScreen } from "@/components/reports/reports-screen";
|
import { ReportsScreen } from "@/components/reports/reports-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "گزارشها" };
|
||||||
|
|
||||||
export default function ReportsPage() {
|
export default function ReportsPage() {
|
||||||
return <ReportsScreen />;
|
return <ReportsScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { ReservationsScreen } from "@/components/reservations/reservations-screen";
|
import { ReservationsScreen } from "@/components/reservations/reservations-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "رزرو" };
|
||||||
|
|
||||||
export default function ReservationsPage() {
|
export default function ReservationsPage() {
|
||||||
return <ReservationsScreen />;
|
return <ReservationsScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { ReviewsScreen } from "@/components/reviews/reviews-screen";
|
import { ReviewsScreen } from "@/components/reviews/reviews-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "نظرات" };
|
||||||
|
|
||||||
export default function ReviewsPage() {
|
export default function ReviewsPage() {
|
||||||
return <ReviewsScreen />;
|
return <ReviewsScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
import { SettingsScreen } from "@/components/settings/settings-screen";
|
import { SettingsScreen } from "@/components/settings/settings-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "تنظیمات" };
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { ShiftsScreen } from "@/components/shifts/shifts-screen";
|
import { ShiftsScreen } from "@/components/shifts/shifts-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "بستن شیفت" };
|
||||||
|
|
||||||
export default function ShiftsPage() {
|
export default function ShiftsPage() {
|
||||||
return <ShiftsScreen />;
|
return <ShiftsScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { SmsScreen } from "@/components/sms/sms-screen";
|
import { SmsScreen } from "@/components/sms/sms-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "پیامک" };
|
||||||
|
|
||||||
export default function SmsPage() {
|
export default function SmsPage() {
|
||||||
return <SmsScreen />;
|
return <SmsScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
import { CheckoutScreen } from "@/components/subscription/checkout-screen";
|
import { CheckoutScreen } from "@/components/subscription/checkout-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "تسویه اشتراک" };
|
||||||
|
|
||||||
export default function SubscriptionCheckoutPage() {
|
export default function SubscriptionCheckoutPage() {
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
import { SubscriptionScreen } from "@/components/subscription/subscription-screen";
|
import { SubscriptionScreen } from "@/components/subscription/subscription-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "اشتراک و پلن" };
|
||||||
|
|
||||||
export default function SubscriptionPage() {
|
export default function SubscriptionPage() {
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { SupportTicketDetailScreen } from "@/components/support/support-screen";
|
import { SupportTicketDetailScreen } from "@/components/support/support-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "تیکت پشتیبانی" };
|
||||||
|
|
||||||
export default function SupportTicketPage() {
|
export default function SupportTicketPage() {
|
||||||
return <SupportTicketDetailScreen />;
|
return <SupportTicketDetailScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { SupportScreen } from "@/components/support/support-screen";
|
import { SupportScreen } from "@/components/support/support-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "پشتیبانی" };
|
||||||
|
|
||||||
export default function SupportPage() {
|
export default function SupportPage() {
|
||||||
return <SupportScreen />;
|
return <SupportScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { TablesScreen } from "@/components/tables/tables-screen";
|
import { TablesScreen } from "@/components/tables/tables-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "میزها" };
|
||||||
|
|
||||||
export default function TablesPage() {
|
export default function TablesPage() {
|
||||||
return <TablesScreen />;
|
return <TablesScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { TaxesScreen } from "@/components/taxes/taxes-screen";
|
import { TaxesScreen } from "@/components/taxes/taxes-screen";
|
||||||
|
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "مالیات" };
|
||||||
|
|
||||||
export default function TaxesPage() {
|
export default function TaxesPage() {
|
||||||
return <TaxesScreen />;
|
return <TaxesScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { Metadata, Viewport } from "next";
|
||||||
import { NextIntlClientProvider } from "next-intl";
|
import { NextIntlClientProvider } from "next-intl";
|
||||||
import { getMessages, setRequestLocale } from "next-intl/server";
|
import { getMessages, setRequestLocale } from "next-intl/server";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
@@ -6,6 +7,42 @@ import { routing } from "@/i18n/routing";
|
|||||||
import { Providers } from "@/components/providers";
|
import { Providers } from "@/components/providers";
|
||||||
import "../globals.css";
|
import "../globals.css";
|
||||||
|
|
||||||
|
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "https://app.meezi.ir";
|
||||||
|
|
||||||
|
// Default metadata for the whole panel. `title.template` gives every page a
|
||||||
|
// "<page> — میزی" title; per-page `metadata.title` fills in the page name.
|
||||||
|
// Icons/manifest here also fix pages that previously had no favicon/app icon.
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
metadataBase: new URL(SITE_URL),
|
||||||
|
title: {
|
||||||
|
default: "میزی — پنل مدیریت کافه",
|
||||||
|
template: "%s — میزی",
|
||||||
|
},
|
||||||
|
description: "پنل مدیریت کافه و رستوران میزی — صندوق، منو، گزارش و مدیریت.",
|
||||||
|
applicationName: "میزی",
|
||||||
|
manifest: "/manifest.webmanifest",
|
||||||
|
icons: {
|
||||||
|
icon: [
|
||||||
|
{ url: "/icons/icon-192.png", sizes: "192x192", type: "image/png" },
|
||||||
|
{ url: "/icons/icon-512.png", sizes: "512x512", type: "image/png" },
|
||||||
|
],
|
||||||
|
shortcut: "/icons/icon-192.png",
|
||||||
|
apple: "/icons/icon-192.png",
|
||||||
|
},
|
||||||
|
appleWebApp: {
|
||||||
|
capable: true,
|
||||||
|
title: "میزی",
|
||||||
|
statusBarStyle: "default",
|
||||||
|
},
|
||||||
|
robots: { index: false, follow: false }, // private merchant panel
|
||||||
|
};
|
||||||
|
|
||||||
|
export const viewport: Viewport = {
|
||||||
|
themeColor: "#0F6E56",
|
||||||
|
width: "device-width",
|
||||||
|
initialScale: 1,
|
||||||
|
};
|
||||||
|
|
||||||
const vazirmatn = localFont({
|
const vazirmatn = localFont({
|
||||||
src: "../../fonts/Vazirmatn-Variable.woff2",
|
src: "../../fonts/Vazirmatn-Variable.woff2",
|
||||||
variable: "--font-vazirmatn",
|
variable: "--font-vazirmatn",
|
||||||
|
|||||||
@@ -1,9 +1,24 @@
|
|||||||
|
import type { Metadata, Viewport } from "next";
|
||||||
import { NextIntlClientProvider } from "next-intl";
|
import { NextIntlClientProvider } from "next-intl";
|
||||||
import localFont from "next/font/local";
|
import localFont from "next/font/local";
|
||||||
import faMessages from "../../../messages/fa.json";
|
import faMessages from "../../../messages/fa.json";
|
||||||
import { MeeziToaster } from "@/components/ui/meezi-toaster";
|
import { MeeziToaster } from "@/components/ui/meezi-toaster";
|
||||||
import "../globals.css";
|
import "../globals.css";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "منوی کافه — میزی",
|
||||||
|
description: "مشاهده منو و ثبت سفارش از میز",
|
||||||
|
manifest: "/manifest.webmanifest",
|
||||||
|
icons: { icon: "/icons/icon-192.png", apple: "/icons/icon-192.png" },
|
||||||
|
robots: { index: false, follow: false },
|
||||||
|
};
|
||||||
|
|
||||||
|
export const viewport: Viewport = {
|
||||||
|
themeColor: "#0F6E56",
|
||||||
|
width: "device-width",
|
||||||
|
initialScale: 1,
|
||||||
|
};
|
||||||
|
|
||||||
const vazirmatn = localFont({
|
const vazirmatn = localFont({
|
||||||
src: "../../fonts/Vazirmatn-Variable.woff2",
|
src: "../../fonts/Vazirmatn-Variable.woff2",
|
||||||
variable: "--font-vazirmatn",
|
variable: "--font-vazirmatn",
|
||||||
|
|||||||
Reference in New Issue
Block a user