Move business logic out of App Router into module packages, add boundary validation scripts, and keep all routes as thin re-exports without changing URLs or API behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
322 lines
11 KiB
TypeScript
322 lines
11 KiB
TypeScript
import type { LucideIcon } from "lucide-react";
|
|
import {
|
|
LayoutDashboard,
|
|
Calendar,
|
|
Users,
|
|
ClipboardList,
|
|
Building2,
|
|
Settings,
|
|
Bell,
|
|
Search,
|
|
BarChart3,
|
|
Shield,
|
|
Clock,
|
|
UserCircle,
|
|
CreditCard,
|
|
Star,
|
|
Heart,
|
|
Scissors,
|
|
Gift,
|
|
Megaphone,
|
|
Sparkles,
|
|
UserCog,
|
|
LogIn,
|
|
CheckCircle,
|
|
Package,
|
|
MessageSquare,
|
|
} from "lucide-react";
|
|
|
|
export type BeautyPortalId = "customer" | "owner" | "reception" | "staff" | "admin";
|
|
|
|
export type PortalNavItem = { href: string; label: string; icon?: LucideIcon };
|
|
export type PortalNavGroup = {
|
|
id: string;
|
|
label: string;
|
|
icon: LucideIcon;
|
|
href?: string;
|
|
items?: PortalNavItem[];
|
|
};
|
|
|
|
export const BUSINESS_FORMAT_LABELS: Record<string, string> = {
|
|
salon: "سالن زیبایی",
|
|
barbershop: "آرایشگاه",
|
|
clinic: "کلینیک زیبایی",
|
|
laser: "لیزر",
|
|
skin_care: "مراقبت پوست",
|
|
hair_treatment: "درمان مو",
|
|
spa: "اسپا",
|
|
mixed: "ترکیبی",
|
|
};
|
|
|
|
export const BEAUTY_PORTALS: {
|
|
id: BeautyPortalId;
|
|
label: string;
|
|
description: string;
|
|
basePath: string;
|
|
icon: LucideIcon;
|
|
}[] = [
|
|
{
|
|
id: "customer",
|
|
label: "پورتال مشتری",
|
|
description: "نوبتها، پکیجها، پروفایل",
|
|
basePath: "/beauty/customer",
|
|
icon: UserCircle,
|
|
},
|
|
{
|
|
id: "owner",
|
|
label: "مدیریت سالن",
|
|
description: "داشبورد، CRM، بازاریابی",
|
|
basePath: "/beauty",
|
|
icon: Sparkles,
|
|
},
|
|
{
|
|
id: "reception",
|
|
label: "پذیرش",
|
|
description: "صف، پذیرش، تقویم",
|
|
basePath: "/beauty/reception",
|
|
icon: ClipboardList,
|
|
},
|
|
{
|
|
id: "staff",
|
|
label: "پورتال پرسنل",
|
|
description: "برنامه، کمیسیون",
|
|
basePath: "/beauty/staff-portal",
|
|
icon: Scissors,
|
|
},
|
|
{
|
|
id: "admin",
|
|
label: "مدیر سیستم",
|
|
description: "تنظیمات، دسترسیها",
|
|
basePath: "/beauty/admin",
|
|
icon: Shield,
|
|
},
|
|
];
|
|
|
|
export const CUSTOMER_NAV: PortalNavGroup[] = [
|
|
{ id: "dash", label: "داشبورد", icon: LayoutDashboard, href: "/beauty/customer" },
|
|
{
|
|
id: "appts",
|
|
label: "نوبتها",
|
|
icon: Calendar,
|
|
items: [
|
|
{ href: "/beauty/customer/appointments/upcoming", label: "نوبتهای آینده" },
|
|
{ href: "/beauty/customer/appointments/past", label: "سوابق نوبت" },
|
|
{ href: "/beauty/customer/appointments/book", label: "رزرو نوبت" },
|
|
],
|
|
},
|
|
{
|
|
id: "packages",
|
|
label: "پکیجها",
|
|
icon: Gift,
|
|
items: [
|
|
{ href: "/beauty/customer/packages", label: "پکیجهای من" },
|
|
{ href: "/beauty/customer/memberships", label: "عضویتها" },
|
|
{ href: "/beauty/customer/sessions", label: "جلسات باقیمانده" },
|
|
],
|
|
},
|
|
{
|
|
id: "billing",
|
|
label: "مالی",
|
|
icon: CreditCard,
|
|
items: [
|
|
{ href: "/beauty/customer/invoices", label: "فاکتورها" },
|
|
{ href: "/beauty/customer/payments", label: "پرداختها" },
|
|
{ href: "/beauty/customer/wallet", label: "کیف پول" },
|
|
{ href: "/beauty/customer/loyalty", label: "امتیاز وفاداری" },
|
|
],
|
|
},
|
|
{
|
|
id: "social",
|
|
label: "ارتباط",
|
|
icon: MessageSquare,
|
|
items: [
|
|
{ href: "/beauty/customer/favorites/centers", label: "مراکز محبوب" },
|
|
{ href: "/beauty/customer/favorites/staff", label: "پرسنل محبوب" },
|
|
{ href: "/beauty/customer/messages", label: "پیامها" },
|
|
{ href: "/beauty/customer/notifications", label: "اعلانها" },
|
|
{ href: "/beauty/customer/reviews", label: "نظرات" },
|
|
],
|
|
},
|
|
{
|
|
id: "account",
|
|
label: "حساب",
|
|
icon: Settings,
|
|
items: [
|
|
{ href: "/beauty/customer/profile", label: "پروفایل" },
|
|
{ href: "/beauty/customer/favorites", label: "علاقهمندیها" },
|
|
{ href: "/beauty/customer/settings", label: "تنظیمات" },
|
|
],
|
|
},
|
|
];
|
|
|
|
export const OWNER_NAV: PortalNavGroup[] = [
|
|
{ id: "dash", label: "داشبورد", icon: LayoutDashboard, href: "/beauty" },
|
|
{
|
|
id: "insights",
|
|
label: "تحلیل و یکپارچگی",
|
|
icon: BarChart3,
|
|
items: [
|
|
{ href: "/beauty/owner/analytics", label: "آنالیتیکس" },
|
|
{ href: "/beauty/owner/calendar", label: "تقویم" },
|
|
{ href: "/beauty/owner/crm-integration", label: "CRM" },
|
|
{ href: "/beauty/owner/accounting-integration", label: "حسابداری" },
|
|
{ href: "/beauty/owner/marketing", label: "بازاریابی" },
|
|
{ href: "/beauty/owner/coupons", label: "کوپن و کمپین" },
|
|
],
|
|
},
|
|
{
|
|
id: "foundation",
|
|
label: "زیرساخت سالن",
|
|
icon: Building2,
|
|
items: [
|
|
{ href: "/beauty/organizations", label: "سازمانها" },
|
|
{ href: "/beauty/branches", label: "شعب" },
|
|
{ href: "/beauty/settings", label: "تنظیمات" },
|
|
],
|
|
},
|
|
{
|
|
id: "booking",
|
|
label: "نوبتدهی",
|
|
icon: Calendar,
|
|
items: [
|
|
{ href: "/beauty/appointments", label: "نوبتها" },
|
|
{ href: "/beauty/booking/schedules", label: "برنامه کاری" },
|
|
{ href: "/beauty/booking/waiting-list", label: "لیست انتظار" },
|
|
],
|
|
},
|
|
{
|
|
id: "salon",
|
|
label: "سالن",
|
|
icon: Sparkles,
|
|
items: [
|
|
{ href: "/beauty/salon/rooms", label: "اتاقها" },
|
|
{ href: "/beauty/salon/stations", label: "ایستگاهها" },
|
|
{ href: "/beauty/salon/policies", label: "سیاستهای شعبه" },
|
|
],
|
|
},
|
|
{
|
|
id: "catalog",
|
|
label: "کاتالوگ",
|
|
icon: Scissors,
|
|
items: [
|
|
{ href: "/beauty/catalog/categories", label: "دستهبندیها" },
|
|
{ href: "/beauty/catalog/services", label: "خدمات" },
|
|
],
|
|
},
|
|
{ id: "customers", label: "مشتریان", icon: Users, href: "/beauty/customers" },
|
|
{
|
|
id: "packages-mgmt",
|
|
label: "بستهها",
|
|
icon: Gift,
|
|
items: [
|
|
{ href: "/beauty/packages", label: "پکیجها" },
|
|
{ href: "/beauty/packages/memberships", label: "عضویتها" },
|
|
],
|
|
},
|
|
{
|
|
id: "staff-mgmt",
|
|
label: "پرسنل",
|
|
icon: UserCog,
|
|
items: [
|
|
{ href: "/beauty/staff", label: "کارکنان" },
|
|
{ href: "/beauty/staff/commissions", label: "کمیسیونها" },
|
|
],
|
|
},
|
|
{
|
|
id: "marketing-mgmt",
|
|
label: "بازاریابی",
|
|
icon: Megaphone,
|
|
items: [
|
|
{ href: "/beauty/marketing/campaigns", label: "کمپینها" },
|
|
{ href: "/beauty/marketing/integrations", label: "یکپارچهسازیها" },
|
|
],
|
|
},
|
|
];
|
|
|
|
export const RECEPTION_NAV: PortalNavGroup[] = [
|
|
{ id: "dash", label: "داشبورد", icon: LayoutDashboard, href: "/beauty/reception" },
|
|
{ id: "calendar", label: "تقویم", icon: Calendar, href: "/beauty/reception/calendar" },
|
|
{ id: "walkin", label: "مراجعه حضوری", icon: Users, href: "/beauty/reception/walk-in" },
|
|
{ id: "checkin", label: "پذیرش", icon: LogIn, href: "/beauty/reception/check-in" },
|
|
{ id: "checkout", label: "ترخیص", icon: CheckCircle, href: "/beauty/reception/check-out" },
|
|
{ id: "queue", label: "صف انتظار", icon: Clock, href: "/beauty/reception/queue" },
|
|
{ id: "payments", label: "پرداخت", icon: CreditCard, href: "/beauty/reception/payments" },
|
|
{ id: "reports", label: "گزارش", icon: BarChart3, href: "/beauty/reception/reports" },
|
|
];
|
|
|
|
export const STAFF_NAV: PortalNavGroup[] = [
|
|
{ id: "dash", label: "داشبورد", icon: LayoutDashboard, href: "/beauty/staff-portal" },
|
|
{ id: "schedule", label: "برنامه", icon: Calendar, href: "/beauty/staff-portal/schedule" },
|
|
{ id: "commission", label: "کمیسیون", icon: CreditCard, href: "/beauty/staff-portal/commission" },
|
|
{ id: "appointments", label: "نوبتها", icon: ClipboardList, href: "/beauty/staff-portal/appointments" },
|
|
{ id: "notifications", label: "اعلانها", icon: Bell, href: "/beauty/staff-portal/notifications" },
|
|
{ id: "settings", label: "تنظیمات", icon: Settings, href: "/beauty/staff-portal/settings" },
|
|
];
|
|
|
|
export const ADMIN_NAV: PortalNavGroup[] = [
|
|
{ id: "dash", label: "داشبورد", icon: LayoutDashboard, href: "/beauty/admin" },
|
|
{ id: "orgs", label: "سازمانها", icon: Building2, href: "/beauty/admin/organizations" },
|
|
{ id: "branches", label: "شعب", icon: Sparkles, href: "/beauty/admin/branches" },
|
|
{ id: "staff", label: "پرسنل", icon: UserCog, href: "/beauty/admin/staff" },
|
|
{ id: "customers", label: "مشتریان", icon: Users, href: "/beauty/admin/customers" },
|
|
{ id: "permissions", label: "دسترسیها", icon: Shield, href: "/beauty/admin/permissions" },
|
|
{ id: "reports", label: "گزارش", icon: BarChart3, href: "/beauty/admin/reports" },
|
|
{ id: "analytics", label: "آنالیتیکس", icon: Heart, href: "/beauty/admin/analytics" },
|
|
{ id: "monitoring", label: "مانیتورینگ", icon: Package, href: "/beauty/admin/monitoring" },
|
|
{ id: "settings", label: "تنظیمات", icon: Settings, href: "/beauty/admin/settings" },
|
|
];
|
|
|
|
export const PUBLIC_NAV = [
|
|
{ href: "/beauty/site", label: "خانه" },
|
|
{ href: "/beauty/site/features", label: "امکانات" },
|
|
{ href: "/beauty/site/pricing", label: "قیمتگذاری" },
|
|
{ href: "/beauty/site/faq", label: "سوالات" },
|
|
{ href: "/beauty/site/about", label: "درباره" },
|
|
{ href: "/beauty/site/contact", label: "تماس" },
|
|
{ href: "/beauty/site/find-salon", label: "یافتن سالن" },
|
|
{ href: "/beauty/site/find-laser", label: "یافتن لیزر" },
|
|
{ href: "/beauty/site/find-spa", label: "یافتن اسپا" },
|
|
];
|
|
|
|
export function navForPortal(portal: BeautyPortalId): PortalNavGroup[] {
|
|
switch (portal) {
|
|
case "customer":
|
|
return CUSTOMER_NAV;
|
|
case "owner":
|
|
return OWNER_NAV;
|
|
case "reception":
|
|
return RECEPTION_NAV;
|
|
case "staff":
|
|
return STAFF_NAV;
|
|
case "admin":
|
|
return ADMIN_NAV;
|
|
default:
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export function detectPortal(pathname: string): BeautyPortalId | null {
|
|
if (pathname === "/beauty/customer" || pathname.startsWith("/beauty/customer/")) return "customer";
|
|
if (pathname === "/beauty/reception" || pathname.startsWith("/beauty/reception/")) return "reception";
|
|
if (pathname === "/beauty/staff-portal" || pathname.startsWith("/beauty/staff-portal/")) return "staff";
|
|
if (pathname === "/beauty/admin" || pathname.startsWith("/beauty/admin/")) return "admin";
|
|
if (
|
|
pathname === "/beauty" ||
|
|
pathname.startsWith("/beauty/organizations") ||
|
|
pathname.startsWith("/beauty/branches") ||
|
|
pathname.startsWith("/beauty/appointments") ||
|
|
pathname.startsWith("/beauty/booking") ||
|
|
pathname.startsWith("/beauty/salon") ||
|
|
pathname.startsWith("/beauty/catalog") ||
|
|
pathname.startsWith("/beauty/customers") ||
|
|
pathname.startsWith("/beauty/packages") ||
|
|
pathname.startsWith("/beauty/staff") ||
|
|
pathname.startsWith("/beauty/marketing") ||
|
|
pathname.startsWith("/beauty/settings") ||
|
|
pathname.startsWith("/beauty/owner")
|
|
) {
|
|
return "owner";
|
|
}
|
|
return null;
|
|
}
|