disable ssl and splash
Build and Deploy Docker Images / build_and_deploy (push) Has been cancelled

This commit is contained in:
hamid zarghami
2026-05-31 10:07:00 +03:30
parent 09e61d5edb
commit 40a1d6b964
3 changed files with 51 additions and 194 deletions
+7 -98
View File
@@ -1,111 +1,20 @@
'use client';
import PreferenceWrapper from '@/components/wrapper/PreferenceWrapper'
import React from 'react'
import type { Metadata, Viewport } from 'next'
import { getRestaurant } from './lib/getRestaurant'
import { notFound } from 'next/navigation'
import CartChecker from '@/components/CartChecker'
import ActiveChecker from '@/components/ActiveChecker'
export const dynamic = 'force-dynamic'
export const revalidate = 0
type LayoutParams = { name: string }
export async function generateMetadata({
params
}: {
params: Promise<LayoutParams>
}): Promise<Metadata> {
const { name } = await params
try {
const restaurant = await getRestaurant(name)
const title = restaurant.seoTitle || restaurant.name
const logo = restaurant.logo
const defaultIcon = "/icons/web-app-manifest-192x192.png"
// استفاده از API route برای تبدیل لوگو به مربع
let iconUrl = defaultIcon
let icon192Url = defaultIcon
let icon512Url = "/icons/web-app-manifest-512x512.png"
if (logo && logo.trim() !== "") {
iconUrl = `/${name}/api/logo?url=${encodeURIComponent(logo)}&size=192`
icon192Url = `/${name}/api/logo?url=${encodeURIComponent(logo)}&size=192`
icon512Url = `/${name}/api/logo?url=${encodeURIComponent(logo)}&size=512`
}
return {
title,
description: restaurant.seoDescription || restaurant.description || `منوی ${restaurant.name}`,
manifest: `/${name}/manifest.webmanifest`,
icons: {
icon: [
{ url: iconUrl },
{ url: icon192Url, sizes: "192x192", type: "image/png" },
{ url: icon512Url, sizes: "512x512", type: "image/png" },
],
shortcut: iconUrl,
apple: iconUrl,
},
}
} catch {
return {
title: `${name} - Dashboard`,
description: `PWA dashboard for ${name}`,
manifest: `/${name}/manifest.webmanifest`,
icons: {
icon: [
{ url: "/icons/web-app-manifest-192x192.png" },
{ url: "/icons/web-app-manifest-192x192.png", sizes: "192x192", type: "image/png" },
{ url: "/icons/web-app-manifest-512x512.png", sizes: "512x512", type: "image/png" },
],
shortcut: "/icons/web-app-manifest-192x192.png",
apple: "/icons/web-app-manifest-192x192.png",
},
}
}
}
export async function generateViewport({
params
}: {
params: Promise<LayoutParams>
}): Promise<Viewport> {
try {
const { name } = await params
const restaurant = await getRestaurant(name)
return {
themeColor: restaurant.menuColor || '#F4F5F9'
}
} catch {
return {
themeColor: '#F4F5F9'
}
}
}
export default async function Layout({
export default function Layout({
children,
params
}: {
children: React.ReactNode
params: Promise<LayoutParams>
}): Promise<React.ReactNode> {
try {
const { name } = await params
await getRestaurant(name)
return <>
}) {
return (
<>
<PreferenceWrapper>{children}</PreferenceWrapper>
<CartChecker />
<ActiveChecker />
</>
} catch (error) {
if (error instanceof Error && error.message === 'RESTAURANT_NOT_FOUND') {
notFound()
}
throw error
}
)
}
+3 -57
View File
@@ -1,16 +1,14 @@
'use client';
import usePreference from '@/hooks/helpers/usePreference';
import React, { useEffect, useState } from 'react';
import React, { useEffect } from 'react';
import { useGetAbout } from '@/app/[name]/(Main)/about/hooks/useAboutData';
import SplashScreen from '@/components/overlays/SplashScreen';
import { hexToOklch, calculateBrightness } from '@/lib/helpers/colorUtils';
type Props = {
children: React.ReactNode
}
// تابع برای اعمال رنگ primary
function applyPrimaryColor(colorHex: string) {
const root = document.documentElement;
const oklchColor = hexToOklch(colorHex);
@@ -28,42 +26,17 @@ function PreferenceWrapper({ children }: Props) {
const { state: nightMode } = usePreference('night-mode', false);
const { data: aboutData } = useGetAbout();
// بررسی اینکه آیا باید اسپلش نمایش داده بشه
const [showSplash, setShowSplash] = useState(() => {
if (typeof window === 'undefined') return true;
const navigationEntries = performance.getEntriesByType('navigation') as PerformanceNavigationTiming[];
const isReload = navigationEntries.length > 0 && navigationEntries[0].type === 'reload';
return !sessionStorage.getItem('app-loaded') || isReload;
});
const [cachedLogo, setCachedLogo] = useState<string | null>(null);
const [cachedName, setCachedName] = useState<string | null>(null);
// بارگذاری رنگ و اطلاعات از localStorage در اولین رندر
useEffect(() => {
// بارگذاری رنگ
const savedColor = localStorage.getItem('theme-primary-color');
if (savedColor) {
applyPrimaryColor(savedColor);
}
// بارگذاری لوگو و نام
const savedLogo = localStorage.getItem('restaurant-logo');
const savedName = localStorage.getItem('restaurant-name');
if (savedLogo) setCachedLogo(savedLogo);
if (savedName) setCachedName(savedName);
// ثبت اینکه app لود شده
sessionStorage.setItem('app-loaded', 'true');
}, []);
// اعمال رنگ primary از about (با ذخیره در localStorage)
useEffect(() => {
if (aboutData?.data?.menuColor) {
// ذخیره رنگ و اطلاعات در localStorage
localStorage.setItem('theme-primary-color', aboutData.data.menuColor);
// ذخیره لوگو و نام برای اسپلش
if (aboutData.data.logo) {
localStorage.setItem('restaurant-logo', aboutData.data.logo);
}
@@ -76,39 +49,12 @@ function PreferenceWrapper({ children }: Props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [aboutData?.data?.menuColor]);
// اعمال تم تاریک/روشن
useEffect(() => {
const theme = nightMode;
document.documentElement.setAttribute("data-theme", theme ? "dark" : "light");
}, [nightMode]);
// بستن اسپلش بعد از مدت زمان مشخص
useEffect(() => {
if (showSplash) {
const timer = setTimeout(() => {
setShowSplash(false);
}, 2500);
return () => clearTimeout(timer);
}
}, [showSplash]);
// استفاده از داده‌های cache شده برای اسپلش
const splashLogo = aboutData?.data?.logo || cachedLogo || undefined;
const splashName = aboutData?.data?.name || cachedName || undefined;
return (
<>
{showSplash && (
<SplashScreen
logo={splashLogo}
restaurantName={splashName}
duration={2500}
/>
)}
{!showSplash && children}
</>
)
return <>{children}</>;
}
export default PreferenceWrapper
export default PreferenceWrapper
+41 -39
View File
@@ -2,47 +2,49 @@ import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
// Map host → tenant path
const HOST_MAP: Record<string, string> = {
"theboote.tahavol-mr.ir": "/boote",
"thesun.tahavol-mr.ir": "/suncafe",
"passataplus.ir": "/passata",
// دامنه‌های جدید اینجا اضافه می‌شوند
};
// const HOST_MAP: Record<string, string> = {
// "theboote.tahavol-mr.ir": "/boote",
// "thesun.tahavol-mr.ir": "/suncafe",
// "passataplus.ir": "/passata",
// // دامنه‌های جدید اینجا اضافه می‌شوند
// };
export function middleware(req: NextRequest) {
const host = req.headers.get("host") || "";
const tenantPath = HOST_MAP[host.toLowerCase()] || "";
export function middleware(_req: NextRequest) {
return NextResponse.next();
if (!tenantPath) {
return NextResponse.next();
}
const pathname = req.nextUrl.pathname;
// مسیرهای api و استاتیک را rewrite نکن
if (
pathname.startsWith("/api") ||
pathname.startsWith("/_next") ||
pathname.includes(".")
) {
return NextResponse.next();
}
// اگر کاربر ریشه دامنه را باز کرده، به مسیر tenant ریدایرکت کن (آدرس‌بار /passata و غیره نشون بده)
if (pathname === "/") {
const url = req.nextUrl.clone();
url.pathname = tenantPath;
return NextResponse.redirect(url);
}
// اگر مسیر از قبل با tenant یکی است (مثلاً /passata یا /passata/menu)، rewrite نکن
if (pathname === tenantPath || pathname.startsWith(tenantPath + "/")) {
return NextResponse.next();
}
const url = req.nextUrl.clone();
url.pathname = `${tenantPath}${pathname}`;
return NextResponse.rewrite(url);
// const host = req.headers.get("host") || "";
// const tenantPath = HOST_MAP[host.toLowerCase()] || "";
//
// if (!tenantPath) {
// return NextResponse.next();
// }
//
// const pathname = req.nextUrl.pathname;
//
// // مسیرهای api و استاتیک را rewrite نکن
// if (
// pathname.startsWith("/api") ||
// pathname.startsWith("/_next") ||
// pathname.includes(".")
// ) {
// return NextResponse.next();
// }
//
// // اگر کاربر ریشه دامنه را باز کرده، به مسیر tenant ریدایرکت کن (آدرس‌بار /passata و غیره نشون بده)
// if (pathname === "/") {
// const url = req.nextUrl.clone();
// url.pathname = tenantPath;
// return NextResponse.redirect(url);
// }
//
// // اگر مسیر از قبل با tenant یکی است (مثلاً /passata یا /passata/menu)، rewrite نکن
// if (pathname === tenantPath || pathname.startsWith(tenantPath + "/")) {
// return NextResponse.next();
// }
//
// const url = req.nextUrl.clone();
// url.pathname = `${tenantPath}${pathname}`;
// return NextResponse.rewrite(url);
}
export const config = {