admin/components/layouts/PageNavbar.tsx
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

89 lines
4.2 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import React from 'react'
import clsx from 'clsx'
import SidebarMobile from '@/components/layouts/SidebarMobile'
import { useMediaQuery } from '@/hooks/useMediaQuery'
interface PageNavbarProps {
description?: string
pageTitle?: string
startSlot?: React.ReactNode
centerSlot?: React.ReactNode
endSlot?: React.ReactNode
className?: string
}
const ADMIN_PAGE_DESCRIPTIONS: Record<string, string> = {
پیشخوان: 'نمای کلی وضعیت و فعالیت‌های سامانه',
کاربران: 'مشاهده و مدیریت حساب‌های کاربری',
رویدادها: 'بررسی، ایجاد و مدیریت رویدادها',
رزروها: 'پیگیری رزروها و وضعیت حضور مهمانان',
پرداختها: 'مشاهده تراکنش‌ها و وضعیت پرداخت‌ها',
تسویهها: 'مدیریت تسویه‌حساب‌های مالی',
'درخواست‌های برداشت': 'بررسی و پردازش درخواست‌های مالی',
'دسته‌بندی‌های رویداد': 'مدیریت ساختار دسته‌بندی رویدادها',
'لیست‌های مهمان': 'مشاهده و مدیریت فهرست مهمانان',
'مدیریت نظرات': 'بررسی و مدیریت بازخورد کاربران',
شهرها: 'مدیریت اطلاعات جغرافیایی شهرها',
'احراز هویت میزبان': 'بررسی مدارک و وضعیت احراز هویت میزبانان',
اعلانها: 'ارسال و پیگیری اعلان درون‌برنامه‌ای، پوش و پیامک',
پیامکها: 'پیگیری پیامک‌های ارسالی سامانه',
'ارسال اعلان دستی': 'ارسال اعلان درون‌برنامه‌ای و پوش به کاربران منتخب',
'تحویل پوش': 'عیب‌یابی وضعیت ارسال، نمایش و بازشدن اعلان‌های پوش',
'گزارش‌های کاربران': 'بررسی گزارش‌ها و تخلف‌های ثبت‌شده',
'پیام‌های تماس': 'مشاهده پیام‌های فرم تماس عمومی',
'نظارت بر گفتگوها': 'مشاهده فقط‌خواندنی گفتگوهای گروهی و خصوصی',
}
const PageNavbar = ({ description, pageTitle, startSlot, centerSlot, endSlot, className }: PageNavbarProps) => {
const isMobile = useMediaQuery('(max-width: 768px)')
const pageDescription =
description ?? (pageTitle ? (ADMIN_PAGE_DESCRIPTIONS[pageTitle] ?? `مدیریت و مشاهده اطلاعات ${pageTitle}`) : undefined)
return (
<header
className={clsx(
'admin-page-header sticky top-0 z-30 grid min-h-16 items-center gap-2 border-b border-secondary-40/70 bg-white/90 px-3 py-2 backdrop-blur-xl md:min-h-[76px] md:grid-cols-3 md:gap-0 md:px-7',
isMobile && !endSlot ? 'grid-cols-1' : isMobile ? 'grid-cols-[minmax(0,1fr)_auto]' : 'grid-cols-2',
className
)}
>
<div className="flex min-w-0 items-center justify-start">
{isMobile && <SidebarMobile />}
{pageTitle ? (
<div className="flex min-w-0 items-center gap-3 text-right">
<span
aria-hidden
className="hidden h-9 w-1 rounded-full bg-primary-600 sm:block"
/>
<div className="min-w-0">
<h1 className="truncate text-base font-bold tracking-normal text-secondary-10 md:text-xl">{pageTitle}</h1>
{pageDescription ? <p className="mt-1 hidden text-smt-neutral-30 lg:block">{pageDescription}</p> : null}
</div>
</div>
) : (
startSlot
)}
</div>
{isMobile ? (
<>
{endSlot && <div className="flex max-w-[52vw] items-center justify-end overflow-x-auto pb-1">{endSlot}</div>}
{centerSlot && <div className="flex items-center justify-center col-span-2">{centerSlot}</div>}
</>
) : (
<>
{centerSlot ? <div className="flex items-center justify-center">{centerSlot}</div> : <div />}
{endSlot && <div className="flex items-center justify-end">{endSlot}</div>}
</>
)}
</header>
)
}
export default PageNavbar