feat(settings): restructure settings into payment, shipping, and rich page builder v2 with SEO and icons
Some checks failed
Deploy Canina / deploy (push) Has been cancelled

This commit is contained in:
parsa aghaei 2026-08-18 20:08:07 +03:30
parent aa10ee735f
commit a291fa0c4a
22 changed files with 37783 additions and 35567 deletions

View File

@ -25,6 +25,8 @@ import {
Languages, Languages,
UserCheck, UserCheck,
DollarSign, DollarSign,
CreditCard,
Truck,
Sliders, Sliders,
Globe, Globe,
ChevronDown, ChevronDown,
@ -102,7 +104,9 @@ export default function Sidebar({ isOpen, setIsOpen }: SidebarProps) {
badge: newOrdersCount > 0 ? newOrdersCount : undefined, badge: newOrdersCount > 0 ? newOrdersCount : undefined,
}, },
{ icon: Receipt, label: 'تراکنش‌ها و لاگ پرداخت', path: '/transactions' }, { icon: Receipt, label: 'تراکنش‌ها و لاگ پرداخت', path: '/transactions' },
{ icon: DollarSign, label: 'تنظیمات مالی و ارسال', path: '/settings/financial' }, { icon: CreditCard, label: 'روش‌های پرداخت و زیبال', path: '/settings/payment-methods' },
{ icon: Truck, label: 'تنظیمات ارسال و کرایه', path: '/settings/shipping' },
{ icon: DollarSign, label: 'تنظیمات مالی و مالیات', path: '/settings/financial' },
], ],
}, },
{ {
@ -151,7 +155,10 @@ export default function Sidebar({ isOpen, setIsOpen }: SidebarProps) {
icon: Settings, icon: Settings,
items: [ items: [
{ icon: Settings, label: 'تنظیمات اصلی فروشگاه', path: '/settings' }, { icon: Settings, label: 'تنظیمات اصلی فروشگاه', path: '/settings' },
{ icon: Languages, label: 'متون رابط کاربری', path: '/ui-texts' }, { icon: Languages, label: 'ویرایشگر محتوای صفحات (Page Builder)', path: '/ui-texts' },
{ icon: CreditCard, label: 'روش‌های پرداخت و زیبال', path: '/settings/payment-methods' },
{ icon: Truck, label: 'تنظیمات ارسال و کرایه', path: '/settings/shipping' },
{ icon: DollarSign, label: 'تنظیمات مالی و مالیات', path: '/settings/financial' },
{ icon: MessageSquare, label: 'درگاه پیامک (MeliPayamak)', path: '/settings/sms' }, { icon: MessageSquare, label: 'درگاه پیامک (MeliPayamak)', path: '/settings/sms' },
{ icon: ShieldCheck, label: 'گواهی SSL و امنیت', path: '/settings/ssl' }, { icon: ShieldCheck, label: 'گواهی SSL و امنیت', path: '/settings/ssl' },
{ icon: Globe, label: 'تنظیمات سئو (SEO)', path: '/settings/seo' }, { icon: Globe, label: 'تنظیمات سئو (SEO)', path: '/settings/seo' },

View File

@ -0,0 +1,182 @@
import React, { useState, useMemo } from 'react';
import {
X,
Search,
Check,
Smile,
Pill,
ShieldCheck,
HeartPulse,
Sparkles,
ShoppingBag,
User,
Building2,
PhoneCall,
Activity,
Heart,
Dog,
BookOpen,
FileText,
Video,
Award,
Star,
Truck,
HelpCircle,
MessageSquare,
Globe,
Settings,
Flame,
CheckCircle2,
AlertCircle,
ThumbsUp,
Package,
Layers,
Compass,
MapPin,
Mail,
Send,
Zap,
Tag,
Gift,
Clock,
} from 'lucide-react';
interface IconPickerModalProps {
isOpen: boolean;
onClose: () => void;
currentIcon?: string;
onSelect: (iconName: string) => void;
}
export const ICON_REGISTRY: Record<string, React.ComponentType<{ className?: string }>> = {
Pill,
ShieldCheck,
HeartPulse,
Sparkles,
ShoppingBag,
User,
Building2,
PhoneCall,
Activity,
Heart,
Dog,
BookOpen,
FileText,
Video,
Award,
Star,
Truck,
HelpCircle,
MessageSquare,
Globe,
Settings,
Flame,
CheckCircle2,
AlertCircle,
ThumbsUp,
Package,
Layers,
Compass,
MapPin,
Mail,
Send,
Zap,
Tag,
Gift,
Clock,
Smile,
};
export default function IconPickerModal({
isOpen,
onClose,
currentIcon,
onSelect,
}: IconPickerModalProps) {
const [search, setSearch] = useState('');
const filteredIcons = useMemo(() => {
const query = search.toLowerCase().trim();
return Object.keys(ICON_REGISTRY).filter((name) =>
name.toLowerCase().includes(query)
);
}, [search]);
if (!isOpen) return null;
return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-gray-900/60 backdrop-blur-sm font-vazir" dir="rtl">
<div className="bg-white rounded-3xl w-full max-w-lg shadow-2xl overflow-hidden border border-gray-100 animate-in zoom-in-95 duration-200">
{/* Header */}
<div className="p-6 border-b border-gray-100 flex items-center justify-between bg-gray-50/50">
<div>
<h3 className="text-base font-black text-gray-900">انتخاب آیکون (Lucide Icons)</h3>
<p className="text-xs text-gray-500 font-medium mt-0.5">آیکون مورد نظر برای این بخش را انتخاب کنید</p>
</div>
<button
onClick={onClose}
className="p-2 text-gray-400 hover:text-gray-700 hover:bg-gray-100 rounded-xl transition-all cursor-pointer"
>
<X className="w-5 h-5" />
</button>
</div>
{/* Search */}
<div className="p-4 border-b border-gray-100 bg-white">
<div className="relative">
<Search className="w-4 h-4 text-gray-400 absolute right-3.5 top-3" />
<input
type="text"
placeholder="جستجوی نام آیکون (مانند Pill, Heart, Shield, Award)..."
value={search}
onChange={(e) => setSearch(e.target.value)}
className="w-full pr-10 pl-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl text-xs font-bold focus:outline-none focus:ring-2 focus:ring-purple-500"
dir="ltr"
/>
</div>
</div>
{/* Icon Grid */}
<div className="p-6 max-h-[360px] overflow-y-auto grid grid-cols-4 sm:grid-cols-6 gap-3">
{filteredIcons.map((name) => {
const IconComp = ICON_REGISTRY[name];
const isSelected = currentIcon === name;
return (
<button
key={name}
type="button"
onClick={() => {
onSelect(name);
onClose();
}}
className={`p-3 rounded-2xl flex flex-col items-center gap-1.5 transition-all border cursor-pointer group ${
isSelected
? 'bg-purple-600 text-white border-purple-600 shadow-md shadow-purple-200 scale-105'
: 'bg-white hover:bg-purple-50 text-gray-700 border-gray-100 hover:border-purple-200 hover:text-purple-700'
}`}
>
<IconComp className="w-6 h-6 transition-transform group-hover:scale-110" />
<span className="text-[10px] font-mono font-bold truncate max-w-full" dir="ltr">
{name}
</span>
{isSelected && <Check className="w-3 h-3 text-amber-300" />}
</button>
);
})}
</div>
{/* Footer */}
<div className="p-4 border-t border-gray-100 flex justify-end bg-gray-50/50">
<button
type="button"
onClick={onClose}
className="px-5 py-2 text-xs font-bold text-gray-600 hover:bg-gray-200 rounded-xl transition-all cursor-pointer"
>
بستن
</button>
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,239 @@
import React, { useRef } from 'react';
import {
Bold,
Italic,
Underline,
Heading1,
Heading2,
Heading3,
List,
ListOrdered,
Link,
AlignRight,
AlignCenter,
AlignLeft,
Palette,
Undo,
Redo,
} from 'lucide-react';
interface RichTextEditorProps {
value: string;
onChange: (html: string) => void;
placeholder?: string;
className?: string;
}
const COLORS = [
{ label: 'سیاه / پیش‌فرض', value: '#111827' },
{ label: 'خاکستری', value: '#4b5563' },
{ label: 'آبی کنینا', value: '#1d4ed8' },
{ label: 'بنفش اختصاصی', value: '#7c3aed' },
{ label: 'سبز درمانی', value: '#059669' },
{ label: 'قرمز هشدار', value: '#dc2626' },
{ label: 'کهربایی / زرد', value: '#d97706' },
];
export default function RichTextEditor({
value,
onChange,
placeholder,
className = '',
}: RichTextEditorProps) {
const editorRef = useRef<HTMLDivElement>(null);
const exec = (command: string, val: string | undefined = undefined) => {
document.execCommand(command, false, val);
if (editorRef.current) {
onChange(editorRef.current.innerHTML);
}
};
const handleLink = () => {
const url = prompt('آدرس لینک (URL) را وارد کنید:', 'https://');
if (url) {
exec('createLink', url);
}
};
const handleInput = () => {
if (editorRef.current) {
onChange(editorRef.current.innerHTML);
}
};
return (
<div className={`border border-gray-200 rounded-2xl bg-white overflow-hidden shadow-xs ${className}`}>
{/* Toolbar */}
<div className="bg-gray-50/80 border-b border-gray-100 p-2 flex flex-wrap items-center gap-1 text-gray-700">
{/* Headings */}
<div className="flex items-center gap-0.5 bg-white p-0.5 rounded-xl border border-gray-200">
<button
type="button"
onClick={() => exec('formatBlock', '<h1>')}
className="p-1.5 hover:bg-gray-100 rounded-lg text-xs font-bold transition-colors cursor-pointer"
title="تگ تیتر H1 (برای سئو)"
>
<Heading1 className="w-4 h-4 text-purple-700" />
</button>
<button
type="button"
onClick={() => exec('formatBlock', '<h2>')}
className="p-1.5 hover:bg-gray-100 rounded-lg text-xs font-bold transition-colors cursor-pointer"
title="تگ تیتر H2"
>
<Heading2 className="w-4 h-4 text-purple-600" />
</button>
<button
type="button"
onClick={() => exec('formatBlock', '<h3>')}
className="p-1.5 hover:bg-gray-100 rounded-lg text-xs font-bold transition-colors cursor-pointer"
title="تگ تیتر H3"
>
<Heading3 className="w-4 h-4 text-purple-500" />
</button>
<button
type="button"
onClick={() => exec('formatBlock', '<p>')}
className="p-1.5 hover:bg-gray-100 rounded-lg text-[11px] font-bold transition-colors cursor-pointer text-gray-600 px-2"
title="پاراگراف عادی (P)"
>
P
</button>
</div>
{/* Basic Formats */}
<div className="flex items-center gap-0.5 bg-white p-0.5 rounded-xl border border-gray-200">
<button
type="button"
onClick={() => exec('bold')}
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer"
title="Bold"
>
<Bold className="w-4 h-4" />
</button>
<button
type="button"
onClick={() => exec('italic')}
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer"
title="Italic"
>
<Italic className="w-4 h-4" />
</button>
<button
type="button"
onClick={() => exec('underline')}
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer"
title="Underline"
>
<Underline className="w-4 h-4" />
</button>
</div>
{/* Alignment */}
<div className="flex items-center gap-0.5 bg-white p-0.5 rounded-xl border border-gray-200">
<button
type="button"
onClick={() => exec('justifyRight')}
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer"
title="راست‌چین"
>
<AlignRight className="w-4 h-4" />
</button>
<button
type="button"
onClick={() => exec('justifyCenter')}
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer"
title="وسط‌چین"
>
<AlignCenter className="w-4 h-4" />
</button>
<button
type="button"
onClick={() => exec('justifyLeft')}
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer"
title="چپ‌چین"
>
<AlignLeft className="w-4 h-4" />
</button>
</div>
{/* Lists & Link */}
<div className="flex items-center gap-0.5 bg-white p-0.5 rounded-xl border border-gray-200">
<button
type="button"
onClick={() => exec('insertUnorderedList')}
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer"
title="لیست بالت‌دار"
>
<List className="w-4 h-4" />
</button>
<button
type="button"
onClick={() => exec('insertOrderedList')}
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer"
title="لیست شماره‌دار"
>
<ListOrdered className="w-4 h-4" />
</button>
<button
type="button"
onClick={handleLink}
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer text-blue-600"
title="درج لینک"
>
<Link className="w-4 h-4" />
</button>
</div>
{/* Color Palette */}
<div className="flex items-center gap-1 bg-white px-2 py-1 rounded-xl border border-gray-200">
<Palette className="w-3.5 h-3.5 text-gray-400" />
<div className="flex items-center gap-1">
{COLORS.map((c) => (
<button
key={c.value}
type="button"
onClick={() => exec('foreColor', c.value)}
className="w-3.5 h-3.5 rounded-full border border-black/10 cursor-pointer hover:scale-125 transition-transform"
style={{ backgroundColor: c.value }}
title={c.label}
/>
))}
</div>
</div>
{/* Undo / Redo */}
<div className="flex items-center gap-0.5 ms-auto">
<button
type="button"
onClick={() => exec('undo')}
className="p-1.5 hover:bg-gray-200 rounded-lg transition-colors cursor-pointer"
title="Undo"
>
<Undo className="w-3.5 h-3.5 text-gray-500" />
</button>
<button
type="button"
onClick={() => exec('redo')}
className="p-1.5 hover:bg-gray-200 rounded-lg transition-colors cursor-pointer"
title="Redo"
>
<Redo className="w-3.5 h-3.5 text-gray-500" />
</button>
</div>
</div>
{/* Editable Area */}
<div
ref={editorRef}
contentEditable
onInput={handleInput}
dangerouslySetInnerHTML={{ __html: value }}
data-placeholder={placeholder}
className="p-4 min-h-[140px] max-h-[350px] overflow-y-auto outline-none text-xs leading-relaxed text-gray-800 font-vazir empty:before:content-[attr(data-placeholder)] empty:before:text-gray-400"
dir="rtl"
/>
</div>
);
}

View File

@ -1,5 +1,5 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { DollarSign, Save, Plus, X } from 'lucide-react'; import { DollarSign, Save, Plus, X, Heart, Percent, Wallet } from 'lucide-react';
import { toast } from 'react-hot-toast'; import { toast } from 'react-hot-toast';
import api from '../services/api'; import api from '../services/api';
import Spinner from '../components/ui/Spinner'; import Spinner from '../components/ui/Spinner';
@ -14,16 +14,20 @@ export default function FinancialSettingsPage() {
charityDonationOptions: [10000, 20000, 50000], charityDonationOptions: [10000, 20000, 50000],
walletWithdrawalEnabled: false, walletWithdrawalEnabled: false,
}); });
const [charityStep, setCharityStep] = useState('10000');
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false); const [isSaving, setIsSaving] = useState(false);
const [donationInput, setDonationInput] = useState(''); const [donationInput, setDonationInput] = useState('');
useEffect(() => { useEffect(() => {
let isSubscribed = true; let isSubscribed = true;
api.get('/settings/financial') Promise.all([
.then(res => { api.get('/settings/financial'),
api.get('/admin/settings'),
])
.then(([resFin, resAdmin]) => {
if (!isSubscribed) return; if (!isSubscribed) return;
const data = res.data?.data || res.data; const data = resFin.data?.data || resFin.data;
if (data) { if (data) {
setFinancial({ setFinancial({
taxPercentage: Number(data.taxPercentage ?? 10), taxPercentage: Number(data.taxPercentage ?? 10),
@ -35,8 +39,11 @@ export default function FinancialSettingsPage() {
walletWithdrawalEnabled: Boolean(data.walletWithdrawalEnabled ?? false), walletWithdrawalEnabled: Boolean(data.walletWithdrawalEnabled ?? false),
}); });
} }
if (resAdmin.data?.success) {
setCharityStep(resAdmin.data.data.CHARITY_ROUND_STEP || '10000');
}
}) })
.catch(err => { .catch((err) => {
console.warn('Failed to fetch Financial settings', err); console.warn('Failed to fetch Financial settings', err);
}) })
.finally(() => { .finally(() => {
@ -51,8 +58,14 @@ export default function FinancialSettingsPage() {
e.preventDefault(); e.preventDefault();
try { try {
setIsSaving(true); setIsSaving(true);
await api.patch('/settings/financial', financial); await Promise.all([
toast.success('تنظیمات مالی و ارسال با موفقیت بروزرسانی شد'); api.patch('/settings/financial', financial),
api.put('/admin/settings', {
TAX_PERCENTAGE: String(financial.taxPercentage),
CHARITY_ROUND_STEP: charityStep,
}),
]);
toast.success('تنظیمات مالی با موفقیت بروزرسانی شد');
} catch (err) { } catch (err) {
console.error('Failed to update financial settings:', err); console.error('Failed to update financial settings:', err);
toast.error('خطا در بروزرسانی تنظیمات مالی'); toast.error('خطا در بروزرسانی تنظیمات مالی');
@ -75,29 +88,37 @@ export default function FinancialSettingsPage() {
const removeDonationOption = (amount: number) => { const removeDonationOption = (amount: number) => {
setFinancial({ setFinancial({
...financial, ...financial,
charityDonationOptions: financial.charityDonationOptions.filter(a => a !== amount), charityDonationOptions: financial.charityDonationOptions.filter((a) => a !== amount),
}); });
}; };
return ( return (
<div className="space-y-6"> <div className="space-y-6 font-vazir" dir="rtl">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4"> <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div> <div>
<h2 className="text-2xl font-black text-gray-900 flex items-center gap-2"> <h2 className="text-2xl font-black text-gray-900 flex items-center gap-2">
<DollarSign className="w-6 h-6 text-purple-600" /> <DollarSign className="w-6 h-6 text-emerald-600" />
تنظیمات مالی و ارسال (Financial & Shipping Settings) تنظیمات مالی، مالیات و خیریه (Financial Settings)
</h2> </h2>
<p className="text-gray-500 font-medium mt-1">تنظیم درصد مالیات، آستانه ارسال رایگان و گزینههای کمک به خیریه</p> <p className="text-gray-500 font-medium mt-1">
تعیین درصد مالیات بر ارزش افزوده، کمکهای خیریه ردپای مهربانی و تسویهحساب کیف پول
</p>
</div> </div>
</div> </div>
{isLoading ? ( {isLoading ? (
<div className="flex justify-center p-12"><Spinner size="lg" className="text-purple-600" /></div> <div className="flex justify-center p-12">
<Spinner size="lg" className="text-emerald-600" />
</div>
) : ( ) : (
<form onSubmit={handleSave} className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-6"> <form onSubmit={handleSave} className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Tax Percentage */}
<div> <div>
<label className="block text-sm font-bold text-gray-700 mb-1">درصد مالیات ارزش افزوده (taxPercentage) *</label> <label className="block text-sm font-bold text-gray-700 mb-1.5 flex items-center gap-1.5">
<Percent className="w-4 h-4 text-emerald-600" />
<span>درصد مالیات بر ارزش افزوده (VAT) *</span>
</label>
<div className="relative"> <div className="relative">
<input <input
required required
@ -106,36 +127,35 @@ export default function FinancialSettingsPage() {
max="100" max="100"
value={financial.taxPercentage} value={financial.taxPercentage}
onChange={(e) => setFinancial({ ...financial, taxPercentage: Number(e.target.value) })} onChange={(e) => setFinancial({ ...financial, taxPercentage: Number(e.target.value) })}
className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 outline-none font-bold text-sm" className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-emerald-500 outline-none font-bold text-sm"
dir="ltr" dir="ltr"
/> />
<span className="absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 font-bold">%</span> <span className="absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 font-bold">%</span>
</div> </div>
<p className="text-xs text-gray-500 mt-1">درصد قانونی محاسبه مالیات بر ارزش افزوده در فاکتور نهایی سفارشات.</p>
</div> </div>
{/* Charity Round Step */}
<div> <div>
<label className="block text-sm font-bold text-gray-700 mb-1">هزینه ارسال استاندارد (standardShippingFee) *</label> <label className="block text-sm font-bold text-gray-700 mb-1.5 flex items-center gap-1.5">
<Heart className="w-4 h-4 text-rose-500" />
<span>پله رند کردن کمک به خیریه ردپای مهربانی (تومان)</span>
</label>
<PriceInput <PriceInput
required value={charityStep}
value={financial.standardShippingFee} onChange={(val) => setCharityStep(val)}
onChange={(val) => setFinancial({ ...financial, standardShippingFee: Number(val) })} placeholder="10000"
className="px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 text-sm" className="px-4 py-3 rounded-xl border border-gray-200 focus:border-emerald-500 text-sm"
/> />
<p className="text-xs text-gray-500 mt-1">مبلغ فاکتور به نزدیکترین ضریب این عدد (مثلاً ۱۰,۰۰۰ یا ۵۰,۰۰۰ تومان) رند میگردد.</p>
</div> </div>
<div className="md:col-span-2"> {/* Charity Donation Options */}
<label className="block text-sm font-bold text-gray-700 mb-1">آستانه ارسال رایگان (freeShippingThreshold) *</label> <div className="md:col-span-2 space-y-2 pt-3 border-t border-gray-100">
<PriceInput <label className="block text-sm font-bold text-gray-700 mb-1 flex items-center gap-1.5">
required <Heart className="w-4 h-4 text-rose-500" />
value={financial.freeShippingThreshold} <span>گزینههای دلخواه کمک مستقیم به خیریه (charityDonationOptions)</span>
onChange={(val) => setFinancial({ ...financial, freeShippingThreshold: Number(val) })} </label>
className="px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 text-sm"
/>
<p className="text-xs text-gray-500 mt-1">سبدهای خرید با مبلغ بالاتر از این مقدار، ارسال رایگان خواهند داشت.</p>
</div>
<div className="md:col-span-2 space-y-2">
<label className="block text-sm font-bold text-gray-700 mb-1">گزینههای کمک به خیریه ردپای مهربانی (charityDonationOptions)</label>
<div className="flex gap-2 max-w-md"> <div className="flex gap-2 max-w-md">
<PriceInput <PriceInput
placeholder="مبلغ جدید (مثال: ۱۰۰,۰۰۰)" placeholder="مبلغ جدید (مثال: ۱۰۰,۰۰۰)"
@ -146,17 +166,24 @@ export default function FinancialSettingsPage() {
<button <button
type="button" type="button"
onClick={addDonationOption} onClick={addDonationOption}
className="px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-xl text-xs font-bold flex items-center gap-1 shrink-0" className="px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-white rounded-xl text-xs font-bold flex items-center gap-1 shrink-0 cursor-pointer"
> >
<Plus className="w-4 h-4" /> افزودن <Plus className="w-4 h-4" /> افزودن
</button> </button>
</div> </div>
<div className="flex flex-wrap gap-2 pt-2"> <div className="flex flex-wrap gap-2 pt-2">
{financial.charityDonationOptions.map(amount => ( {financial.charityDonationOptions.map((amount) => (
<span key={amount} className="inline-flex items-center gap-1.5 px-3 py-1.5 bg-purple-50 text-purple-700 text-xs font-bold rounded-xl border border-purple-200"> <span
key={amount}
className="inline-flex items-center gap-1.5 px-3 py-1.5 bg-rose-50 text-rose-700 text-xs font-bold rounded-xl border border-rose-200"
>
{amount.toLocaleString('fa-IR')} تومان {amount.toLocaleString('fa-IR')} تومان
<button type="button" onClick={() => removeDonationOption(amount)} className="hover:text-red-500"> <button
type="button"
onClick={() => removeDonationOption(amount)}
className="hover:text-red-500 cursor-pointer"
>
<X className="w-3.5 h-3.5" /> <X className="w-3.5 h-3.5" />
</button> </button>
</span> </span>
@ -166,16 +193,21 @@ export default function FinancialSettingsPage() {
{/* Wallet Withdrawal Feature Toggle */} {/* Wallet Withdrawal Feature Toggle */}
<div className="md:col-span-2 pt-4 border-t border-gray-100"> <div className="md:col-span-2 pt-4 border-t border-gray-100">
<label className="flex items-center gap-3 cursor-pointer p-4 bg-purple-50/50 hover:bg-purple-50 rounded-2xl border border-purple-100 transition-colors"> <label className="flex items-center gap-3 cursor-pointer p-4 bg-emerald-50/50 hover:bg-emerald-50 rounded-2xl border border-emerald-100 transition-colors">
<input <input
type="checkbox" type="checkbox"
checked={Boolean(financial.walletWithdrawalEnabled)} checked={Boolean(financial.walletWithdrawalEnabled)}
onChange={(e) => setFinancial({ ...financial, walletWithdrawalEnabled: e.target.checked })} onChange={(e) => setFinancial({ ...financial, walletWithdrawalEnabled: e.target.checked })}
className="w-5 h-5 rounded-lg text-purple-600 focus:ring-purple-500 border-gray-300 cursor-pointer" className="w-5 h-5 rounded-lg text-emerald-600 focus:ring-emerald-500 border-gray-300 cursor-pointer"
/> />
<div> <div>
<span className="text-sm font-black text-gray-900 block">فعالسازی امکان ثبت درخواست برداشت و تسویهحساب کیف پول (wallet_withdrawal_enabled)</span> <span className="text-sm font-black text-gray-900 block flex items-center gap-2">
<span className="text-xs text-gray-500 font-medium block mt-0.5">در صورت فعال بودن، کاربران میتوانند از طریق داشبورد خود درخواست تسویه و واریز وجه به شماره شبا ثبت کنند.</span> <Wallet className="w-4 h-4 text-emerald-600" />
فعالسازی امکان ثبت درخواست برداشت و تسویهحساب کیف پول
</span>
<span className="text-xs text-gray-500 font-medium block mt-0.5">
در صورت فعال بودن، کاربران میتوانند از طریق داشبورد خود درخواست تسویه و واریز وجه کیف پول به شماره شبا ثبت کنند.
</span>
</div> </div>
</label> </label>
</div> </div>
@ -185,7 +217,7 @@ export default function FinancialSettingsPage() {
<button <button
type="submit" type="submit"
disabled={isSaving} disabled={isSaving}
className="bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-8 rounded-xl transition-colors flex items-center gap-2 shadow-md shadow-purple-200" className="bg-emerald-600 hover:bg-emerald-700 text-white font-bold py-3 px-8 rounded-xl transition-colors flex items-center gap-2 shadow-md shadow-emerald-200 cursor-pointer"
> >
{isSaving ? <Spinner size="sm" /> : <Save className="w-5 h-5" />} {isSaving ? <Spinner size="sm" /> : <Save className="w-5 h-5" />}
ذخیره تنظیمات مالی ذخیره تنظیمات مالی

View File

@ -0,0 +1,270 @@
import { useState, useEffect } from 'react';
import { CreditCard, Save, ShieldCheck, Wallet, ArrowLeftRight, CheckCircle2 } from 'lucide-react';
import { toast } from 'react-hot-toast';
import api from '../services/api';
import Spinner from '../components/ui/Spinner';
export default function PaymentGatewaysPage() {
const [settings, setSettings] = useState({
PAY_GATEWAY_CARD_ENABLE: 'true',
PAY_GATEWAY_WALLET_ENABLE: 'true',
PAY_GATEWAY_ONLINE_ENABLE: 'true',
PAY_GATEWAY_COD_ENABLE: 'false',
ZIBAL_MERCHANT: 'zibal',
ZIBAL_SANDBOX: 'true',
FRONTEND_URL: 'https://canina.ir',
});
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
useEffect(() => {
let isSubscribed = true;
api.get('/admin/settings')
.then((res) => {
if (!isSubscribed) return;
if (res.data?.success) {
const d = res.data.data;
setSettings({
PAY_GATEWAY_CARD_ENABLE: d.PAY_GATEWAY_CARD_ENABLE ?? 'true',
PAY_GATEWAY_WALLET_ENABLE: d.PAY_GATEWAY_WALLET_ENABLE ?? 'true',
PAY_GATEWAY_ONLINE_ENABLE: d.PAY_GATEWAY_ONLINE_ENABLE ?? 'true',
PAY_GATEWAY_COD_ENABLE: d.PAY_GATEWAY_COD_ENABLE ?? 'false',
ZIBAL_MERCHANT: d.ZIBAL_MERCHANT || 'zibal',
ZIBAL_SANDBOX: d.ZIBAL_SANDBOX ?? 'true',
FRONTEND_URL: d.FRONTEND_URL || 'https://canina.ir',
});
}
})
.catch((err) => {
console.error('Failed to fetch payment settings', err);
})
.finally(() => {
if (isSubscribed) setIsLoading(false);
});
return () => {
isSubscribed = false;
};
}, []);
const handleSave = async (e: React.FormEvent) => {
e.preventDefault();
try {
setIsSaving(true);
await api.put('/admin/settings', settings);
toast.success('تنظیمات روش‌های پرداخت با موفقیت بروزرسانی شد.');
} catch (err) {
console.error('Failed to update payment settings', err);
toast.error('خطا در ذخیره تنظیمات درگاه پرداخت');
} finally {
setIsSaving(false);
}
};
return (
<div className="space-y-6 font-vazir" dir="rtl">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div>
<h2 className="text-2xl font-black text-gray-900 flex items-center gap-2">
<CreditCard className="w-6 h-6 text-indigo-600" />
مدیریت روشهای پرداخت و درگاه بانکی
</h2>
<p className="text-gray-500 font-medium mt-1">
پیکربندی پایانههای پرداخت اینترنتی زیبال، کیف پول داخلی، کارت به کارت و پرداخت در محل
</p>
</div>
</div>
{isLoading ? (
<div className="flex justify-center p-12">
<Spinner size="lg" className="text-indigo-600" />
</div>
) : (
<form onSubmit={handleSave} className="space-y-6">
{/* Methods Cards */}
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-6">
<h3 className="text-base font-black text-gray-900 border-b border-gray-100 pb-3 flex items-center gap-2">
<ShieldCheck className="w-5 h-5 text-indigo-600" />
وضعیت فعال بودن روشهای پرداخت در تسویهحساب
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{/* Zibal IPG */}
<div className="flex items-center justify-between p-4 bg-indigo-50/50 rounded-2xl border border-indigo-100">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-indigo-600 text-white flex items-center justify-center font-black">
Z
</div>
<div>
<h4 className="font-bold text-gray-900 text-sm">درگاه آنلاین شتاب (زیبال)</h4>
<p className="text-xs text-gray-500 mt-0.5">پرداخت اینترنتی کلیه کارتهای عضو شتاب</p>
</div>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={settings.PAY_GATEWAY_ONLINE_ENABLE === 'true'}
onChange={(e) =>
setSettings({
...settings,
PAY_GATEWAY_ONLINE_ENABLE: e.target.checked ? 'true' : 'false',
})
}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-indigo-600"></div>
</label>
</div>
{/* Wallet Internal */}
<div className="flex items-center justify-between p-4 bg-blue-50/50 rounded-2xl border border-blue-100">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-blue-600 text-white flex items-center justify-center font-black">
<Wallet className="w-5 h-5" />
</div>
<div>
<h4 className="font-bold text-gray-900 text-sm">اعتبار کیف پول کنینا</h4>
<p className="text-xs text-gray-500 mt-0.5">پرداخت لحظهای از موجودی شارژشده کاربر</p>
</div>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={settings.PAY_GATEWAY_WALLET_ENABLE === 'true'}
onChange={(e) =>
setSettings({
...settings,
PAY_GATEWAY_WALLET_ENABLE: e.target.checked ? 'true' : 'false',
})
}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
</label>
</div>
{/* Card to Card */}
<div className="flex items-center justify-between p-4 bg-slate-50 rounded-2xl border border-gray-200">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-slate-700 text-white flex items-center justify-center font-black">
<ArrowLeftRight className="w-5 h-5" />
</div>
<div>
<h4 className="font-bold text-gray-900 text-sm">کارت به کارت (واریز مستقیم)</h4>
<p className="text-xs text-gray-500 mt-0.5">واریز به شماره شبا / کارت رسمی و ثبت فیش</p>
</div>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={settings.PAY_GATEWAY_CARD_ENABLE === 'true'}
onChange={(e) =>
setSettings({
...settings,
PAY_GATEWAY_CARD_ENABLE: e.target.checked ? 'true' : 'false',
})
}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-slate-700"></div>
</label>
</div>
{/* Cash On Delivery */}
<div className="flex items-center justify-between p-4 bg-amber-50/50 rounded-2xl border border-amber-100">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-amber-600 text-white flex items-center justify-center font-black">
<CreditCard className="w-5 h-5" />
</div>
<div>
<h4 className="font-bold text-gray-900 text-sm">پرداخت در محل (COD)</h4>
<p className="text-xs text-gray-500 mt-0.5">پرداخت با پوز هنگام دریافت سفارش</p>
</div>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={settings.PAY_GATEWAY_COD_ENABLE === 'true'}
onChange={(e) =>
setSettings({
...settings,
PAY_GATEWAY_COD_ENABLE: e.target.checked ? 'true' : 'false',
})
}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-amber-600"></div>
</label>
</div>
</div>
</div>
{/* Zibal Configuration Card */}
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-5">
<div className="flex items-center justify-between border-b border-gray-100 pb-3">
<h3 className="text-base font-black text-gray-900 flex items-center gap-2">
<ShieldCheck className="w-5 h-5 text-indigo-600" />
پیکربندی پایانه پرداخت زیبال (Zibal IPG Config)
</h3>
{settings.ZIBAL_MERCHANT === 'zibal' && (
<span className="bg-amber-100 text-amber-800 text-xs px-3 py-1 rounded-xl font-bold flex items-center gap-1">
<CheckCircle2 className="w-3.5 h-3.5" />
حالت آزمایشی (Sandbox)
</span>
)}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
<div>
<label className="block text-xs font-bold text-gray-700 mb-1.5">
کد مرچنت زیبال (Merchant ID) *
</label>
<input
type="text"
required
value={settings.ZIBAL_MERCHANT}
onChange={(e) => setSettings({ ...settings, ZIBAL_MERCHANT: e.target.value })}
placeholder="zibal یا کد مرچنت دریافتی"
className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-indigo-500 text-xs font-mono font-bold"
dir="ltr"
/>
<p className="text-[11px] text-gray-400 mt-1">
جهت فعالسازی درگاه زنده، مرچنت آیدی رسمی زیبال را در این کادر قرار دهید.
</p>
</div>
<div>
<label className="block text-xs font-bold text-gray-700 mb-1.5">
دامنه بازگشت پس از پرداخت (Frontend Return Domain) *
</label>
<input
type="text"
required
value={settings.FRONTEND_URL}
onChange={(e) => setSettings({ ...settings, FRONTEND_URL: e.target.value })}
placeholder="https://canina.ir"
className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-indigo-500 text-xs font-mono font-bold"
dir="ltr"
/>
<p className="text-[11px] text-gray-400 mt-1">
آدرس صفحهای که نتیجه تراکنش به آن ارجاع داده میشود.
</p>
</div>
</div>
</div>
<div className="flex justify-end">
<button
type="submit"
disabled={isSaving}
className="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-8 rounded-xl transition-colors flex items-center gap-2 shadow-md shadow-indigo-200 cursor-pointer"
>
{isSaving ? <Spinner size="sm" /> : <Save className="w-5 h-5" />}
<span>ذخیره تغییرات روشهای پرداخت</span>
</button>
</div>
</form>
)}
</div>
);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,164 @@
import { useState, useEffect } from 'react';
import { Truck, Save, Gift, ShieldAlert } from 'lucide-react';
import { toast } from 'react-hot-toast';
import api from '../services/api';
import Spinner from '../components/ui/Spinner';
import PriceInput from '../components/ui/PriceInput';
export default function ShippingSettingsPage() {
const [shipping, setShipping] = useState({
SHIPPING_FEE: '85000',
FREE_SHIPPING_THRESHOLD: '2000000',
MIN_ORDER_AMOUNT: '0',
shipping_notice:
'ارسال رایگان برای سفارش‌های بالای ۱۵۰ هزار تومان — گارانتی اصالت کنینا آلمان — مشاوره تخصصی مکمل‌های دارویی سگ و گربه با کادر دامپزشکان مجرب',
});
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
useEffect(() => {
let isSubscribed = true;
api.get('/admin/settings')
.then((res) => {
if (!isSubscribed) return;
if (res.data?.success) {
const d = res.data.data;
setShipping({
SHIPPING_FEE: String(d.SHIPPING_FEE || d.shipping_fee || d.standardShippingFee || '85000'),
FREE_SHIPPING_THRESHOLD: String(d.FREE_SHIPPING_THRESHOLD || d.free_shipping_threshold || d.freeShippingThreshold || '2000000'),
MIN_ORDER_AMOUNT: String(d.MIN_ORDER_AMOUNT || d.min_order_amount || d.minOrderAmount || '0'),
shipping_notice: d.shipping_notice || d.SHIPPING_NOTICE || 'ارسال رایگان برای سفارش‌های بالای ۱۵۰ هزار تومان — گارانتی اصالت کنینا آلمان',
});
}
})
.catch((err) => {
console.error('Failed to fetch shipping settings', err);
})
.finally(() => {
if (isSubscribed) setIsLoading(false);
});
return () => {
isSubscribed = false;
};
}, []);
const handleSave = async (e: React.FormEvent) => {
e.preventDefault();
try {
setIsSaving(true);
await api.put('/admin/settings', shipping);
toast.success('تنظیمات ارسال و کرایه حمل با موفقیت بروزرسانی شد.');
} catch (err) {
console.error('Failed to update shipping settings:', err);
toast.error('خطا در ذخیره تنظیمات ارسال');
} finally {
setIsSaving(false);
}
};
return (
<div className="space-y-6 font-vazir" dir="rtl">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div>
<h2 className="text-2xl font-black text-gray-900 flex items-center gap-2">
<Truck className="w-6 h-6 text-blue-600" />
تنظیمات ارسال و کرایه حمل (Shipping & Delivery)
</h2>
<p className="text-gray-500 font-medium mt-1">
تعیین هزینه پایه پست، آستانه ارسال رایگان، حداقل مجاز مبلغ سفارش و نوار اعلان تحویل
</p>
</div>
</div>
{isLoading ? (
<div className="flex justify-center p-12">
<Spinner size="lg" className="text-blue-600" />
</div>
) : (
<form onSubmit={handleSave} className="space-y-6">
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-6">
<h3 className="text-base font-black text-gray-900 border-b border-gray-100 pb-3 flex items-center gap-2">
<Truck className="w-5 h-5 text-blue-600" />
قوانین هزینه و کرایه ارسال
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="block text-sm font-bold text-gray-700 mb-2">
هزینه ثابت ارسال (تومان) *
</label>
<PriceInput
value={shipping.SHIPPING_FEE}
onChange={(val) => setShipping({ ...shipping, SHIPPING_FEE: val })}
placeholder="مثال: ۸۵,۰۰۰"
className="border border-gray-200 rounded-xl p-3 focus:ring-2 focus:ring-blue-500"
/>
<p className="text-xs text-gray-500 mt-1.5 font-medium">
هزینه استاندارد پستی که برای سفارشهای عادی منظور میشود.
</p>
</div>
<div>
<label className="block text-sm font-bold text-gray-700 mb-2">
آستانه ارسال رایگان (تومان) *
</label>
<PriceInput
value={shipping.FREE_SHIPPING_THRESHOLD}
onChange={(val) => setShipping({ ...shipping, FREE_SHIPPING_THRESHOLD: val })}
placeholder="مثال: ۲,۰۰۰,۰۰۰"
className="border border-gray-200 rounded-xl p-3 focus:ring-2 focus:ring-blue-500"
/>
<p className="text-xs text-gray-500 mt-1.5 font-medium">
سفارشهای با جمع مبلغ بالاتر از این عدد، به طور خودکار رایگان ارسال میشوند.
</p>
</div>
<div>
<label className="block text-sm font-bold text-gray-700 mb-2">
حداقل مبلغ سفارش مجاز (تومان)
</label>
<PriceInput
value={shipping.MIN_ORDER_AMOUNT}
onChange={(val) => setShipping({ ...shipping, MIN_ORDER_AMOUNT: val })}
placeholder="۰ = بدون محدودیت"
className="border border-gray-200 rounded-xl p-3 focus:ring-2 focus:ring-blue-500"
/>
<p className="text-xs text-gray-500 mt-1.5 font-medium">
سفارشات کمتر از این عدد اجازه ورود به درگاه را نخواهند داشت (۰ برای لغو شرط).
</p>
</div>
<div className="md:col-span-2">
<label className="block text-sm font-bold text-gray-700 mb-2">
متن نوار متحرک اعلان بالای سایت (Ticker Announcement)
</label>
<textarea
rows={2}
value={shipping.shipping_notice}
onChange={(e) => setShipping({ ...shipping, shipping_notice: e.target.value })}
placeholder="ارسال رایگان برای سفارش‌های بالای ۱۵۰ هزار تومان — ..."
className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-blue-500 text-xs font-bold bg-amber-50/40"
/>
<p className="text-xs text-gray-500 mt-1 font-medium">
این متن در نوار زرد متحرک بالای تمام صفحات سایت نمایش داده میشود.
</p>
</div>
</div>
</div>
<div className="flex justify-end">
<button
type="submit"
disabled={isSaving}
className="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-8 rounded-xl transition-colors flex items-center gap-2 shadow-md shadow-blue-200 cursor-pointer"
>
{isSaving ? <Spinner size="sm" /> : <Save className="w-5 h-5" />}
<span>ذخیره تغییرات ارسال</span>
</button>
</div>
</form>
)}
</div>
);
}

View File

@ -1,5 +1,16 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Sliders, Save, AlertTriangle } from 'lucide-react'; import { Link } from 'react-router-dom';
import {
Sliders,
Save,
AlertTriangle,
ShieldAlert,
MessageSquare,
BookOpen,
ShoppingBag,
Info,
CheckCircle2,
} from 'lucide-react';
import { toast } from 'react-hot-toast'; import { toast } from 'react-hot-toast';
import api from '../services/api'; import api from '../services/api';
import Spinner from '../components/ui/Spinner'; import Spinner from '../components/ui/Spinner';
@ -12,26 +23,49 @@ export default function SystemSettingsPage() {
b2bRegistrationOpen: true, b2bRegistrationOpen: true,
supportPhone: '021-12345678', supportPhone: '021-12345678',
}); });
const [catalogSettings, setCatalogSettings] = useState({
CATALOG_ONLY_MODE: 'false',
CATALOG_SHOW_PRICES: 'true',
CATALOG_ALLOW_CART: 'false',
CATALOG_ALLOW_CHECKOUT: 'false',
CATALOG_PREORDER_BTN: 'false',
});
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false); const [isSaving, setIsSaving] = useState(false);
useEffect(() => { useEffect(() => {
let isSubscribed = true; let isSubscribed = true;
api.get('/settings/system') Promise.all([
.then(res => { api.get('/settings/system'),
api.get('/admin/settings'),
])
.then(([resSys, resAdmin]) => {
if (!isSubscribed) return; if (!isSubscribed) return;
const data = res.data?.data || res.data; const data = resSys.data?.data || resSys.data;
if (data) { if (data) {
setSystem(prev => ({ setSystem((prev) => ({
maintenanceMode: Boolean(data.maintenanceMode), maintenanceMode: Boolean(data.maintenanceMode),
allowGuestCheckout: Boolean(data.allowGuestCheckout ?? true), allowGuestCheckout: Boolean(data.allowGuestCheckout ?? true),
b2bRegistrationOpen: Boolean(data.b2bRegistrationOpen ?? true), b2bRegistrationOpen: Boolean(data.b2bRegistrationOpen ?? true),
supportPhone: data.supportPhone || prev.supportPhone, supportPhone: data.supportPhone || prev.supportPhone,
})); }));
} }
if (resAdmin.data?.success) {
const d = resAdmin.data.data;
setCatalogSettings({
CATALOG_ONLY_MODE: d.CATALOG_ONLY_MODE || 'false',
CATALOG_SHOW_PRICES: d.CATALOG_SHOW_PRICES || 'true',
CATALOG_ALLOW_CART: d.CATALOG_ALLOW_CART || 'false',
CATALOG_ALLOW_CHECKOUT: d.CATALOG_ALLOW_CHECKOUT || 'false',
CATALOG_PREORDER_BTN: d.CATALOG_PREORDER_BTN || 'false',
});
}
}) })
.catch(err => { .catch((err) => {
console.warn('Failed to fetch System settings, using default state', err); console.warn('Failed to fetch system/catalog settings', err);
}) })
.finally(() => { .finally(() => {
if (isSubscribed) setIsLoading(false); if (isSubscribed) setIsLoading(false);
@ -45,8 +79,14 @@ export default function SystemSettingsPage() {
e.preventDefault(); e.preventDefault();
try { try {
setIsSaving(true); setIsSaving(true);
await api.patch('/settings/system', system); await Promise.all([
toast.success('تنظیمات سیستمی با موفقیت بروزرسانی شد'); api.patch('/settings/system', system),
api.put('/admin/settings', {
MAINTENANCE_MODE: system.maintenanceMode ? 'true' : 'false',
...catalogSettings,
}),
]);
toast.success('تنظیمات سیستمی و حالت‌های فروشگاه با موفقیت ذخیره شد.');
} catch (err) { } catch (err) {
console.error('Failed to update system settings:', err); console.error('Failed to update system settings:', err);
toast.error('خطا در بروزرسانی تنظیمات سیستمی'); toast.error('خطا در بروزرسانی تنظیمات سیستمی');
@ -56,29 +96,61 @@ export default function SystemSettingsPage() {
}; };
return ( return (
<div className="space-y-6"> <div className="space-y-6 font-vazir" dir="rtl">
{/* Top Header with Quick Security and SMS links */}
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4"> <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div> <div>
<h2 className="text-2xl font-black text-gray-900 flex items-center gap-2"> <h2 className="text-2xl font-black text-gray-900 flex items-center gap-2">
<Sliders className="w-6 h-6 text-purple-600" /> <Sliders className="w-6 h-6 text-purple-600" />
تنظیمات سیستمی و کنترل حالتها (System Settings) تنظیمات سیستمی پیشرفته و کنترل دسترسی
</h2> </h2>
<p className="text-gray-500 font-medium mt-1">مدیریت حالت تعمیرات، خرید مهمان و ثبتنام همکاران B2B</p> <p className="text-gray-500 font-medium mt-1">
مدیریت وضعیت صیانت و تعمیرات، کنترل کاتالوگمود، خرید مهمان و ابزارهای امنیتی
</p>
</div>
{/* Action buttons for SSL and SMS as requested */}
<div className="flex items-center gap-2.5 flex-wrap">
<Link
to="/settings/ssl"
className="bg-emerald-50 text-emerald-700 hover:bg-emerald-100 border border-emerald-200 text-xs font-black px-4 py-2.5 rounded-xl transition-all flex items-center gap-2 shadow-xs"
>
<ShieldAlert className="w-4 h-4 text-emerald-600" />
<span>مدیریت گواهی SSL و امنیت</span>
</Link>
<Link
to="/settings/sms"
className="bg-purple-50 text-purple-700 hover:bg-purple-100 border border-purple-200 text-xs font-black px-4 py-2.5 rounded-xl transition-all flex items-center gap-2 shadow-xs"
>
<MessageSquare className="w-4 h-4 text-purple-600" />
<span>تنظیمات درگاه پیامک (MeliPayamak)</span>
</Link>
</div> </div>
</div> </div>
{isLoading ? ( {isLoading ? (
<div className="flex justify-center p-12"><Spinner size="lg" className="text-purple-600" /></div> <div className="flex justify-center p-12">
<Spinner size="lg" className="text-purple-600" />
</div>
) : ( ) : (
<form onSubmit={handleSave} className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-6"> <form onSubmit={handleSave} className="space-y-6">
<div className="space-y-4"> {/* Maintenance Mode Card */}
{/* Maintenance Mode */} <div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-4">
<div className="flex items-center justify-between p-4 bg-amber-50/60 rounded-xl border border-amber-200"> <h3 className="text-base font-black text-gray-900 border-b border-gray-100 pb-3 flex items-center gap-2">
<AlertTriangle className="w-5 h-5 text-amber-500" />
حالت تعمیرات و صیانت موقت سایت (Maintenance Mode)
</h3>
<div className="flex items-center justify-between p-4 bg-amber-50/70 rounded-2xl border border-amber-200">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<AlertTriangle className="w-6 h-6 text-amber-600" /> <div className="w-10 h-10 rounded-xl bg-amber-500 text-white flex items-center justify-center font-black">
<AlertTriangle className="w-5 h-5" />
</div>
<div> <div>
<h4 className="font-bold text-gray-900 text-sm">حالت تعمیرات (maintenanceMode)</h4> <h4 className="font-bold text-gray-900 text-sm">فعالسازی حالت تعمیرات</h4>
<p className="text-xs text-gray-600 mt-0.5">غیرفعالسازی موقت فرانتاند جهت بروزرسانی دیتابیس یا سرور</p> <p className="text-xs text-gray-600 mt-0.5">
با فعال کردن این گزینه، فرانتاند سایت برای کاربران قفل شده و صفحه «در حال بروزرسانی» نمایش داده میشود.
</p>
</div> </div>
</div> </div>
<label className="relative inline-flex items-center cursor-pointer"> <label className="relative inline-flex items-center cursor-pointer">
@ -88,66 +160,177 @@ export default function SystemSettingsPage() {
checked={system.maintenanceMode} checked={system.maintenanceMode}
onChange={(e) => setSystem({ ...system, maintenanceMode: e.target.checked })} onChange={(e) => setSystem({ ...system, maintenanceMode: e.target.checked })}
/> />
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-amber-600"></div> <div className="w-12 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-amber-500"></div>
</label> </label>
</div> </div>
{/* Guest Checkout */}
<div className="flex items-center justify-between p-4 bg-gray-50 rounded-xl border border-gray-200">
<div>
<h4 className="font-bold text-gray-900 text-sm">اجازه خرید کاربر مهمان (allowGuestCheckout)</h4>
<p className="text-xs text-gray-500 mt-0.5">امکان تسویهحساب سریع بدون نیاز به ایجاد حساب کاربری قبل از ثبت سفارش</p>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={system.allowGuestCheckout}
onChange={(e) => setSystem({ ...system, allowGuestCheckout: e.target.checked })}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
</label>
</div>
{/* B2B Registration Open */}
<div className="flex items-center justify-between p-4 bg-gray-50 rounded-xl border border-gray-200">
<div>
<h4 className="font-bold text-gray-900 text-sm">ثبتنام متقاضیان همکار باز است (b2bRegistrationOpen)</h4>
<p className="text-xs text-gray-500 mt-0.5">فعال بودن فرم پذیرش درخواستهای جدید عمدهفروشی در سایت</p>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={system.b2bRegistrationOpen}
onChange={(e) => setSystem({ ...system, b2bRegistrationOpen: e.target.checked })}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
</label>
</div>
{/* Support Phone */}
<div>
<label className="block text-sm font-bold text-gray-700 mb-1">شماره تلفن پشتیبانی اصلی (supportPhone) *</label>
<input
required
type="text"
value={system.supportPhone}
onChange={(e) => setSystem({ ...system, supportPhone: e.target.value })}
className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 outline-none text-sm font-bold"
dir="ltr"
/>
</div>
</div> </div>
<div className="flex justify-end pt-4 border-t border-gray-100"> {/* Catalog Only Mode Card */}
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-4">
<h3 className="text-base font-black text-gray-900 border-b border-gray-100 pb-3 flex items-center gap-2">
<BookOpen className="w-5 h-5 text-purple-600" />
حالت کاتالوگ آنلاین بدون فروش مستقیم (Catalog Only Mode)
</h3>
<div className="p-4 bg-purple-50/60 rounded-2xl border border-purple-100 space-y-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-purple-600 text-white flex items-center justify-center font-black">
<BookOpen className="w-5 h-5" />
</div>
<div>
<h4 className="font-bold text-gray-900 text-sm">فعالسازی حالت کاتالوگ</h4>
<p className="text-xs text-gray-600 mt-0.5">
مناسب برای زمانی که قصد دارید محصولات را صرفاً به عنوان دایرکتوری و مشخصات فنی معرفی کنید.
</p>
</div>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={catalogSettings.CATALOG_ONLY_MODE === 'true'}
onChange={(e) =>
setCatalogSettings({
...catalogSettings,
CATALOG_ONLY_MODE: e.target.checked ? 'true' : 'false',
})
}
/>
<div className="w-12 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
</label>
</div>
{catalogSettings.CATALOG_ONLY_MODE === 'true' && (
<div className="pt-4 border-t border-purple-200/60 grid grid-cols-1 md:grid-cols-2 gap-3 text-xs">
<label className="flex items-center gap-2.5 font-bold text-gray-800 p-2.5 bg-white rounded-xl border border-purple-100 cursor-pointer">
<input
type="checkbox"
checked={catalogSettings.CATALOG_SHOW_PRICES === 'true'}
onChange={(e) =>
setCatalogSettings({
...catalogSettings,
CATALOG_SHOW_PRICES: e.target.checked ? 'true' : 'false',
})
}
className="w-4 h-4 rounded text-purple-600 focus:ring-purple-500"
/>
<span>نمایش قیمت محصولات در حالت کاتالوگ</span>
</label>
<label className="flex items-center gap-2.5 font-bold text-gray-800 p-2.5 bg-white rounded-xl border border-purple-100 cursor-pointer">
<input
type="checkbox"
checked={catalogSettings.CATALOG_ALLOW_CART === 'true'}
onChange={(e) =>
setCatalogSettings({
...catalogSettings,
CATALOG_ALLOW_CART: e.target.checked ? 'true' : 'false',
})
}
className="w-4 h-4 rounded text-purple-600 focus:ring-purple-500"
/>
<span>امکان افزودن به سبد خرید</span>
</label>
<label className="flex items-center gap-2.5 font-bold text-gray-800 p-2.5 bg-white rounded-xl border border-purple-100 cursor-pointer">
<input
type="checkbox"
checked={catalogSettings.CATALOG_ALLOW_CHECKOUT === 'true'}
onChange={(e) =>
setCatalogSettings({
...catalogSettings,
CATALOG_ALLOW_CHECKOUT: e.target.checked ? 'true' : 'false',
})
}
className="w-4 h-4 rounded text-purple-600 focus:ring-purple-500"
/>
<span>امکان ورود به صفحه تسویهحساب (ثبت فاکتور)</span>
</label>
<label className="flex items-center gap-2.5 font-bold text-gray-800 p-2.5 bg-white rounded-xl border border-purple-100 cursor-pointer">
<input
type="checkbox"
checked={catalogSettings.CATALOG_PREORDER_BTN === 'true'}
onChange={(e) =>
setCatalogSettings({
...catalogSettings,
CATALOG_PREORDER_BTN: e.target.checked ? 'true' : 'false',
})
}
className="w-4 h-4 rounded text-purple-600 focus:ring-purple-500"
/>
<span>نمایش دکمه «ثبت پیشخرید» به جای خرید مستقیم</span>
</label>
</div>
)}
</div>
</div>
{/* User & B2B System Rules */}
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-200 space-y-4">
<h3 className="text-base font-black text-gray-900 border-b border-gray-100 pb-3 flex items-center gap-2">
<ShoppingBag className="w-5 h-5 text-slate-700" />
قوانین خرید مهمان و ثبتنام متقاضیان همکار
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="flex items-center justify-between p-4 bg-gray-50 rounded-2xl border border-gray-200">
<div>
<h4 className="font-bold text-gray-900 text-sm">اجازه خرید کاربر مهمان</h4>
<p className="text-xs text-gray-500 mt-0.5">تسویهحساب بدون نیاز به ساخت حساب کاربری قبلی</p>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={system.allowGuestCheckout}
onChange={(e) => setSystem({ ...system, allowGuestCheckout: e.target.checked })}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
</label>
</div>
<div className="flex items-center justify-between p-4 bg-gray-50 rounded-2xl border border-gray-200">
<div>
<h4 className="font-bold text-gray-900 text-sm">فرم ثبتنام همکاران B2B باز است</h4>
<p className="text-xs text-gray-500 mt-0.5">امکان ارسال درخواست نمایندگی جدید در سایت</p>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={system.b2bRegistrationOpen}
onChange={(e) => setSystem({ ...system, b2bRegistrationOpen: e.target.checked })}
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-600"></div>
</label>
</div>
<div className="md:col-span-2">
<label className="block text-sm font-bold text-gray-700 mb-1">
شماره تماس پشتیبانی اضطراری (در زمان تعمیرات)
</label>
<input
required
type="text"
value={system.supportPhone}
onChange={(e) => setSystem({ ...system, supportPhone: e.target.value })}
className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-purple-500 outline-none text-xs font-bold"
dir="ltr"
/>
</div>
</div>
</div>
<div className="flex justify-end">
<button <button
type="submit" type="submit"
disabled={isSaving} disabled={isSaving}
className="bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-8 rounded-xl transition-colors flex items-center gap-2 shadow-md shadow-purple-200" className="bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-8 rounded-xl transition-colors flex items-center gap-2 shadow-md shadow-purple-200 cursor-pointer"
> >
{isSaving ? <Spinner size="sm" /> : <Save className="w-5 h-5" />} {isSaving ? <Spinner size="sm" /> : <Save className="w-5 h-5" />}
ذخیره تنظیمات سیستمی <span>ذخیره تنظیمات سیستمی</span>
</button> </button>
</div> </div>
</form> </form>

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,8 @@ const PrescriptionsManager = lazyWithRetry(() => import('../pages/PrescriptionsM
const B2BManager = lazyWithRetry(() => import('../pages/B2BManager')); const B2BManager = lazyWithRetry(() => import('../pages/B2BManager'));
const SeoSettingsPage = lazyWithRetry(() => import('../pages/SeoSettingsPage')); const SeoSettingsPage = lazyWithRetry(() => import('../pages/SeoSettingsPage'));
const FinancialSettingsPage = lazyWithRetry(() => import('../pages/FinancialSettingsPage')); const FinancialSettingsPage = lazyWithRetry(() => import('../pages/FinancialSettingsPage'));
const PaymentGatewaysPage = lazyWithRetry(() => import('../pages/PaymentGatewaysPage'));
const ShippingSettingsPage = lazyWithRetry(() => import('../pages/ShippingSettingsPage'));
const SystemSettingsPage = lazyWithRetry(() => import('../pages/SystemSettingsPage')); const SystemSettingsPage = lazyWithRetry(() => import('../pages/SystemSettingsPage'));
const SmsSettingsPage = lazyWithRetry(() => import('../pages/SmsSettingsPage')); const SmsSettingsPage = lazyWithRetry(() => import('../pages/SmsSettingsPage'));
const SslSettingsPage = lazyWithRetry(() => import('../pages/SslSettingsPage')); const SslSettingsPage = lazyWithRetry(() => import('../pages/SslSettingsPage'));
@ -68,6 +70,8 @@ export const router = createBrowserRouter([
{ path: 'transactions/*', element: <Transactions /> }, { path: 'transactions/*', element: <Transactions /> },
{ path: 'coupons/*', element: <Coupons /> }, { path: 'coupons/*', element: <Coupons /> },
{ path: 'settings', element: <Settings /> }, { path: 'settings', element: <Settings /> },
{ path: 'settings/payment-methods', element: <PaymentGatewaysPage /> },
{ path: 'settings/shipping', element: <ShippingSettingsPage /> },
{ path: 'settings/ssl', element: <SslSettingsPage /> }, { path: 'settings/ssl', element: <SslSettingsPage /> },
{ path: 'settings/sms', element: <SmsSettingsPage /> }, { path: 'settings/sms', element: <SmsSettingsPage /> },
{ path: 'settings/seo', element: <SeoSettingsPage /> }, { path: 'settings/seo', element: <SeoSettingsPage /> },

View File

@ -3,10 +3,10 @@
"1": "productService.ts", "1": "productService.ts",
"2": "CmsController", "2": "CmsController",
"3": "app.module.ts", "3": "app.module.ts",
"4": "reviews.controller.ts", "4": "CreateReviewDto",
"5": "tickets.controller.ts", "5": "tickets.controller.ts",
"6": "UserDashboard.tsx", "6": "UserDashboard.tsx",
"7": "Spinner.tsx", "7": "MediaSelector.tsx",
"8": "admin.module.ts", "8": "admin.module.ts",
"9": "PetProfile.tsx", "9": "PetProfile.tsx",
"10": "DoctorsService", "10": "DoctorsService",
@ -28,7 +28,7 @@
"26": "TEST-001", "26": "TEST-001",
"27": "DEVOPS-001", "27": "DEVOPS-001",
"28": "DOC-001", "28": "DOC-001",
"29": "WholesaleService", "29": "WholesaleApplyDto",
"30": "main.ts", "30": "main.ts",
"31": "JwtAuthGuard", "31": "JwtAuthGuard",
"32": "ZibalService", "32": "ZibalService",
@ -42,9 +42,9 @@
"40": "SslController", "40": "SslController",
"41": "PodcastPlayerModal.tsx", "41": "PodcastPlayerModal.tsx",
"42": "IngredientsService", "42": "IngredientsService",
"43": "AuthService", "43": "RedisService",
"44": "MediaController", "44": "MediaController",
"45": "Transactions.tsx", "45": "Pagination.tsx",
"46": "SmsService", "46": "SmsService",
"47": "PetsService", "47": "PetsService",
"48": "PrescriptionsService", "48": "PrescriptionsService",
@ -69,8 +69,8 @@
"67": "Operational Rules & Boundaries", "67": "Operational Rules & Boundaries",
"68": "Operational Rules & Boundaries", "68": "Operational Rules & Boundaries",
"69": "WikiController", "69": "WikiController",
"70": "ApiOperation", "70": "AdminQueryDto",
"71": "PetsController", "71": ".update",
"72": "seo.module.ts", "72": "seo.module.ts",
"73": "admin.service.ts", "73": "admin.service.ts",
"74": "🏢 AI Software Agency — Master Orchestration Protocol v3", "74": "🏢 AI Software Agency — Master Orchestration Protocol v3",
@ -97,38 +97,38 @@
"95": "Operational Rules & Boundaries", "95": "Operational Rules & Boundaries",
"96": "exclude", "96": "exclude",
"97": "jest", "97": "jest",
"98": "AdminController", "98": "AdminService",
"99": "Comprehensive Change Log", "99": "Comprehensive Change Log",
"100": "Operational Rules & Boundaries", "100": "Operational Rules & Boundaries",
"101": "Body", "101": "UITexts.tsx",
"102": "eslint-plugin-prettier", "102": "eslint-plugin-prettier",
"103": "ProductDto", "103": "SettingsController",
"104": "AuthController", "104": "AuthController",
"105": "1. Summary of Integrity Repairs Performed", "105": "1. Summary of Integrity Repairs Performed",
"106": "AdminService", "106": "orders.service.ts",
"107": "Operational Rules & Boundaries", "107": "Operational Rules & Boundaries",
"108": "Operational Rules & Boundaries", "108": "Operational Rules & Boundaries",
"109": "Operational Rules & Boundaries", "109": "Operational Rules & Boundaries",
"110": "AppService", "110": "AppService",
"111": "SmsLogQueryDto", "111": "SmsLogQueryDto",
"112": "BlogsService", "112": "PetsController",
"113": "Vazirmatn Changelog", "113": "Vazirmatn Changelog",
"114": "Vazirmatn Font فونت وزیرمتن", "114": "Vazirmatn Font فونت وزیرمتن",
"115": "Operational Rules & Boundaries", "115": "Operational Rules & Boundaries",
"116": "compilerOptions", "116": "compilerOptions",
"117": "compilerOptions", "117": "compilerOptions",
"118": "backend/README.md", "118": "backend/README.md",
"119": "devDependencies", "119": "eslint",
"120": "Repository Map", "120": "Repository Map",
"121": "validate_integrity.js", "121": "validate_integrity.js",
"122": "admin-panel/package.json", "122": "admin-panel/package.json",
"123": "Sahel-Font", "123": "Sahel-Font",
"124": "Reports.tsx", "124": "Spinner.tsx",
"125": "Sahel-Font", "125": "Sahel-Font",
"126": "Role & Core Objective", "126": "Role & Core Objective",
"127": "orchestrate.py", "127": "orchestrate.py",
"128": "backend/package.json", "128": "backend/package.json",
"129": "wholesale.controller.ts", "129": "WikiService",
"130": "graphify reference: extra exports and benchmark", "130": "graphify reference: extra exports and benchmark",
"131": "Phase 2 Final Quality Gate Summary Report", "131": "Phase 2 Final Quality Gate Summary Report",
"132": "Task Modifications Log", "132": "Task Modifications Log",
@ -141,7 +141,7 @@
"139": "System Discovery", "139": "System Discovery",
"140": "Product Requirement Document (PRD)", "140": "Product Requirement Document (PRD)",
"141": "WikiController", "141": "WikiController",
"142": "globals", "142": "devDependencies",
"143": "@nestjs/cli", "143": "@nestjs/cli",
"144": "Baseline Command Plan & Reconciled Command History", "144": "Baseline Command Plan & Reconciled Command History",
"145": "SmsSettingsPage.tsx", "145": "SmsSettingsPage.tsx",
@ -213,8 +213,8 @@
"211": "@types/multer", "211": "@types/multer",
"212": "CreateHealthLogDto", "212": "CreateHealthLogDto",
"213": "@testing-library/jest-dom", "213": "@testing-library/jest-dom",
"214": "LoginDto", "214": "MetricsController",
"215": ".addPattern", "215": "CreateReminderDto",
"216": "FormField.tsx", "216": "FormField.tsx",
"217": "Input.tsx", "217": "Input.tsx",
"218": "Textarea.tsx", "218": "Textarea.tsx",
@ -237,12 +237,12 @@
"235": "typescript", "235": "typescript",
"236": "vitest", "236": "vitest",
"237": "axios", "237": "axios",
"238": "@types/passport-jwt", "238": "bcryptjs",
"239": "@types/supertest", "239": "helmet",
"240": "ts-loader", "240": "ts-loader",
"241": "typescript", "241": "js-yaml",
"242": "@types/bcrypt", "242": "@types/bcrypt",
"243": "RedisService", "243": "@nestjs/jwt",
"244": "blog.entity.ts", "244": "blog.entity.ts",
"245": "home.entity.ts", "245": "home.entity.ts",
"246": "wiki.entity.ts", "246": "wiki.entity.ts",
@ -289,10 +289,25 @@
"287": "Production Docker Compose", "287": "Production Docker Compose",
"288": "Staging Docker Compose", "288": "Staging Docker Compose",
"289": "tailwindcss", "289": "tailwindcss",
"290": "@nestjs/swagger",
"291": "NetworkBanner.tsx", "291": "NetworkBanner.tsx",
"292": "@nestjs/throttler",
"293": "passport-jwt",
"294": "@prisma/client",
"295": "reflect-metadata",
"296": "swagger-ui-express",
"297": "@eslint/eslintrc", "297": "@eslint/eslintrc",
"298": "@types/react-dom", "298": "eslint-config-prettier",
"299": "@eslint/js",
"300": "jest",
"301": "@nestjs/schematics",
"302": "@nestjs/testing",
"303": "source-map-support",
"304": "ts-jest",
"305": "RouteErrorBoundary", "305": "RouteErrorBoundary",
"307": "AdminLoginDto", "306": "tsconfig-paths",
"307": "@types/bcryptjs",
"308": "typescript-eslint",
"309": "eslint-config-next",
"312": "tailwindcss" "312": "tailwindcss"
} }

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
{ {
"0": ".retryPayment", "0": "OrdersService",
"1": "productService.ts", "1": "productService.ts",
"2": "CmsController", "2": "CmsController",
"3": "app.module.ts", "3": "app.module.ts",
@ -28,28 +28,28 @@
"26": "TEST-001", "26": "TEST-001",
"27": "DEVOPS-001", "27": "DEVOPS-001",
"28": "DOC-001", "28": "DOC-001",
"29": "WholesaleApplyDto", "29": "WholesaleService",
"30": "main.ts", "30": "main.ts",
"31": "JwtAuthGuard", "31": "JwtAuthGuard",
"32": "ZibalService", "32": "ZibalService",
"33": "راهنمای تست سیستم (Software Testing)", "33": "راهنمای تست سیستم (Software Testing)",
"34": "CategoriesController", "34": "CategoriesController",
"35": "B2BController", "35": "B2BService",
"36": "What You Must Do When Invoked", "36": "What You Must Do When Invoked",
"37": "userStore.ts", "37": "userStore.ts",
"38": "UsersService", "38": "UsersService",
"39": "What You Must Do When Invoked", "39": "What You Must Do When Invoked",
"40": "SslController", "40": "SslController",
"41": "PodcastPlayerModal.tsx", "41": "PodcastPlayerModal.tsx",
"42": "IngredientsController", "42": "IngredientsService",
"43": "AuthService", "43": "AuthService",
"44": "MediaController", "44": "MediaController",
"45": "Transactions.tsx", "45": "Transactions.tsx",
"46": "SmsService", "46": "SmsService",
"47": "PetsService", "47": "PetsService",
"48": "PrescriptionsController", "48": "PrescriptionsService",
"49": "SmartAdvisorService", "49": "SmartAdvisorService",
"50": "TestimonialsController", "50": "TestimonialsService",
"51": "Role & Core Objective", "51": "Role & Core Objective",
"52": "ContactService", "52": "ContactService",
"53": "PaymentController", "53": "PaymentController",
@ -57,13 +57,13 @@
"55": "Media.tsx", "55": "Media.tsx",
"56": "compilerOptions", "56": "compilerOptions",
"57": "PetsController", "57": "PetsController",
"58": "BlogsController", "58": "PaginationDto",
"59": "dependencies", "59": "dependencies",
"60": "compilerOptions", "60": "compilerOptions",
"61": "HomeClient.tsx", "61": "HomeClient.tsx",
"62": "BlogsController", "62": "BlogsController",
"63": "SettingsService", "63": "SettingsService",
"64": "BannersController", "64": "BannersService",
"65": "Required Review Group Closures", "65": "Required Review Group Closures",
"66": "Coupons.tsx", "66": "Coupons.tsx",
"67": "Operational Rules & Boundaries", "67": "Operational Rules & Boundaries",
@ -111,7 +111,7 @@
"109": "Operational Rules & Boundaries", "109": "Operational Rules & Boundaries",
"110": "AppService", "110": "AppService",
"111": "SmsLogQueryDto", "111": "SmsLogQueryDto",
"112": "SettingsController", "112": "BlogsService",
"113": "Vazirmatn Changelog", "113": "Vazirmatn Changelog",
"114": "Vazirmatn Font فونت وزیرمتن", "114": "Vazirmatn Font فونت وزیرمتن",
"115": "Operational Rules & Boundaries", "115": "Operational Rules & Boundaries",
@ -128,7 +128,7 @@
"126": "Role & Core Objective", "126": "Role & Core Objective",
"127": "orchestrate.py", "127": "orchestrate.py",
"128": "backend/package.json", "128": "backend/package.json",
"129": "OrdersController", "129": "wholesale.controller.ts",
"130": "graphify reference: extra exports and benchmark", "130": "graphify reference: extra exports and benchmark",
"131": "Phase 2 Final Quality Gate Summary Report", "131": "Phase 2 Final Quality Gate Summary Report",
"132": "Task Modifications Log", "132": "Task Modifications Log",
@ -140,7 +140,7 @@
"138": "InitiatePaymentDto", "138": "InitiatePaymentDto",
"139": "System Discovery", "139": "System Discovery",
"140": "Product Requirement Document (PRD)", "140": "Product Requirement Document (PRD)",
"141": "PaginationDto", "141": "WikiController",
"142": "globals", "142": "globals",
"143": "@nestjs/cli", "143": "@nestjs/cli",
"144": "Baseline Command Plan & Reconciled Command History", "144": "Baseline Command Plan & Reconciled Command History",
@ -214,7 +214,7 @@
"212": "CreateHealthLogDto", "212": "CreateHealthLogDto",
"213": "@testing-library/jest-dom", "213": "@testing-library/jest-dom",
"214": "LoginDto", "214": "LoginDto",
"215": "CreateOrderDto", "215": ".addPattern",
"216": "FormField.tsx", "216": "FormField.tsx",
"217": "Input.tsx", "217": "Input.tsx",
"218": "Textarea.tsx", "218": "Textarea.tsx",
@ -233,10 +233,10 @@
"231": "typescript", "231": "typescript",
"232": "RegisterDto", "232": "RegisterDto",
"233": "@testing-library/react", "233": "@testing-library/react",
"234": "OrdersService", "234": "@types/react",
"235": "typescript", "235": "typescript",
"236": "vitest", "236": "vitest",
"237": "WikiService", "237": "axios",
"238": "@types/passport-jwt", "238": "@types/passport-jwt",
"239": "@types/supertest", "239": "@types/supertest",
"240": "ts-loader", "240": "ts-loader",
@ -288,14 +288,8 @@
"286": "Shabnam Font Sample", "286": "Shabnam Font Sample",
"287": "Production Docker Compose", "287": "Production Docker Compose",
"288": "Staging Docker Compose", "288": "Staging Docker Compose",
"289": "eslint-config-next", "289": "tailwindcss",
"290": "MetricsController",
"291": "NetworkBanner.tsx", "291": "NetworkBanner.tsx",
"292": ".findAll",
"293": "CreateReminderDto",
"294": "TestimonialsService",
"295": "prescriptions.controller.ts",
"296": "ValidateCouponDto",
"297": "@eslint/eslintrc", "297": "@eslint/eslintrc",
"298": "@types/react-dom", "298": "@types/react-dom",
"305": "RouteErrorBoundary", "305": "RouteErrorBoundary",

View File

@ -1,11 +1,11 @@
# Graph Report - canina (2026-08-18) # Graph Report - canina (2026-08-18)
## Corpus Check ## Corpus Check
- 513 files · ~735,602 words - 513 files · ~735,601 words
- Verdict: corpus is large enough that graph structure adds value. - Verdict: corpus is large enough that graph structure adds value.
## Summary ## Summary
- 3648 nodes · 6193 edges · 302 communities (200 shown, 102 thin omitted) - 3650 nodes · 6193 edges · 296 communities (194 shown, 102 thin omitted)
- Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 230 edges (avg confidence: 0.79) - Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 230 edges (avg confidence: 0.79)
- Token cost: 0 input · 0 output - Token cost: 0 input · 0 output
@ -15,7 +15,7 @@
- Run `graphify update .` after code changes (no API cost). - Run `graphify update .` after code changes (no API cost).
## Community Hubs (Navigation) ## Community Hubs (Navigation)
- .retryPayment - OrdersService
- productService.ts - productService.ts
- CmsController - CmsController
- app.module.ts - app.module.ts
@ -44,28 +44,28 @@
- TEST-001 - TEST-001
- DEVOPS-001 - DEVOPS-001
- DOC-001 - DOC-001
- WholesaleApplyDto - WholesaleService
- main.ts - main.ts
- JwtAuthGuard - JwtAuthGuard
- ZibalService - ZibalService
- راهنمای تست سیستم (Software Testing) - راهنمای تست سیستم (Software Testing)
- CategoriesController - CategoriesController
- B2BController - B2BService
- What You Must Do When Invoked - What You Must Do When Invoked
- userStore.ts - userStore.ts
- UsersService - UsersService
- What You Must Do When Invoked - What You Must Do When Invoked
- SslController - SslController
- PodcastPlayerModal.tsx - PodcastPlayerModal.tsx
- IngredientsController - IngredientsService
- AuthService - AuthService
- MediaController - MediaController
- Transactions.tsx - Transactions.tsx
- SmsService - SmsService
- PetsService - PetsService
- PrescriptionsController - PrescriptionsService
- SmartAdvisorService - SmartAdvisorService
- TestimonialsController - TestimonialsService
- Role & Core Objective - Role & Core Objective
- ContactService - ContactService
- PaymentController - PaymentController
@ -73,13 +73,13 @@
- Media.tsx - Media.tsx
- compilerOptions - compilerOptions
- PetsController - PetsController
- BlogsController - PaginationDto
- dependencies - dependencies
- compilerOptions - compilerOptions
- HomeClient.tsx - HomeClient.tsx
- BlogsController - BlogsController
- SettingsService - SettingsService
- BannersController - BannersService
- Required Review Group Closures - Required Review Group Closures
- Coupons.tsx - Coupons.tsx
- Operational Rules & Boundaries - Operational Rules & Boundaries
@ -127,7 +127,7 @@
- Operational Rules & Boundaries - Operational Rules & Boundaries
- AppService - AppService
- SmsLogQueryDto - SmsLogQueryDto
- SettingsController - BlogsService
- Vazirmatn Changelog - Vazirmatn Changelog
- Vazirmatn Font فونت وزیرمتن - Vazirmatn Font فونت وزیرمتن
- Operational Rules & Boundaries - Operational Rules & Boundaries
@ -144,7 +144,7 @@
- Role & Core Objective - Role & Core Objective
- orchestrate.py - orchestrate.py
- backend/package.json - backend/package.json
- OrdersController - wholesale.controller.ts
- graphify reference: extra exports and benchmark - graphify reference: extra exports and benchmark
- Phase 2 Final Quality Gate Summary Report - Phase 2 Final Quality Gate Summary Report
- Task Modifications Log - Task Modifications Log
@ -156,7 +156,7 @@
- InitiatePaymentDto - InitiatePaymentDto
- System Discovery - System Discovery
- Product Requirement Document (PRD) - Product Requirement Document (PRD)
- PaginationDto - WikiController
- globals - globals
- @nestjs/cli - @nestjs/cli
- Baseline Command Plan & Reconciled Command History - Baseline Command Plan & Reconciled Command History
@ -230,7 +230,7 @@
- CreateHealthLogDto - CreateHealthLogDto
- @testing-library/jest-dom - @testing-library/jest-dom
- LoginDto - LoginDto
- CreateOrderDto - .addPattern
- FormField.tsx - FormField.tsx
- Input.tsx - Input.tsx
- Textarea.tsx - Textarea.tsx
@ -249,10 +249,9 @@
- typescript - typescript
- RegisterDto - RegisterDto
- @testing-library/react - @testing-library/react
- OrdersService - @types/react
- typescript - typescript
- vitest - vitest
- WikiService
- @types/passport-jwt - @types/passport-jwt
- @types/supertest - @types/supertest
- ts-loader - ts-loader
@ -291,14 +290,7 @@
- Shabnam Font Sample - Shabnam Font Sample
- Production Docker Compose - Production Docker Compose
- Staging Docker Compose - Staging Docker Compose
- eslint-config-next
- MetricsController
- NetworkBanner.tsx - NetworkBanner.tsx
- .findAll
- CreateReminderDto
- TestimonialsService
- prescriptions.controller.ts
- ValidateCouponDto
- @eslint/eslintrc - @eslint/eslintrc
- @types/react-dom - @types/react-dom
- RouteErrorBoundary - RouteErrorBoundary
@ -320,14 +312,14 @@
## Surprising Connections (you probably didn't know these) ## Surprising Connections (you probably didn't know these)
- `User Profile Photo` --conceptually_related_to--> `User Roles and Capabilities` [INFERRED] - `User Profile Photo` --conceptually_related_to--> `User Roles and Capabilities` [INFERRED]
backend/uploads/1781288429353-508765350.jpg → docs/02-user-guide.md backend/uploads/1781288429353-508765350.jpg → docs/02-user-guide.md
- `OrdersController` --references--> `ApiResponse` [EXTRACTED]
backend/src/orders/orders.controller.ts → frontend/admin-panel/src/types/admin.ts
- `AuthController` --references--> `ApiResponse` [EXTRACTED] - `AuthController` --references--> `ApiResponse` [EXTRACTED]
backend/src/auth/auth.controller.ts → frontend/admin-panel/src/types/admin.ts backend/src/auth/auth.controller.ts → frontend/admin-panel/src/types/admin.ts
- `WikiController` --references--> `ApiResponse` [EXTRACTED] - `BlogsController` --references--> `ApiResponse` [EXTRACTED]
backend/src/wiki/wiki.controller.ts → frontend/admin-panel/src/types/admin.ts backend/src/blogs/blogs.controller.ts → frontend/admin-panel/src/types/admin.ts
- `ProductsController` --references--> `ApiResponse` [EXTRACTED] - `HomeController` --references--> `ApiResponse` [EXTRACTED]
backend/src/products/products.controller.ts → frontend/admin-panel/src/types/admin.ts backend/src/home/home.controller.ts → frontend/admin-panel/src/types/admin.ts
- `OrdersController` --references--> `ApiResponse` [EXTRACTED]
backend/src/orders/orders.controller.ts → frontend/admin-panel/src/types/admin.ts
## Import Cycles ## Import Cycles
- 3-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/services/authService.ts -> frontend/application/lib/services/api.ts` - 3-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/services/authService.ts -> frontend/application/lib/services/api.ts`
@ -338,11 +330,11 @@
- **Rastikerdar Font Ecosystem** — frontend_application_public_fonts_shabnam_font_v5_0_1_readme, frontend_application_public_fonts_vazirmatn_v33_003_readme, vazir_font [EXTRACTED 0.95] - **Rastikerdar Font Ecosystem** — frontend_application_public_fonts_shabnam_font_v5_0_1_readme, frontend_application_public_fonts_vazirmatn_v33_003_readme, vazir_font [EXTRACTED 0.95]
- **Canina Deployment Stack** — scripts_compose_prod, scripts_compose_stage [EXTRACTED 1.00] - **Canina Deployment Stack** — scripts_compose_prod, scripts_compose_stage [EXTRACTED 1.00]
## Communities (302 total, 102 thin omitted) ## Communities (296 total, 102 thin omitted)
### Community 0 - ".retryPayment" ### Community 0 - "OrdersService"
Cohesion: 0.19 Cohesion: 0.06
Nodes (11): ApiBadRequestResponse, ApiCreatedResponse, ApiNotFoundResponse, ApiOkResponse, ApiOperation, Body, Get, Param (+3 more) Nodes (35): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+27 more)
### Community 1 - "productService.ts" ### Community 1 - "productService.ts"
Cohesion: 0.06 Cohesion: 0.06
@ -354,7 +346,7 @@ Nodes (24): CmsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controlle
### Community 3 - "app.module.ts" ### Community 3 - "app.module.ts"
Cohesion: 0.08 Cohesion: 0.08
Nodes (29): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+21 more) Nodes (30): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+22 more)
### Community 4 - "reviews.controller.ts" ### Community 4 - "reviews.controller.ts"
Cohesion: 0.07 Cohesion: 0.07
@ -374,7 +366,7 @@ Nodes (21): ConfirmModal(), ConfirmModalProps, getFileType(), Media, MediaSelect
### Community 8 - "admin.module.ts" ### Community 8 - "admin.module.ts"
Cohesion: 0.06 Cohesion: 0.06
Nodes (21): AdminModule, Module, BlogQuery, BlogsService, Injectable, PetQuery, PetsService, Injectable (+13 more) Nodes (21): AdminModule, Module, PetQuery, PetsService, Injectable, ReportsController, ApiBearerAuth, ApiOperation (+13 more)
### Community 9 - "PetProfile.tsx" ### Community 9 - "PetProfile.tsx"
Cohesion: 0.14 Cohesion: 0.14
@ -394,14 +386,14 @@ Nodes (29): App(), HeroBanner, VetTestimonial, ContactInfoItem, ContactSubmissio
### Community 13 - "PrismaService" ### Community 13 - "PrismaService"
Cohesion: 0.07 Cohesion: 0.07
Nodes (20): CategoryQuery, B2BService, B2BWholesaleOrderItem, Injectable, BannersService, Injectable, MeliPayamakPattern, MeliPayamakResponse (+12 more) Nodes (19): ApiExcludeController, CategoryQuery, MetricsController, Controller, Get, Res, MeliPayamakPattern, MeliPayamakResponse (+11 more)
### Community 14 - "pets/pets.controller.ts" ### Community 14 - "pets/pets.controller.ts"
Cohesion: 0.16 Cohesion: 0.11
Nodes (13): CreatePetDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional, IsString (+5 more) Nodes (19): CreatePetDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional, IsString (+11 more)
### Community 15 - "ProductsService" ### Community 15 - "ProductsService"
Cohesion: 0.10 Cohesion: 0.09
Nodes (19): GetProductsDto, ApiPropertyOptional, IsEnum, IsOptional, IsString, ProductsController, ApiOperation, ApiTags (+11 more) Nodes (19): GetProductsDto, ApiPropertyOptional, IsEnum, IsOptional, IsString, ProductsController, ApiOperation, ApiTags (+11 more)
### Community 16 - "lib/services/api.ts" ### Community 16 - "lib/services/api.ts"
@ -425,8 +417,8 @@ Cohesion: 0.06
Nodes (32): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, BE-001, Category, Completion Statement, Confidence (+24 more) Nodes (32): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, BE-001, Category, Completion Statement, Confidence (+24 more)
### Community 21 - "Roles" ### Community 21 - "Roles"
Cohesion: 0.29 Cohesion: 0.20
Nodes (9): Roles(), ApiBearerAuth, Body, Delete, Param, Patch, Post, Put (+1 more) Nodes (15): Roles(), SettingsController, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+7 more)
### Community 22 - "FE-001" ### Community 22 - "FE-001"
Cohesion: 0.06 Cohesion: 0.06
@ -456,17 +448,17 @@ Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternati
Cohesion: 0.06 Cohesion: 0.06
Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more) Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more)
### Community 29 - "WholesaleApplyDto" ### Community 29 - "WholesaleService"
Cohesion: 0.10 Cohesion: 0.14
Nodes (20): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto, ApiBearerAuth, ApiOperation (+12 more) Nodes (14): ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param, Post (+6 more)
### Community 30 - "main.ts" ### Community 30 - "main.ts"
Cohesion: 0.11 Cohesion: 0.11
Nodes (11): AppModule, Module, CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable (+3 more) Nodes (11): AppModule, Module, CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable (+3 more)
### Community 31 - "JwtAuthGuard" ### Community 31 - "JwtAuthGuard"
Cohesion: 0.17 Cohesion: 0.15
Nodes (7): JwtAuthGuard, Injectable, ROLES_KEY, SortOrder, RequestWithUser, RolesGuard, Injectable Nodes (9): JwtAuthGuard, Injectable, B2BWholesaleOrderItem, ROLES_KEY, SortOrder, RequestWithUser, RolesGuard, Injectable (+1 more)
### Community 32 - "ZibalService" ### Community 32 - "ZibalService"
Cohesion: 0.15 Cohesion: 0.15
@ -480,9 +472,9 @@ Nodes (25): اجرای بک‌اند, اجرای فرانت‌اند, اجرای
Cohesion: 0.10 Cohesion: 0.10
Nodes (16): CategoriesController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+8 more) Nodes (16): CategoriesController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+8 more)
### Community 35 - "B2BController" ### Community 35 - "B2BService"
Cohesion: 0.14 Cohesion: 0.14
Nodes (12): B2BController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+4 more) Nodes (14): B2BController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+6 more)
### Community 36 - "What You Must Do When Invoked" ### Community 36 - "What You Must Do When Invoked"
Cohesion: 0.07 Cohesion: 0.07
@ -508,9 +500,9 @@ Nodes (14): SslController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controlle
Cohesion: 0.40 Cohesion: 0.40
Nodes (3): PLAYBACK_RATES, PodcastPlayerModal(), PodcastPlayerModalProps Nodes (3): PLAYBACK_RATES, PodcastPlayerModal(), PodcastPlayerModalProps
### Community 42 - "IngredientsController" ### Community 42 - "IngredientsService"
Cohesion: 0.13 Cohesion: 0.13
Nodes (12): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+4 more) Nodes (14): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
### Community 43 - "AuthService" ### Community 43 - "AuthService"
Cohesion: 0.22 Cohesion: 0.22
@ -524,17 +516,17 @@ Nodes (16): MediaController, ApiBearerAuth, ApiOperation, ApiTags, Body, Control
Cohesion: 0.33 Cohesion: 0.33
Nodes (4): GatewayHealth, Stats, Transaction, Transactions Nodes (4): GatewayHealth, Stats, Transaction, Transactions
### Community 48 - "PrescriptionsController" ### Community 48 - "PrescriptionsService"
Cohesion: 0.15 Cohesion: 0.14
Nodes (12): PrescriptionsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+4 more) Nodes (14): PrescriptionsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+6 more)
### Community 49 - "SmartAdvisorService" ### Community 49 - "SmartAdvisorService"
Cohesion: 0.13 Cohesion: 0.13
Nodes (14): SmartAdvisorController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more) Nodes (14): SmartAdvisorController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
### Community 50 - "TestimonialsController" ### Community 50 - "TestimonialsService"
Cohesion: 0.14 Cohesion: 0.13
Nodes (12): TestimonialsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+4 more) Nodes (14): TestimonialsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
### Community 51 - "Role & Core Objective" ### Community 51 - "Role & Core Objective"
Cohesion: 0.09 Cohesion: 0.09
@ -564,9 +556,9 @@ Nodes (23): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, jsx
Cohesion: 0.15 Cohesion: 0.15
Nodes (11): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+3 more) Nodes (11): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+3 more)
### Community 58 - "BlogsController" ### Community 58 - "PaginationDto"
Cohesion: 0.13 Cohesion: 0.09
Nodes (13): BlogsController, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param (+5 more) Nodes (21): BlogsController, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param (+13 more)
### Community 59 - "dependencies" ### Community 59 - "dependencies"
Cohesion: 0.05 Cohesion: 0.05
@ -585,12 +577,12 @@ Cohesion: 0.13
Nodes (15): BlogsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+7 more) Nodes (15): BlogsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+7 more)
### Community 63 - "SettingsService" ### Community 63 - "SettingsService"
Cohesion: 0.10 Cohesion: 0.12
Nodes (3): SmsLogQuery, SettingsService, Injectable Nodes (3): SmsLogQuery, SettingsService, Injectable
### Community 64 - "BannersController" ### Community 64 - "BannersService"
Cohesion: 0.13 Cohesion: 0.13
Nodes (13): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+5 more) Nodes (15): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+7 more)
### Community 65 - "Required Review Group Closures" ### Community 65 - "Required Review Group Closures"
Cohesion: 0.10 Cohesion: 0.10
@ -658,7 +650,7 @@ Nodes (9): GatewayHealthResult, IPaymentGateway, PaymentInquiryResult, PaymentRe
### Community 81 - "devDependencies" ### Community 81 - "devDependencies"
Cohesion: 0.13 Cohesion: 0.13
Nodes (15): devDependencies, eslint, jsdom, tailwindcss, @tailwindcss/postcss, @types/node, @types/react, @vitejs/plugin-react (+7 more) Nodes (15): eslint-config-next, devDependencies, eslint, eslint-config-next, jsdom, tailwindcss, @tailwindcss/postcss, @types/node (+7 more)
### Community 82 - "api" ### Community 82 - "api"
Cohesion: 0.15 Cohesion: 0.15
@ -702,7 +694,7 @@ Nodes (32): compilerOptions, allowJs, esModuleInterop, incremental, isolatedModu
### Community 92 - "scripts" ### Community 92 - "scripts"
Cohesion: 0.14 Cohesion: 0.14
Nodes (14): scripts, build, docs:generate, format, lint, start, start:debug, start:dev (+6 more) Nodes (14): scripts, build, docs:generate, lint, prestart:dev, start, start:debug, start:dev (+6 more)
### Community 93 - "Deep Audit Summary Report" ### Community 93 - "Deep Audit Summary Report"
Cohesion: 0.14 Cohesion: 0.14
@ -768,9 +760,9 @@ Nodes (5): AppController, Controller, Get, AppService, Injectable
Cohesion: 0.25 Cohesion: 0.25
Nodes (7): SmsLogQueryDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type Nodes (7): SmsLogQueryDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type
### Community 112 - "SettingsController" ### Community 112 - "BlogsService"
Cohesion: 0.24 Cohesion: 0.22
Nodes (7): SettingsController, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Query Nodes (3): BlogQuery, BlogsService, Injectable
### Community 113 - "Vazirmatn Changelog" ### Community 113 - "Vazirmatn Changelog"
Cohesion: 0.18 Cohesion: 0.18
@ -836,9 +828,9 @@ Nodes (8): cmd_next_task(), cmd_progress(), cmd_reset(), cmd_status(), cmd_unblo
Cohesion: 0.22 Cohesion: 0.22
Nodes (8): author, description, license, name, prisma, seed, private, version Nodes (8): author, description, license, name, prisma, seed, private, version
### Community 129 - "OrdersController" ### Community 129 - "wholesale.controller.ts"
Cohesion: 0.22 Cohesion: 0.31
Nodes (7): OrdersController, ApiBearerAuth, ApiTags, Controller, UseGuards, OrdersModule, Module Nodes (6): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto
### Community 130 - "graphify reference: extra exports and benchmark" ### Community 130 - "graphify reference: extra exports and benchmark"
Cohesion: 0.22 Cohesion: 0.22
@ -884,9 +876,9 @@ Nodes (7): Active Core Applications, Current Architecture, Evidence-Based Status
Cohesion: 0.29 Cohesion: 0.29
Nodes (6): 1. Executive Vision, 2. Target Audience, 3. Functional Requirements, 4. Non-Functional Requirements (Performance, Security), 5. Epic / Feature Breakdown, Product Requirement Document (PRD) Nodes (6): 1. Executive Vision, 2. Target Audience, 3. Functional Requirements, 4. Non-Functional Requirements (Performance, Security), 5. Epic / Feature Breakdown, Product Requirement Document (PRD)
### Community 141 - "PaginationDto" ### Community 141 - "WikiController"
Cohesion: 0.11 Cohesion: 0.13
Nodes (15): PaginationDto, ApiPropertyOptional, IsEnum, IsInt, IsOptional, IsString, Min, Type (+7 more) Nodes (13): ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param, Query (+5 more)
### Community 144 - "Baseline Command Plan & Reconciled Command History" ### Community 144 - "Baseline Command Plan & Reconciled Command History"
Cohesion: 0.29 Cohesion: 0.29
@ -1040,10 +1032,6 @@ Nodes (6): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsO
Cohesion: 0.33 Cohesion: 0.33
Nodes (5): LoginDto, ApiProperty, IsNotEmpty, IsString, MinLength Nodes (5): LoginDto, ApiProperty, IsNotEmpty, IsString, MinLength
### Community 215 - "CreateOrderDto"
Cohesion: 0.22
Nodes (11): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+3 more)
### Community 223 - "Shabnam Font README" ### Community 223 - "Shabnam Font README"
Cohesion: 0.67 Cohesion: 0.67
Nodes (3): Shabnam Font README, Shabnam Font Sample, Vazir Font Nodes (3): Shabnam Font README, Shabnam Font Sample, Vazir Font
@ -1052,34 +1040,6 @@ Nodes (3): Shabnam Font README, Shabnam Font Sample, Vazir Font
Cohesion: 0.22 Cohesion: 0.22
Nodes (8): RegisterDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty, IsOptional, IsString, MinLength Nodes (8): RegisterDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty, IsOptional, IsString, MinLength
### Community 237 - "WikiService"
Cohesion: 0.22
Nodes (3): Injectable, WikiQuery, WikiService
### Community 290 - "MetricsController"
Cohesion: 0.25
Nodes (5): ApiExcludeController, MetricsController, Controller, Get, Res
### Community 292 - ".findAll"
Cohesion: 0.32
Nodes (6): ApiNotFoundResponse, ApiOkResponse, ApiOperation, Get, Param, Query
### Community 293 - "CreateReminderDto"
Cohesion: 0.29
Nodes (6): CreateReminderDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString
### Community 294 - "TestimonialsService"
Cohesion: 0.33
Nodes (4): TestimonialsModule, Module, TestimonialsService, Injectable
### Community 295 - "prescriptions.controller.ts"
Cohesion: 0.53
Nodes (3): UserReqPayload, PrescriptionsService, Injectable
### Community 296 - "ValidateCouponDto"
Cohesion: 0.50
Nodes (4): IsNotEmpty, IsNumber, IsString, ValidateCouponDto
### Community 305 - "RouteErrorBoundary" ### Community 305 - "RouteErrorBoundary"
Cohesion: 0.22 Cohesion: 0.22
Nodes (3): Props, RouteErrorBoundary, State Nodes (3): Props, RouteErrorBoundary, State
@ -1089,24 +1049,24 @@ Cohesion: 0.29
Nodes (6): AdminLoginDto, ApiProperty, IsEmail, IsNotEmpty, IsString, MinLength Nodes (6): AdminLoginDto, ApiProperty, IsEmail, IsNotEmpty, IsString, MinLength
## Knowledge Gaps ## Knowledge Gaps
- **1242 isolated node(s):** `BlogPost`, `SmartAdvisorProps`, `DosageResult`, `FAQ`, `Specialist` (+1237 more) - **1242 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1237 more)
These have ≤1 connection - possible missing edges or undocumented components. These have ≤1 connection - possible missing edges or undocumented components.
- **102 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes. - **102 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions ## Suggested Questions
_Questions this graph is uniquely positioned to answer:_ _Questions this graph is uniquely positioned to answer:_
- **Why does `ApiResponse` connect `src/services/api.ts` to `OrdersController`, `UsersService`, `PetsController`, `AuthController`, `PaginationDto`, `HomeController`, `ProductsService`, `BlogsController`?** - **Why does `Roles()` connect `Roles` to `BannersService`, `wholesale.controller.ts`, `CmsController`, `B2BService`, `reviews.controller.ts`, `tickets.controller.ts`, `SslController`, `IngredientsService`, `ProductsService`, `PrescriptionsService`, `SmartAdvisorService`, `TestimonialsService`, `ContactService`, `PaymentController`, `.addPattern`, `WholesaleService`, `JwtAuthGuard`?**
_High betweenness centrality (0.060) - this node is a cross-community bridge._ _High betweenness centrality (0.051) - this node is a cross-community bridge._
- **Why does `Roles()` connect `Roles` to `BannersController`, `CmsController`, `B2BController`, `reviews.controller.ts`, `tickets.controller.ts`, `prescriptions.controller.ts`, `SslController`, `IngredientsController`, `ProductsService`, `PrescriptionsController`, `SettingsController`, `SmartAdvisorService`, `TestimonialsController`, `ContactService`, `PaymentController`, `WholesaleApplyDto`, `JwtAuthGuard`?** - **Why does `ApiResponse` connect `src/services/api.ts` to `OrdersService`, `UsersService`, `PetsController`, `AuthController`, `WikiController`, `HomeController`, `ProductsService`, `PaginationDto`?**
_High betweenness centrality (0.045) - this node is a cross-community bridge._ _High betweenness centrality (0.040) - this node is a cross-community bridge._
- **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `OrdersController`, `app.module.ts`, `reviews.controller.ts`, `tickets.controller.ts`, `UsersService`, `prescriptions.controller.ts`, `admin.module.ts`, `admin.service.ts`, `MediaController`, `pets/pets.controller.ts`, `ProductsService`, `CreateVideoDto`, `auth.service.ts`?** - **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `OrdersService`, `wholesale.controller.ts`, `CmsController`, `reviews.controller.ts`, `tickets.controller.ts`, `UsersService`, `admin.module.ts`, `admin.service.ts`, `MediaController`, `PrismaService`, `pets/pets.controller.ts`, `ProductsService`, `CreateVideoDto`, `auth.service.ts`?**
_High betweenness centrality (0.026) - this node is a cross-community bridge._ _High betweenness centrality (0.024) - this node is a cross-community bridge._
- **What connects `BlogPost`, `SmartAdvisorProps`, `DosageResult` to the rest of the system?** - **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?**
_1242 weakly-connected nodes found - possible documentation gaps or missing edges._ _1242 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `OrdersService` be split into smaller, more focused modules?**
_Cohesion score 0.06168831168831169 - nodes in this community are weakly interconnected._
- **Should `productService.ts` be split into smaller, more focused modules?** - **Should `productService.ts` be split into smaller, more focused modules?**
_Cohesion score 0.05888376856118792 - nodes in this community are weakly interconnected._ _Cohesion score 0.05888376856118792 - nodes in this community are weakly interconnected._
- **Should `CmsController` be split into smaller, more focused modules?** - **Should `CmsController` be split into smaller, more focused modules?**
_Cohesion score 0.08823529411764706 - nodes in this community are weakly interconnected._ _Cohesion score 0.0899854862119013 - nodes in this community are weakly interconnected._
- **Should `app.module.ts` be split into smaller, more focused modules?**
_Cohesion score 0.08350951374207188 - nodes in this community are weakly interconnected._

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,16 @@
# Graph Report - canina (2026-08-18) # Graph Report - canina (2026-08-18)
## Corpus Check ## Corpus Check
- 513 files · ~735,601 words - 517 files · ~740,145 words
- Verdict: corpus is large enough that graph structure adds value. - Verdict: corpus is large enough that graph structure adds value.
## Summary ## Summary
- 3650 nodes · 6193 edges · 296 communities (194 shown, 102 thin omitted) - 3669 nodes · 6227 edges · 311 communities (195 shown, 116 thin omitted)
- Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 230 edges (avg confidence: 0.79) - Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 230 edges (avg confidence: 0.79)
- Token cost: 0 input · 0 output - Token cost: 0 input · 0 output
## Graph Freshness ## Graph Freshness
- Built from commit: `2ee85848` - Built from commit: `aa10ee73`
- Run `git rev-parse HEAD` and compare to check if the graph is stale. - Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost). - Run `graphify update .` after code changes (no API cost).
@ -19,10 +19,10 @@
- productService.ts - productService.ts
- CmsController - CmsController
- app.module.ts - app.module.ts
- reviews.controller.ts - CreateReviewDto
- tickets.controller.ts - tickets.controller.ts
- UserDashboard.tsx - UserDashboard.tsx
- Spinner.tsx - MediaSelector.tsx
- admin.module.ts - admin.module.ts
- PetProfile.tsx - PetProfile.tsx
- DoctorsService - DoctorsService
@ -44,7 +44,7 @@
- TEST-001 - TEST-001
- DEVOPS-001 - DEVOPS-001
- DOC-001 - DOC-001
- WholesaleService - WholesaleApplyDto
- main.ts - main.ts
- JwtAuthGuard - JwtAuthGuard
- ZibalService - ZibalService
@ -58,9 +58,9 @@
- SslController - SslController
- PodcastPlayerModal.tsx - PodcastPlayerModal.tsx
- IngredientsService - IngredientsService
- AuthService - RedisService
- MediaController - MediaController
- Transactions.tsx - Pagination.tsx
- SmsService - SmsService
- PetsService - PetsService
- PrescriptionsService - PrescriptionsService
@ -85,8 +85,8 @@
- Operational Rules & Boundaries - Operational Rules & Boundaries
- Operational Rules & Boundaries - Operational Rules & Boundaries
- WikiController - WikiController
- ApiOperation - AdminQueryDto
- PetsController - .update
- seo.module.ts - seo.module.ts
- admin.service.ts - admin.service.ts
- 🏢 AI Software Agency — Master Orchestration Protocol v3 - 🏢 AI Software Agency — Master Orchestration Protocol v3
@ -113,38 +113,38 @@
- Operational Rules & Boundaries - Operational Rules & Boundaries
- exclude - exclude
- jest - jest
- AdminController - AdminService
- Comprehensive Change Log - Comprehensive Change Log
- Operational Rules & Boundaries - Operational Rules & Boundaries
- Body - UITexts.tsx
- eslint-plugin-prettier - eslint-plugin-prettier
- ProductDto - SettingsController
- AuthController - AuthController
- 1. Summary of Integrity Repairs Performed - 1. Summary of Integrity Repairs Performed
- AdminService - orders.service.ts
- Operational Rules & Boundaries - Operational Rules & Boundaries
- Operational Rules & Boundaries - Operational Rules & Boundaries
- Operational Rules & Boundaries - Operational Rules & Boundaries
- AppService - AppService
- SmsLogQueryDto - SmsLogQueryDto
- BlogsService - PetsController
- Vazirmatn Changelog - Vazirmatn Changelog
- Vazirmatn Font فونت وزیرمتن - Vazirmatn Font فونت وزیرمتن
- Operational Rules & Boundaries - Operational Rules & Boundaries
- compilerOptions - compilerOptions
- compilerOptions - compilerOptions
- backend/README.md - backend/README.md
- devDependencies - eslint
- Repository Map - Repository Map
- validate_integrity.js - validate_integrity.js
- admin-panel/package.json - admin-panel/package.json
- Sahel-Font - Sahel-Font
- Reports.tsx - Spinner.tsx
- Sahel-Font - Sahel-Font
- Role & Core Objective - Role & Core Objective
- orchestrate.py - orchestrate.py
- backend/package.json - backend/package.json
- wholesale.controller.ts - WikiService
- graphify reference: extra exports and benchmark - graphify reference: extra exports and benchmark
- Phase 2 Final Quality Gate Summary Report - Phase 2 Final Quality Gate Summary Report
- Task Modifications Log - Task Modifications Log
@ -157,7 +157,7 @@
- System Discovery - System Discovery
- Product Requirement Document (PRD) - Product Requirement Document (PRD)
- WikiController - WikiController
- globals - devDependencies
- @nestjs/cli - @nestjs/cli
- Baseline Command Plan & Reconciled Command History - Baseline Command Plan & Reconciled Command History
- SmsSettingsPage.tsx - SmsSettingsPage.tsx
@ -229,8 +229,8 @@
- @types/multer - @types/multer
- CreateHealthLogDto - CreateHealthLogDto
- @testing-library/jest-dom - @testing-library/jest-dom
- LoginDto - MetricsController
- .addPattern - CreateReminderDto
- FormField.tsx - FormField.tsx
- Input.tsx - Input.tsx
- Textarea.tsx - Textarea.tsx
@ -252,12 +252,12 @@
- @types/react - @types/react
- typescript - typescript
- vitest - vitest
- @types/passport-jwt - bcryptjs
- @types/supertest - helmet
- ts-loader - ts-loader
- typescript - js-yaml
- @types/bcrypt - @types/bcrypt
- RedisService - @nestjs/jwt
- blog.entity.ts - blog.entity.ts
- home.entity.ts - home.entity.ts
- wiki.entity.ts - wiki.entity.ts
@ -290,11 +290,26 @@
- Shabnam Font Sample - Shabnam Font Sample
- Production Docker Compose - Production Docker Compose
- Staging Docker Compose - Staging Docker Compose
- @nestjs/swagger
- NetworkBanner.tsx - NetworkBanner.tsx
- @nestjs/throttler
- passport-jwt
- @prisma/client
- reflect-metadata
- swagger-ui-express
- @eslint/eslintrc - @eslint/eslintrc
- @types/react-dom - eslint-config-prettier
- @eslint/js
- jest
- @nestjs/schematics
- @nestjs/testing
- source-map-support
- ts-jest
- RouteErrorBoundary - RouteErrorBoundary
- AdminLoginDto - tsconfig-paths
- @types/bcryptjs
- typescript-eslint
- eslint-config-next
- tailwindcss - tailwindcss
## God Nodes (most connected - your core abstractions) ## God Nodes (most connected - your core abstractions)
@ -302,8 +317,8 @@
2. `Roles()` - 75 edges 2. `Roles()` - 75 edges
3. `useSettingsStore` - 47 edges 3. `useSettingsStore` - 47 edges
4. `SmsService` - 42 edges 4. `SmsService` - 42 edges
5. `PaginationDto` - 39 edges 5. `api` - 40 edges
6. `api` - 38 edges 6. `PaginationDto` - 39 edges
7. `AdminService` - 34 edges 7. `AdminService` - 34 edges
8. `AdminController` - 33 edges 8. `AdminController` - 33 edges
9. `JwtAuthGuard` - 32 edges 9. `JwtAuthGuard` - 32 edges
@ -330,11 +345,11 @@
- **Rastikerdar Font Ecosystem** — frontend_application_public_fonts_shabnam_font_v5_0_1_readme, frontend_application_public_fonts_vazirmatn_v33_003_readme, vazir_font [EXTRACTED 0.95] - **Rastikerdar Font Ecosystem** — frontend_application_public_fonts_shabnam_font_v5_0_1_readme, frontend_application_public_fonts_vazirmatn_v33_003_readme, vazir_font [EXTRACTED 0.95]
- **Canina Deployment Stack** — scripts_compose_prod, scripts_compose_stage [EXTRACTED 1.00] - **Canina Deployment Stack** — scripts_compose_prod, scripts_compose_stage [EXTRACTED 1.00]
## Communities (296 total, 102 thin omitted) ## Communities (311 total, 116 thin omitted)
### Community 0 - "OrdersService" ### Community 0 - "OrdersService"
Cohesion: 0.06 Cohesion: 0.07
Nodes (35): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+27 more) Nodes (29): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+21 more)
### Community 1 - "productService.ts" ### Community 1 - "productService.ts"
Cohesion: 0.06 Cohesion: 0.06
@ -345,28 +360,28 @@ Cohesion: 0.09
Nodes (24): CmsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+16 more) Nodes (24): CmsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+16 more)
### Community 3 - "app.module.ts" ### Community 3 - "app.module.ts"
Cohesion: 0.08
Nodes (30): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+22 more)
### Community 4 - "reviews.controller.ts"
Cohesion: 0.07 Cohesion: 0.07
Nodes (31): CreateReviewDto, ApiProperty, IsInt, IsNotEmpty, IsOptional, IsString, Min, ApiProperty (+23 more) Nodes (36): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+28 more)
### Community 4 - "CreateReviewDto"
Cohesion: 0.07
Nodes (29): CreateReviewDto, ApiProperty, IsInt, IsNotEmpty, IsOptional, IsString, Min, ApiProperty (+21 more)
### Community 5 - "tickets.controller.ts" ### Community 5 - "tickets.controller.ts"
Cohesion: 0.09 Cohesion: 0.09
Nodes (31): AdminUpdateTicketDto, CreateTicketDto, ReplyTicketDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString (+23 more) Nodes (29): AdminUpdateTicketDto, CreateTicketDto, ReplyTicketDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString (+21 more)
### Community 6 - "UserDashboard.tsx" ### Community 6 - "UserDashboard.tsx"
Cohesion: 0.09 Cohesion: 0.09
Nodes (28): VerifyContent(), AddressModal(), AddressModalProps, BackButton(), BackButtonProps, DeleteConfirmModal(), DeleteConfirmModalProps, HeaderButton() (+20 more) Nodes (28): VerifyContent(), AddressModal(), AddressModalProps, BackButton(), BackButtonProps, DeleteConfirmModal(), DeleteConfirmModalProps, HeaderButton() (+20 more)
### Community 7 - "Spinner.tsx" ### Community 7 - "MediaSelector.tsx"
Cohesion: 0.11 Cohesion: 0.07
Nodes (21): ConfirmModal(), ConfirmModalProps, getFileType(), Media, MediaSelector(), MediaSelectorProps, Pagination(), PaginationProps (+13 more) Nodes (27): ConfirmModal(), ConfirmModalProps, getFileType(), Media, MediaSelector(), MediaSelectorProps, BlogPost, Category (+19 more)
### Community 8 - "admin.module.ts" ### Community 8 - "admin.module.ts"
Cohesion: 0.06 Cohesion: 0.07
Nodes (21): AdminModule, Module, PetQuery, PetsService, Injectable, ReportsController, ApiBearerAuth, ApiOperation (+13 more) Nodes (20): AdminModule, Module, BlogQuery, BlogsService, Injectable, MediaService, Injectable, ReportsController (+12 more)
### Community 9 - "PetProfile.tsx" ### Community 9 - "PetProfile.tsx"
Cohesion: 0.14 Cohesion: 0.14
@ -381,16 +396,16 @@ Cohesion: 0.14
Nodes (14): metadata, BrandLogo(), BrandLogoProps, EnamadBadge(), Footer(), Hero(), StatCounter(), MaintenancePage() (+6 more) Nodes (14): metadata, BrandLogo(), BrandLogoProps, EnamadBadge(), Footer(), Hero(), StatCounter(), MaintenancePage() (+6 more)
### Community 12 - "adminRoutes.tsx" ### Community 12 - "adminRoutes.tsx"
Cohesion: 0.05 Cohesion: 0.09
Nodes (29): App(), HeroBanner, VetTestimonial, ContactInfoItem, ContactSubmission, CategoryDist, DashboardData, SslStatus (+21 more) Nodes (16): App(), HeroBanner, VetTestimonial, ContactInfoItem, ContactSubmission, CategoryDist, DashboardData, Ticket (+8 more)
### Community 13 - "PrismaService" ### Community 13 - "PrismaService"
Cohesion: 0.07 Cohesion: 0.08
Nodes (19): ApiExcludeController, CategoryQuery, MetricsController, Controller, Get, Res, MeliPayamakPattern, MeliPayamakResponse (+11 more) Nodes (15): B2BWholesaleOrderItem, MeliPayamakPattern, MeliPayamakResponse, SendPatternSmsOptions, SmsConfig, SmsLogQuery, CreateContactSubmissionDto, UpdateContactInfoItemDto (+7 more)
### Community 14 - "pets/pets.controller.ts" ### Community 14 - "pets/pets.controller.ts"
Cohesion: 0.11 Cohesion: 0.16
Nodes (19): CreatePetDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional, IsString (+11 more) Nodes (13): CreatePetDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional, IsString (+5 more)
### Community 15 - "ProductsService" ### Community 15 - "ProductsService"
Cohesion: 0.09 Cohesion: 0.09
@ -401,24 +416,24 @@ Cohesion: 0.06
Nodes (18): metadata, ContactFormClient(), ContactInfoItem, Testimonial, TestimonialsSection(), api, ApiErrorPayload, BASE_DOMAIN (+10 more) Nodes (18): metadata, ContactFormClient(), ContactInfoItem, Testimonial, TestimonialsSection(), api, ApiErrorPayload, BASE_DOMAIN (+10 more)
### Community 17 - "CreateVideoDto" ### Community 17 - "CreateVideoDto"
Cohesion: 0.07 Cohesion: 0.09
Nodes (32): CreateVideoDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString, UpdateVideoDto (+24 more) Nodes (24): CreateVideoDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString, UpdateVideoDto (+16 more)
### Community 18 - "src/services/api.ts" ### Community 18 - "src/services/api.ts"
Cohesion: 0.09 Cohesion: 0.10
Nodes (25): ProtectedRoute(), Login(), B2BManager, SeoSettingsPage, SmartAdvisorManager, SystemSettingsPage, ApiErrorPayload, failedQueue (+17 more) Nodes (23): ProtectedRoute(), SEARCHABLE_PAGES, Topbar(), TopbarProps, Login(), B2BManager, SmartAdvisorManager, SystemSettingsPage (+15 more)
### Community 19 - "auth.service.ts" ### Community 19 - "auth.service.ts"
Cohesion: 0.15 Cohesion: 0.08
Nodes (14): AdminLoginInput, LoginInput, RegisterInput, SendOtpDto, ApiProperty, IsNotEmpty, IsString, Matches (+6 more) Nodes (25): AdminLoginInput, LoginInput, RegisterInput, AdminLoginDto, ApiProperty, IsEmail, IsNotEmpty, IsString (+17 more)
### Community 20 - "BE-001" ### Community 20 - "BE-001"
Cohesion: 0.06 Cohesion: 0.06
Nodes (32): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, BE-001, Category, Completion Statement, Confidence (+24 more) Nodes (32): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, BE-001, Category, Completion Statement, Confidence (+24 more)
### Community 21 - "Roles" ### Community 21 - "Roles"
Cohesion: 0.20 Cohesion: 0.25
Nodes (15): Roles(), SettingsController, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+7 more) Nodes (10): Roles(), ApiBearerAuth, ApiOperation, Body, Delete, Param, Patch, Post (+2 more)
### Community 22 - "FE-001" ### Community 22 - "FE-001"
Cohesion: 0.06 Cohesion: 0.06
@ -448,20 +463,20 @@ Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternati
Cohesion: 0.06 Cohesion: 0.06
Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more) Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more)
### Community 29 - "WholesaleService" ### Community 29 - "WholesaleApplyDto"
Cohesion: 0.14 Cohesion: 0.10
Nodes (14): ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param, Post (+6 more) Nodes (20): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto, ApiBearerAuth, ApiOperation (+12 more)
### Community 30 - "main.ts" ### Community 30 - "main.ts"
Cohesion: 0.11 Cohesion: 0.11
Nodes (11): AppModule, Module, CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable (+3 more) Nodes (11): AppModule, Module, CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable (+3 more)
### Community 31 - "JwtAuthGuard" ### Community 31 - "JwtAuthGuard"
Cohesion: 0.15 Cohesion: 0.18
Nodes (9): JwtAuthGuard, Injectable, B2BWholesaleOrderItem, ROLES_KEY, SortOrder, RequestWithUser, RolesGuard, Injectable (+1 more) Nodes (7): JwtAuthGuard, Injectable, ROLES_KEY, RequestWithUser, RolesGuard, Injectable, UserReqPayload
### Community 32 - "ZibalService" ### Community 32 - "ZibalService"
Cohesion: 0.15 Cohesion: 0.14
Nodes (4): PaymentService, Injectable, Injectable, ZibalService Nodes (4): PaymentService, Injectable, Injectable, ZibalService
### Community 33 - "راهنمای تست سیستم (Software Testing)" ### Community 33 - "راهنمای تست سیستم (Software Testing)"
@ -469,8 +484,8 @@ Cohesion: 0.07
Nodes (25): اجرای بک‌اند, اجرای فرانت‌اند, اجرای پروژه در سرور با PM2, برای راه‌اندازی بک‌اند:, برای راه‌اندازی فرانت‌اند Next.js:, بیلد کردن پروژه (Building), ذخیره پروسه‌ها تا پس از ری‌استارت سرور قطع نشوند:, راه‌اندازی و انتشار سیستم (Setup & Deployment) (+17 more) Nodes (25): اجرای بک‌اند, اجرای فرانت‌اند, اجرای پروژه در سرور با PM2, برای راه‌اندازی بک‌اند:, برای راه‌اندازی فرانت‌اند Next.js:, بیلد کردن پروژه (Building), ذخیره پروسه‌ها تا پس از ری‌استارت سرور قطع نشوند:, راه‌اندازی و انتشار سیستم (Setup & Deployment) (+17 more)
### Community 34 - "CategoriesController" ### Community 34 - "CategoriesController"
Cohesion: 0.10 Cohesion: 0.09
Nodes (16): CategoriesController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+8 more) Nodes (17): CategoriesController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+9 more)
### Community 35 - "B2BService" ### Community 35 - "B2BService"
Cohesion: 0.14 Cohesion: 0.14
@ -485,8 +500,8 @@ Cohesion: 0.09
Nodes (32): ClientLayout(), ArchiveProductCard(), AuthModal(), AuthModalProps, extractOtpFromText(), B2BPortal(), CartDrawer(), CheckoutPage() (+24 more) Nodes (32): ClientLayout(), ArchiveProductCard(), AuthModal(), AuthModalProps, extractOtpFromText(), B2BPortal(), CartDrawer(), CheckoutPage() (+24 more)
### Community 38 - "UsersService" ### Community 38 - "UsersService"
Cohesion: 0.05 Cohesion: 0.06
Nodes (42): DEFAULT_JWT_REFRESH_SECRET, DEFAULT_JWT_SECRET, getJwtSecret(), AuthModule, Module, JwtPayload, JwtStrategy, Injectable (+34 more) Nodes (41): DEFAULT_JWT_REFRESH_SECRET, DEFAULT_JWT_SECRET, getJwtSecret(), AuthModule, Module, JwtPayload, JwtStrategy, Injectable (+33 more)
### Community 39 - "What You Must Do When Invoked" ### Community 39 - "What You Must Do When Invoked"
Cohesion: 0.07 Cohesion: 0.07
@ -504,17 +519,17 @@ Nodes (3): PLAYBACK_RATES, PodcastPlayerModal(), PodcastPlayerModalProps
Cohesion: 0.13 Cohesion: 0.13
Nodes (14): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more) Nodes (14): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
### Community 43 - "AuthService" ### Community 43 - "RedisService"
Cohesion: 0.22 Cohesion: 0.09
Nodes (3): AuthService, Injectable, normalizeMobile() Nodes (6): AuthService, Injectable, normalizeMobile(), RedisService, Injectable, UserAddressInput
### Community 44 - "MediaController" ### Community 44 - "MediaController"
Cohesion: 0.11 Cohesion: 0.11
Nodes (16): MediaController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+8 more) Nodes (14): MediaController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
### Community 45 - "Transactions.tsx" ### Community 45 - "Pagination.tsx"
Cohesion: 0.33 Cohesion: 0.13
Nodes (4): GatewayHealth, Stats, Transaction, Transactions Nodes (11): Pagination(), PaginationProps, Pet, GatewayHealth, Stats, Transaction, ProductItem, WikiTerm (+3 more)
### Community 48 - "PrescriptionsService" ### Community 48 - "PrescriptionsService"
Cohesion: 0.14 Cohesion: 0.14
@ -545,24 +560,24 @@ Cohesion: 0.06
Nodes (31): compilerOptions, allowSyntheticDefaultImports, baseUrl, declaration, emitDecoratorMetadata, esModuleInterop, experimentalDecorators, forceConsistentCasingInFileNames (+23 more) Nodes (31): compilerOptions, allowSyntheticDefaultImports, baseUrl, declaration, emitDecoratorMetadata, esModuleInterop, experimentalDecorators, forceConsistentCasingInFileNames (+23 more)
### Community 55 - "Media.tsx" ### Community 55 - "Media.tsx"
Cohesion: 0.09 Cohesion: 0.14
Nodes (20): Badge(), BadgeProps, BadgeVariant, variantStyles, ImagePreviewModal(), ImagePreviewModalProps, ToggleSwitch(), ToggleSwitchProps (+12 more) Nodes (13): Badge(), BadgeProps, BadgeVariant, variantStyles, ImagePreviewModal(), ImagePreviewModalProps, getFileType(), Media (+5 more)
### Community 56 - "compilerOptions" ### Community 56 - "compilerOptions"
Cohesion: 0.08 Cohesion: 0.08
Nodes (23): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, jsx, lib, module, moduleDetection, moduleResolution (+15 more) Nodes (23): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, jsx, lib, module, moduleDetection, moduleResolution (+15 more)
### Community 57 - "PetsController" ### Community 57 - "PetsController"
Cohesion: 0.15 Cohesion: 0.10
Nodes (11): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+3 more) Nodes (14): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+6 more)
### Community 58 - "PaginationDto" ### Community 58 - "PaginationDto"
Cohesion: 0.09 Cohesion: 0.06
Nodes (21): BlogsController, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param (+13 more) Nodes (31): BlogsController, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param (+23 more)
### Community 59 - "dependencies" ### Community 59 - "dependencies"
Cohesion: 0.05 Cohesion: 0.10
Nodes (41): dependencies, bcrypt, bcryptjs, class-transformer, class-validator, helmet, ioredis, js-yaml (+33 more) Nodes (21): dependencies, bcrypt, class-transformer, class-validator, ioredis, @nestjs/common, @nestjs/core, @nestjs/passport (+13 more)
### Community 60 - "compilerOptions" ### Community 60 - "compilerOptions"
Cohesion: 0.10 Cohesion: 0.10
@ -576,10 +591,6 @@ Nodes (20): HomeClient(), HomeClientProps, getHomeData(), Home(), metadata, meta
Cohesion: 0.13 Cohesion: 0.13
Nodes (15): BlogsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+7 more) Nodes (15): BlogsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+7 more)
### Community 63 - "SettingsService"
Cohesion: 0.12
Nodes (3): SmsLogQuery, SettingsService, Injectable
### Community 64 - "BannersService" ### Community 64 - "BannersService"
Cohesion: 0.13 Cohesion: 0.13
Nodes (15): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+7 more) Nodes (15): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+7 more)
@ -604,21 +615,21 @@ Nodes (18): 1. Framework-Aware Analysis, 2. DOM & Semantic Structure Analysis, 3
Cohesion: 0.13 Cohesion: 0.13
Nodes (14): ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete, Get (+6 more) Nodes (14): ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete, Get (+6 more)
### Community 70 - "ApiOperation" ### Community 70 - "AdminQueryDto"
Cohesion: 0.14 Cohesion: 0.20
Nodes (8): ApiOperation, ApiQuery, Get, Query, AdminQueryDto, ApiPropertyOptional, IsOptional, IsString Nodes (7): ApiQuery, Get, Query, AdminQueryDto, ApiPropertyOptional, IsOptional, IsString
### Community 71 - "PetsController" ### Community 71 - ".update"
Cohesion: 0.14 Cohesion: 0.24
Nodes (20): PetsController, ApiBadRequestResponse, ApiBearerAuth, ApiCreatedResponse, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags (+12 more) Nodes (11): ApiNotFoundResponse, ApiOkResponse, ApiOperation, Body, Delete, Get, Param, Patch (+3 more)
### Community 72 - "seo.module.ts" ### Community 72 - "seo.module.ts"
Cohesion: 0.16 Cohesion: 0.16
Nodes (10): SeoController, ApiOperation, ApiTags, Controller, Get, Param, SeoModule, Module (+2 more) Nodes (10): SeoController, ApiOperation, ApiTags, Controller, Get, Param, SeoModule, Module (+2 more)
### Community 73 - "admin.service.ts" ### Community 73 - "admin.service.ts"
Cohesion: 0.18 Cohesion: 0.13
Nodes (13): CouponInput, CouponTargetInput, PaginationQuery, CreateUserDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty (+5 more) Nodes (21): CouponInput, CouponTargetInput, PaginationQuery, ProductDto, ApiPropertyOptional, IsArray, IsBoolean, IsNumber (+13 more)
### Community 74 - "🏢 AI Software Agency — Master Orchestration Protocol v3" ### Community 74 - "🏢 AI Software Agency — Master Orchestration Protocol v3"
Cohesion: 0.11 Cohesion: 0.11
@ -650,11 +661,11 @@ Nodes (9): GatewayHealthResult, IPaymentGateway, PaymentInquiryResult, PaymentRe
### Community 81 - "devDependencies" ### Community 81 - "devDependencies"
Cohesion: 0.13 Cohesion: 0.13
Nodes (15): eslint-config-next, devDependencies, eslint, eslint-config-next, jsdom, tailwindcss, @tailwindcss/postcss, @types/node (+7 more) Nodes (15): devDependencies, eslint, jsdom, tailwindcss, @tailwindcss/postcss, @types/node, @types/react-dom, @vitejs/plugin-react (+7 more)
### Community 82 - "api" ### Community 82 - "api"
Cohesion: 0.15 Cohesion: 0.29
Nodes (13): Layout(), MenuGroup, Sidebar(), SidebarProps, SubMenuItem, SEARCHABLE_PAGES, Topbar(), TopbarProps (+5 more) Nodes (6): Layout(), MenuGroup, Sidebar(), SidebarProps, SubMenuItem, api
### Community 83 - "Orders.tsx" ### Community 83 - "Orders.tsx"
Cohesion: 0.14 Cohesion: 0.14
@ -716,9 +727,9 @@ Nodes (8): exclude, extends, dist, node_modules, prisma, **/*spec.ts, test, ./ts
Cohesion: 0.15 Cohesion: 0.15
Nodes (13): jest, collectCoverageFrom, coverageDirectory, moduleFileExtensions, rootDir, testEnvironment, testRegex, transform (+5 more) Nodes (13): jest, collectCoverageFrom, coverageDirectory, moduleFileExtensions, rootDir, testEnvironment, testRegex, transform (+5 more)
### Community 98 - "AdminController" ### Community 98 - "AdminService"
Cohesion: 0.12 Cohesion: 0.09
Nodes (8): AdminController, ApiBearerAuth, ApiTags, Controller, Delete, Param, Put, UseGuards Nodes (13): AdminController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Param (+5 more)
### Community 99 - "Comprehensive Change Log" ### Community 99 - "Comprehensive Change Log"
Cohesion: 0.15 Cohesion: 0.15
@ -728,9 +739,13 @@ Nodes (12): 10. `TASK-VERIFY-001`, 1. `TASK-SEC-001`, 2. `TASK-SEC-002`, 3. `TAS
Cohesion: 0.17 Cohesion: 0.17
Nodes (11): 1. Detect Test Runner from Tech Stack, 2. Execution Output Capture (Mandatory), 3. Acceptance Criteria Verification, 4. Failure Routing Protocol, 5. Success Routing Protocol, 6. Forbidden Actions, Expected JSON Output Schema, Operational Rules & Boundaries (+3 more) Nodes (11): 1. Detect Test Runner from Tech Stack, 2. Execution Output Capture (Mandatory), 3. Acceptance Criteria Verification, 4. Failure Routing Protocol, 5. Success Routing Protocol, 6. Forbidden Actions, Expected JSON Output Schema, Operational Rules & Boundaries (+3 more)
### Community 103 - "ProductDto" ### Community 101 - "UITexts.tsx"
Cohesion: 0.22 Cohesion: 0.10
Nodes (7): ProductDto, ApiPropertyOptional, IsArray, IsBoolean, IsNumber, IsOptional, IsString Nodes (18): ICON_REGISTRY, IconPickerModal(), IconPickerModalProps, COLORS, RichTextEditor(), RichTextEditorProps, ToggleSwitch(), ToggleSwitchProps (+10 more)
### Community 103 - "SettingsController"
Cohesion: 0.21
Nodes (6): SettingsController, ApiOkResponse, ApiTags, Controller, Get, Query
### Community 104 - "AuthController" ### Community 104 - "AuthController"
Cohesion: 0.27 Cohesion: 0.27
@ -740,6 +755,10 @@ Nodes (12): AuthController, ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse,
Cohesion: 0.17 Cohesion: 0.17
Nodes (11): 1.1 Authoritative Source File Inventory Rebuilt, 1.2 Raw Finding Dispositions Reconciled, 1.3 Finding Identifier Normalization, 1.4 Rejected Finding Cleanup, 1. Summary of Integrity Repairs Performed, 2. Final Verified Finding Metrics, 3. Reference and Compiler Integrity Results, 4. Quality Gate Conclusion (+3 more) Nodes (11): 1.1 Authoritative Source File Inventory Rebuilt, 1.2 Raw Finding Dispositions Reconciled, 1.3 Finding Identifier Normalization, 1.4 Rejected Finding Cleanup, 1. Summary of Integrity Repairs Performed, 2. Final Verified Finding Metrics, 3. Reference and Compiler Integrity Results, 4. Quality Gate Conclusion (+3 more)
### Community 106 - "orders.service.ts"
Cohesion: 0.24
Nodes (6): IsNotEmpty, IsNumber, IsString, ValidateCouponDto, OrdersModule, Module
### Community 107 - "Operational Rules & Boundaries" ### Community 107 - "Operational Rules & Boundaries"
Cohesion: 0.18 Cohesion: 0.18
Nodes (10): 1. Detect Tech Stack First (Universal), 2. Explicit Scoring Methodology (Universal), 3. Code Coverage Ratio Rule, 4. Deep Directory Scanning, 5. Forbidden Actions, Expected JSON Output Schema, Operational Rules & Boundaries, Required Output Artifacts (What files to write/update) (+2 more) Nodes (10): 1. Detect Tech Stack First (Universal), 2. Explicit Scoring Methodology (Universal), 3. Code Coverage Ratio Rule, 4. Deep Directory Scanning, 5. Forbidden Actions, Expected JSON Output Schema, Operational Rules & Boundaries, Required Output Artifacts (What files to write/update) (+2 more)
@ -760,9 +779,9 @@ Nodes (5): AppController, Controller, Get, AppService, Injectable
Cohesion: 0.25 Cohesion: 0.25
Nodes (7): SmsLogQueryDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type Nodes (7): SmsLogQueryDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type
### Community 112 - "BlogsService" ### Community 112 - "PetsController"
Cohesion: 0.22 Cohesion: 0.18
Nodes (3): BlogQuery, BlogsService, Injectable Nodes (9): PetsController, ApiBadRequestResponse, ApiBearerAuth, ApiCreatedResponse, ApiTags, Controller, UploadedFile, UseGuards (+1 more)
### Community 113 - "Vazirmatn Changelog" ### Community 113 - "Vazirmatn Changelog"
Cohesion: 0.18 Cohesion: 0.18
@ -788,10 +807,6 @@ Nodes (9): compilerOptions, esModuleInterop, module, moduleResolution, skipLibCh
Cohesion: 0.20 Cohesion: 0.20
Nodes (9): Compile and run the project, Deployment, Description, License, Project setup, Resources, Run tests, Stay in touch (+1 more) Nodes (9): Compile and run the project, Deployment, Description, License, Project setup, Resources, Run tests, Stay in touch (+1 more)
### Community 119 - "devDependencies"
Cohesion: 0.09
Nodes (23): devDependencies, eslint, eslint-config-prettier, @eslint/js, jest, @nestjs/schematics, @nestjs/testing, source-map-support (+15 more)
### Community 120 - "Repository Map" ### Community 120 - "Repository Map"
Cohesion: 0.20 Cohesion: 0.20
Nodes (9): 1. Active Customer Storefront: React 19 + Vite Application, 2. Active Backend Service: NestJS Application, 3. Excluded Placeholder / Non-Auditable Directories, Active Applications & Non-Auditable Scopes, Documentation Governance, Important Configuration & Infrastructure Files, Mandatory Global Audit Exclusions, Repository Map (+1 more) Nodes (9): 1. Active Customer Storefront: React 19 + Vite Application, 2. Active Backend Service: NestJS Application, 3. Excluded Placeholder / Non-Auditable Directories, Active Applications & Non-Auditable Scopes, Documentation Governance, Important Configuration & Infrastructure Files, Mandatory Global Audit Exclusions, Repository Map (+1 more)
@ -808,9 +823,9 @@ Nodes (9): name, private, scripts, build, dev, lint, preview, type (+1 more)
Cohesion: 0.20 Cohesion: 0.20
Nodes (9): Arch Linux, Contributors, Install, Known problems for variable version, License, Sahel-Font, To Do (variable), طریقه استفاده از نسخه متغیر variable (+1 more) Nodes (9): Arch Linux, Contributors, Install, Known problems for variable version, License, Sahel-Font, To Do (variable), طریقه استفاده از نسخه متغیر variable (+1 more)
### Community 124 - "Reports.tsx" ### Community 124 - "Spinner.tsx"
Cohesion: 0.20 Cohesion: 0.08
Nodes (7): BestSellerItem, CategoryDistItem, COLORS, CustomTooltipProps, ReportData, TopCouponItem, Reports Nodes (18): Spinner(), BestSellerItem, CategoryDistItem, COLORS, CustomTooltipProps, ReportData, TopCouponItem, ProductReview (+10 more)
### Community 125 - "Sahel-Font" ### Community 125 - "Sahel-Font"
Cohesion: 0.20 Cohesion: 0.20
@ -828,9 +843,9 @@ Nodes (8): cmd_next_task(), cmd_progress(), cmd_reset(), cmd_status(), cmd_unblo
Cohesion: 0.22 Cohesion: 0.22
Nodes (8): author, description, license, name, prisma, seed, private, version Nodes (8): author, description, license, name, prisma, seed, private, version
### Community 129 - "wholesale.controller.ts" ### Community 129 - "WikiService"
Cohesion: 0.31 Cohesion: 0.22
Nodes (6): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto Nodes (3): Injectable, WikiQuery, WikiService
### Community 130 - "graphify reference: extra exports and benchmark" ### Community 130 - "graphify reference: extra exports and benchmark"
Cohesion: 0.22 Cohesion: 0.22
@ -877,8 +892,12 @@ Cohesion: 0.29
Nodes (6): 1. Executive Vision, 2. Target Audience, 3. Functional Requirements, 4. Non-Functional Requirements (Performance, Security), 5. Epic / Feature Breakdown, Product Requirement Document (PRD) Nodes (6): 1. Executive Vision, 2. Target Audience, 3. Functional Requirements, 4. Non-Functional Requirements (Performance, Security), 5. Epic / Feature Breakdown, Product Requirement Document (PRD)
### Community 141 - "WikiController" ### Community 141 - "WikiController"
Cohesion: 0.13 Cohesion: 0.21
Nodes (13): ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param, Query (+5 more) Nodes (9): ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param, Query (+1 more)
### Community 142 - "devDependencies"
Cohesion: 0.22
Nodes (9): devDependencies, globals, @types/passport-jwt, @types/supertest, typescript, globals, typescript, @types/passport-jwt (+1 more)
### Community 144 - "Baseline Command Plan & Reconciled Command History" ### Community 144 - "Baseline Command Plan & Reconciled Command History"
Cohesion: 0.29 Cohesion: 0.29
@ -1028,9 +1047,13 @@ Nodes (3): ADR-AUTH-001: Admin Panel Authentication Architecture & Token Managem
Cohesion: 0.29 Cohesion: 0.29
Nodes (6): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString Nodes (6): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString
### Community 214 - "LoginDto" ### Community 214 - "MetricsController"
Cohesion: 0.33 Cohesion: 0.29
Nodes (5): LoginDto, ApiProperty, IsNotEmpty, IsString, MinLength Nodes (5): ApiExcludeController, MetricsController, Controller, Get, Res
### Community 215 - "CreateReminderDto"
Cohesion: 0.29
Nodes (6): CreateReminderDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString
### Community 223 - "Shabnam Font README" ### Community 223 - "Shabnam Font README"
Cohesion: 0.67 Cohesion: 0.67
@ -1044,28 +1067,24 @@ Nodes (8): RegisterDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty, I
Cohesion: 0.22 Cohesion: 0.22
Nodes (3): Props, RouteErrorBoundary, State Nodes (3): Props, RouteErrorBoundary, State
### Community 307 - "AdminLoginDto"
Cohesion: 0.29
Nodes (6): AdminLoginDto, ApiProperty, IsEmail, IsNotEmpty, IsString, MinLength
## Knowledge Gaps ## Knowledge Gaps
- **1242 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1237 more) - **1250 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1245 more)
These have ≤1 connection - possible missing edges or undocumented components. These have ≤1 connection - possible missing edges or undocumented components.
- **102 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes. - **116 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions ## Suggested Questions
_Questions this graph is uniquely positioned to answer:_ _Questions this graph is uniquely positioned to answer:_
- **Why does `Roles()` connect `Roles` to `BannersService`, `wholesale.controller.ts`, `CmsController`, `B2BService`, `reviews.controller.ts`, `tickets.controller.ts`, `SslController`, `IngredientsService`, `ProductsService`, `PrescriptionsService`, `SmartAdvisorService`, `TestimonialsService`, `ContactService`, `PaymentController`, `.addPattern`, `WholesaleService`, `JwtAuthGuard`?** - **Why does `Roles()` connect `Roles` to `BannersService`, `CmsController`, `B2BService`, `CreateReviewDto`, `tickets.controller.ts`, `SettingsController`, `SslController`, `IngredientsService`, `ProductsService`, `PrescriptionsService`, `SmartAdvisorService`, `TestimonialsService`, `ContactService`, `PaymentController`, `WholesaleApplyDto`, `JwtAuthGuard`?**
_High betweenness centrality (0.051) - this node is a cross-community bridge._ _High betweenness centrality (0.051) - this node is a cross-community bridge._
- **Why does `ApiResponse` connect `src/services/api.ts` to `OrdersService`, `UsersService`, `PetsController`, `AuthController`, `WikiController`, `HomeController`, `ProductsService`, `PaginationDto`?** - **Why does `ApiResponse` connect `src/services/api.ts` to `OrdersService`, `UsersService`, `AuthController`, `WikiController`, `HomeController`, `PetsController`, `ProductsService`, `PaginationDto`?**
_High betweenness centrality (0.040) - this node is a cross-community bridge._ _High betweenness centrality (0.042) - this node is a cross-community bridge._
- **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `OrdersService`, `wholesale.controller.ts`, `CmsController`, `reviews.controller.ts`, `tickets.controller.ts`, `UsersService`, `admin.module.ts`, `admin.service.ts`, `MediaController`, `PrismaService`, `pets/pets.controller.ts`, `ProductsService`, `CreateVideoDto`, `auth.service.ts`?** - **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `WikiService`, `CategoriesController`, `CmsController`, `tickets.controller.ts`, `UsersService`, `admin.module.ts`, `admin.service.ts`, `orders.service.ts`, `PrismaService`, `pets/pets.controller.ts`, `auth.service.ts`, `PetsController`, `PaginationDto`?**
_High betweenness centrality (0.024) - this node is a cross-community bridge._ _High betweenness centrality (0.024) - this node is a cross-community bridge._
- **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?** - **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?**
_1242 weakly-connected nodes found - possible documentation gaps or missing edges._ _1250 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `OrdersService` be split into smaller, more focused modules?** - **Should `OrdersService` be split into smaller, more focused modules?**
_Cohesion score 0.06168831168831169 - nodes in this community are weakly interconnected._ _Cohesion score 0.07171717171717172 - nodes in this community are weakly interconnected._
- **Should `productService.ts` be split into smaller, more focused modules?** - **Should `productService.ts` be split into smaller, more focused modules?**
_Cohesion score 0.05888376856118792 - nodes in this community are weakly interconnected._ _Cohesion score 0.05888376856118792 - nodes in this community are weakly interconnected._
- **Should `CmsController` be split into smaller, more focused modules?** - **Should `CmsController` be split into smaller, more focused modules?**

1
graphify-out/cache/last_query_stamp vendored Normal file
View File

@ -0,0 +1 @@
1787069487.057531

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff