feat(payment): fix zibal refund api, add maskable fields, receipt modal, standardized buttons and order refund options
All checks were successful
Deploy Canina / deploy (push) Successful in 41s
All checks were successful
Deploy Canina / deploy (push) Successful in 41s
This commit is contained in:
parent
f9e40564cf
commit
d62787cd99
@ -172,6 +172,21 @@ export class AdminController {
|
||||
return { success: true, data: order };
|
||||
}
|
||||
|
||||
@Post('orders/:id/refund-wallet')
|
||||
@ApiOperation({ summary: 'استرداد مستقیم مبلغ سفارش به کیف پول کاربر' })
|
||||
async refundOrderToWallet(
|
||||
@Param('id') id: string,
|
||||
@Body('amount') amount?: number,
|
||||
@Body('reason') reason?: string,
|
||||
) {
|
||||
const result = await this.adminService.refundOrderToWallet(
|
||||
id,
|
||||
amount ? Number(amount) : undefined,
|
||||
reason,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Get('coupons')
|
||||
@ApiOperation({ summary: 'لیست کد تخفیفها' })
|
||||
@ApiQuery({ name: 'page', required: false, description: 'شماره صفحه' })
|
||||
|
||||
@ -615,6 +615,65 @@ export class AdminService {
|
||||
});
|
||||
}
|
||||
|
||||
async refundOrderToWallet(orderId: string, customAmount?: number, reason?: string) {
|
||||
const order = await this.prisma.order.findUnique({
|
||||
where: { id: orderId },
|
||||
include: { user: true },
|
||||
});
|
||||
|
||||
if (!order) {
|
||||
throw new NotFoundException('سفارش مورد نظر یافت نشد');
|
||||
}
|
||||
|
||||
if (!order.userId || !order.user) {
|
||||
throw new BadRequestException('این سفارش به کاربر ثبتنامشدهای متصل نیست');
|
||||
}
|
||||
|
||||
const refundAmount = customAmount !== undefined && customAmount > 0
|
||||
? customAmount
|
||||
: Number(order.totalAmount || 0);
|
||||
|
||||
if (refundAmount <= 0) {
|
||||
throw new BadRequestException('مبلغ استرداد باید بیشتر از صفر باشد');
|
||||
}
|
||||
|
||||
await this.prisma.$transaction(async (tx) => {
|
||||
// 1. Increment user wallet balance
|
||||
await tx.user.update({
|
||||
where: { id: order.userId },
|
||||
data: {
|
||||
walletBalance: { increment: refundAmount },
|
||||
},
|
||||
});
|
||||
|
||||
// 2. Create wallet transaction entry
|
||||
await tx.walletTransaction.create({
|
||||
data: {
|
||||
userId: order.userId,
|
||||
amount: refundAmount,
|
||||
type: 'deposit',
|
||||
status: 'completed',
|
||||
description: reason || `استرداد وجه سفارش لغو شده #${order.trackingNumber || order.id.slice(0, 8)} به کیف پول`,
|
||||
},
|
||||
});
|
||||
|
||||
// 3. Mark order as cancelled and note refund
|
||||
await tx.order.update({
|
||||
where: { id: order.id },
|
||||
data: {
|
||||
status: 'cancelled',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `مبلغ ${refundAmount.toLocaleString('fa-IR')} تومان با موفقیت به کیف پول کاربر بازگردانده شد.`,
|
||||
refundAmount,
|
||||
userId: order.userId,
|
||||
};
|
||||
}
|
||||
|
||||
async getCoupons(query: PaginationQuery = {}) {
|
||||
const page = Number(query.page) || 1;
|
||||
const limit = Number(query.limit) || 10;
|
||||
|
||||
@ -25,6 +25,9 @@ async function bootstrap() {
|
||||
|
||||
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
||||
|
||||
// Trust reverse proxy (Nginx / Docker ingress) to resolve real client IP from X-Forwarded-For
|
||||
app.set('trust proxy', true);
|
||||
|
||||
// Serve static uploads folder under both /uploads/ and /api/uploads/
|
||||
app.useStaticAssets(join(process.cwd(), 'uploads'), {
|
||||
prefix: '/uploads/',
|
||||
|
||||
@ -45,6 +45,23 @@ export class PaymentController {
|
||||
private readonly zibalEBankService: ZibalEBankService,
|
||||
) {}
|
||||
|
||||
private extractRealClientIp(req: Request, fallbackIp?: string): string {
|
||||
const xForwardedFor = req.headers['x-forwarded-for'];
|
||||
if (xForwardedFor) {
|
||||
const forwardedIps = Array.isArray(xForwardedFor)
|
||||
? xForwardedFor[0]
|
||||
: xForwardedFor.split(',')[0];
|
||||
if (forwardedIps && forwardedIps.trim()) {
|
||||
return forwardedIps.trim().replace(/^::ffff:/, '');
|
||||
}
|
||||
}
|
||||
const xRealIp = req.headers['x-real-ip'];
|
||||
if (xRealIp && typeof xRealIp === 'string') {
|
||||
return xRealIp.trim().replace(/^::ffff:/, '');
|
||||
}
|
||||
return (fallbackIp || req.ip || '').replace(/^::ffff:/, '');
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@Post('zibal/initiate')
|
||||
@ -56,16 +73,17 @@ export class PaymentController {
|
||||
description: 'خطا در ایجاد تراکنش یا نامعتبر بودن سفارش',
|
||||
})
|
||||
async initiateOrderPayment(
|
||||
@Req() req: { user: { id: string } },
|
||||
@Req() req: Request & { user: { id: string } },
|
||||
@Body() body: InitiatePaymentDto,
|
||||
@Ip() ip: string,
|
||||
@Headers('user-agent') userAgent?: string,
|
||||
) {
|
||||
const realIp = this.extractRealClientIp(req, ip);
|
||||
return this.paymentService.initiateOrderPayment(
|
||||
req.user.id,
|
||||
body.orderId,
|
||||
body.customCallbackUrl,
|
||||
{ ipAddress: ip, userAgent },
|
||||
{ ipAddress: realIp, userAgent },
|
||||
);
|
||||
}
|
||||
|
||||
@ -77,16 +95,17 @@ export class PaymentController {
|
||||
description: 'لینک هدایت به درگاه پرداخت برای شارژ کیف پول',
|
||||
})
|
||||
async initiateWalletTopup(
|
||||
@Req() req: { user: { id: string } },
|
||||
@Req() req: Request & { user: { id: string } },
|
||||
@Body() body: InitiateWalletTopupDto,
|
||||
@Ip() ip: string,
|
||||
@Headers('user-agent') userAgent?: string,
|
||||
) {
|
||||
const realIp = this.extractRealClientIp(req, ip);
|
||||
return this.paymentService.initiateWalletTopup(
|
||||
req.user.id,
|
||||
Number(body.amount),
|
||||
body.customCallbackUrl,
|
||||
{ ipAddress: ip, userAgent },
|
||||
{ ipAddress: realIp, userAgent },
|
||||
);
|
||||
}
|
||||
|
||||
@ -95,11 +114,13 @@ export class PaymentController {
|
||||
summary: 'دریافت کالبک بازگشت از درگاه زیبال و تایید تراکنش',
|
||||
})
|
||||
async handleZibalCallback(
|
||||
@Req() req: Request,
|
||||
@Query() query: ZibalCallbackQueryDto,
|
||||
@Res() res: Response,
|
||||
@Ip() ip: string,
|
||||
@Headers('user-agent') userAgent?: string,
|
||||
) {
|
||||
const realIp = this.extractRealClientIp(req, ip);
|
||||
const trackId = query.trackId || '';
|
||||
const success = query.success;
|
||||
const status = query.status;
|
||||
@ -119,7 +140,7 @@ export class PaymentController {
|
||||
success,
|
||||
status,
|
||||
orderId,
|
||||
{ ipAddress: ip, userAgent },
|
||||
{ ipAddress: realIp, userAgent },
|
||||
);
|
||||
|
||||
const params = new URLSearchParams({
|
||||
|
||||
@ -540,19 +540,26 @@ export class ZibalService implements IPaymentGateway {
|
||||
cardNumber?: string;
|
||||
description?: string;
|
||||
}) {
|
||||
const accountId =
|
||||
options.accountId ||
|
||||
(await this.prisma.uiText.findUnique({ where: { key: 'ZIBAL_EBANK_ACCOUNT_ID' } }))?.value;
|
||||
const merchant = await this.getMerchant();
|
||||
const accountIdSetting = (
|
||||
await this.prisma.uiText.findUnique({ where: { key: 'ZIBAL_EBANK_ACCOUNT_ID' } })
|
||||
)?.value;
|
||||
|
||||
const payload = {
|
||||
const payload: Record<string, any> = {
|
||||
merchant: merchant || undefined,
|
||||
merchantId: merchant || undefined,
|
||||
trackId: Number(options.trackId),
|
||||
accountId: accountId || 'default',
|
||||
tryReverse: options.tryReverse ?? false,
|
||||
amount: options.amount,
|
||||
cardNumber: options.cardNumber,
|
||||
amount: options.amount ? Number(options.amount) : undefined,
|
||||
cardNumber: options.cardNumber || undefined,
|
||||
description: options.description || 'استرداد وجه سفارش در کنینا',
|
||||
};
|
||||
|
||||
const finalAccountId = options.accountId || accountIdSetting;
|
||||
if (finalAccountId && finalAccountId.trim() !== '') {
|
||||
payload.accountId = finalAccountId.trim();
|
||||
}
|
||||
|
||||
return this.apiRequest<any>('/v1/account/refund', 'POST', payload);
|
||||
}
|
||||
|
||||
@ -563,7 +570,10 @@ export class ZibalService implements IPaymentGateway {
|
||||
refundId?: number | string;
|
||||
transactionTrackId?: number | string;
|
||||
}) {
|
||||
const merchant = await this.getMerchant();
|
||||
return this.apiRequest<any>('/v1/account/refund/inquiry', 'POST', {
|
||||
merchant: merchant || undefined,
|
||||
merchantId: merchant || undefined,
|
||||
refundId: params.refundId ? Number(params.refundId) : undefined,
|
||||
transactionTrackId: params.transactionTrackId
|
||||
? Number(params.transactionTrackId)
|
||||
@ -582,9 +592,12 @@ export class ZibalService implements IPaymentGateway {
|
||||
fromDate?: string;
|
||||
toDate?: string;
|
||||
}) {
|
||||
const merchant = await this.getMerchant();
|
||||
return this.apiRequest<any>('/v1/account/refund/list', 'POST', {
|
||||
merchant: merchant || undefined,
|
||||
merchantId: merchant || undefined,
|
||||
status: filter.status,
|
||||
type: filter.type || 4,
|
||||
type: filter.type,
|
||||
page: filter.page || 1,
|
||||
size: filter.size || 20,
|
||||
fromDate: filter.fromDate,
|
||||
|
||||
235
frontend/admin-panel/src/components/TransactionReceiptModal.tsx
Normal file
235
frontend/admin-panel/src/components/TransactionReceiptModal.tsx
Normal file
@ -0,0 +1,235 @@
|
||||
import React from 'react';
|
||||
import { Printer, X, CheckCircle2, ShieldCheck, Copy } from 'lucide-react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import Button from './ui/Button';
|
||||
|
||||
export interface TransactionReceiptData {
|
||||
trackId?: string | number;
|
||||
refNumber?: string | number;
|
||||
amountRials?: number | string;
|
||||
amountTomans?: number | string;
|
||||
statusText?: string;
|
||||
orderNumber?: string;
|
||||
orderId?: string;
|
||||
cardNumber?: string;
|
||||
paidAt?: string;
|
||||
createdAt?: string;
|
||||
fee?: number | string;
|
||||
mobile?: string;
|
||||
description?: string;
|
||||
psp?: string;
|
||||
ip?: string;
|
||||
}
|
||||
|
||||
interface TransactionReceiptModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
data: TransactionReceiptData | null;
|
||||
}
|
||||
|
||||
export default function TransactionReceiptModal({
|
||||
isOpen,
|
||||
onClose,
|
||||
data,
|
||||
}: TransactionReceiptModalProps) {
|
||||
if (!isOpen || !data) return null;
|
||||
|
||||
const handlePrint = () => {
|
||||
window.print();
|
||||
};
|
||||
|
||||
const handleCopy = (text: string, label: string) => {
|
||||
if (!text) return;
|
||||
navigator.clipboard.writeText(text);
|
||||
toast.success(`${label} کپی شد`);
|
||||
};
|
||||
|
||||
const rials =
|
||||
data.amountRials !== undefined
|
||||
? Number(data.amountRials)
|
||||
: (Number(data.amountTomans || 0) * 10);
|
||||
const tomans =
|
||||
data.amountTomans !== undefined
|
||||
? Number(data.amountTomans)
|
||||
: Math.floor(Number(data.amountRials || 0) / 10);
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm print:p-0 print:bg-white">
|
||||
<div className="bg-white rounded-3xl max-w-sm w-full shadow-2xl border border-gray-100 overflow-hidden print:border-none print:shadow-none font-vazir" dir="rtl">
|
||||
{/* Modal Header */}
|
||||
<div className="p-4 border-b border-gray-100 flex items-center justify-between print:hidden">
|
||||
<h3 className="font-black text-sm text-gray-900 flex items-center gap-1.5">
|
||||
<ShieldCheck className="w-4 h-4 text-emerald-600" />
|
||||
<span>رسید تراکنش {data.trackId || ''}</span>
|
||||
</h3>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-gray-400 hover:text-gray-700 font-bold p-1 cursor-pointer"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* The Zigzag Receipt Slip (Matching Zibal screenshot exactly) */}
|
||||
<div className="p-6 space-y-5 bg-white relative">
|
||||
{/* Top Jagged Border (CSS Jagged effect) */}
|
||||
<div className="w-full h-3 bg-indigo-50/50 -mt-6 mb-3 flex justify-between overflow-hidden opacity-60">
|
||||
{Array.from({ length: 24 }).map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="w-0 h-0 border-l-[6px] border-l-transparent border-r-[6px] border-r-transparent border-t-[8px] border-t-white"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Amount Display */}
|
||||
<div className="text-center space-y-1">
|
||||
<div className="text-2xl font-black text-emerald-600 font-mono">
|
||||
{rials.toLocaleString('fa-IR')}{' '}
|
||||
<span className="text-sm font-black text-emerald-700">ریال</span>
|
||||
</div>
|
||||
<p className="text-[11px] font-bold text-gray-400 font-mono">
|
||||
({tomans.toLocaleString('fa-IR')} تومان)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Data List (Aligned exactly like Zibal slip) */}
|
||||
<div className="space-y-2.5 text-xs">
|
||||
{/* Track ID */}
|
||||
<div className="flex items-center justify-between py-1 border-b border-gray-50">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleCopy(String(data.trackId || ''), 'شماره تراکنش')}
|
||||
className="text-indigo-600 hover:text-indigo-800 flex items-center gap-1 font-mono font-bold cursor-pointer"
|
||||
title="کپی"
|
||||
>
|
||||
<Copy className="w-3 h-3" />
|
||||
<span>{data.trackId || '-'}</span>
|
||||
</button>
|
||||
<span className="text-gray-500 font-bold">شماره تراکنش</span>
|
||||
</div>
|
||||
|
||||
{/* Reference Number */}
|
||||
<div className="flex items-center justify-between py-1 border-b border-gray-50">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleCopy(String(data.refNumber || ''), 'شناسه مرجع')}
|
||||
className="text-indigo-600 hover:text-indigo-800 flex items-center gap-1 font-mono font-bold cursor-pointer"
|
||||
title="کپی"
|
||||
>
|
||||
<Copy className="w-3 h-3" />
|
||||
<span>{data.refNumber || '-'}</span>
|
||||
</button>
|
||||
<span className="text-gray-500 font-bold">شناسه مرجع</span>
|
||||
</div>
|
||||
|
||||
{/* Paid At */}
|
||||
<div className="flex items-center justify-between py-1 border-b border-gray-50">
|
||||
<span className="font-mono text-gray-700 font-bold dir-ltr">
|
||||
{data.paidAt || data.createdAt || '-'}
|
||||
</span>
|
||||
<span className="text-gray-500 font-bold">تاریخ پرداخت</span>
|
||||
</div>
|
||||
|
||||
{/* Status */}
|
||||
<div className="flex items-center justify-between py-1 border-b border-gray-50">
|
||||
<span className="text-emerald-600 font-black flex items-center gap-1">
|
||||
<span className="w-2 h-2 rounded-full bg-emerald-500 inline-block"></span>
|
||||
<span>{data.statusText || 'پرداخت موفق'}</span>
|
||||
</span>
|
||||
<span className="text-gray-500 font-bold">وضعیت</span>
|
||||
</div>
|
||||
|
||||
{/* Order ID */}
|
||||
<div className="flex items-center justify-between py-1.5 px-2 bg-gray-50/80 rounded-lg">
|
||||
<span className="font-mono font-bold text-gray-900">
|
||||
{data.orderNumber || data.orderId || '-'}
|
||||
</span>
|
||||
<span className="text-gray-500 font-bold">شناسه سفارش</span>
|
||||
</div>
|
||||
|
||||
{/* Card Number */}
|
||||
<div className="flex items-center justify-between py-1 border-b border-gray-50">
|
||||
<span className="font-mono text-gray-800 font-bold dir-ltr">
|
||||
{data.cardNumber || '-'}
|
||||
</span>
|
||||
<span className="text-gray-500 font-bold">شماره کارت</span>
|
||||
</div>
|
||||
|
||||
{/* Creation Date */}
|
||||
<div className="flex items-center justify-between py-1.5 px-2 bg-gray-50/80 rounded-lg">
|
||||
<span className="font-mono font-bold text-gray-700 dir-ltr">
|
||||
{data.createdAt || data.paidAt || '-'}
|
||||
</span>
|
||||
<span className="text-gray-500 font-bold">تاریخ ایجاد</span>
|
||||
</div>
|
||||
|
||||
{/* Mobile */}
|
||||
<div className="flex items-center justify-between py-1.5 px-2 bg-gray-50/80 rounded-lg">
|
||||
<span className="font-mono font-bold text-gray-800 dir-ltr">
|
||||
{data.mobile || '-'}
|
||||
</span>
|
||||
<span className="text-gray-500 font-bold">شماره موبایل</span>
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<div className="flex items-center justify-between py-1 border-b border-gray-50">
|
||||
<span className="text-gray-800 font-bold max-w-[180px] truncate text-left">
|
||||
{data.description || 'پرداخت آنلاین - پت شاپ کنینا'}
|
||||
</span>
|
||||
<span className="text-gray-500 font-bold">توضیحات</span>
|
||||
</div>
|
||||
|
||||
{/* PSP */}
|
||||
<div className="flex items-center justify-between py-1.5 px-2 bg-gray-50/80 rounded-lg">
|
||||
<span className="font-bold text-indigo-700 text-[11px]">
|
||||
{data.psp || 'زیبال / بهپرداخت ملت'}
|
||||
</span>
|
||||
<span className="text-gray-500 font-bold">PSP</span>
|
||||
</div>
|
||||
|
||||
{/* Real IP */}
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleCopy(String(data.ip || ''), 'آیپی کاربر')}
|
||||
className="text-indigo-600 hover:text-indigo-800 flex items-center gap-1 font-mono font-bold cursor-pointer dir-ltr"
|
||||
title="کپی آیپی"
|
||||
>
|
||||
<Copy className="w-3 h-3" />
|
||||
<span>{data.ip || '-'}</span>
|
||||
</button>
|
||||
<span className="text-gray-500 font-bold">IP</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Jagged Border */}
|
||||
<div className="w-full h-3 bg-indigo-50/50 -mb-6 mt-4 flex justify-between overflow-hidden opacity-60">
|
||||
{Array.from({ length: 24 }).map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="w-0 h-0 border-l-[6px] border-l-transparent border-r-[6px] border-r-transparent border-b-[8px] border-b-white"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Actions / Print Footer */}
|
||||
<div className="p-4 bg-gray-50/80 border-t border-gray-100 flex items-center justify-between print:hidden">
|
||||
<Button variant="outline" size="sm" onClick={onClose}>
|
||||
بستن
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
startIcon={Printer}
|
||||
onClick={handlePrint}
|
||||
className="border-gray-300 hover:border-indigo-600 text-indigo-600 hover:bg-indigo-50"
|
||||
>
|
||||
چاپ رسید
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
114
frontend/admin-panel/src/components/ui/Button.tsx
Normal file
114
frontend/admin-panel/src/components/ui/Button.tsx
Normal file
@ -0,0 +1,114 @@
|
||||
import React from 'react';
|
||||
import { Info } from 'lucide-react';
|
||||
import Spinner from './Spinner';
|
||||
|
||||
export type ButtonVariant =
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| 'danger'
|
||||
| 'success'
|
||||
| 'warning'
|
||||
| 'outline'
|
||||
| 'ghost';
|
||||
|
||||
export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';
|
||||
|
||||
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
variant?: ButtonVariant;
|
||||
size?: ButtonSize;
|
||||
isLoading?: boolean;
|
||||
startIcon?: React.ComponentType<{ className?: string }>;
|
||||
endIcon?: React.ComponentType<{ className?: string }>;
|
||||
info?: string;
|
||||
badge?: string | number;
|
||||
fullWidth?: boolean;
|
||||
}
|
||||
|
||||
export default function Button({
|
||||
children,
|
||||
variant = 'primary',
|
||||
size = 'md',
|
||||
isLoading = false,
|
||||
startIcon: StartIcon,
|
||||
endIcon: EndIcon,
|
||||
info,
|
||||
badge,
|
||||
fullWidth = false,
|
||||
className = '',
|
||||
disabled,
|
||||
...props
|
||||
}: ButtonProps) {
|
||||
// Base styles: strict whitespace-nowrap and touch-friendly cursor
|
||||
const baseClasses =
|
||||
'inline-flex items-center justify-center font-bold whitespace-nowrap transition-all select-none rounded-xl cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none focus:outline-none focus:ring-2 focus:ring-offset-2';
|
||||
|
||||
// Size styling
|
||||
const sizeClasses: Record<ButtonSize, string> = {
|
||||
xs: 'px-2.5 py-1 text-[11px] gap-1.5',
|
||||
sm: 'px-3.5 py-1.5 text-xs gap-2',
|
||||
md: 'px-4 py-2.5 text-xs sm:text-sm gap-2',
|
||||
lg: 'px-6 py-3 text-sm sm:text-base gap-2.5 shadow-md',
|
||||
};
|
||||
|
||||
// Variant styling
|
||||
const variantClasses: Record<ButtonVariant, string> = {
|
||||
primary:
|
||||
'bg-indigo-600 hover:bg-indigo-700 text-white shadow-sm shadow-indigo-200 focus:ring-indigo-500 border border-indigo-600',
|
||||
secondary:
|
||||
'bg-slate-100 hover:bg-slate-200 text-slate-700 focus:ring-slate-400 border border-slate-200',
|
||||
danger:
|
||||
'bg-rose-600 hover:bg-rose-700 text-white shadow-sm shadow-rose-200 focus:ring-rose-500 border border-rose-600',
|
||||
success:
|
||||
'bg-emerald-600 hover:bg-emerald-700 text-white shadow-sm shadow-emerald-200 focus:ring-emerald-500 border border-emerald-600',
|
||||
warning:
|
||||
'bg-amber-500 hover:bg-amber-600 text-white shadow-sm shadow-amber-200 focus:ring-amber-400 border border-amber-500',
|
||||
outline:
|
||||
'bg-white hover:bg-gray-50 text-gray-700 border border-gray-300 focus:ring-indigo-500',
|
||||
ghost:
|
||||
'bg-transparent hover:bg-gray-100 text-gray-600 focus:ring-gray-300 border border-transparent',
|
||||
};
|
||||
|
||||
const iconSizes: Record<ButtonSize, string> = {
|
||||
xs: 'w-3 h-3',
|
||||
sm: 'w-3.5 h-3.5',
|
||||
md: 'w-4 h-4',
|
||||
lg: 'w-5 h-5',
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
disabled={disabled || isLoading}
|
||||
className={`
|
||||
${baseClasses}
|
||||
${sizeClasses[size]}
|
||||
${variantClasses[variant]}
|
||||
${fullWidth ? 'w-full' : ''}
|
||||
${className}
|
||||
`}
|
||||
{...props}
|
||||
>
|
||||
{isLoading ? (
|
||||
<Spinner size={size === 'lg' ? 'md' : 'sm'} />
|
||||
) : (
|
||||
<>
|
||||
{StartIcon && <StartIcon className={iconSizes[size]} />}
|
||||
{children && <span>{children}</span>}
|
||||
{badge !== undefined && (
|
||||
<span className="px-1.5 py-0.5 rounded-full text-[10px] bg-white/20 text-current font-mono">
|
||||
{badge}
|
||||
</span>
|
||||
)}
|
||||
{EndIcon && <EndIcon className={iconSizes[size]} />}
|
||||
{info && (
|
||||
<span
|
||||
className="inline-flex items-center text-current/80 hover:text-current cursor-help ml-0.5"
|
||||
title={info}
|
||||
>
|
||||
<Info className="w-3.5 h-3.5" />
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
96
frontend/admin-panel/src/components/ui/MaskableField.tsx
Normal file
96
frontend/admin-panel/src/components/ui/MaskableField.tsx
Normal file
@ -0,0 +1,96 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Eye, EyeOff, Copy, Check } from 'lucide-react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
|
||||
interface MaskableFieldProps {
|
||||
value?: string | number | null;
|
||||
maskedValue?: string;
|
||||
isMaskedByDefault?: boolean;
|
||||
label?: string;
|
||||
copyable?: boolean;
|
||||
className?: string;
|
||||
valueClassName?: string;
|
||||
dir?: 'ltr' | 'rtl';
|
||||
}
|
||||
|
||||
export default function MaskableField({
|
||||
value,
|
||||
maskedValue,
|
||||
isMaskedByDefault = true,
|
||||
label,
|
||||
copyable = true,
|
||||
className = '',
|
||||
valueClassName = '',
|
||||
dir = 'ltr',
|
||||
}: MaskableFieldProps) {
|
||||
const [isRevealed, setIsRevealed] = useState(!isMaskedByDefault);
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
const rawVal = value !== undefined && value !== null ? String(value) : '';
|
||||
|
||||
// Create mask if not provided
|
||||
const generateMask = (str: string) => {
|
||||
if (!str) return '-';
|
||||
if (str.length <= 4) return '****';
|
||||
if (str.length === 16) {
|
||||
// 16-digit Card: 6037-99**-****-1234
|
||||
return `${str.slice(0, 4)}-${str.slice(4, 6)}**-****-${str.slice(12)}`;
|
||||
}
|
||||
const visibleStart = Math.min(4, Math.floor(str.length / 3));
|
||||
const visibleEnd = Math.min(4, Math.floor(str.length / 3));
|
||||
return `${str.slice(0, visibleStart)}${'*'.repeat(Math.max(4, str.length - visibleStart - visibleEnd))}${str.slice(-visibleEnd)}`;
|
||||
};
|
||||
|
||||
const displayMasked = maskedValue || generateMask(rawVal);
|
||||
const currentText = isRevealed ? (rawVal || '-') : displayMasked;
|
||||
|
||||
const handleCopy = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
if (!rawVal) return;
|
||||
navigator.clipboard.writeText(rawVal);
|
||||
setCopied(true);
|
||||
toast.success(`${label || 'مقدار'} در کلیپبورد کپی شد`);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`inline-flex items-center gap-1.5 ${className}`}>
|
||||
<span
|
||||
dir={dir}
|
||||
className={`font-mono text-xs select-all ${valueClassName}`}
|
||||
title={isRevealed ? 'مقدار واقعی' : 'مقدار پنهانشده'}
|
||||
>
|
||||
{currentText}
|
||||
</span>
|
||||
|
||||
{rawVal && (
|
||||
<div className="inline-flex items-center gap-1">
|
||||
{/* Toggle Eye Button */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setIsRevealed(!isRevealed);
|
||||
}}
|
||||
className="p-1 text-gray-400 hover:text-indigo-600 hover:bg-indigo-50 rounded-md transition-colors cursor-pointer"
|
||||
title={isRevealed ? 'پنهانسازی' : 'نمایش مقدار اصلی'}
|
||||
>
|
||||
{isRevealed ? <EyeOff className="w-3.5 h-3.5" /> : <Eye className="w-3.5 h-3.5" />}
|
||||
</button>
|
||||
|
||||
{/* Copy to Clipboard Button */}
|
||||
{copyable && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleCopy}
|
||||
className="p-1 text-gray-400 hover:text-emerald-600 hover:bg-emerald-50 rounded-md transition-colors cursor-pointer"
|
||||
title="کپی در کلیپبورد"
|
||||
>
|
||||
{copied ? <Check className="w-3.5 h-3.5 text-emerald-600" /> : <Copy className="w-3.5 h-3.5" />}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -22,12 +22,16 @@ import {
|
||||
CreditCard,
|
||||
ArrowUpDown,
|
||||
ArrowUp,
|
||||
ArrowDown
|
||||
ArrowDown,
|
||||
Undo2,
|
||||
Wallet,
|
||||
} from 'lucide-react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import api from '../services/api';
|
||||
import Skeleton from '../components/ui/Skeleton';
|
||||
import Spinner from '../components/ui/Spinner';
|
||||
import Pagination from '../components/ui/Pagination';
|
||||
import Button from '../components/ui/Button';
|
||||
|
||||
export interface OrderItem {
|
||||
id?: string;
|
||||
@ -269,16 +273,79 @@ export default function Orders() {
|
||||
setIsSavingTracking(true);
|
||||
await api.put(`/admin/orders/${selectedOrder.id}/status`, {
|
||||
status: modalStatus,
|
||||
trackingNumber: modalTrackingCode
|
||||
trackingNumber: modalTrackingCode,
|
||||
});
|
||||
await fetchOrders();
|
||||
toast.success('تغییرات سفارش با موفقیت ذخیره شد');
|
||||
} catch (err) {
|
||||
console.error('Failed to save tracking number', err);
|
||||
toast.error('خطا در ذخیره تغییرات سفارش');
|
||||
} finally {
|
||||
setIsSavingTracking(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Refund Order State & Handlers
|
||||
const [refundModalOrder, setRefundModalOrder] = useState<Order | null>(null);
|
||||
const [refundTarget, setRefundTarget] = useState<'wallet' | 'zibal'>('wallet');
|
||||
const [refundAmount, setRefundAmount] = useState<string>('');
|
||||
const [refundReason, setRefundReason] = useState<string>('');
|
||||
const [isProcessingRefund, setIsProcessingRefund] = useState(false);
|
||||
|
||||
const openOrderRefundModal = (order: Order) => {
|
||||
setRefundModalOrder(order);
|
||||
const amt = Number(order.totalAmount || order.total || 0);
|
||||
setRefundAmount(String(amt));
|
||||
// If order was paid by wallet, default to wallet. If online, let admin choose.
|
||||
setRefundTarget(order.paymentMethod === 'wallet' ? 'wallet' : 'zibal');
|
||||
setRefundReason(`استرداد سفارش #${order.trackingNumber || order.id.slice(0, 8)}`);
|
||||
};
|
||||
|
||||
const handleExecuteOrderRefund = async () => {
|
||||
if (!refundModalOrder) return;
|
||||
try {
|
||||
setIsProcessingRefund(true);
|
||||
if (refundTarget === 'wallet') {
|
||||
const res = await api.post(`/admin/orders/${refundModalOrder.id}/refund-wallet`, {
|
||||
amount: refundAmount ? Number(refundAmount) : undefined,
|
||||
reason: refundReason,
|
||||
});
|
||||
toast.success(res.data?.message || 'مبلغ با موفقیت به کیف پول کاربر عودت داده شد.');
|
||||
setRefundModalOrder(null);
|
||||
await fetchOrders();
|
||||
} else {
|
||||
// Find transaction trackId if exists
|
||||
const tx = refundModalOrder.paymentTransactions?.[0];
|
||||
const trackId = tx?.trackId;
|
||||
if (!trackId) {
|
||||
toast.error('شماره تراکنش زیبال (Track ID) برای این سفارش یافت نشد. لطفاً از گزینه کیف پول استفاده کنید.');
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await api.post('/payment/admin/refund', {
|
||||
trackId,
|
||||
amount: refundAmount ? Number(refundAmount) * 10 : undefined,
|
||||
tryReverse: true,
|
||||
description: refundReason || `استرداد وجه سفارش #${refundModalOrder.trackingNumber || refundModalOrder.id.slice(0, 8)}`,
|
||||
});
|
||||
|
||||
if (res.data?.result === 1 || res.data?.status === 1 || res.data?.success) {
|
||||
toast.success('درخواست استرداد وجه به درگاه زیبال با موفقیت ارسال شد.');
|
||||
// Also mark order as cancelled
|
||||
await api.put(`/admin/orders/${refundModalOrder.id}/status`, { status: 'cancelled' });
|
||||
setRefundModalOrder(null);
|
||||
await fetchOrders();
|
||||
} else {
|
||||
toast.error(res.data?.message || 'خطا در ارسال استرداد وجه به زیبال');
|
||||
}
|
||||
}
|
||||
} catch (err: any) {
|
||||
toast.error(err?.response?.data?.message || 'خطا در انجام عملیات استرداد وجه');
|
||||
} finally {
|
||||
setIsProcessingRefund(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePrintInvoice = (orderToPrint: Order) => {
|
||||
if (!orderToPrint) return;
|
||||
const printWindow = window.open('', '_blank');
|
||||
@ -649,24 +716,37 @@ export default function Orders() {
|
||||
</select>
|
||||
</td>
|
||||
<td className="py-4 px-6">
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<div className="flex items-center justify-center gap-1.5">
|
||||
<button
|
||||
onClick={() => openOrderModal(order)}
|
||||
className="text-purple-600 hover:bg-purple-50 p-2 rounded-xl transition-colors flex items-center gap-1 font-bold text-xs"
|
||||
className="text-purple-600 hover:bg-purple-50 p-2 rounded-xl transition-colors flex items-center gap-1 font-bold text-xs cursor-pointer"
|
||||
title="مشاهده فاکتور و جزئیات کامل"
|
||||
disabled={isProcessing}
|
||||
>
|
||||
<Eye className="w-4 h-4" />
|
||||
<span>جزئیات</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => handlePrintInvoice(order)}
|
||||
className="text-gray-600 hover:bg-gray-100 p-2 rounded-xl transition-colors"
|
||||
className="text-gray-600 hover:bg-gray-100 p-2 rounded-xl transition-colors cursor-pointer"
|
||||
title="چاپ فوری فاکتور رسمی"
|
||||
disabled={isProcessing}
|
||||
>
|
||||
<Printer className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
{(order.status === 'cancelled' || order.status === 'pending_payment') && (
|
||||
<button
|
||||
onClick={() => openOrderRefundModal(order)}
|
||||
className="text-rose-600 hover:bg-rose-50 p-2 rounded-xl transition-colors flex items-center gap-1 font-bold text-xs cursor-pointer"
|
||||
title="استرداد وجه به کاربر (کیف پول / شاپرک)"
|
||||
disabled={isProcessing}
|
||||
>
|
||||
<Undo2 className="w-4 h-4" />
|
||||
<span>استرداد</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -886,21 +966,142 @@ export default function Orders() {
|
||||
</div>
|
||||
|
||||
{/* Modal Footer */}
|
||||
<div className="p-6 bg-gray-50 border-t border-gray-200 flex gap-4 shrink-0">
|
||||
<button
|
||||
<div className="p-6 bg-gray-50 border-t border-gray-200 flex flex-wrap gap-3 shrink-0">
|
||||
<Button
|
||||
variant="primary"
|
||||
startIcon={Download}
|
||||
onClick={() => handlePrintInvoice(selectedOrder)}
|
||||
className="flex-1 py-3.5 bg-purple-600 text-white rounded-xl font-black text-sm flex items-center justify-center gap-2 hover:bg-purple-700 transition-all shadow-lg shadow-purple-600/20"
|
||||
className="flex-1"
|
||||
>
|
||||
<Download className="w-4 h-4" />
|
||||
دانلود و چاپ فاکتور رسمی
|
||||
</button>
|
||||
<button
|
||||
</Button>
|
||||
|
||||
{(selectedOrder.status === 'cancelled' || selectedOrder.status === 'pending_payment') && (
|
||||
<Button
|
||||
variant="danger"
|
||||
startIcon={Undo2}
|
||||
onClick={() => {
|
||||
const ord = selectedOrder;
|
||||
setSelectedOrder(null);
|
||||
openOrderRefundModal(ord);
|
||||
}}
|
||||
>
|
||||
استرداد وجه سفارش
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => setSelectedOrder(null)}
|
||||
className="px-6 py-3.5 bg-white border border-gray-200 text-gray-700 rounded-xl font-bold text-sm hover:bg-gray-100 transition-all"
|
||||
>
|
||||
بستن
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Order Refund Modal (Wallet / Zibal Gateway) */}
|
||||
{refundModalOrder && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm font-vazir" dir="rtl">
|
||||
<div className="bg-white rounded-3xl w-full max-w-lg border border-gray-200 shadow-2xl p-6 sm:p-8 space-y-5">
|
||||
<div className="flex items-center justify-between border-b border-gray-100 pb-4">
|
||||
<h3 className="text-base font-black text-gray-900 flex items-center gap-2">
|
||||
<Undo2 className="w-5 h-5 text-rose-600" />
|
||||
استرداد وجه سفارش #{refundModalOrder.trackingNumber || refundModalOrder.id.slice(0, 8)}
|
||||
</h3>
|
||||
<button
|
||||
onClick={() => setRefundModalOrder(null)}
|
||||
className="text-gray-400 hover:text-gray-700 font-bold text-lg cursor-pointer"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4 text-xs">
|
||||
{/* Destination selector */}
|
||||
<div>
|
||||
<label className="block font-bold text-gray-700 mb-2">روش عودت و بازگشت وجه:</label>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setRefundTarget('wallet')}
|
||||
className={`p-4 rounded-2xl border text-right transition-all cursor-pointer flex flex-col gap-1.5 ${
|
||||
refundTarget === 'wallet'
|
||||
? 'border-purple-600 bg-purple-50/60 ring-2 ring-purple-600/20'
|
||||
: 'border-gray-200 hover:border-gray-300'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-2 font-black text-gray-900">
|
||||
<Wallet className="w-4 h-4 text-purple-600" />
|
||||
<span>شارژ کیف پول کاربر</span>
|
||||
</div>
|
||||
<p className="text-[11px] text-gray-500 font-medium leading-relaxed">
|
||||
افزایش فوری اعتبار کیف پول جهت خریدهای بعدی مشتری
|
||||
</p>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setRefundTarget('zibal')}
|
||||
className={`p-4 rounded-2xl border text-right transition-all cursor-pointer flex flex-col gap-1.5 ${
|
||||
refundTarget === 'zibal'
|
||||
? 'border-rose-600 bg-rose-50/60 ring-2 ring-rose-600/20'
|
||||
: 'border-gray-200 hover:border-gray-300'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-2 font-black text-gray-900">
|
||||
<CreditCard className="w-4 h-4 text-rose-600" />
|
||||
<span>استرداد شاپرک (زیبال)</span>
|
||||
</div>
|
||||
<p className="text-[11px] text-gray-500 font-medium leading-relaxed">
|
||||
برگشت مستقیم به کارت بانکی مشتری از طریق درگاه پرداخت
|
||||
</p>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block font-bold text-gray-700 mb-1">مبلغ استرداد به تومان</label>
|
||||
<input
|
||||
type="number"
|
||||
value={refundAmount}
|
||||
onChange={(e) => setRefundAmount(e.target.value)}
|
||||
placeholder="مبلغ استرداد"
|
||||
className="w-full border border-gray-200 rounded-xl p-3 font-mono outline-none focus:ring-2 focus:ring-purple-500 font-bold"
|
||||
dir="ltr"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block font-bold text-gray-700 mb-1">علت استرداد</label>
|
||||
<textarea
|
||||
rows={2}
|
||||
value={refundReason}
|
||||
onChange={(e) => setRefundReason(e.target.value)}
|
||||
placeholder="علت لغو سفارش یا مرجوعی کالا..."
|
||||
className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-3 pt-3 border-t border-gray-100">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setRefundModalOrder(null)}
|
||||
>
|
||||
انصراف
|
||||
</Button>
|
||||
<Button
|
||||
variant={refundTarget === 'wallet' ? 'primary' : 'danger'}
|
||||
size="sm"
|
||||
isLoading={isProcessingRefund}
|
||||
onClick={handleExecuteOrderRefund}
|
||||
>
|
||||
{refundTarget === 'wallet' ? 'تایید و افزایش اعتبار کیف پول' : 'ارسال درخواست استرداد به زیبال'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -25,11 +25,15 @@ import {
|
||||
Code,
|
||||
Send,
|
||||
Undo2,
|
||||
Printer,
|
||||
} from 'lucide-react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import api from '../services/api';
|
||||
import Spinner from '../components/ui/Spinner';
|
||||
import Pagination from '../components/ui/Pagination';
|
||||
import Button from '../components/ui/Button';
|
||||
import MaskableField from '../components/ui/MaskableField';
|
||||
import TransactionReceiptModal, { type TransactionReceiptData } from '../components/TransactionReceiptModal';
|
||||
|
||||
interface Transaction {
|
||||
id: string;
|
||||
@ -114,8 +118,13 @@ export default function Transactions() {
|
||||
const [liveInquiryData, setLiveInquiryData] = useState<any>(null);
|
||||
const [showRawLogs, setShowRawLogs] = useState(false);
|
||||
|
||||
// Refund Modal State
|
||||
// Receipt Modal State
|
||||
const [receiptModalOpen, setReceiptModalOpen] = useState(false);
|
||||
const [receiptData, setReceiptData] = useState<TransactionReceiptData | null>(null);
|
||||
|
||||
// Refund Modal State & Confirmation
|
||||
const [refundModalOpen, setRefundModalOpen] = useState(false);
|
||||
const [refundConfirmOpen, setRefundConfirmOpen] = useState(false);
|
||||
const [refundForm, setRefundForm] = useState({
|
||||
trackId: '',
|
||||
amount: '',
|
||||
@ -125,6 +134,32 @@ export default function Transactions() {
|
||||
});
|
||||
const [isSubmittingRefund, setIsSubmittingRefund] = useState(false);
|
||||
|
||||
const openReceiptModal = (tx: Transaction) => {
|
||||
setReceiptData({
|
||||
trackId: tx.trackId || '-',
|
||||
refNumber: tx.refNumber || '-',
|
||||
amountTomans: tx.amount,
|
||||
amountRials: tx.amountRials || Number(tx.amount) * 10,
|
||||
statusText: tx.status === 'VERIFIED' ? 'پرداخت موفق' : tx.status === 'PENDING' ? 'در انتظار پرداخت' : 'ناموفق',
|
||||
orderNumber: tx.order?.orderNumber || (tx.orderId ? `سفارش ${tx.orderId.slice(0, 8)}` : '-'),
|
||||
orderId: tx.orderId || undefined,
|
||||
cardNumber: tx.cardNumber || '-',
|
||||
paidAt: tx.paidAt ? new Date(tx.paidAt).toLocaleDateString('fa-IR') : undefined,
|
||||
createdAt: new Date(tx.createdAt).toLocaleDateString('fa-IR', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
}),
|
||||
mobile: tx.user?.mobile || '-',
|
||||
description: tx.description || 'پرداخت سفارش آنلاین کنینا',
|
||||
psp: tx.gateway === 'zibal' ? 'زیبال / بهپرداخت ملت' : tx.gateway,
|
||||
ip: tx.ipAddress || '-',
|
||||
});
|
||||
setReceiptModalOpen(true);
|
||||
};
|
||||
|
||||
const openRefundModal = (tx: Transaction) => {
|
||||
setRefundForm({
|
||||
trackId: tx.trackId || '',
|
||||
@ -136,8 +171,7 @@ export default function Transactions() {
|
||||
setRefundModalOpen(true);
|
||||
};
|
||||
|
||||
const handleRefundSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
const executeRefund = async () => {
|
||||
if (!refundForm.trackId) {
|
||||
toast.error('شناسه تراکنش (Track ID) الزامی است');
|
||||
return;
|
||||
@ -154,6 +188,7 @@ export default function Transactions() {
|
||||
|
||||
if (res.data?.result === 1 || res.data?.status === 1 || res.data?.success) {
|
||||
toast.success(res.data?.message || 'درخواست استرداد وجه با موفقیت به زیبال ارسال شد.');
|
||||
setRefundConfirmOpen(false);
|
||||
setRefundModalOpen(false);
|
||||
fetchTransactions();
|
||||
fetchStats();
|
||||
@ -167,6 +202,16 @@ export default function Transactions() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleRefundSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!refundForm.trackId) {
|
||||
toast.error('شناسه تراکنش (Track ID) الزامی است');
|
||||
return;
|
||||
}
|
||||
// Open confirmation prompt modal
|
||||
setRefundConfirmOpen(true);
|
||||
};
|
||||
|
||||
const fetchStats = async () => {
|
||||
try {
|
||||
const res = await api.get('/payment/admin/stats');
|
||||
@ -656,12 +701,20 @@ export default function Transactions() {
|
||||
setLiveInquiryData(null);
|
||||
setShowRawLogs(false);
|
||||
}}
|
||||
className="p-2 bg-gray-100 hover:bg-purple-50 text-gray-600 hover:text-purple-600 rounded-xl transition-all"
|
||||
className="p-2 bg-gray-100 hover:bg-purple-50 text-gray-600 hover:text-purple-600 rounded-xl transition-all cursor-pointer"
|
||||
title="مشاهده جزئیات و عیبیابی"
|
||||
>
|
||||
<Eye className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => openReceiptModal(tx)}
|
||||
className="p-2 bg-emerald-50 hover:bg-emerald-100 text-emerald-600 rounded-xl transition-all cursor-pointer"
|
||||
title="رسید تراکنش و چاپ"
|
||||
>
|
||||
<Printer className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
{tx.gateway === 'zibal' && tx.trackId && (
|
||||
<button
|
||||
onClick={() => {
|
||||
@ -757,31 +810,47 @@ export default function Transactions() {
|
||||
|
||||
<div>
|
||||
<span className="text-gray-400 block font-medium">شناسه پیگیری (Track ID):</span>
|
||||
<span className="font-mono font-bold text-gray-900 dir-ltr inline-block">
|
||||
{selectedTx.trackId || 'ثبت نشده'}
|
||||
</span>
|
||||
<div className="mt-0.5">
|
||||
<MaskableField
|
||||
value={selectedTx.trackId}
|
||||
isMaskedByDefault={false}
|
||||
label="شناسه پیگیری"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="text-gray-400 block font-medium">شماره مرجع بانکی:</span>
|
||||
<span className="font-mono font-bold text-gray-900 dir-ltr inline-block">
|
||||
{selectedTx.refNumber || 'ثبت نشده'}
|
||||
</span>
|
||||
<div className="mt-0.5">
|
||||
<MaskableField
|
||||
value={selectedTx.refNumber}
|
||||
isMaskedByDefault={false}
|
||||
label="شماره مرجع بانکی"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="text-gray-400 block font-medium">شماره کارت ماسک شده:</span>
|
||||
<span className="font-mono font-bold text-gray-900 dir-ltr inline-block">
|
||||
{selectedTx.cardNumber || 'ثبت نشده'}
|
||||
</span>
|
||||
<span className="text-gray-400 block font-medium">شماره کارت:</span>
|
||||
<div className="mt-0.5">
|
||||
<MaskableField
|
||||
value={selectedTx.cardNumber}
|
||||
isMaskedByDefault={true}
|
||||
label="شماره کارت"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{selectedTx.ipAddress && (
|
||||
<div>
|
||||
<span className="text-gray-400 block font-medium">IP کلاینت:</span>
|
||||
<span className="font-mono font-bold text-gray-700 dir-ltr inline-block">
|
||||
{selectedTx.ipAddress}
|
||||
</span>
|
||||
<div className="mt-0.5">
|
||||
<MaskableField
|
||||
value={selectedTx.ipAddress}
|
||||
isMaskedByDefault={false}
|
||||
label="IP کلاینت"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -893,59 +962,86 @@ export default function Transactions() {
|
||||
|
||||
{/* Modal Actions */}
|
||||
<div className="flex items-center justify-between gap-3 pt-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
startIcon={Printer}
|
||||
onClick={() => {
|
||||
const tx = selectedTx;
|
||||
setSelectedTx(null);
|
||||
openReceiptModal(tx);
|
||||
}}
|
||||
>
|
||||
رسید و چاپ
|
||||
</Button>
|
||||
|
||||
{selectedTx.gateway !== 'zibal' && selectedTx.gateway !== 'online' && selectedTx.status !== 'VERIFIED' && (
|
||||
<button
|
||||
<Button
|
||||
type="button"
|
||||
variant="success"
|
||||
size="sm"
|
||||
startIcon={CheckCircle2}
|
||||
onClick={() => handleManualVerify(selectedTx.id)}
|
||||
className="bg-emerald-600 hover:bg-emerald-700 text-white font-black px-4 py-2.5 rounded-xl text-xs flex items-center gap-1.5 shadow-md shadow-emerald-600/20 transition-all cursor-pointer"
|
||||
>
|
||||
<CheckCircle2 className="w-4 h-4" />
|
||||
<span>تایید دستی واریز کارت به کارت</span>
|
||||
</button>
|
||||
تایید دستی کارت به کارت
|
||||
</Button>
|
||||
)}
|
||||
{selectedTx.gateway !== 'zibal' && selectedTx.gateway !== 'online' && selectedTx.status === 'PENDING' && (
|
||||
<button
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
startIcon={XCircle}
|
||||
className="text-rose-600 border-rose-200 hover:bg-rose-50"
|
||||
onClick={() => handleManualReject(selectedTx.id)}
|
||||
className="bg-rose-50 hover:bg-rose-100 text-rose-700 border border-rose-200 font-bold px-4 py-2.5 rounded-xl text-xs flex items-center gap-1.5 transition-all cursor-pointer"
|
||||
>
|
||||
<XCircle className="w-4 h-4" />
|
||||
<span>رد فیش کارت به کارت</span>
|
||||
</button>
|
||||
رد فیش
|
||||
</Button>
|
||||
)}
|
||||
{selectedTx.gateway === 'zibal' && selectedTx.trackId && selectedTx.status === 'VERIFIED' && (
|
||||
<button
|
||||
<Button
|
||||
type="button"
|
||||
variant="danger"
|
||||
size="sm"
|
||||
startIcon={Undo2}
|
||||
info="برگشت وجه به حساب یا کارت مشتری"
|
||||
onClick={() => {
|
||||
const tx = selectedTx;
|
||||
setSelectedTx(null);
|
||||
openRefundModal(tx);
|
||||
}}
|
||||
className="bg-rose-600 hover:bg-rose-700 text-white font-black px-4 py-2.5 rounded-xl text-xs flex items-center gap-1.5 shadow-md shadow-rose-600/20 transition-all cursor-pointer"
|
||||
>
|
||||
<Undo2 className="w-4 h-4" />
|
||||
<span>استرداد وجه به مشتری (Refund / Reverse)</span>
|
||||
</button>
|
||||
استرداد وجه
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setSelectedTx(null);
|
||||
setLiveInquiryData(null);
|
||||
setShowRawLogs(false);
|
||||
}}
|
||||
className="bg-gray-100 hover:bg-gray-200 text-gray-800 font-bold px-6 py-2.5 rounded-xl text-xs transition-colors cursor-pointer"
|
||||
>
|
||||
بستن
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Refund Submission Modal */}
|
||||
{/* Transaction Receipt Modal */}
|
||||
<TransactionReceiptModal
|
||||
isOpen={receiptModalOpen}
|
||||
onClose={() => setReceiptModalOpen(false)}
|
||||
data={receiptData}
|
||||
/>
|
||||
|
||||
{/* Refund Submission Form Modal */}
|
||||
{refundModalOpen && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm">
|
||||
<div className="bg-white rounded-3xl w-full max-w-lg border border-gray-200 shadow-2xl p-6 sm:p-8 space-y-6">
|
||||
@ -1025,26 +1121,87 @@ export default function Transactions() {
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-3 pt-3">
|
||||
<button
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setRefundModalOpen(false)}
|
||||
className="px-5 py-2.5 rounded-xl font-bold bg-gray-100 hover:bg-gray-200 text-gray-600 cursor-pointer"
|
||||
>
|
||||
انصراف
|
||||
</button>
|
||||
<button
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isSubmittingRefund}
|
||||
className="bg-rose-600 hover:bg-rose-700 text-white font-bold px-6 py-2.5 rounded-xl transition-colors flex items-center gap-2 cursor-pointer shadow-md shadow-rose-200"
|
||||
variant="danger"
|
||||
size="sm"
|
||||
startIcon={Send}
|
||||
>
|
||||
{isSubmittingRefund ? <Spinner size="sm" /> : <Send className="w-4 h-4" />}
|
||||
<span>ارسال استرداد وجه به زیبال</span>
|
||||
</button>
|
||||
بررسی و تایید نهایی استرداد
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Confirmation Modal Before Sending Refund */}
|
||||
{refundConfirmOpen && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm">
|
||||
<div className="bg-white rounded-3xl w-full max-w-md border border-gray-200 shadow-2xl p-6 sm:p-8 space-y-6 font-vazir" dir="rtl">
|
||||
<div className="flex items-center gap-3 text-rose-600">
|
||||
<div className="w-12 h-12 bg-rose-50 rounded-2xl flex items-center justify-center">
|
||||
<AlertTriangle className="w-6 h-6" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-base font-black text-gray-900">تایید عملیات استرداد وجه شاپرک</h3>
|
||||
<p className="text-xs text-gray-500 mt-0.5">آیا از ارسال درخواست استرداد زیر به زیبال اطمینان دارید؟</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-rose-50/60 border border-rose-100 rounded-2xl p-4 space-y-2 text-xs">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-500 font-bold">شماره تراکنش:</span>
|
||||
<span className="font-mono font-black text-gray-900">{refundForm.trackId}</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-500 font-bold">مبلغ استرداد:</span>
|
||||
<span className="font-mono font-black text-rose-700">
|
||||
{refundForm.amount ? `${Number(refundForm.amount).toLocaleString('fa-IR')} تومان` : 'کل مبلغ تراکنش'}
|
||||
</span>
|
||||
</div>
|
||||
{refundForm.cardNumber && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-500 font-bold">کارت مقصد:</span>
|
||||
<span className="font-mono font-bold text-gray-800">{refundForm.cardNumber}</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-500 font-bold">روش بازگشت:</span>
|
||||
<span className="font-bold text-gray-900">
|
||||
{refundForm.tryReverse ? 'برگشت آنی شاپرک (Reverse)' : 'واریز پایا بانکی (Refund)'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-3 pt-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setRefundConfirmOpen(false)}
|
||||
>
|
||||
بازگشت و ویرایش
|
||||
</Button>
|
||||
<Button
|
||||
variant="danger"
|
||||
size="sm"
|
||||
isLoading={isSubmittingRefund}
|
||||
onClick={executeRefund}
|
||||
>
|
||||
تایید قطعی و ارسال به زیبال
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -319,53 +319,53 @@ export default function ZibalPortalPage() {
|
||||
</div>
|
||||
|
||||
{/* Main Feature Tabs (Matching Zibal Panel layout) */}
|
||||
<div className="bg-white p-2 rounded-2xl shadow-sm border border-gray-200 flex items-center justify-between overflow-x-auto gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="bg-white p-2 rounded-2xl shadow-sm border border-gray-200 flex items-center justify-between overflow-x-auto gap-2 no-scrollbar">
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
<button
|
||||
onClick={() => setActiveMainTab('refunds')}
|
||||
className={`px-5 py-2.5 rounded-xl font-black text-xs sm:text-sm transition-all flex items-center gap-2 cursor-pointer ${
|
||||
className={`px-5 py-2.5 rounded-xl font-black text-xs sm:text-sm transition-all flex items-center gap-2 cursor-pointer whitespace-nowrap ${
|
||||
activeMainTab === 'refunds'
|
||||
? 'bg-indigo-600 text-white shadow-md shadow-indigo-200'
|
||||
: 'text-gray-600 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<RotateCcw className="w-4 h-4" />
|
||||
<RotateCcw className="w-4 h-4 shrink-0" />
|
||||
<span>استرداد وجه</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setActiveMainTab('checkouts')}
|
||||
className={`px-5 py-2.5 rounded-xl font-black text-xs sm:text-sm transition-all flex items-center gap-2 cursor-pointer ${
|
||||
className={`px-5 py-2.5 rounded-xl font-black text-xs sm:text-sm transition-all flex items-center gap-2 cursor-pointer whitespace-nowrap ${
|
||||
activeMainTab === 'checkouts'
|
||||
? 'bg-indigo-600 text-white shadow-md shadow-indigo-200'
|
||||
: 'text-gray-600 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<CreditCard className="w-4 h-4" />
|
||||
<CreditCard className="w-4 h-4 shrink-0" />
|
||||
<span>گزارش واریز و تسویه</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setActiveMainTab('queue')}
|
||||
className={`px-5 py-2.5 rounded-xl font-black text-xs sm:text-sm transition-all flex items-center gap-2 cursor-pointer ${
|
||||
className={`px-5 py-2.5 rounded-xl font-black text-xs sm:text-sm transition-all flex items-center gap-2 cursor-pointer whitespace-nowrap ${
|
||||
activeMainTab === 'queue'
|
||||
? 'bg-indigo-600 text-white shadow-md shadow-indigo-200'
|
||||
: 'text-gray-600 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<ListOrdered className="w-4 h-4" />
|
||||
<ListOrdered className="w-4 h-4 shrink-0" />
|
||||
<span>صف تسویه</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setActiveMainTab('gateway_transactions')}
|
||||
className={`px-5 py-2.5 rounded-xl font-black text-xs sm:text-sm transition-all flex items-center gap-2 cursor-pointer ${
|
||||
className={`px-5 py-2.5 rounded-xl font-black text-xs sm:text-sm transition-all flex items-center gap-2 cursor-pointer whitespace-nowrap ${
|
||||
activeMainTab === 'gateway_transactions'
|
||||
? 'bg-indigo-600 text-white shadow-md shadow-indigo-200'
|
||||
: 'text-gray-600 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<TrendingUp className="w-4 h-4" />
|
||||
<TrendingUp className="w-4 h-4 shrink-0" />
|
||||
<span>تراکنشهای درگاه (IPG)</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
"3": "app.module.ts",
|
||||
"4": "reviews.controller.ts",
|
||||
"5": "tickets.controller.ts",
|
||||
"6": "userStore.ts",
|
||||
"6": "AuthService",
|
||||
"7": "MediaSelector.tsx",
|
||||
"8": "PetProfile.tsx",
|
||||
"9": "Roles",
|
||||
@ -13,12 +13,12 @@
|
||||
"11": "MenuService",
|
||||
"12": "adminRoutes.tsx",
|
||||
"13": "PrismaService",
|
||||
"14": "PetsController",
|
||||
"14": "pets/pets.controller.ts",
|
||||
"15": "ProductsService",
|
||||
"16": "UserDashboard.tsx",
|
||||
"17": "CreateVideoDto",
|
||||
"18": "src/services/api.ts",
|
||||
"19": "auth.controller.ts",
|
||||
"19": ".adminLogin",
|
||||
"20": "BE-001",
|
||||
"21": "SmsService",
|
||||
"22": "FE-001",
|
||||
@ -36,7 +36,7 @@
|
||||
"34": "CategoriesController",
|
||||
"35": "B2BService",
|
||||
"36": "What You Must Do When Invoked",
|
||||
"37": "useSettingsStore",
|
||||
"37": ".update",
|
||||
"38": "UsersService",
|
||||
"39": "What You Must Do When Invoked",
|
||||
"40": "SslController",
|
||||
@ -44,28 +44,28 @@
|
||||
"42": "IngredientsService",
|
||||
"43": "FaqService",
|
||||
"44": "MediaController",
|
||||
"45": "Media.tsx",
|
||||
"45": "Coupons.tsx",
|
||||
"46": "ContactService",
|
||||
"47": "zibal.service.ts",
|
||||
"48": "PrescriptionsService",
|
||||
"49": "SmartAdvisorService",
|
||||
"50": "TestimonialsService",
|
||||
"51": "Role & Core Objective",
|
||||
"52": ".initiateOrderPayment",
|
||||
"52": ".handleZibalCallback",
|
||||
"53": "ZibalEBankService",
|
||||
"54": "compilerOptions",
|
||||
"55": "PrescriptionsManager.tsx",
|
||||
"55": "Media.tsx",
|
||||
"56": "compilerOptions",
|
||||
"57": "PetsController",
|
||||
"58": "PaginationDto",
|
||||
"59": "dependencies",
|
||||
"60": "compilerOptions",
|
||||
"61": "ArchivePage.tsx",
|
||||
"61": "HomeClient.tsx",
|
||||
"62": "BlogsController",
|
||||
"63": "ApiOperation",
|
||||
"64": "BannersService",
|
||||
"65": "Required Review Group Closures",
|
||||
"66": "Coupons.tsx",
|
||||
"66": "Products.tsx",
|
||||
"67": "Operational Rules & Boundaries",
|
||||
"68": "Operational Rules & Boundaries",
|
||||
"69": "WikiController",
|
||||
@ -78,10 +78,10 @@
|
||||
"76": "Operational Rules & Boundaries",
|
||||
"77": "scripts",
|
||||
"78": "Role & Core Objective",
|
||||
"79": "HomeController",
|
||||
"80": "B2BPortal.tsx",
|
||||
"79": "Transactions.tsx",
|
||||
"80": "SafeImage.tsx",
|
||||
"81": "devDependencies",
|
||||
"82": "api",
|
||||
"82": "auth.controller.ts",
|
||||
"83": "Orders.tsx",
|
||||
"84": "devDependencies",
|
||||
"85": "seed-products.ts",
|
||||
@ -101,9 +101,9 @@
|
||||
"99": "Comprehensive Change Log",
|
||||
"100": "Operational Rules & Boundaries",
|
||||
"101": "UITexts.tsx",
|
||||
"102": "BlogsController",
|
||||
"103": "AdminTransactionFilterDto",
|
||||
"104": "CreateOrderDto",
|
||||
"102": "ApiResponse",
|
||||
"103": "payment.service.ts",
|
||||
"104": "PetsService",
|
||||
"105": "1. Summary of Integrity Repairs Performed",
|
||||
"106": "@nestjs/cli",
|
||||
"107": "Operational Rules & Boundaries",
|
||||
@ -140,9 +140,9 @@
|
||||
"138": "InitiatePaymentDto",
|
||||
"139": "System Discovery",
|
||||
"140": "Product Requirement Document (PRD)",
|
||||
"141": "WikiController",
|
||||
"142": "useCartStore",
|
||||
"143": "RedisService",
|
||||
"141": "PetsController",
|
||||
"142": "lib/services/api.ts",
|
||||
"143": "auth.service.ts",
|
||||
"144": "Baseline Command Plan & Reconciled Command History",
|
||||
"145": "catalog/page.tsx",
|
||||
"146": "ErrorPages.tsx",
|
||||
@ -173,7 +173,7 @@
|
||||
"171": "🎨 Frontend & Admin Panel Technical Review (06_dev_frontend)",
|
||||
"172": "🚀 SEO & Content Strategy Review (12_seo_content)",
|
||||
"173": "@types/node",
|
||||
"174": "shop/page.tsx",
|
||||
"174": "MetricsController",
|
||||
"175": "seed-ui-texts.ts",
|
||||
"176": "seed-wiki.ts",
|
||||
"177": "update-blog.dto.ts",
|
||||
@ -185,7 +185,7 @@
|
||||
"183": "Raw Finding Verification & Disposition Report",
|
||||
"184": "React + TypeScript + Vite",
|
||||
"185": "Select.tsx",
|
||||
"186": "Reports.tsx",
|
||||
"186": "RegisterDto",
|
||||
"187": "ts-node",
|
||||
"188": "application/README.md",
|
||||
"189": "@types/express",
|
||||
@ -213,14 +213,14 @@
|
||||
"211": "@types/multer",
|
||||
"212": "videos/page.tsx",
|
||||
"213": "@testing-library/jest-dom",
|
||||
"214": "checkout/page.tsx",
|
||||
"214": "AdminLoginDto",
|
||||
"215": "AdminController",
|
||||
"216": "FormField.tsx",
|
||||
"217": "Input.tsx",
|
||||
"218": "Textarea.tsx",
|
||||
"219": "admin-panel/tsconfig.json",
|
||||
"220": "getPageMetadata",
|
||||
"221": "AuthService",
|
||||
"221": "AuthController",
|
||||
"222": "next.config.ts",
|
||||
"223": "Shabnam Font README",
|
||||
"224": "AGENTS.md",
|
||||
@ -237,10 +237,10 @@
|
||||
"235": "typescript",
|
||||
"236": "vitest",
|
||||
"237": "axios",
|
||||
"238": ".createCoupon",
|
||||
"238": "Body",
|
||||
"239": "WholesaleApplyDto",
|
||||
"240": "ts-loader",
|
||||
"241": "zibal-ebank.service.ts",
|
||||
"241": "VerifyOtpDto",
|
||||
"242": "@types/bcrypt",
|
||||
"243": "app.e2e-spec.js",
|
||||
"244": "blog.entity.ts",
|
||||
@ -290,13 +290,18 @@
|
||||
"288": "Staging Docker Compose",
|
||||
"289": "tailwindcss",
|
||||
"290": "@types/passport-jwt",
|
||||
"291": "ClientLayout.tsx",
|
||||
"291": "useSettingsStore",
|
||||
"292": "@types/supertest",
|
||||
"293": "typescript",
|
||||
"294": "app-audit-verification.e2e-spec.d.ts",
|
||||
"295": "app.e2e-spec.d.ts",
|
||||
"296": "@types/react-dom",
|
||||
"297": "CreateHealthLogDto",
|
||||
"298": "eslint-config-prettier",
|
||||
"299": "CreateReminderDto",
|
||||
"300": ".sendOtp",
|
||||
"301": "track/page.tsx",
|
||||
"302": "dashboard/page.tsx",
|
||||
"303": "eslint-plugin-prettier",
|
||||
"305": "RouteErrorBoundary",
|
||||
"309": "globals",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -15,12 +15,12 @@
|
||||
"13": "PrismaService",
|
||||
"14": "PetsController",
|
||||
"15": "ProductsService",
|
||||
"16": "useUserStore",
|
||||
"16": "UserDashboard.tsx",
|
||||
"17": "CreateVideoDto",
|
||||
"18": "src/services/api.ts",
|
||||
"19": "auth.controller.ts",
|
||||
"20": "BE-001",
|
||||
"21": "SettingsController",
|
||||
"21": "SmsService",
|
||||
"22": "FE-001",
|
||||
"23": "ADM-001",
|
||||
"24": "DB-001",
|
||||
@ -28,7 +28,7 @@
|
||||
"26": "TEST-001",
|
||||
"27": "DEVOPS-001",
|
||||
"28": "DOC-001",
|
||||
"29": "WholesaleApplyDto",
|
||||
"29": "WholesaleService",
|
||||
"30": "app-audit-verification.e2e-spec.js",
|
||||
"31": "JwtAuthGuard",
|
||||
"32": "ZibalService",
|
||||
@ -47,7 +47,7 @@
|
||||
"45": "Media.tsx",
|
||||
"46": "ContactService",
|
||||
"47": "zibal.service.ts",
|
||||
"48": "PrescriptionsController",
|
||||
"48": "PrescriptionsService",
|
||||
"49": "SmartAdvisorService",
|
||||
"50": "TestimonialsService",
|
||||
"51": "Role & Core Objective",
|
||||
@ -62,7 +62,7 @@
|
||||
"60": "compilerOptions",
|
||||
"61": "ArchivePage.tsx",
|
||||
"62": "BlogsController",
|
||||
"63": "SmsService",
|
||||
"63": "ApiOperation",
|
||||
"64": "BannersService",
|
||||
"65": "Required Review Group Closures",
|
||||
"66": "Coupons.tsx",
|
||||
@ -103,7 +103,7 @@
|
||||
"101": "UITexts.tsx",
|
||||
"102": "BlogsController",
|
||||
"103": "AdminTransactionFilterDto",
|
||||
"104": "prescriptions.controller.ts",
|
||||
"104": "CreateOrderDto",
|
||||
"105": "1. Summary of Integrity Repairs Performed",
|
||||
"106": "@nestjs/cli",
|
||||
"107": "Operational Rules & Boundaries",
|
||||
@ -142,7 +142,7 @@
|
||||
"140": "Product Requirement Document (PRD)",
|
||||
"141": "WikiController",
|
||||
"142": "useCartStore",
|
||||
"143": "auth.service.ts",
|
||||
"143": "RedisService",
|
||||
"144": "Baseline Command Plan & Reconciled Command History",
|
||||
"145": "catalog/page.tsx",
|
||||
"146": "ErrorPages.tsx",
|
||||
@ -214,12 +214,13 @@
|
||||
"212": "videos/page.tsx",
|
||||
"213": "@testing-library/jest-dom",
|
||||
"214": "checkout/page.tsx",
|
||||
"215": "eslint-config-next",
|
||||
"215": "AdminController",
|
||||
"216": "FormField.tsx",
|
||||
"217": "Input.tsx",
|
||||
"218": "Textarea.tsx",
|
||||
"219": "admin-panel/tsconfig.json",
|
||||
"220": "getPageMetadata",
|
||||
"221": "AuthService",
|
||||
"222": "next.config.ts",
|
||||
"223": "Shabnam Font README",
|
||||
"224": "AGENTS.md",
|
||||
@ -230,12 +231,16 @@
|
||||
"229": "eslint-plugin-react-refresh",
|
||||
"230": "@tailwindcss/postcss",
|
||||
"231": "typescript",
|
||||
"232": "ProductDto",
|
||||
"233": "@testing-library/react",
|
||||
"234": "@types/react",
|
||||
"235": "typescript",
|
||||
"236": "vitest",
|
||||
"237": "axios",
|
||||
"238": ".createCoupon",
|
||||
"239": "WholesaleApplyDto",
|
||||
"240": "ts-loader",
|
||||
"241": "zibal-ebank.service.ts",
|
||||
"242": "@types/bcrypt",
|
||||
"243": "app.e2e-spec.js",
|
||||
"244": "blog.entity.ts",
|
||||
@ -290,6 +295,7 @@
|
||||
"293": "typescript",
|
||||
"294": "app-audit-verification.e2e-spec.d.ts",
|
||||
"295": "app.e2e-spec.d.ts",
|
||||
"296": "@types/react-dom",
|
||||
"298": "eslint-config-prettier",
|
||||
"303": "eslint-plugin-prettier",
|
||||
"305": "RouteErrorBoundary",
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
# Graph Report - canina (2026-08-22)
|
||||
|
||||
## Corpus Check
|
||||
- 536 files · ~759,121 words
|
||||
- 536 files · ~759,763 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
- 3887 nodes · 6840 edges · 297 communities (197 shown, 100 thin omitted)
|
||||
- 3887 nodes · 6841 edges · 303 communities (203 shown, 100 thin omitted)
|
||||
- Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 261 edges (avg confidence: 0.79)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Graph Freshness
|
||||
- Built from commit: `bf41ba03`
|
||||
- Built from commit: `ee32b4c1`
|
||||
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
|
||||
- Run `graphify update .` after code changes (no API cost).
|
||||
|
||||
@ -31,12 +31,12 @@
|
||||
- PrismaService
|
||||
- PetsController
|
||||
- ProductsService
|
||||
- useUserStore
|
||||
- UserDashboard.tsx
|
||||
- CreateVideoDto
|
||||
- src/services/api.ts
|
||||
- auth.controller.ts
|
||||
- BE-001
|
||||
- SettingsController
|
||||
- SmsService
|
||||
- FE-001
|
||||
- ADM-001
|
||||
- DB-001
|
||||
@ -44,7 +44,7 @@
|
||||
- TEST-001
|
||||
- DEVOPS-001
|
||||
- DOC-001
|
||||
- WholesaleApplyDto
|
||||
- WholesaleService
|
||||
- app-audit-verification.e2e-spec.js
|
||||
- JwtAuthGuard
|
||||
- ZibalService
|
||||
@ -63,7 +63,7 @@
|
||||
- Media.tsx
|
||||
- ContactService
|
||||
- zibal.service.ts
|
||||
- PrescriptionsController
|
||||
- PrescriptionsService
|
||||
- SmartAdvisorService
|
||||
- TestimonialsService
|
||||
- Role & Core Objective
|
||||
@ -78,7 +78,7 @@
|
||||
- compilerOptions
|
||||
- ArchivePage.tsx
|
||||
- BlogsController
|
||||
- SmsService
|
||||
- ApiOperation
|
||||
- BannersService
|
||||
- Required Review Group Closures
|
||||
- Coupons.tsx
|
||||
@ -119,7 +119,7 @@
|
||||
- UITexts.tsx
|
||||
- BlogsController
|
||||
- AdminTransactionFilterDto
|
||||
- prescriptions.controller.ts
|
||||
- CreateOrderDto
|
||||
- 1. Summary of Integrity Repairs Performed
|
||||
- @nestjs/cli
|
||||
- Operational Rules & Boundaries
|
||||
@ -158,7 +158,7 @@
|
||||
- Product Requirement Document (PRD)
|
||||
- WikiController
|
||||
- useCartStore
|
||||
- auth.service.ts
|
||||
- RedisService
|
||||
- Baseline Command Plan & Reconciled Command History
|
||||
- catalog/page.tsx
|
||||
- ErrorPages.tsx
|
||||
@ -230,12 +230,13 @@
|
||||
- videos/page.tsx
|
||||
- @testing-library/jest-dom
|
||||
- checkout/page.tsx
|
||||
- eslint-config-next
|
||||
- AdminController
|
||||
- FormField.tsx
|
||||
- Input.tsx
|
||||
- Textarea.tsx
|
||||
- admin-panel/tsconfig.json
|
||||
- getPageMetadata
|
||||
- AuthService
|
||||
- next.config.ts
|
||||
- Shabnam Font README
|
||||
- AGENTS.md
|
||||
@ -246,11 +247,15 @@
|
||||
- eslint-plugin-react-refresh
|
||||
- @tailwindcss/postcss
|
||||
- typescript
|
||||
- ProductDto
|
||||
- @testing-library/react
|
||||
- @types/react
|
||||
- typescript
|
||||
- vitest
|
||||
- .createCoupon
|
||||
- WholesaleApplyDto
|
||||
- ts-loader
|
||||
- zibal-ebank.service.ts
|
||||
- @types/bcrypt
|
||||
- app.e2e-spec.js
|
||||
- blog.entity.ts
|
||||
@ -289,6 +294,7 @@
|
||||
- ClientLayout.tsx
|
||||
- @types/supertest
|
||||
- typescript
|
||||
- @types/react-dom
|
||||
- eslint-config-prettier
|
||||
- eslint-plugin-prettier
|
||||
- RouteErrorBoundary
|
||||
@ -329,23 +335,23 @@
|
||||
- **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]
|
||||
|
||||
## Communities (297 total, 100 thin omitted)
|
||||
## Communities (303 total, 100 thin omitted)
|
||||
|
||||
### Community 0 - "OrdersService"
|
||||
Cohesion: 0.06
|
||||
Nodes (35): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+27 more)
|
||||
Cohesion: 0.10
|
||||
Nodes (18): OrdersController, ApiBadRequestResponse, ApiBearerAuth, ApiCreatedResponse, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags (+10 more)
|
||||
|
||||
### Community 1 - "productService.ts"
|
||||
Cohesion: 0.08
|
||||
Nodes (29): BlogPost, CatalogPageSpread(), CatalogPageSpreadProps, CategoryMeta, getFormBadge(), getSpeciesBadge(), FlipbookCatalog(), FlipbookCatalogProps (+21 more)
|
||||
Cohesion: 0.09
|
||||
Nodes (26): BlogPost, CatalogPageSpread(), CatalogPageSpreadProps, CategoryMeta, getFormBadge(), getSpeciesBadge(), FlipbookCatalog(), FlipbookCatalogProps (+18 more)
|
||||
|
||||
### Community 2 - "CmsController"
|
||||
Cohesion: 0.09
|
||||
Nodes (24): CmsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+16 more)
|
||||
|
||||
### Community 3 - "app.module.ts"
|
||||
Cohesion: 0.08
|
||||
Nodes (32): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+24 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (34): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+26 more)
|
||||
|
||||
### Community 4 - "reviews.controller.ts"
|
||||
Cohesion: 0.07
|
||||
@ -364,8 +370,8 @@ Cohesion: 0.08
|
||||
Nodes (26): ConfirmModal(), ConfirmModalProps, ImagePreviewModal(), ImagePreviewModalProps, getFileType(), Media, MediaSelector(), MediaSelectorProps (+18 more)
|
||||
|
||||
### Community 8 - "PetProfile.tsx"
|
||||
Cohesion: 0.13
|
||||
Nodes (17): CheckoutPage(), FeaturedProducts(), ProductCard(), PetProfile(), SearchResultsPage(), OrderRowSkeleton(), PetProfileSkeleton(), ProductCardSkeleton() (+9 more)
|
||||
Cohesion: 0.12
|
||||
Nodes (19): CheckoutPage(), FeaturedProducts(), ProductCard(), PetProfile(), PrescriptionUploadModal(), PrescriptionUploadModalProps, SearchResultsPage(), OrderRowSkeleton() (+11 more)
|
||||
|
||||
### Community 9 - "Roles"
|
||||
Cohesion: 0.24
|
||||
@ -384,8 +390,8 @@ Cohesion: 0.09
|
||||
Nodes (16): App(), HeroBanner, VetTestimonial, ContactInfoItem, ContactSubmission, CategoryDist, DashboardData, Ticket (+8 more)
|
||||
|
||||
### Community 13 - "PrismaService"
|
||||
Cohesion: 0.07
|
||||
Nodes (20): CategoryQuery, MeliPayamakPattern, MeliPayamakResponse, SendPatternSmsOptions, SmsConfig, SmsLogQuery, CreateContactSubmissionDto, UpdateContactInfoItemDto (+12 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (18): CategoryQuery, AdminLoginInput, LoginInput, RegisterInput, MeliPayamakPattern, MeliPayamakResponse, SendPatternSmsOptions, SmsConfig (+10 more)
|
||||
|
||||
### Community 14 - "PetsController"
|
||||
Cohesion: 0.05
|
||||
@ -395,9 +401,9 @@ Nodes (47): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, Is
|
||||
Cohesion: 0.09
|
||||
Nodes (19): GetProductsDto, ApiPropertyOptional, IsEnum, IsOptional, IsString, ProductsController, ApiOperation, ApiTags (+11 more)
|
||||
|
||||
### Community 16 - "useUserStore"
|
||||
Cohesion: 0.12
|
||||
Nodes (23): VerifyContent(), AddressModal(), AddressModalProps, AuthModal(), AuthModalProps, extractOtpFromText(), BackButton(), BackButtonProps (+15 more)
|
||||
### Community 16 - "UserDashboard.tsx"
|
||||
Cohesion: 0.10
|
||||
Nodes (30): VerifyContent(), AddressModal(), AddressModalProps, AuthModal(), AuthModalProps, extractOtpFromText(), BackButton(), BackButtonProps (+22 more)
|
||||
|
||||
### Community 17 - "CreateVideoDto"
|
||||
Cohesion: 0.07
|
||||
@ -415,9 +421,9 @@ Nodes (42): AuthController, ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse,
|
||||
Cohesion: 0.06
|
||||
Nodes (32): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, BE-001, Category, Completion Statement, Confidence (+24 more)
|
||||
|
||||
### Community 21 - "SettingsController"
|
||||
Cohesion: 0.08
|
||||
Nodes (24): SmsLogQueryDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type, SettingsController (+16 more)
|
||||
### Community 21 - "SmsService"
|
||||
Cohesion: 0.06
|
||||
Nodes (27): SmsLogQuery, SmsService, Injectable, SmsLogQueryDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional (+19 more)
|
||||
|
||||
### Community 22 - "FE-001"
|
||||
Cohesion: 0.06
|
||||
@ -447,17 +453,17 @@ Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternati
|
||||
Cohesion: 0.06
|
||||
Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more)
|
||||
|
||||
### Community 29 - "WholesaleApplyDto"
|
||||
Cohesion: 0.10
|
||||
Nodes (20): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto, ApiBearerAuth, ApiOperation (+12 more)
|
||||
### Community 29 - "WholesaleService"
|
||||
Cohesion: 0.14
|
||||
Nodes (14): ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param, Post (+6 more)
|
||||
|
||||
### Community 30 - "app-audit-verification.e2e-spec.js"
|
||||
Cohesion: 0.07
|
||||
Nodes (22): AppModule, Module, CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable (+14 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (20): CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable, ApiErrorResponse, ErrorDetailField (+12 more)
|
||||
|
||||
### Community 31 - "JwtAuthGuard"
|
||||
Cohesion: 0.20
|
||||
Nodes (6): JwtAuthGuard, Injectable, ROLES_KEY, RequestWithUser, RolesGuard, Injectable
|
||||
Nodes (7): JwtAuthGuard, Injectable, ROLES_KEY, RequestWithUser, RolesGuard, Injectable, UserReqPayload
|
||||
|
||||
### Community 32 - "ZibalService"
|
||||
Cohesion: 0.09
|
||||
@ -480,8 +486,8 @@ Cohesion: 0.07
|
||||
Nodes (26): For /graphify add and --watch, For /graphify query, For the commit hook and native CLAUDE.md integration, For --update and --cluster-only, /graphify, Honesty Rules, Interpreter guard for subcommands, Part A - Structural extraction for code files (+18 more)
|
||||
|
||||
### Community 37 - "useSettingsStore"
|
||||
Cohesion: 0.08
|
||||
Nodes (33): HomeClient(), BlogPost, BlogPreviewSection(), ContactInfoItem, DeleteConfirmModal(), DeleteConfirmModalProps, EnamadBadge(), FAQItem (+25 more)
|
||||
Cohesion: 0.09
|
||||
Nodes (29): HomeClient(), HomeClientProps, BlogPost, BlogPreviewSection(), ContactInfoItem, EnamadBadge(), FAQItem, FAQSection() (+21 more)
|
||||
|
||||
### Community 38 - "UsersService"
|
||||
Cohesion: 0.06
|
||||
@ -523,9 +529,9 @@ Nodes (11): ContactController, Body, Controller, Get, Param, Post, Put, Query (+
|
||||
Cohesion: 0.16
|
||||
Nodes (9): GatewayHealthResult, IPaymentGateway, PaymentInquiryResult, PaymentRequestOptions, PaymentRequestResult, PaymentVerifyResult, ZibalInquiryResponse, ZibalRequestResponse (+1 more)
|
||||
|
||||
### Community 48 - "PrescriptionsController"
|
||||
Cohesion: 0.15
|
||||
Nodes (12): PrescriptionsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+4 more)
|
||||
### Community 48 - "PrescriptionsService"
|
||||
Cohesion: 0.14
|
||||
Nodes (14): PrescriptionsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+6 more)
|
||||
|
||||
### Community 49 - "SmartAdvisorService"
|
||||
Cohesion: 0.13
|
||||
@ -540,7 +546,7 @@ Cohesion: 0.09
|
||||
Nodes (22): CREATE MODE — Normal Operation, Expected JSON Output Schema, File Scope Boundary, Forbidden Actions, MODE 1: REVIEW (called during Review Phase), MODE 2: CONTENT CREATION (standalone task from backlog), Operating Modes, Operational Rules & Boundaries (+14 more)
|
||||
|
||||
### Community 52 - ".initiateOrderPayment"
|
||||
Cohesion: 0.18
|
||||
Cohesion: 0.19
|
||||
Nodes (10): ApiPropertyOptional, IsOptional, IsString, ZibalCallbackQueryDto, ApiBadRequestResponse, ApiOkResponse, Req, Res (+2 more)
|
||||
|
||||
### Community 54 - "compilerOptions"
|
||||
@ -556,12 +562,12 @@ Cohesion: 0.08
|
||||
Nodes (23): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, jsx, lib, module, moduleDetection, moduleResolution (+15 more)
|
||||
|
||||
### Community 57 - "PetsController"
|
||||
Cohesion: 0.15
|
||||
Nodes (11): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+3 more)
|
||||
Cohesion: 0.10
|
||||
Nodes (14): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+6 more)
|
||||
|
||||
### Community 58 - "PaginationDto"
|
||||
Cohesion: 0.06
|
||||
Nodes (19): BlogsService, Injectable, BlogsModule, Module, BlogsService, Injectable, PaginationDto, SortOrder (+11 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (15): BlogsService, Injectable, BlogsModule, Module, BlogsService, Injectable, PaginationDto, SortOrder (+7 more)
|
||||
|
||||
### Community 59 - "dependencies"
|
||||
Cohesion: 0.05
|
||||
@ -572,13 +578,17 @@ Cohesion: 0.10
|
||||
Nodes (20): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, lib, module, moduleDetection, moduleResolution, noEmit (+12 more)
|
||||
|
||||
### Community 61 - "ArchivePage.tsx"
|
||||
Cohesion: 0.13
|
||||
Nodes (15): HomeClientProps, ArchiveProductCard(), CATEGORY_MAP, ICON_MAP, BannerPlacement(), BannerPlacementProps, B2BInquiry, Banner (+7 more)
|
||||
Cohesion: 0.15
|
||||
Nodes (13): ArchiveProductCard(), CATEGORY_MAP, ICON_MAP, BannerPlacement(), BannerPlacementProps, B2BInquiry, Banner, DosageConfig (+5 more)
|
||||
|
||||
### Community 62 - "BlogsController"
|
||||
Cohesion: 0.14
|
||||
Nodes (16): BlogsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+8 more)
|
||||
|
||||
### Community 63 - "ApiOperation"
|
||||
Cohesion: 0.14
|
||||
Nodes (8): ApiOperation, ApiQuery, Get, Query, AdminQueryDto, ApiPropertyOptional, IsOptional, IsString
|
||||
|
||||
### Community 64 - "BannersService"
|
||||
Cohesion: 0.13
|
||||
Nodes (15): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+7 more)
|
||||
@ -604,8 +614,8 @@ Cohesion: 0.13
|
||||
Nodes (14): ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete, Get (+6 more)
|
||||
|
||||
### Community 70 - "admin.service.ts"
|
||||
Cohesion: 0.15
|
||||
Nodes (14): CouponInput, CouponTargetInput, PaginationQuery, CreateUserDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty (+6 more)
|
||||
Cohesion: 0.20
|
||||
Nodes (13): CouponInput, CouponTargetInput, PaginationQuery, CreateUserDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty (+5 more)
|
||||
|
||||
### Community 71 - "getSeoConfig"
|
||||
Cohesion: 0.24
|
||||
@ -649,7 +659,7 @@ Nodes (11): ProductDetailModalProps, SafeImage(), SafeImageProps, DisplayVideoIt
|
||||
|
||||
### Community 81 - "devDependencies"
|
||||
Cohesion: 0.13
|
||||
Nodes (15): devDependencies, eslint, jsdom, tailwindcss, @tailwindcss/postcss, @types/node, @types/react-dom, @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"
|
||||
Cohesion: 0.15
|
||||
@ -716,8 +726,8 @@ Cohesion: 0.15
|
||||
Nodes (13): jest, collectCoverageFrom, coverageDirectory, moduleFileExtensions, rootDir, testEnvironment, testRegex, transform (+5 more)
|
||||
|
||||
### Community 98 - "AdminService"
|
||||
Cohesion: 0.06
|
||||
Nodes (27): AdminController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+19 more)
|
||||
Cohesion: 0.15
|
||||
Nodes (5): Body, Param, Put, AdminService, Injectable
|
||||
|
||||
### Community 99 - "Comprehensive Change Log"
|
||||
Cohesion: 0.15
|
||||
@ -739,9 +749,9 @@ Nodes (14): BlogsController, ApiBearerAuth, ApiNotFoundResponse, ApiOkResponse,
|
||||
Cohesion: 0.22
|
||||
Nodes (7): AdminTransactionFilterDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type
|
||||
|
||||
### Community 104 - "prescriptions.controller.ts"
|
||||
Cohesion: 0.31
|
||||
Nodes (5): UserReqPayload, PrescriptionsModule, Module, PrescriptionsService, Injectable
|
||||
### Community 104 - "CreateOrderDto"
|
||||
Cohesion: 0.13
|
||||
Nodes (17): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+9 more)
|
||||
|
||||
### Community 105 - "1. Summary of Integrity Repairs Performed"
|
||||
Cohesion: 0.17
|
||||
@ -880,16 +890,16 @@ 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)
|
||||
|
||||
### Community 141 - "WikiController"
|
||||
Cohesion: 0.21
|
||||
Nodes (9): ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param, Query (+1 more)
|
||||
Cohesion: 0.13
|
||||
Nodes (13): ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param, Query (+5 more)
|
||||
|
||||
### Community 142 - "useCartStore"
|
||||
Cohesion: 0.12
|
||||
Nodes (11): CartDrawer(), OrderSuccess(), OrderTracking(), mockProduct, ApiErr, Order, OrderItem, OrderService (+3 more)
|
||||
|
||||
### Community 143 - "auth.service.ts"
|
||||
### Community 143 - "RedisService"
|
||||
Cohesion: 0.08
|
||||
Nodes (12): ApiExcludeController, AdminLoginInput, AuthService, LoginInput, RegisterInput, Injectable, MetricsController, Controller (+4 more)
|
||||
Nodes (12): ApiExcludeController, AppModule, Module, MetricsController, Controller, Get, Res, RedisModule (+4 more)
|
||||
|
||||
### Community 144 - "Baseline Command Plan & Reconciled Command History"
|
||||
Cohesion: 0.29
|
||||
@ -1027,14 +1037,34 @@ Nodes (3): COMPOSE_DOCKER_CLI_BUILD, DOCKER_BUILDKIT, deploy.sh script
|
||||
Cohesion: 0.67
|
||||
Nodes (3): ADR-AUTH-001: Admin Panel Authentication Architecture & Token Management, Master Task Backlog (Phase 3.3), Phase 3 Master Execution Plan
|
||||
|
||||
### Community 215 - "AdminController"
|
||||
Cohesion: 0.18
|
||||
Nodes (6): AdminController, ApiBearerAuth, ApiTags, Controller, Delete, UseGuards
|
||||
|
||||
### Community 220 - "getPageMetadata"
|
||||
Cohesion: 0.14
|
||||
Nodes (7): generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), getPageMetadata()
|
||||
|
||||
### Community 221 - "AuthService"
|
||||
Cohesion: 0.22
|
||||
Nodes (3): AuthService, Injectable, normalizeMobile()
|
||||
|
||||
### Community 223 - "Shabnam Font README"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): Shabnam Font README, Shabnam Font Sample, Vazir Font
|
||||
|
||||
### Community 232 - "ProductDto"
|
||||
Cohesion: 0.22
|
||||
Nodes (7): ProductDto, ApiPropertyOptional, IsArray, IsBoolean, IsNumber, IsOptional, IsString
|
||||
|
||||
### Community 239 - "WholesaleApplyDto"
|
||||
Cohesion: 0.29
|
||||
Nodes (6): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto
|
||||
|
||||
### Community 241 - "zibal-ebank.service.ts"
|
||||
Cohesion: 0.40
|
||||
Nodes (4): EBankCheckoutListFilter, EBankCheckoutOptions, EBankIdentifiedPaymentFilter, EBankStatementFilter
|
||||
|
||||
### Community 243 - "app.e2e-spec.js"
|
||||
Cohesion: 0.50
|
||||
Nodes (3): app_module_1, supertest_1, testing_1
|
||||
@ -1048,8 +1078,8 @@ Cohesion: 0.22
|
||||
Nodes (3): Props, RouteErrorBoundary, State
|
||||
|
||||
### Community 310 - "admin.module.ts"
|
||||
Cohesion: 0.06
|
||||
Nodes (21): AdminModule, Module, PetQuery, PetsService, Injectable, ReportsController, ApiBearerAuth, ApiOperation (+13 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (15): AdminModule, Module, ReportsController, ApiBearerAuth, ApiOperation, ApiTags, Controller, Get (+7 more)
|
||||
|
||||
## Knowledge Gaps
|
||||
- **1269 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1264 more)
|
||||
@ -1061,15 +1091,15 @@ _Questions this graph is uniquely positioned to answer:_
|
||||
|
||||
- **Why does `ApiResponse` connect `src/services/api.ts` to `OrdersService`, `BlogsController`, `UsersService`, `WikiController`, `PetsController`, `HomeController`, `ProductsService`, `auth.controller.ts`?**
|
||||
_High betweenness centrality (0.064) - this node is a cross-community bridge._
|
||||
- **Why does `Roles()` connect `Roles` to `BannersService`, `CmsController`, `B2BService`, `reviews.controller.ts`, `tickets.controller.ts`, `SslController`, `prescriptions.controller.ts`, `IngredientsService`, `FaqService`, `MenuService`, `ContactService`, `ProductsService`, `PrescriptionsController`, `SmartAdvisorService`, `TestimonialsService`, `SettingsController`, `WholesaleApplyDto`, `JwtAuthGuard`?**
|
||||
- **Why does `Roles()` connect `Roles` to `BannersService`, `CmsController`, `B2BService`, `reviews.controller.ts`, `tickets.controller.ts`, `SslController`, `IngredientsService`, `FaqService`, `MenuService`, `ContactService`, `ProductsService`, `PrescriptionsService`, `SmartAdvisorService`, `TestimonialsService`, `SmsService`, `WholesaleService`, `JwtAuthGuard`?**
|
||||
_High betweenness centrality (0.062) - this node is a cross-community bridge._
|
||||
- **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `OrdersService`, `CmsController`, `reviews.controller.ts`, `tickets.controller.ts`, `admin.service.ts`, `UsersService`, `prescriptions.controller.ts`, `DoctorQueryDto`, `PetsController`, `ProductsService`, `CreateVideoDto`, `auth.controller.ts`, `admin.module.ts`, `PaginationDto`?**
|
||||
- **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `CmsController`, `reviews.controller.ts`, `tickets.controller.ts`, `admin.service.ts`, `UsersService`, `CreateOrderDto`, `DoctorQueryDto`, `PetsController`, `ProductsService`, `CreateVideoDto`, `auth.controller.ts`, `admin.module.ts`, `PetsController`, `PaginationDto`?**
|
||||
_High betweenness centrality (0.032) - this node is a cross-community bridge._
|
||||
- **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?**
|
||||
_1269 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._
|
||||
_Cohesion score 0.10160427807486631 - nodes in this community are weakly interconnected._
|
||||
- **Should `productService.ts` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.08156028368794327 - nodes in this community are weakly interconnected._
|
||||
_Cohesion score 0.08985200845665962 - nodes in this community are weakly interconnected._
|
||||
- **Should `CmsController` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.0899854862119013 - 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
@ -1,16 +1,16 @@
|
||||
# Graph Report - canina (2026-08-22)
|
||||
|
||||
## Corpus Check
|
||||
- 536 files · ~759,763 words
|
||||
- 539 files · ~762,534 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
- 3887 nodes · 6841 edges · 303 communities (203 shown, 100 thin omitted)
|
||||
- Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 261 edges (avg confidence: 0.79)
|
||||
- 3902 nodes · 6878 edges · 308 communities (207 shown, 101 thin omitted)
|
||||
- Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 262 edges (avg confidence: 0.79)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Graph Freshness
|
||||
- Built from commit: `ee32b4c1`
|
||||
- Built from commit: `f9e40564`
|
||||
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
|
||||
- Run `graphify update .` after code changes (no API cost).
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
- app.module.ts
|
||||
- reviews.controller.ts
|
||||
- tickets.controller.ts
|
||||
- userStore.ts
|
||||
- AuthService
|
||||
- MediaSelector.tsx
|
||||
- PetProfile.tsx
|
||||
- Roles
|
||||
@ -29,12 +29,12 @@
|
||||
- MenuService
|
||||
- adminRoutes.tsx
|
||||
- PrismaService
|
||||
- PetsController
|
||||
- pets/pets.controller.ts
|
||||
- ProductsService
|
||||
- UserDashboard.tsx
|
||||
- CreateVideoDto
|
||||
- src/services/api.ts
|
||||
- auth.controller.ts
|
||||
- .adminLogin
|
||||
- BE-001
|
||||
- SmsService
|
||||
- FE-001
|
||||
@ -52,7 +52,7 @@
|
||||
- CategoriesController
|
||||
- B2BService
|
||||
- What You Must Do When Invoked
|
||||
- useSettingsStore
|
||||
- .update
|
||||
- UsersService
|
||||
- What You Must Do When Invoked
|
||||
- SslController
|
||||
@ -60,28 +60,28 @@
|
||||
- IngredientsService
|
||||
- FaqService
|
||||
- MediaController
|
||||
- Media.tsx
|
||||
- Coupons.tsx
|
||||
- ContactService
|
||||
- zibal.service.ts
|
||||
- PrescriptionsService
|
||||
- SmartAdvisorService
|
||||
- TestimonialsService
|
||||
- Role & Core Objective
|
||||
- .initiateOrderPayment
|
||||
- .handleZibalCallback
|
||||
- ZibalEBankService
|
||||
- compilerOptions
|
||||
- PrescriptionsManager.tsx
|
||||
- Media.tsx
|
||||
- compilerOptions
|
||||
- PetsController
|
||||
- PaginationDto
|
||||
- dependencies
|
||||
- compilerOptions
|
||||
- ArchivePage.tsx
|
||||
- HomeClient.tsx
|
||||
- BlogsController
|
||||
- ApiOperation
|
||||
- BannersService
|
||||
- Required Review Group Closures
|
||||
- Coupons.tsx
|
||||
- Products.tsx
|
||||
- Operational Rules & Boundaries
|
||||
- Operational Rules & Boundaries
|
||||
- WikiController
|
||||
@ -94,10 +94,10 @@
|
||||
- Operational Rules & Boundaries
|
||||
- scripts
|
||||
- Role & Core Objective
|
||||
- HomeController
|
||||
- B2BPortal.tsx
|
||||
- Transactions.tsx
|
||||
- SafeImage.tsx
|
||||
- devDependencies
|
||||
- api
|
||||
- auth.controller.ts
|
||||
- Orders.tsx
|
||||
- devDependencies
|
||||
- seed-products.ts
|
||||
@ -117,9 +117,9 @@
|
||||
- Comprehensive Change Log
|
||||
- Operational Rules & Boundaries
|
||||
- UITexts.tsx
|
||||
- BlogsController
|
||||
- AdminTransactionFilterDto
|
||||
- CreateOrderDto
|
||||
- ApiResponse
|
||||
- payment.service.ts
|
||||
- PetsService
|
||||
- 1. Summary of Integrity Repairs Performed
|
||||
- @nestjs/cli
|
||||
- Operational Rules & Boundaries
|
||||
@ -156,9 +156,9 @@
|
||||
- InitiatePaymentDto
|
||||
- System Discovery
|
||||
- Product Requirement Document (PRD)
|
||||
- WikiController
|
||||
- useCartStore
|
||||
- RedisService
|
||||
- PetsController
|
||||
- lib/services/api.ts
|
||||
- auth.service.ts
|
||||
- Baseline Command Plan & Reconciled Command History
|
||||
- catalog/page.tsx
|
||||
- ErrorPages.tsx
|
||||
@ -189,7 +189,7 @@
|
||||
- 🎨 Frontend & Admin Panel Technical Review (06_dev_frontend)
|
||||
- 🚀 SEO & Content Strategy Review (12_seo_content)
|
||||
- @types/node
|
||||
- shop/page.tsx
|
||||
- MetricsController
|
||||
- seed-ui-texts.ts
|
||||
- seed-wiki.ts
|
||||
- update-blog.dto.ts
|
||||
@ -201,7 +201,7 @@
|
||||
- Raw Finding Verification & Disposition Report
|
||||
- React + TypeScript + Vite
|
||||
- Select.tsx
|
||||
- Reports.tsx
|
||||
- RegisterDto
|
||||
- ts-node
|
||||
- application/README.md
|
||||
- @types/express
|
||||
@ -229,14 +229,14 @@
|
||||
- @types/multer
|
||||
- videos/page.tsx
|
||||
- @testing-library/jest-dom
|
||||
- checkout/page.tsx
|
||||
- AdminLoginDto
|
||||
- AdminController
|
||||
- FormField.tsx
|
||||
- Input.tsx
|
||||
- Textarea.tsx
|
||||
- admin-panel/tsconfig.json
|
||||
- getPageMetadata
|
||||
- AuthService
|
||||
- AuthController
|
||||
- next.config.ts
|
||||
- Shabnam Font README
|
||||
- AGENTS.md
|
||||
@ -252,10 +252,10 @@
|
||||
- @types/react
|
||||
- typescript
|
||||
- vitest
|
||||
- .createCoupon
|
||||
- Body
|
||||
- WholesaleApplyDto
|
||||
- ts-loader
|
||||
- zibal-ebank.service.ts
|
||||
- VerifyOtpDto
|
||||
- @types/bcrypt
|
||||
- app.e2e-spec.js
|
||||
- blog.entity.ts
|
||||
@ -291,11 +291,15 @@
|
||||
- Production Docker Compose
|
||||
- Staging Docker Compose
|
||||
- @types/passport-jwt
|
||||
- ClientLayout.tsx
|
||||
- useSettingsStore
|
||||
- @types/supertest
|
||||
- typescript
|
||||
- @types/react-dom
|
||||
- CreateHealthLogDto
|
||||
- eslint-config-prettier
|
||||
- CreateReminderDto
|
||||
- track/page.tsx
|
||||
- dashboard/page.tsx
|
||||
- eslint-plugin-prettier
|
||||
- RouteErrorBoundary
|
||||
- globals
|
||||
@ -309,22 +313,22 @@
|
||||
4. `api` - 43 edges
|
||||
5. `SmsService` - 42 edges
|
||||
6. `PaginationDto` - 41 edges
|
||||
7. `ZibalService` - 37 edges
|
||||
8. `PaymentController` - 36 edges
|
||||
9. `JwtAuthGuard` - 35 edges
|
||||
10. `AdminService` - 34 edges
|
||||
7. `PaymentController` - 37 edges
|
||||
8. `ZibalService` - 37 edges
|
||||
9. `AdminService` - 35 edges
|
||||
10. `JwtAuthGuard` - 35 edges
|
||||
|
||||
## Surprising Connections (you probably didn't know these)
|
||||
- `User Profile Photo` --conceptually_related_to--> `User Roles and Capabilities` [INFERRED]
|
||||
backend/uploads/1781288429353-508765350.jpg → docs/02-user-guide.md
|
||||
- `AuthController` --references--> `ApiResponse` [EXTRACTED]
|
||||
backend/src/auth/auth.controller.ts → frontend/admin-panel/src/types/admin.ts
|
||||
- `BlogsController` --references--> `ApiResponse` [EXTRACTED]
|
||||
backend/src/blogs/blogs.controller.ts → frontend/admin-panel/src/types/admin.ts
|
||||
- `HomeController` --references--> `ApiResponse` [EXTRACTED]
|
||||
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
|
||||
- `PetsController` --references--> `ApiResponse` [EXTRACTED]
|
||||
backend/src/pets/pets.controller.ts → frontend/admin-panel/src/types/admin.ts
|
||||
- `ProductsController` --references--> `ApiResponse` [EXTRACTED]
|
||||
backend/src/products/products.controller.ts → frontend/admin-panel/src/types/admin.ts
|
||||
|
||||
## 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`
|
||||
@ -335,15 +339,15 @@
|
||||
- **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]
|
||||
|
||||
## Communities (303 total, 100 thin omitted)
|
||||
## Communities (308 total, 101 thin omitted)
|
||||
|
||||
### Community 0 - "OrdersService"
|
||||
Cohesion: 0.10
|
||||
Nodes (18): OrdersController, ApiBadRequestResponse, ApiBearerAuth, ApiCreatedResponse, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags (+10 more)
|
||||
Cohesion: 0.06
|
||||
Nodes (35): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+27 more)
|
||||
|
||||
### Community 1 - "productService.ts"
|
||||
Cohesion: 0.09
|
||||
Nodes (26): BlogPost, CatalogPageSpread(), CatalogPageSpreadProps, CategoryMeta, getFormBadge(), getSpeciesBadge(), FlipbookCatalog(), FlipbookCatalogProps (+18 more)
|
||||
Cohesion: 0.10
|
||||
Nodes (24): BlogPost, CatalogPageSpread(), CatalogPageSpreadProps, CategoryMeta, getFormBadge(), getSpeciesBadge(), FlipbookCatalog(), FlipbookCatalogProps (+16 more)
|
||||
|
||||
### Community 2 - "CmsController"
|
||||
Cohesion: 0.09
|
||||
@ -351,7 +355,7 @@ Nodes (24): CmsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controlle
|
||||
|
||||
### Community 3 - "app.module.ts"
|
||||
Cohesion: 0.07
|
||||
Nodes (34): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+26 more)
|
||||
Nodes (36): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+28 more)
|
||||
|
||||
### Community 4 - "reviews.controller.ts"
|
||||
Cohesion: 0.07
|
||||
@ -359,31 +363,27 @@ Nodes (31): CreateReviewDto, ApiProperty, IsInt, IsNotEmpty, IsOptional, IsStrin
|
||||
|
||||
### Community 5 - "tickets.controller.ts"
|
||||
Cohesion: 0.09
|
||||
Nodes (29): AdminUpdateTicketDto, CreateTicketDto, ReplyTicketDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString (+21 more)
|
||||
|
||||
### Community 6 - "userStore.ts"
|
||||
Cohesion: 0.11
|
||||
Nodes (10): LoginModal(), LoginModalProps, ApiErr, AuthResponse, AuthService, User, Transaction, UserProfile (+2 more)
|
||||
Nodes (31): AdminUpdateTicketDto, CreateTicketDto, ReplyTicketDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString (+23 more)
|
||||
|
||||
### Community 7 - "MediaSelector.tsx"
|
||||
Cohesion: 0.08
|
||||
Nodes (26): ConfirmModal(), ConfirmModalProps, ImagePreviewModal(), ImagePreviewModalProps, getFileType(), Media, MediaSelector(), MediaSelectorProps (+18 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (26): ConfirmModal(), ConfirmModalProps, getFileType(), Media, MediaSelector(), MediaSelectorProps, BlogPost, Category (+18 more)
|
||||
|
||||
### Community 8 - "PetProfile.tsx"
|
||||
Cohesion: 0.12
|
||||
Nodes (19): CheckoutPage(), FeaturedProducts(), ProductCard(), PetProfile(), PrescriptionUploadModal(), PrescriptionUploadModalProps, SearchResultsPage(), OrderRowSkeleton() (+11 more)
|
||||
Cohesion: 0.11
|
||||
Nodes (18): FeaturedProducts(), ProductCard(), OrderSuccess(), PrescriptionUploadModal(), PrescriptionUploadModalProps, SearchResultsPage(), OrderRowSkeleton(), PetProfileSkeleton() (+10 more)
|
||||
|
||||
### Community 9 - "Roles"
|
||||
Cohesion: 0.24
|
||||
Nodes (13): Roles(), PaymentController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get (+5 more)
|
||||
Cohesion: 0.20
|
||||
Nodes (15): Roles(), PaymentController, ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags, Body (+7 more)
|
||||
|
||||
### Community 10 - "DoctorQueryDto"
|
||||
Cohesion: 0.09
|
||||
Nodes (24): DoctorsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+16 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (26): DoctorsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+18 more)
|
||||
|
||||
### Community 11 - "MenuService"
|
||||
Cohesion: 0.10
|
||||
Nodes (19): MenuController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+11 more)
|
||||
Cohesion: 0.12
|
||||
Nodes (16): MenuController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+8 more)
|
||||
|
||||
### Community 12 - "adminRoutes.tsx"
|
||||
Cohesion: 0.09
|
||||
@ -391,31 +391,31 @@ Nodes (16): App(), HeroBanner, VetTestimonial, ContactInfoItem, ContactSubmissio
|
||||
|
||||
### Community 13 - "PrismaService"
|
||||
Cohesion: 0.08
|
||||
Nodes (18): CategoryQuery, AdminLoginInput, LoginInput, RegisterInput, MeliPayamakPattern, MeliPayamakResponse, SendPatternSmsOptions, SmsConfig (+10 more)
|
||||
Nodes (18): MeliPayamakPattern, MeliPayamakResponse, SendPatternSmsOptions, SmsConfig, SmsLogQuery, CreateContactSubmissionDto, UpdateContactInfoItemDto, MenuType (+10 more)
|
||||
|
||||
### Community 14 - "PetsController"
|
||||
Cohesion: 0.05
|
||||
Nodes (47): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, CreatePetDto, ApiProperty (+39 more)
|
||||
### Community 14 - "pets/pets.controller.ts"
|
||||
Cohesion: 0.16
|
||||
Nodes (13): CreatePetDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional, IsString (+5 more)
|
||||
|
||||
### Community 15 - "ProductsService"
|
||||
Cohesion: 0.09
|
||||
Nodes (19): GetProductsDto, ApiPropertyOptional, IsEnum, IsOptional, IsString, ProductsController, ApiOperation, ApiTags (+11 more)
|
||||
Cohesion: 0.13
|
||||
Nodes (12): ProductsController, ApiOperation, ApiTags, Body, Controller, Get, Param, Patch (+4 more)
|
||||
|
||||
### Community 16 - "UserDashboard.tsx"
|
||||
Cohesion: 0.10
|
||||
Nodes (30): VerifyContent(), AddressModal(), AddressModalProps, AuthModal(), AuthModalProps, extractOtpFromText(), BackButton(), BackButtonProps (+22 more)
|
||||
Cohesion: 0.09
|
||||
Nodes (41): VerifyContent(), AddressModal(), AddressModalProps, ArchiveProductCard(), AuthModal(), AuthModalProps, extractOtpFromText(), B2BPortal() (+33 more)
|
||||
|
||||
### Community 17 - "CreateVideoDto"
|
||||
Cohesion: 0.07
|
||||
Nodes (31): CreateVideoDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString, UpdateVideoDto (+23 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (29): CreateVideoDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString, UpdateVideoDto (+21 more)
|
||||
|
||||
### Community 18 - "src/services/api.ts"
|
||||
Cohesion: 0.09
|
||||
Nodes (25): ProtectedRoute(), SEARCHABLE_PAGES, Topbar(), TopbarProps, Login(), B2BManager, SeoSettingsPage, SmartAdvisorManager (+17 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (30): Layout(), ProtectedRoute(), MenuGroup, Sidebar(), SidebarProps, SubMenuItem, SEARCHABLE_PAGES, Topbar() (+22 more)
|
||||
|
||||
### Community 19 - "auth.controller.ts"
|
||||
Cohesion: 0.06
|
||||
Nodes (42): AuthController, ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+34 more)
|
||||
### Community 19 - ".adminLogin"
|
||||
Cohesion: 0.34
|
||||
Nodes (9): ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse, ApiOperation, Body, Post, Req, UseGuards (+1 more)
|
||||
|
||||
### Community 20 - "BE-001"
|
||||
Cohesion: 0.06
|
||||
@ -423,7 +423,7 @@ Nodes (32): Acceptance Criteria, Affected Application, Affected Files, Alternati
|
||||
|
||||
### Community 21 - "SmsService"
|
||||
Cohesion: 0.06
|
||||
Nodes (27): SmsLogQuery, SmsService, Injectable, SmsLogQueryDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional (+19 more)
|
||||
Nodes (26): SmsService, Injectable, SmsLogQueryDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString (+18 more)
|
||||
|
||||
### Community 22 - "FE-001"
|
||||
Cohesion: 0.06
|
||||
@ -458,8 +458,8 @@ Cohesion: 0.14
|
||||
Nodes (14): ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param, Post (+6 more)
|
||||
|
||||
### Community 30 - "app-audit-verification.e2e-spec.js"
|
||||
Cohesion: 0.08
|
||||
Nodes (20): CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable, ApiErrorResponse, ErrorDetailField (+12 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (22): AppModule, Module, CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable (+14 more)
|
||||
|
||||
### Community 31 - "JwtAuthGuard"
|
||||
Cohesion: 0.20
|
||||
@ -467,7 +467,7 @@ Nodes (7): JwtAuthGuard, Injectable, ROLES_KEY, RequestWithUser, RolesGuard, Inj
|
||||
|
||||
### Community 32 - "ZibalService"
|
||||
Cohesion: 0.09
|
||||
Nodes (4): PaymentService, Injectable, Injectable, ZibalService
|
||||
Nodes (5): Put, PaymentService, Injectable, Injectable, ZibalService
|
||||
|
||||
### Community 33 - "راهنمای تست سیستم (Software Testing)"
|
||||
Cohesion: 0.07
|
||||
@ -485,9 +485,9 @@ Nodes (15): B2BController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controlle
|
||||
Cohesion: 0.07
|
||||
Nodes (26): For /graphify add and --watch, For /graphify query, For the commit hook and native CLAUDE.md integration, For --update and --cluster-only, /graphify, Honesty Rules, Interpreter guard for subcommands, Part A - Structural extraction for code files (+18 more)
|
||||
|
||||
### Community 37 - "useSettingsStore"
|
||||
Cohesion: 0.09
|
||||
Nodes (29): HomeClient(), HomeClientProps, BlogPost, BlogPreviewSection(), ContactInfoItem, EnamadBadge(), FAQItem, FAQSection() (+21 more)
|
||||
### Community 37 - ".update"
|
||||
Cohesion: 0.24
|
||||
Nodes (11): ApiNotFoundResponse, ApiOkResponse, ApiOperation, Body, Delete, Get, Param, Patch (+3 more)
|
||||
|
||||
### Community 38 - "UsersService"
|
||||
Cohesion: 0.06
|
||||
@ -517,9 +517,9 @@ Nodes (14): FaqController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controlle
|
||||
Cohesion: 0.11
|
||||
Nodes (16): MediaController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+8 more)
|
||||
|
||||
### Community 45 - "Media.tsx"
|
||||
Cohesion: 0.11
|
||||
Nodes (15): Pagination(), PaginationProps, getFileType(), Media, MediaManager(), Pet, GatewayHealth, Stats (+7 more)
|
||||
### Community 45 - "Coupons.tsx"
|
||||
Cohesion: 0.12
|
||||
Nodes (12): Pagination(), PaginationProps, Coupon, CouponFormData, CouponModalProps, CouponTarget, Pet, ProductItem (+4 more)
|
||||
|
||||
### Community 46 - "ContactService"
|
||||
Cohesion: 0.13
|
||||
@ -545,17 +545,17 @@ Nodes (14): TestimonialsController, ApiBearerAuth, ApiOperation, ApiTags, Body,
|
||||
Cohesion: 0.09
|
||||
Nodes (22): CREATE MODE — Normal Operation, Expected JSON Output Schema, File Scope Boundary, Forbidden Actions, MODE 1: REVIEW (called during Review Phase), MODE 2: CONTENT CREATION (standalone task from backlog), Operating Modes, Operational Rules & Boundaries (+14 more)
|
||||
|
||||
### Community 52 - ".initiateOrderPayment"
|
||||
Cohesion: 0.19
|
||||
Nodes (10): ApiPropertyOptional, IsOptional, IsString, ZibalCallbackQueryDto, ApiBadRequestResponse, ApiOkResponse, Req, Res (+2 more)
|
||||
### Community 52 - ".handleZibalCallback"
|
||||
Cohesion: 0.25
|
||||
Nodes (7): ApiPropertyOptional, IsOptional, IsString, ZibalCallbackQueryDto, Res, Headers, Ip
|
||||
|
||||
### Community 54 - "compilerOptions"
|
||||
Cohesion: 0.06
|
||||
Nodes (30): compilerOptions, allowSyntheticDefaultImports, baseUrl, declaration, emitDecoratorMetadata, esModuleInterop, experimentalDecorators, forceConsistentCasingInFileNames (+22 more)
|
||||
|
||||
### Community 55 - "PrescriptionsManager.tsx"
|
||||
Cohesion: 0.22
|
||||
Nodes (7): Badge(), BadgeProps, BadgeVariant, variantStyles, ProductItem, PrescriptionsManager, Prescription
|
||||
### Community 55 - "Media.tsx"
|
||||
Cohesion: 0.14
|
||||
Nodes (13): Badge(), BadgeProps, BadgeVariant, variantStyles, ImagePreviewModal(), ImagePreviewModalProps, getFileType(), Media (+5 more)
|
||||
|
||||
### Community 56 - "compilerOptions"
|
||||
Cohesion: 0.08
|
||||
@ -566,8 +566,8 @@ Cohesion: 0.10
|
||||
Nodes (14): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+6 more)
|
||||
|
||||
### Community 58 - "PaginationDto"
|
||||
Cohesion: 0.07
|
||||
Nodes (15): BlogsService, Injectable, BlogsModule, Module, BlogsService, Injectable, PaginationDto, SortOrder (+7 more)
|
||||
Cohesion: 0.06
|
||||
Nodes (24): BlogsService, Injectable, BlogsModule, Module, BlogsService, Injectable, PaginationDto, SortOrder (+16 more)
|
||||
|
||||
### Community 59 - "dependencies"
|
||||
Cohesion: 0.05
|
||||
@ -577,16 +577,16 @@ Nodes (41): dependencies, bcrypt, bcryptjs, class-transformer, class-validator,
|
||||
Cohesion: 0.10
|
||||
Nodes (20): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, lib, module, moduleDetection, moduleResolution, noEmit (+12 more)
|
||||
|
||||
### Community 61 - "ArchivePage.tsx"
|
||||
Cohesion: 0.15
|
||||
Nodes (13): ArchiveProductCard(), CATEGORY_MAP, ICON_MAP, BannerPlacement(), BannerPlacementProps, B2BInquiry, Banner, DosageConfig (+5 more)
|
||||
### Community 61 - "HomeClient.tsx"
|
||||
Cohesion: 0.11
|
||||
Nodes (20): HomeClient(), HomeClientProps, CATEGORY_MAP, ICON_MAP, BannerPlacement(), BannerPlacementProps, FAQItem, FAQSection() (+12 more)
|
||||
|
||||
### Community 62 - "BlogsController"
|
||||
Cohesion: 0.14
|
||||
Nodes (16): BlogsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+8 more)
|
||||
|
||||
### Community 63 - "ApiOperation"
|
||||
Cohesion: 0.14
|
||||
Cohesion: 0.17
|
||||
Nodes (8): ApiOperation, ApiQuery, Get, Query, AdminQueryDto, ApiPropertyOptional, IsOptional, IsString
|
||||
|
||||
### Community 64 - "BannersService"
|
||||
@ -597,9 +597,9 @@ Nodes (15): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Contr
|
||||
Cohesion: 0.10
|
||||
Nodes (19): 10. Orders Backend, 11. Settings & Administrative Backend, 12. Prisma Schema, Migrations & Seed, 13. Redis & Temporary Auth State, 14. Unit & E2E Tests, 15. Docker, NGINX, Prometheus & Deployment Config, 16. Documentation & OpenAPI Artifacts, 1. Storefront Shell & Routing (+11 more)
|
||||
|
||||
### Community 66 - "Coupons.tsx"
|
||||
Cohesion: 0.10
|
||||
Nodes (15): formatPriceWithCommas(), PriceInput(), PriceInputProps, toEnglishDigits(), Coupon, CouponFormData, CouponModalProps, CouponTarget (+7 more)
|
||||
### Community 66 - "Products.tsx"
|
||||
Cohesion: 0.16
|
||||
Nodes (10): formatPriceWithCommas(), PriceInput(), PriceInputProps, toEnglishDigits(), Category, Product, FinancialSettingsPage, Products (+2 more)
|
||||
|
||||
### Community 67 - "Operational Rules & Boundaries"
|
||||
Cohesion: 0.11
|
||||
@ -614,8 +614,8 @@ Cohesion: 0.13
|
||||
Nodes (14): ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete, Get (+6 more)
|
||||
|
||||
### Community 70 - "admin.service.ts"
|
||||
Cohesion: 0.20
|
||||
Nodes (13): CouponInput, CouponTargetInput, PaginationQuery, CreateUserDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty (+5 more)
|
||||
Cohesion: 0.16
|
||||
Nodes (14): CouponTargetInput, PaginationQuery, CreateUserDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty, IsNumber (+6 more)
|
||||
|
||||
### Community 71 - "getSeoConfig"
|
||||
Cohesion: 0.24
|
||||
@ -649,21 +649,21 @@ Nodes (17): concurrently, devDependencies, concurrently, name, private, scripts,
|
||||
Cohesion: 0.12
|
||||
Nodes (16): 1. Active Secret Scanning (All Modified Files), 2. Docker Container Verification (if Dockerfile exists), 3. CI/CD Basic Check (if `.github/workflows/` exists), 4. Failure Routing Protocol, 5. Forbidden Actions, ENFORCE MODE — Normal Operation, Expected JSON Output Schema, Operational Rules & Boundaries (+8 more)
|
||||
|
||||
### Community 79 - "HomeController"
|
||||
Cohesion: 0.16
|
||||
Nodes (10): HomeController, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, HomeModule, Module (+2 more)
|
||||
### Community 79 - "Transactions.tsx"
|
||||
Cohesion: 0.15
|
||||
Nodes (13): TransactionReceiptData, TransactionReceiptModal(), TransactionReceiptModalProps, Button(), ButtonProps, ButtonSize, ButtonVariant, MaskableField() (+5 more)
|
||||
|
||||
### Community 80 - "B2BPortal.tsx"
|
||||
Cohesion: 0.16
|
||||
Nodes (11): ProductDetailModalProps, SafeImage(), SafeImageProps, DisplayVideoItem, FALLBACK_VIDEOS, TestimonialItem, PLAYBACK_RATES, VideoModalPlayer() (+3 more)
|
||||
### Community 80 - "SafeImage.tsx"
|
||||
Cohesion: 0.11
|
||||
Nodes (16): BlogPost, BlogPreviewSection(), ProductDetailModalProps, SafeImage(), SafeImageProps, Testimonial, TestimonialsSection(), DisplayVideoItem (+8 more)
|
||||
|
||||
### Community 81 - "devDependencies"
|
||||
Cohesion: 0.13
|
||||
Nodes (15): eslint-config-next, devDependencies, eslint, eslint-config-next, jsdom, tailwindcss, @tailwindcss/postcss, @types/node (+7 more)
|
||||
|
||||
### Community 82 - "api"
|
||||
Cohesion: 0.15
|
||||
Nodes (10): Layout(), MenuGroup, Sidebar(), SidebarProps, SubMenuItem, MENU_TABS, MenuItem, MenuType (+2 more)
|
||||
### Community 82 - "auth.controller.ts"
|
||||
Cohesion: 0.18
|
||||
Nodes (10): LoginDto, ApiProperty, IsNotEmpty, IsString, MinLength, SendOtpDto, ApiProperty, IsNotEmpty (+2 more)
|
||||
|
||||
### Community 83 - "Orders.tsx"
|
||||
Cohesion: 0.14
|
||||
@ -726,8 +726,8 @@ Cohesion: 0.15
|
||||
Nodes (13): jest, collectCoverageFrom, coverageDirectory, moduleFileExtensions, rootDir, testEnvironment, testRegex, transform (+5 more)
|
||||
|
||||
### Community 98 - "AdminService"
|
||||
Cohesion: 0.15
|
||||
Nodes (5): Body, Param, Put, AdminService, Injectable
|
||||
Cohesion: 0.13
|
||||
Nodes (5): Delete, Param, Put, AdminService, Injectable
|
||||
|
||||
### Community 99 - "Comprehensive Change Log"
|
||||
Cohesion: 0.15
|
||||
@ -741,17 +741,13 @@ Nodes (11): 1. Detect Test Runner from Tech Stack, 2. Execution Output Capture (
|
||||
Cohesion: 0.10
|
||||
Nodes (18): ICON_REGISTRY, IconPickerModal(), IconPickerModalProps, COLORS, RichTextEditor(), RichTextEditorProps, ToggleSwitch(), ToggleSwitchProps (+10 more)
|
||||
|
||||
### Community 102 - "BlogsController"
|
||||
Cohesion: 0.17
|
||||
Nodes (14): BlogsController, ApiBearerAuth, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+6 more)
|
||||
### Community 102 - "ApiResponse"
|
||||
Cohesion: 0.06
|
||||
Nodes (34): BlogsController, ApiBearerAuth, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+26 more)
|
||||
|
||||
### Community 103 - "AdminTransactionFilterDto"
|
||||
Cohesion: 0.22
|
||||
Nodes (7): AdminTransactionFilterDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type
|
||||
|
||||
### Community 104 - "CreateOrderDto"
|
||||
Cohesion: 0.13
|
||||
Nodes (17): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+9 more)
|
||||
### Community 103 - "payment.service.ts"
|
||||
Cohesion: 0.20
|
||||
Nodes (8): AdminTransactionFilterDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type, ClientMetadata
|
||||
|
||||
### Community 105 - "1. Summary of Integrity Repairs Performed"
|
||||
Cohesion: 0.17
|
||||
@ -826,8 +822,8 @@ Cohesion: 0.20
|
||||
Nodes (9): Arch Linux, Contributors, Install, Known problems for variable version, License, Sahel-Font, To Do (variable), طریقه استفاده از نسخه متغیر variable (+1 more)
|
||||
|
||||
### Community 124 - "Spinner.tsx"
|
||||
Cohesion: 0.11
|
||||
Nodes (12): Spinner(), FAQ, ProductReview, Reviews(), toPersianDigits(), SslStatus, FAQManager, PaymentGatewaysPage (+4 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (21): Spinner(), MENU_TABS, MenuItem, MenuType, BestSellerItem, CategoryDistItem, COLORS, CustomTooltipProps (+13 more)
|
||||
|
||||
### Community 125 - "Sahel-Font"
|
||||
Cohesion: 0.20
|
||||
@ -889,17 +885,17 @@ Nodes (7): Active Core Applications, Current Architecture, Evidence-Based Status
|
||||
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)
|
||||
|
||||
### Community 141 - "WikiController"
|
||||
Cohesion: 0.13
|
||||
Nodes (13): ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param, Query (+5 more)
|
||||
### Community 141 - "PetsController"
|
||||
Cohesion: 0.18
|
||||
Nodes (9): PetsController, ApiBadRequestResponse, ApiBearerAuth, ApiCreatedResponse, ApiTags, Controller, UploadedFile, UseGuards (+1 more)
|
||||
|
||||
### Community 142 - "useCartStore"
|
||||
Cohesion: 0.12
|
||||
Nodes (11): CartDrawer(), OrderSuccess(), OrderTracking(), mockProduct, ApiErr, Order, OrderItem, OrderService (+3 more)
|
||||
|
||||
### Community 143 - "RedisService"
|
||||
### Community 142 - "lib/services/api.ts"
|
||||
Cohesion: 0.08
|
||||
Nodes (12): ApiExcludeController, AppModule, Module, MetricsController, Controller, Get, Res, RedisModule (+4 more)
|
||||
Nodes (19): ContactInfoItem, api, ApiErrorPayload, baseURL, ApiErr, AuthResponse, User, ApiErr (+11 more)
|
||||
|
||||
### Community 143 - "auth.service.ts"
|
||||
Cohesion: 0.14
|
||||
Nodes (8): AdminLoginInput, LoginInput, RegisterInput, RedisModule, Global, Module, RedisService, Injectable
|
||||
|
||||
### Community 144 - "Baseline Command Plan & Reconciled Command History"
|
||||
Cohesion: 0.29
|
||||
@ -997,6 +993,10 @@ Nodes (3): Architectural Overview, Critical Review Findings & Required Enhanceme
|
||||
Cohesion: 0.50
|
||||
Nodes (3): Overview & Content Foundation, SEO & Content Requirements, 🚀 SEO & Content Strategy Review (12_seo_content)
|
||||
|
||||
### Community 174 - "MetricsController"
|
||||
Cohesion: 0.20
|
||||
Nodes (5): ApiExcludeController, MetricsController, Controller, Get, Res
|
||||
|
||||
### Community 180 - "graphify reference: add a URL and watch a folder"
|
||||
Cohesion: 0.50
|
||||
Nodes (3): For /graphify add, For --watch, graphify reference: add a URL and watch a folder
|
||||
@ -1021,9 +1021,9 @@ Nodes (3): Expanding the ESLint configuration, React Compiler, React + TypeScrip
|
||||
Cohesion: 0.50
|
||||
Nodes (3): Select, SelectOption, SelectProps
|
||||
|
||||
### Community 186 - "Reports.tsx"
|
||||
Cohesion: 0.20
|
||||
Nodes (7): BestSellerItem, CategoryDistItem, COLORS, CustomTooltipProps, ReportData, TopCouponItem, Reports
|
||||
### Community 186 - "RegisterDto"
|
||||
Cohesion: 0.22
|
||||
Nodes (8): RegisterDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty, IsOptional, IsString, MinLength
|
||||
|
||||
### Community 188 - "application/README.md"
|
||||
Cohesion: 0.50
|
||||
@ -1037,41 +1037,57 @@ Nodes (3): COMPOSE_DOCKER_CLI_BUILD, DOCKER_BUILDKIT, deploy.sh script
|
||||
Cohesion: 0.67
|
||||
Nodes (3): ADR-AUTH-001: Admin Panel Authentication Architecture & Token Management, Master Task Backlog (Phase 3.3), Phase 3 Master Execution Plan
|
||||
|
||||
### Community 214 - "AdminLoginDto"
|
||||
Cohesion: 0.29
|
||||
Nodes (6): AdminLoginDto, ApiProperty, IsEmail, IsNotEmpty, IsString, MinLength
|
||||
|
||||
### Community 215 - "AdminController"
|
||||
Cohesion: 0.18
|
||||
Nodes (6): AdminController, ApiBearerAuth, ApiTags, Controller, Delete, UseGuards
|
||||
Cohesion: 0.25
|
||||
Nodes (5): AdminController, ApiBearerAuth, ApiTags, Controller, UseGuards
|
||||
|
||||
### Community 220 - "getPageMetadata"
|
||||
Cohesion: 0.14
|
||||
Nodes (7): generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), getPageMetadata()
|
||||
Cohesion: 0.13
|
||||
Nodes (8): generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), ArchivePage(), getPageMetadata()
|
||||
|
||||
### Community 221 - "AuthService"
|
||||
Cohesion: 0.22
|
||||
Nodes (3): AuthService, Injectable, normalizeMobile()
|
||||
### Community 221 - "AuthController"
|
||||
Cohesion: 0.20
|
||||
Nodes (5): AuthController, ApiTags, Controller, AuthService, Injectable
|
||||
|
||||
### Community 223 - "Shabnam Font README"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): Shabnam Font README, Shabnam Font Sample, Vazir Font
|
||||
|
||||
### Community 232 - "ProductDto"
|
||||
Cohesion: 0.22
|
||||
Cohesion: 0.20
|
||||
Nodes (7): ProductDto, ApiPropertyOptional, IsArray, IsBoolean, IsNumber, IsOptional, IsString
|
||||
|
||||
### Community 238 - "Body"
|
||||
Cohesion: 0.21
|
||||
Nodes (3): Body, Post, CouponInput
|
||||
|
||||
### Community 239 - "WholesaleApplyDto"
|
||||
Cohesion: 0.29
|
||||
Nodes (6): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto
|
||||
|
||||
### Community 241 - "zibal-ebank.service.ts"
|
||||
Cohesion: 0.40
|
||||
Nodes (4): EBankCheckoutListFilter, EBankCheckoutOptions, EBankIdentifiedPaymentFilter, EBankStatementFilter
|
||||
### Community 241 - "VerifyOtpDto"
|
||||
Cohesion: 0.29
|
||||
Nodes (6): ApiProperty, IsNotEmpty, IsString, Matches, VerifyOtpDto, Length
|
||||
|
||||
### Community 243 - "app.e2e-spec.js"
|
||||
Cohesion: 0.50
|
||||
Nodes (3): app_module_1, supertest_1, testing_1
|
||||
|
||||
### Community 291 - "ClientLayout.tsx"
|
||||
Cohesion: 0.18
|
||||
Nodes (11): ClientLayout(), B2BPortal(), BrandLogo(), BrandLogoProps, Footer(), MaintenancePage(), NetworkBanner(), useNetworkStatus() (+3 more)
|
||||
### Community 291 - "useSettingsStore"
|
||||
Cohesion: 0.13
|
||||
Nodes (20): ClientLayout(), BrandLogo(), BrandLogoProps, EnamadBadge(), Footer(), MENU_ICONS, MaintenancePage(), NetworkBanner() (+12 more)
|
||||
|
||||
### Community 297 - "CreateHealthLogDto"
|
||||
Cohesion: 0.29
|
||||
Nodes (6): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString
|
||||
|
||||
### Community 299 - "CreateReminderDto"
|
||||
Cohesion: 0.29
|
||||
Nodes (6): CreateReminderDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString
|
||||
|
||||
### Community 305 - "RouteErrorBoundary"
|
||||
Cohesion: 0.22
|
||||
@ -1079,27 +1095,27 @@ Nodes (3): Props, RouteErrorBoundary, State
|
||||
|
||||
### Community 310 - "admin.module.ts"
|
||||
Cohesion: 0.08
|
||||
Nodes (15): AdminModule, Module, ReportsController, ApiBearerAuth, ApiOperation, ApiTags, Controller, Get (+7 more)
|
||||
Nodes (16): AdminModule, Module, CategoryQuery, ReportsController, ApiBearerAuth, ApiOperation, ApiTags, Controller (+8 more)
|
||||
|
||||
## Knowledge Gaps
|
||||
- **1269 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1264 more)
|
||||
- **1274 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1269 more)
|
||||
These have ≤1 connection - possible missing edges or undocumented components.
|
||||
- **100 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
|
||||
- **101 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
|
||||
|
||||
## Suggested Questions
|
||||
_Questions this graph is uniquely positioned to answer:_
|
||||
|
||||
- **Why does `ApiResponse` connect `src/services/api.ts` to `OrdersService`, `BlogsController`, `UsersService`, `WikiController`, `PetsController`, `HomeController`, `ProductsService`, `auth.controller.ts`?**
|
||||
- **Why does `ApiResponse` connect `ApiResponse` to `OrdersService`, `UsersService`, `PetsController`, `ProductsService`, `src/services/api.ts`, `AuthController`?**
|
||||
_High betweenness centrality (0.064) - this node is a cross-community bridge._
|
||||
- **Why does `Roles()` connect `Roles` to `BannersService`, `CmsController`, `B2BService`, `reviews.controller.ts`, `tickets.controller.ts`, `SslController`, `IngredientsService`, `FaqService`, `MenuService`, `ContactService`, `ProductsService`, `PrescriptionsService`, `SmartAdvisorService`, `TestimonialsService`, `SmsService`, `WholesaleService`, `JwtAuthGuard`?**
|
||||
_High betweenness centrality (0.062) - this node is a cross-community bridge._
|
||||
- **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `CmsController`, `reviews.controller.ts`, `tickets.controller.ts`, `admin.service.ts`, `UsersService`, `CreateOrderDto`, `DoctorQueryDto`, `PetsController`, `ProductsService`, `CreateVideoDto`, `auth.controller.ts`, `admin.module.ts`, `PetsController`, `PaginationDto`?**
|
||||
_High betweenness centrality (0.032) - this node is a cross-community bridge._
|
||||
- **Why does `Roles()` connect `Roles` to `BannersService`, `ZibalService`, `CmsController`, `B2BService`, `reviews.controller.ts`, `tickets.controller.ts`, `SslController`, `IngredientsService`, `FaqService`, `MenuService`, `ContactService`, `ProductsService`, `PrescriptionsService`, `SmartAdvisorService`, `TestimonialsService`, `SmsService`, `WholesaleService`, `JwtAuthGuard`?**
|
||||
_High betweenness centrality (0.060) - this node is a cross-community bridge._
|
||||
- **Why does `PrismaService` connect `PrismaService` to `OrdersService`, `CmsController`, `app.module.ts`, `reviews.controller.ts`, `tickets.controller.ts`, `DoctorQueryDto`, `MenuService`, `pets/pets.controller.ts`, `auth.service.ts`, `ProductsService`, `CreateVideoDto`, `SmsService`, `WholesaleService`, `ZibalService`, `CategoriesController`, `B2BService`, `UsersService`, `IngredientsService`, `FaqService`, `MediaController`, `MetricsController`, `ContactService`, `zibal.service.ts`, `PrescriptionsService`, `SmartAdvisorService`, `TestimonialsService`, `ZibalEBankService`, `admin.module.ts`, `PetsController`, `PaginationDto`, `BannersService`, `admin.service.ts`, `seo.module.ts`, `AuthController`, `ApiResponse`, `payment.service.ts`, `PetsService`, `WholesaleApplyDto`?**
|
||||
_High betweenness centrality (0.040) - this node is a cross-community bridge._
|
||||
- **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?**
|
||||
_1269 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||
_1274 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||
- **Should `OrdersService` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.10160427807486631 - nodes in this community are weakly interconnected._
|
||||
_Cohesion score 0.059932659932659935 - nodes in this community are weakly interconnected._
|
||||
- **Should `productService.ts` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.08985200845665962 - nodes in this community are weakly interconnected._
|
||||
_Cohesion score 0.09619450317124736 - nodes in this community are weakly interconnected._
|
||||
- **Should `CmsController` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.0899854862119013 - nodes in this community are weakly interconnected._
|
||||
2
graphify-out/cache/stat-index.json
vendored
2
graphify-out/cache/stat-index.json
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
11525
graphify-out/graph.json
11525
graphify-out/graph.json
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user