feat(discount): dedicated «مدیریت تخفیفها» item in the settings menu
Add a standalone settings sidebar entry + route (/admin/discounts) rendering DiscountsPage (DiscountTab inside SettingsLayout, doctor/clinic only), and revert the temporary tab inside the subscription page. Cleaner, discoverable placement. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -51,6 +51,7 @@ import ClinicFormPage from './pages/ClinicFormPage';
|
||||
import PreRegistrationsPage from './pages/PreRegistrationsPage';
|
||||
import StaffPage from './pages/StaffPage';
|
||||
import SubscriptionPage from './pages/SubscriptionPage';
|
||||
import DiscountsPage from './pages/DiscountsPage';
|
||||
import ClinicServicesPage from './pages/ClinicServicesPage';
|
||||
import SmsWalletPage from './pages/SmsWalletPage';
|
||||
import MySecretariesPage from './pages/MySecretariesPage';
|
||||
@@ -225,6 +226,7 @@ export default function App() {
|
||||
<Route path="tags-settings" element={<RoleRoute roles={['doctor', 'clinic']} blockClinicScope><TagsSettingsPage /></RoleRoute>} />
|
||||
<Route path="appointment-settings" element={<RoleRoute roles={['doctor']} blockClinicScope><AppointmentSettingsPage /></RoleRoute>} />
|
||||
<Route path="subscription" element={<RoleRoute roles={['doctor', 'clinic']} blockClinicScope><SubscriptionPage /></RoleRoute>} />
|
||||
<Route path="discounts" element={<RoleRoute roles={['doctor', 'clinic']} blockClinicScope><DiscountsPage /></RoleRoute>} />
|
||||
<Route path="subscription/success" element={<RoleRoute roles={['doctor', 'clinic']} blockClinicScope><PaymentSuccessPage /></RoleRoute>} />
|
||||
<Route path="clinic-services" element={<RoleRoute roles={['doctor', 'clinic']} blockClinicScope><ClinicServicesPage /></RoleRoute>} />
|
||||
<Route path="inventory" element={<RoleRoute roles={['doctor', 'clinic']} blockClinicScope><InventoryPage /></RoleRoute>} />
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import {
|
||||
CreditCardIcon, UserIcon, CalendarDaysIcon, BuildingOffice2Icon,
|
||||
BanknotesIcon, UsersIcon, ShieldCheckIcon,
|
||||
TagIcon, ChatBubbleLeftRightIcon, UserCircleIcon, UserPlusIcon,
|
||||
TagIcon, ChatBubbleLeftRightIcon, UserCircleIcon, UserPlusIcon, ReceiptPercentIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
import PurchaseSubscriptionSidebar from './PurchaseSubscriptionSidebar';
|
||||
|
||||
@@ -28,6 +28,7 @@ export const SETTINGS_MENU: SettingsMenuItem[] = [
|
||||
{ key: 'secretary', label: 'مدیریت منشی', icon: UsersIcon, to: '/admin/my-secretaries' },
|
||||
{ key: 'staff', label: 'پرسنل', icon: UserPlusIcon, to: '/admin/staff' },
|
||||
{ key: 'insurance', label: 'مدیریت بیمه', icon: ShieldCheckIcon, to: '/admin/insurance-pricing' },
|
||||
{ key: 'discounts', label: 'مدیریت تخفیفها', icon: ReceiptPercentIcon, to: '/admin/discounts', roles: ['doctor', 'clinic'] },
|
||||
{ key: 'tags', label: 'برچسبها', icon: TagIcon, to: '/admin/tags-settings' },
|
||||
{ key: 'sms', label: 'پیامکها', icon: ChatBubbleLeftRightIcon, to: '/admin/sms-wallet' },
|
||||
{ key: 'account', label: 'حساب کاربری', icon: UserCircleIcon, to: '/admin/account-settings' },
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import SettingsLayout from '../components/layout/SettingsLayout';
|
||||
import DiscountTab from '../components/DiscountTab';
|
||||
|
||||
/** مدیریت تخفیفها — بخش تنظیمات برای تعریف قوانین تخفیف عمومی (owner-scoped). */
|
||||
export default function DiscountsPage() {
|
||||
return (
|
||||
<SettingsLayout active="discounts">
|
||||
<div
|
||||
style={{ background: 'var(--surface)', minWidth: 0 }}
|
||||
className="px-4 py-4 md:px-6 md:py-6 rounded-[var(--r-lg)]"
|
||||
>
|
||||
<h1 className="section-title" style={{ marginBottom: 16 }}>مدیریت تخفیفها</h1>
|
||||
<DiscountTab />
|
||||
</div>
|
||||
</SettingsLayout>
|
||||
);
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import { usePaymentConfig } from '../hooks/usePaymentConfig';
|
||||
import { formatRial, formatNumber } from '../lib/utils';
|
||||
import Modal from '../components/ui/Modal';
|
||||
import SettingsLayout from '../components/layout/SettingsLayout';
|
||||
import DiscountTab from '../components/DiscountTab';
|
||||
import {
|
||||
SparkleIcon, PlanCardPerson, CloseCircleFilled, GiftIcon, InfoCircleRedFilled,
|
||||
} from './subscriptionIcons';
|
||||
@@ -56,7 +55,6 @@ export const planMetaOf = (name: string) => PLAN_META[name] ?? PLAN_META.free;
|
||||
|
||||
export default function SubscriptionPage() {
|
||||
const qc = useQueryClient();
|
||||
const [tab, setTab] = useState<'plans' | 'discounts'>('plans');
|
||||
const [purchaseTarget, setPurchaseTarget] = useState<{ period: SubscriptionPeriod; planName: string } | null>(null);
|
||||
const [selectedGateway, setSelectedGateway] = useState<string>('');
|
||||
|
||||
@@ -124,14 +122,6 @@ export default function SubscriptionPage() {
|
||||
style={{ background: 'var(--surface)', minWidth: 0 }}
|
||||
className="px-4 py-4 md:px-6 md:py-6 rounded-[var(--r-lg)]"
|
||||
>
|
||||
<div className="seg" style={{ marginBottom: 20 }}>
|
||||
<button className={tab === 'plans' ? 'on' : ''} onClick={() => setTab('plans')}>اشتراک</button>
|
||||
<button className={tab === 'discounts' ? 'on' : ''} onClick={() => setTab('discounts')}>مدیریت تخفیفها</button>
|
||||
</div>
|
||||
|
||||
{tab === 'discounts' ? (
|
||||
<DiscountTab />
|
||||
) : (
|
||||
<div dir="ltr" style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 32, paddingTop: 8 }}>
|
||||
{/* ── Header: current plan (left) + title (right) ── */}
|
||||
<div style={{ display: 'flex', width: '100%', justifyContent: 'space-between', alignItems: 'center', gap: 16, flexWrap: 'wrap' }}>
|
||||
@@ -173,7 +163,6 @@ export default function SubscriptionPage() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</SettingsLayout>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user