fix(mobile): improve scroll restoration, media gesture swipe, 5-digit otp, persistent cooldown and modal android back navigation
This commit is contained in:
parent
00cfd1a2a0
commit
1d2d141514
@ -58,10 +58,28 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
|
||||
}
|
||||
}, [fetchProfile, fetchSettings]);
|
||||
|
||||
// Scroll to top on navigation / pathname change
|
||||
// Track navigation type (push vs pop) to allow smooth scroll restoration on Back/Forward
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined') return;
|
||||
window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
|
||||
|
||||
let popstateTriggered = false;
|
||||
const handlePopState = () => {
|
||||
popstateTriggered = true;
|
||||
};
|
||||
|
||||
window.addEventListener('popstate', handlePopState);
|
||||
|
||||
// Give microtask/frame for popstate event to register before checking
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (!popstateTriggered) {
|
||||
window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
|
||||
}
|
||||
}, 0);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('popstate', handlePopState);
|
||||
clearTimeout(timeoutId);
|
||||
};
|
||||
}, [pathname]);
|
||||
|
||||
// Check Maintenance Mode (Admin / Partner bypass)
|
||||
|
||||
@ -30,6 +30,8 @@ import { authService } from "../lib/services/authService";
|
||||
import { toast } from "sonner";
|
||||
import { toPersian, toEnglishDigits, cn } from "../lib/utils";
|
||||
|
||||
import OtpInput5 from "./OtpInput5";
|
||||
|
||||
interface AuthModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
@ -43,12 +45,15 @@ function extractOtpFromText(text: string): string {
|
||||
return clean.replace(/[^0-9]/g, "").slice(0, 5);
|
||||
}
|
||||
|
||||
// Global OTP expiry timestamp cache by phone number so switching back and forth preserves timer
|
||||
const otpCooldownExpiries: Record<string, number> = {};
|
||||
|
||||
export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
const { fetchProfile } = useUserStore();
|
||||
|
||||
// Auth navigation state
|
||||
const [authMode, setAuthMode] = useState<"login" | "register">("login");
|
||||
const [loginMethod, setLoginMethod] = useState<"otp" | "password">("password");
|
||||
const [loginMethod, setLoginMethod] = useState<"otp" | "password">("otp");
|
||||
const [subView, setSubView] = useState<"main" | "otp-verify" | "forgot-phone" | "forgot-otp" | "reset-password" | "b2b">("main");
|
||||
|
||||
// Form fields
|
||||
@ -69,28 +74,54 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [showNewPassword, setShowNewPassword] = useState(false);
|
||||
|
||||
const otpInputRef = useRef<HTMLInputElement>(null);
|
||||
const phoneNumberRef = useRef(phoneNumber);
|
||||
const subViewRef = useRef(subView);
|
||||
const isOpenRef = useRef(isOpen);
|
||||
const isB2BEnabled = useSettingsStore((s) => s.getBoolean('b2bRegistrationOpen', true) && s.getBoolean('b2b_enabled', true));
|
||||
|
||||
useEffect(() => {
|
||||
phoneNumberRef.current = phoneNumber;
|
||||
}, [phoneNumber]);
|
||||
|
||||
// Focus retry when OTP input is shown
|
||||
useEffect(() => {
|
||||
if (subView === "otp-verify" || subView === "forgot-otp") {
|
||||
const timers = [50, 150, 300, 500].map((delay) =>
|
||||
setTimeout(() => {
|
||||
if (otpInputRef.current) {
|
||||
otpInputRef.current.focus({ preventScroll: true });
|
||||
}
|
||||
}, delay),
|
||||
);
|
||||
return () => timers.forEach((t) => clearTimeout(t));
|
||||
}
|
||||
subViewRef.current = subView;
|
||||
}, [subView]);
|
||||
|
||||
useEffect(() => {
|
||||
isOpenRef.current = isOpen;
|
||||
}, [isOpen]);
|
||||
|
||||
// Handle hardware / browser back button for Android & mobile navigation
|
||||
useEffect(() => {
|
||||
if (!isOpen) return;
|
||||
|
||||
// Push a state for this modal level
|
||||
const currentState = window.history.state || {};
|
||||
window.history.pushState({ ...currentState, __authModalOpen: true, __subView: subView }, "");
|
||||
|
||||
const handlePopState = (e: PopStateEvent) => {
|
||||
// If user hit Android back button
|
||||
if (subViewRef.current !== "main") {
|
||||
// Go back inside modal
|
||||
if (subViewRef.current === "forgot-otp") {
|
||||
setSubView("forgot-phone");
|
||||
} else if (subViewRef.current === "reset-password") {
|
||||
setSubView("forgot-phone");
|
||||
} else {
|
||||
setSubView("main");
|
||||
}
|
||||
} else {
|
||||
// In main view: close modal without navigating the page behind
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("popstate", handlePopState);
|
||||
return () => {
|
||||
window.removeEventListener("popstate", handlePopState);
|
||||
};
|
||||
}, [isOpen, subView, onClose]);
|
||||
|
||||
// Reset modal state on open/close
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
@ -167,9 +198,6 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
const clean = extractOtpFromText(otp.code);
|
||||
if (clean) {
|
||||
setOtpCode(clean);
|
||||
if (otpInputRef.current) {
|
||||
otpInputRef.current.value = clean;
|
||||
}
|
||||
if (clean.length === 5 && subView === "otp-verify") {
|
||||
triggerVerifyOtp(clean);
|
||||
}
|
||||
@ -179,39 +207,15 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
const inputEl = otpInputRef.current;
|
||||
const handleDomAutofill = (e: Event) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
if (target && target.value) {
|
||||
const clean = extractOtpFromText(target.value);
|
||||
setOtpCode(clean);
|
||||
if (clean.length === 5 && subView === "otp-verify") {
|
||||
triggerVerifyOtp(clean);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (inputEl) {
|
||||
inputEl.addEventListener("input", handleDomAutofill);
|
||||
inputEl.addEventListener("change", handleDomAutofill);
|
||||
}
|
||||
|
||||
return () => {
|
||||
isMounted = false;
|
||||
ac.abort();
|
||||
if (inputEl) {
|
||||
inputEl.removeEventListener("input", handleDomAutofill);
|
||||
inputEl.removeEventListener("change", handleDomAutofill);
|
||||
}
|
||||
};
|
||||
}, [subView, triggerVerifyOtp]);
|
||||
|
||||
const handleOtpChange = (val: string) => {
|
||||
const clean = extractOtpFromText(val);
|
||||
setOtpCode(clean);
|
||||
if (otpInputRef.current && otpInputRef.current.value !== clean) {
|
||||
otpInputRef.current.value = clean;
|
||||
}
|
||||
if (clean.length === 5 && subView === "otp-verify") {
|
||||
triggerVerifyOtp(clean);
|
||||
}
|
||||
@ -225,6 +229,17 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if cooldown is still active for this phone number
|
||||
const now = Date.now();
|
||||
const existingExpiry = otpCooldownExpiries[cleanPhone] || 0;
|
||||
const remainingSeconds = Math.max(0, Math.ceil((existingExpiry - now) / 1000));
|
||||
|
||||
if (remainingSeconds > 0) {
|
||||
setCountdown(remainingSeconds);
|
||||
setSubView("otp-verify");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const res = await authService.sendOtp(cleanPhone);
|
||||
@ -235,6 +250,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
toast.success("کد تایید با موفقیت پیامک شد");
|
||||
}
|
||||
setSubView("otp-verify");
|
||||
otpCooldownExpiries[cleanPhone] = Date.now() + 120 * 1000;
|
||||
setCountdown(120);
|
||||
} catch (err: unknown) {
|
||||
const errObj = err as { message?: string };
|
||||
@ -302,10 +318,12 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
|
||||
const handleResendOtp = async () => {
|
||||
if (countdown > 0) return;
|
||||
const cleanPhone = toEnglishDigits(phoneNumber).trim();
|
||||
setIsLoading(true);
|
||||
try {
|
||||
await authService.sendOtp(toEnglishDigits(phoneNumber).trim());
|
||||
await authService.sendOtp(cleanPhone);
|
||||
toast.success("کد تایید جدید پیامک شد");
|
||||
otpCooldownExpiries[cleanPhone] = Date.now() + 120 * 1000;
|
||||
setCountdown(120);
|
||||
} catch (err: unknown) {
|
||||
const errObj = err as { message?: string };
|
||||
@ -483,7 +501,7 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
)}
|
||||
>
|
||||
<KeyRound className="w-3 h-3" />
|
||||
<span>رمز عبور (پیشفرض)</span>
|
||||
<span>رمز عبور</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@ -765,29 +783,13 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
<label className="text-[11px] font-black text-medical-gray-500 block text-center">
|
||||
کد ۵ رقمی ارسالشده به موبایل خود را وارد نمایید
|
||||
</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
ref={otpInputRef}
|
||||
id="otp-code-input"
|
||||
name="one-time-code"
|
||||
type="tel"
|
||||
inputMode="numeric"
|
||||
pattern="[0-9]*"
|
||||
autoComplete="one-time-code"
|
||||
placeholder="• • • • •"
|
||||
value={otpCode}
|
||||
onChange={(e) => handleOtpChange(e.target.value)}
|
||||
onInput={(e) => handleOtpChange((e.target as HTMLInputElement).value)}
|
||||
onPaste={(e) => {
|
||||
e.preventDefault();
|
||||
const pasted = e.clipboardData.getData('text');
|
||||
handleOtpChange(pasted);
|
||||
}}
|
||||
disabled={isLoading}
|
||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-4 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold text-center text-2xl font-mono tracking-[0.4em]"
|
||||
dir="ltr"
|
||||
/>
|
||||
</div>
|
||||
<OtpInput5
|
||||
value={otpCode}
|
||||
onChange={handleOtpChange}
|
||||
disabled={isLoading}
|
||||
autoFocus={true}
|
||||
onComplete={(code) => triggerVerifyOtp(code)}
|
||||
/>
|
||||
<p className="text-[10px] text-medical-gray-400 text-center font-medium">
|
||||
در صورت دریافت پیامک، کد به صورت خودکار شناسایی و وارد میشود.
|
||||
</p>
|
||||
@ -907,20 +909,12 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
<label className="text-[11px] font-black text-medical-gray-500 block text-center font-vazir">
|
||||
کد ۵ رقمی بازیابی پیامکشده را وارد کنید
|
||||
</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
ref={otpInputRef}
|
||||
autoFocus
|
||||
type="text"
|
||||
inputMode="numeric"
|
||||
autoComplete="one-time-code"
|
||||
placeholder="• • • • •"
|
||||
value={otpCode}
|
||||
onChange={(e) => setOtpCode(toEnglishDigits(e.target.value).replace(/[^0-9]/g, "").slice(0, 5))}
|
||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 px-4 focus:ring-2 focus:ring-canina-blue/20 outline-none text-center font-mono font-bold text-2xl tracking-[0.4em]"
|
||||
dir="ltr"
|
||||
/>
|
||||
</div>
|
||||
<OtpInput5
|
||||
value={otpCode}
|
||||
onChange={(val) => setOtpCode(val)}
|
||||
disabled={isLoading}
|
||||
autoFocus={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
|
||||
@ -7,6 +7,8 @@ import { useUserStore } from "../lib/store/userStore";
|
||||
import { toast } from "sonner";
|
||||
import { toPersian } from "../lib/utils";
|
||||
|
||||
import OtpInput5 from "./OtpInput5";
|
||||
|
||||
interface LoginModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
@ -15,6 +17,8 @@ interface LoginModalProps {
|
||||
isAdvisorContext?: boolean;
|
||||
}
|
||||
|
||||
const loginOtpCooldownExpiries: Record<string, number> = {};
|
||||
|
||||
export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdvisorContext }: LoginModalProps) {
|
||||
const [step, setStep] = useState<"phone" | "otp">("phone");
|
||||
const [phoneNumber, setPhoneNumber] = useState("");
|
||||
@ -22,17 +26,33 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [countdown, setCountdown] = useState(0);
|
||||
const { fetchProfile } = useUserStore();
|
||||
const otpInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const stepRef = useRef(step);
|
||||
useEffect(() => {
|
||||
if (step === "otp") {
|
||||
const timer = setTimeout(() => {
|
||||
otpInputRef.current?.focus();
|
||||
}, 100);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
stepRef.current = step;
|
||||
}, [step]);
|
||||
|
||||
// Handle hardware / Android back button
|
||||
useEffect(() => {
|
||||
if (!isOpen) return;
|
||||
|
||||
const currentState = window.history.state || {};
|
||||
window.history.pushState({ ...currentState, __loginModalOpen: true, __loginStep: step }, "");
|
||||
|
||||
const handlePopState = () => {
|
||||
if (stepRef.current === "otp") {
|
||||
setStep("phone");
|
||||
} else {
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("popstate", handlePopState);
|
||||
return () => {
|
||||
window.removeEventListener("popstate", handlePopState);
|
||||
};
|
||||
}, [isOpen, step, onClose]);
|
||||
|
||||
const handleVerifyOtpWithCode = React.useCallback(async (code: string) => {
|
||||
const cleanCode = code.trim();
|
||||
if (cleanCode.length !== 5) {
|
||||
@ -69,8 +89,11 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
||||
})
|
||||
.then((otp) => {
|
||||
if (otp && otp.code) {
|
||||
setOtpCode(otp.code);
|
||||
handleVerifyOtpWithCode(otp.code);
|
||||
const clean = otp.code.replace(/[^0-9]/g, "").slice(0, 5);
|
||||
setOtpCode(clean);
|
||||
if (clean.length === 5) {
|
||||
handleVerifyOtpWithCode(clean);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
@ -80,23 +103,6 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
||||
}
|
||||
}, [step, handleVerifyOtpWithCode]);
|
||||
|
||||
const handleOtpInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const val = e.target.value.replace(/[^0-9]/g, "").slice(0, 5);
|
||||
setOtpCode(val);
|
||||
if (val.length === 5) {
|
||||
handleVerifyOtpWithCode(val);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOtpPaste = (e: React.ClipboardEvent<HTMLInputElement>) => {
|
||||
const pasted = e.clipboardData.getData("text").replace(/[^0-9]/g, "").slice(0, 5);
|
||||
if (pasted.length === 5) {
|
||||
e.preventDefault();
|
||||
setOtpCode(pasted);
|
||||
handleVerifyOtpWithCode(pasted);
|
||||
}
|
||||
};
|
||||
|
||||
// Reset modal state when closed or opened
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
@ -126,6 +132,16 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
||||
return;
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const existingExpiry = loginOtpCooldownExpiries[cleanPhone] || 0;
|
||||
const remainingSeconds = Math.max(0, Math.ceil((existingExpiry - now) / 1000));
|
||||
|
||||
if (remainingSeconds > 0) {
|
||||
setCountdown(remainingSeconds);
|
||||
setStep("otp");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const res = await authService.sendOtp(cleanPhone);
|
||||
@ -136,7 +152,8 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
||||
toast.success("کد تایید پیامک شد");
|
||||
}
|
||||
setStep("otp");
|
||||
setCountdown(120); // 2 minutes cooldown
|
||||
loginOtpCooldownExpiries[cleanPhone] = Date.now() + 120 * 1000;
|
||||
setCountdown(120);
|
||||
} catch (err: unknown) {
|
||||
const errObj = err as { message?: string };
|
||||
toast.error(errObj.message || "خطا در ارسال کد تایید");
|
||||
@ -152,10 +169,12 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
||||
|
||||
const handleResendOtp = async () => {
|
||||
if (countdown > 0) return;
|
||||
const cleanPhone = phoneNumber.trim();
|
||||
setIsLoading(true);
|
||||
try {
|
||||
await authService.sendOtp(phoneNumber.trim());
|
||||
await authService.sendOtp(cleanPhone);
|
||||
toast.success("کد تایید جدید ارسال شد");
|
||||
loginOtpCooldownExpiries[cleanPhone] = Date.now() + 120 * 1000;
|
||||
setCountdown(120);
|
||||
} catch (err: unknown) {
|
||||
const errObj = err as { message?: string };
|
||||
@ -278,19 +297,13 @@ export default function LoginModal({ isOpen, onClose, onLogin, petName, isAdviso
|
||||
ویرایش شماره
|
||||
</button>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<Key className="absolute right-4 top-1/2 -translate-y-1/2 w-5 h-5 text-medical-gray-400" />
|
||||
<input
|
||||
ref={otpInputRef}
|
||||
type="text"
|
||||
maxLength={5}
|
||||
autoComplete="one-time-code"
|
||||
placeholder="کد ۵ رقمی"
|
||||
<div>
|
||||
<OtpInput5
|
||||
value={otpCode}
|
||||
onChange={handleOtpInputChange}
|
||||
onPaste={handleOtpPaste}
|
||||
onChange={(val) => setOtpCode(val)}
|
||||
disabled={isLoading}
|
||||
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canina-blue/20 focus:border-canina-blue outline-none font-black text-2xl text-center tracking-[0.5em]"
|
||||
autoFocus={true}
|
||||
onComplete={(code) => handleVerifyOtpWithCode(code)}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-[10px] text-medical-gray-400 font-bold text-center mt-2">
|
||||
|
||||
142
frontend/application/components/OtpInput5.tsx
Normal file
142
frontend/application/components/OtpInput5.tsx
Normal file
@ -0,0 +1,142 @@
|
||||
"use client";
|
||||
|
||||
import React, { useRef, useEffect } from "react";
|
||||
import { toEnglishDigits } from "../lib/utils";
|
||||
|
||||
interface OtpInput5Props {
|
||||
value: string;
|
||||
onChange: (val: string) => void;
|
||||
disabled?: boolean;
|
||||
autoFocus?: boolean;
|
||||
onComplete?: (code: string) => void;
|
||||
}
|
||||
|
||||
export default function OtpInput5({
|
||||
value,
|
||||
onChange,
|
||||
disabled = false,
|
||||
autoFocus = true,
|
||||
onComplete,
|
||||
}: OtpInput5Props) {
|
||||
const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
|
||||
|
||||
// Array of 5 characters
|
||||
const digits = Array.from({ length: 5 }, (_, i) => value[i] || "");
|
||||
|
||||
useEffect(() => {
|
||||
if (autoFocus && inputRefs.current[0]) {
|
||||
const timer = setTimeout(() => {
|
||||
inputRefs.current[0]?.focus({ preventScroll: true });
|
||||
}, 80);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}, [autoFocus]);
|
||||
|
||||
const handleDigitChange = (index: number, char: string) => {
|
||||
const cleanChars = toEnglishDigits(char).replace(/[^0-9]/g, "");
|
||||
if (!cleanChars) {
|
||||
// Empty / Backspace in controlled input
|
||||
const newDigits = [...digits];
|
||||
newDigits[index] = "";
|
||||
const newVal = newDigits.join("");
|
||||
onChange(newVal);
|
||||
return;
|
||||
}
|
||||
|
||||
// If multiple chars pasted or typed
|
||||
if (cleanChars.length > 1) {
|
||||
const slice5 = cleanChars.slice(0, 5);
|
||||
onChange(slice5);
|
||||
const nextIndex = Math.min(slice5.length, 4);
|
||||
inputRefs.current[nextIndex]?.focus();
|
||||
if (slice5.length === 5 && onComplete) {
|
||||
onComplete(slice5);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const single = cleanChars[0];
|
||||
const newDigits = [...digits];
|
||||
newDigits[index] = single;
|
||||
const newVal = newDigits.join("");
|
||||
onChange(newVal);
|
||||
|
||||
if (index < 4) {
|
||||
inputRefs.current[index + 1]?.focus();
|
||||
}
|
||||
|
||||
if (newVal.length === 5 && onComplete) {
|
||||
onComplete(newVal);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (index: number, e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Backspace") {
|
||||
if (!digits[index] && index > 0) {
|
||||
// Move to previous and clear
|
||||
inputRefs.current[index - 1]?.focus();
|
||||
const newDigits = [...digits];
|
||||
newDigits[index - 1] = "";
|
||||
onChange(newDigits.join(""));
|
||||
}
|
||||
} else if (e.key === "ArrowLeft") {
|
||||
// In LTR inputs, Left goes to previous
|
||||
if (index > 0) {
|
||||
inputRefs.current[index - 1]?.focus();
|
||||
}
|
||||
} else if (e.key === "ArrowRight") {
|
||||
// In LTR inputs, Right goes to next
|
||||
if (index < 4) {
|
||||
inputRefs.current[index + 1]?.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handlePaste = (e: React.ClipboardEvent) => {
|
||||
e.preventDefault();
|
||||
const pasted = e.clipboardData.getData("text");
|
||||
const clean = toEnglishDigits(pasted).replace(/[^0-9]/g, "").slice(0, 5);
|
||||
if (clean) {
|
||||
onChange(clean);
|
||||
const targetIndex = Math.min(clean.length, 4);
|
||||
inputRefs.current[targetIndex]?.focus();
|
||||
if (clean.length === 5 && onComplete) {
|
||||
onComplete(clean);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-2.5 sm:gap-3.5 my-2" dir="ltr">
|
||||
{[0, 1, 2, 3, 4].map((idx) => {
|
||||
const val = digits[idx] || "";
|
||||
const isFilled = Boolean(val);
|
||||
|
||||
return (
|
||||
<input
|
||||
key={idx}
|
||||
ref={(el) => {
|
||||
inputRefs.current[idx] = el;
|
||||
}}
|
||||
type="tel"
|
||||
inputMode="numeric"
|
||||
pattern="[0-9]*"
|
||||
maxLength={1}
|
||||
autoComplete={idx === 0 ? "one-time-code" : "off"}
|
||||
value={val}
|
||||
disabled={disabled}
|
||||
onChange={(e) => handleDigitChange(idx, e.target.value)}
|
||||
onKeyDown={(e) => handleKeyDown(idx, e)}
|
||||
onPaste={handlePaste}
|
||||
onFocus={(e) => e.target.select()}
|
||||
className={`w-12 h-14 sm:w-14 sm:h-16 text-center text-xl sm:text-2xl font-black font-mono rounded-2xl border-2 transition-all outline-none shadow-xs ${
|
||||
isFilled
|
||||
? "border-canina-blue bg-canina-blue/5 text-canina-blue ring-2 ring-canina-blue/20"
|
||||
: "border-medical-gray-200 bg-medical-gray-50/80 text-medical-gray-900 focus:border-canina-blue focus:bg-white focus:ring-4 focus:ring-canina-blue/15"
|
||||
} ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-text"}`}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
"use client";
|
||||
import { useState, useMemo, useEffect } from "react";
|
||||
import { useState, useMemo, useEffect, useRef } from "react";
|
||||
import { motion, AnimatePresence } from "motion/react";
|
||||
import {
|
||||
ArrowRight,
|
||||
@ -148,6 +148,18 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
description?: string;
|
||||
} | null>(null);
|
||||
|
||||
const thumbnailContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Auto-scroll active thumbnail into view when changed via gesture/click
|
||||
useEffect(() => {
|
||||
if (thumbnailContainerRef.current) {
|
||||
const activeEl = thumbnailContainerRef.current.children[activeMediaIndex] as HTMLElement;
|
||||
if (activeEl) {
|
||||
activeEl.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
|
||||
}
|
||||
}
|
||||
}, [activeMediaIndex]);
|
||||
|
||||
useEffect(() => {
|
||||
Promise.resolve().then(() => setIsMounted(true));
|
||||
}, []);
|
||||
@ -442,7 +454,32 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
initial={{ opacity: 0, scale: 0.96 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
className="bg-white rounded-2xl sm:rounded-[2.5rem] border border-medical-gray-200 shadow-xl relative group overflow-hidden h-[280px] sm:h-[390px] flex items-center justify-center p-2 sm:p-4 select-none"
|
||||
drag="x"
|
||||
dragConstraints={{ left: 0, right: 0 }}
|
||||
dragElastic={0.2}
|
||||
onDragEnd={(e, info) => {
|
||||
const swipeThreshold = 50;
|
||||
if (info.offset.x > swipeThreshold || info.velocity.x > 300) {
|
||||
// Swipe right -> in RTL, swipe right goes to previous item, or left/right intuitive navigation
|
||||
if (activeMediaIndex > 0) {
|
||||
const newIdx = activeMediaIndex - 1;
|
||||
setActiveMediaIndex(newIdx);
|
||||
if (galleryMedia[newIdx]?.type === 'image') {
|
||||
setActiveImage(galleryMedia[newIdx].url);
|
||||
}
|
||||
}
|
||||
} else if (info.offset.x < -swipeThreshold || info.velocity.x < -300) {
|
||||
// Swipe left -> go to next item
|
||||
if (activeMediaIndex < galleryMedia.length - 1) {
|
||||
const newIdx = activeMediaIndex + 1;
|
||||
setActiveMediaIndex(newIdx);
|
||||
if (galleryMedia[newIdx]?.type === 'image') {
|
||||
setActiveImage(galleryMedia[newIdx].url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
className="bg-white rounded-2xl sm:rounded-[2.5rem] border border-medical-gray-200 shadow-xl relative group overflow-hidden h-[280px] sm:h-[390px] flex items-center justify-center p-2 sm:p-4 select-none touch-pan-y cursor-grab active:cursor-grabbing"
|
||||
>
|
||||
{/* Top Floating Badges */}
|
||||
<div className="absolute top-4 left-4 sm:top-6 sm:left-6 flex flex-col gap-1.5 sm:gap-2 z-10 items-start pointer-events-none">
|
||||
@ -577,7 +614,10 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
|
||||
{/* Multiple Gallery Media Thumbnails Strip */}
|
||||
{galleryMedia.length > 1 && (
|
||||
<div className="flex items-center gap-2 overflow-x-auto py-2 px-1 sleek-hscroll">
|
||||
<div
|
||||
ref={thumbnailContainerRef}
|
||||
className="flex items-center gap-2 overflow-x-auto py-2 px-1 sleek-hscroll touch-pan-x cursor-grab active:cursor-grabbing select-none"
|
||||
>
|
||||
{galleryMedia.map((item, idx) => {
|
||||
const isSelected = activeMediaIndex === idx;
|
||||
|
||||
@ -601,12 +641,12 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
src={item.thumbnail || item.url || product.image}
|
||||
alt={`${product.name} - ${idx + 1}`}
|
||||
className="w-full h-full"
|
||||
imgClassName="w-full h-full object-contain"
|
||||
imgClassName="w-full h-full object-contain pointer-events-none"
|
||||
/>
|
||||
|
||||
{/* Video Overlay Badge on thumbnail */}
|
||||
{item.type === 'video' && (
|
||||
<div className="absolute inset-0 bg-black/40 flex items-center justify-center">
|
||||
<div className="absolute inset-0 bg-black/40 flex items-center justify-center pointer-events-none">
|
||||
<div className="w-6 h-6 rounded-full bg-canina-blue text-white flex items-center justify-center shadow-md">
|
||||
<Play className="w-3 h-3 fill-white ml-0.5" />
|
||||
</div>
|
||||
@ -618,7 +658,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
|
||||
{/* Podcast Overlay Badge on thumbnail */}
|
||||
{item.type === 'podcast' && (
|
||||
<div className="absolute inset-0 bg-purple-950/60 flex items-center justify-center">
|
||||
<div className="absolute inset-0 bg-purple-950/60 flex items-center justify-center pointer-events-none">
|
||||
<div className="w-6 h-6 rounded-full bg-purple-600 text-white flex items-center justify-center shadow-md">
|
||||
<Headphones className="w-3.5 h-3.5 text-white" />
|
||||
</div>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
{
|
||||
"0": "Roles",
|
||||
"1": "app.module.ts",
|
||||
"2": "getMediaUrl",
|
||||
"2": "VetGallery.tsx",
|
||||
"3": "productService.ts",
|
||||
"4": "PetProfile.tsx",
|
||||
"4": "useSettingsStore",
|
||||
"5": "CmsController",
|
||||
"6": "tickets.controller.ts",
|
||||
"7": "SmsSettingsPage.tsx",
|
||||
@ -20,7 +20,7 @@
|
||||
"18": "JwtAuthGuard",
|
||||
"19": "admin.controller.ts",
|
||||
"20": "CreateVideoDto",
|
||||
"21": "auth.module.ts",
|
||||
"21": "pets/pets.controller.ts",
|
||||
"22": "ProductDto",
|
||||
"23": "MenuService",
|
||||
"24": "BE-001",
|
||||
@ -33,7 +33,7 @@
|
||||
"31": "DOC-001",
|
||||
"32": "adminRoutes.tsx",
|
||||
"33": "WholesaleApplyDto",
|
||||
"34": "B2BService",
|
||||
"34": "B2BController",
|
||||
"35": "ContactService",
|
||||
"36": "FaqController",
|
||||
"37": "راهنمای تست سیستم (Software Testing)",
|
||||
@ -42,12 +42,12 @@
|
||||
"40": "MediaController",
|
||||
"41": "What You Must Do When Invoked",
|
||||
"42": "SslController",
|
||||
"43": "BannersService",
|
||||
"44": "TestimonialsService",
|
||||
"43": "BannersController",
|
||||
"44": "TestimonialsController",
|
||||
"45": "What You Must Do When Invoked",
|
||||
"46": "20260526145407_init/migration.sql",
|
||||
"47": "IngredientsService",
|
||||
"48": "AuthController",
|
||||
"47": "IngredientsController",
|
||||
"48": "WikiController",
|
||||
"49": "devDependencies",
|
||||
"50": "devDependencies",
|
||||
"51": "BlogsController",
|
||||
@ -57,17 +57,17 @@
|
||||
"55": "UITexts.tsx",
|
||||
"56": "Orders.tsx",
|
||||
"57": "Role & Core Objective",
|
||||
"58": "auth.service.ts",
|
||||
"58": "AuthService",
|
||||
"59": "compilerOptions",
|
||||
"60": "CreateUserDto",
|
||||
"61": "ProductPage.tsx",
|
||||
"62": "torob.controller.ts",
|
||||
"62": "ReportsController",
|
||||
"63": "dependencies",
|
||||
"64": "compilerOptions",
|
||||
"65": "admin.service.ts",
|
||||
"66": "AdminQueryDto",
|
||||
"66": "ApiOperation",
|
||||
"67": "admin.module.ts",
|
||||
"68": "useSettingsStore",
|
||||
"68": "HomeClient.tsx",
|
||||
"69": "Required Review Group Closures",
|
||||
"70": "compilerOptions",
|
||||
"71": "getPageMetadata",
|
||||
@ -84,12 +84,12 @@
|
||||
"82": "scripts",
|
||||
"83": "dependencies",
|
||||
"84": "Role & Core Objective",
|
||||
"85": "auth.controller.ts",
|
||||
"85": "auth.service.ts",
|
||||
"86": "zibal.service.ts",
|
||||
"87": "dependencies",
|
||||
"88": "CreateEBankCheckoutDto",
|
||||
"89": "seed-products.ts",
|
||||
"90": "orderService.ts",
|
||||
"90": "cartStore.ts",
|
||||
"91": "Reconciled Audit Roles & Assignments",
|
||||
"92": "OrdersService",
|
||||
"93": "components/Skeleton.tsx",
|
||||
@ -112,7 +112,7 @@
|
||||
"110": "Operational Rules & Boundaries",
|
||||
"111": "Operational Rules & Boundaries",
|
||||
"112": "Operational Rules & Boundaries",
|
||||
"113": "PetsController",
|
||||
"113": "MetricsController",
|
||||
"114": "AppService",
|
||||
"115": "Spinner.tsx",
|
||||
"116": "Vazirmatn Changelog",
|
||||
@ -122,12 +122,12 @@
|
||||
"120": "compilerOptions",
|
||||
"121": "backend/README.md",
|
||||
"122": "AdminService",
|
||||
"123": "UsersController",
|
||||
"123": "B2BService",
|
||||
"124": "Repository Map",
|
||||
"125": "validate_integrity.js",
|
||||
"126": "admin-panel/package.json",
|
||||
"127": "Sahel-Font",
|
||||
"128": "Body",
|
||||
"128": "zibal-ebank.service.ts",
|
||||
"129": "Reports.tsx",
|
||||
"130": "Sahel-Font",
|
||||
"131": "Role & Core Objective",
|
||||
@ -144,14 +144,14 @@
|
||||
"142": "start-dev.js",
|
||||
"143": "generate-openapi.js",
|
||||
"144": "lib/services/api.ts",
|
||||
"145": "orders.service.ts",
|
||||
"145": "trust-seals/page.tsx",
|
||||
"146": "System Discovery",
|
||||
"147": "HomeController",
|
||||
"148": "RouteErrorBoundary",
|
||||
"149": "wiki/[slug]/page.tsx",
|
||||
"150": "Product Requirement Document (PRD)",
|
||||
"151": "AddressDto",
|
||||
"152": "RedisService",
|
||||
"151": "@nestjs/swagger",
|
||||
"152": "RevalidationService",
|
||||
"153": "exclude",
|
||||
"154": "Baseline Command Plan & Reconciled Command History",
|
||||
"155": "seo-backfill.ts",
|
||||
@ -196,9 +196,9 @@
|
||||
"194": "Raw Finding Verification & Disposition Report",
|
||||
"195": "React + TypeScript + Vite",
|
||||
"196": "Select.tsx",
|
||||
"197": "ClientLayout.tsx",
|
||||
"197": "toPersian",
|
||||
"198": "@tailwindcss/postcss",
|
||||
"199": "track/page.tsx",
|
||||
"199": "prisma",
|
||||
"200": "application/README.md",
|
||||
"201": "deploy.sh",
|
||||
"202": "🔒 Security & Performance Review (09_devops_security)",
|
||||
@ -219,7 +219,7 @@
|
||||
"217": "sync_honest_manifest.js",
|
||||
"218": "sync_manifest.js",
|
||||
"219": "FormField.tsx",
|
||||
"220": "class-transformer",
|
||||
"220": "eslint-config-next",
|
||||
"221": "Textarea.tsx",
|
||||
"222": "admin-panel/tsconfig.json",
|
||||
"223": "tailwindcss",
|
||||
@ -303,7 +303,6 @@
|
||||
"301": "reflect-metadata",
|
||||
"302": "typescript-eslint",
|
||||
"303": "swagger-ui-express",
|
||||
"304": "eslint",
|
||||
"305": "eslint-config-prettier",
|
||||
"306": "@eslint/js",
|
||||
"307": "@eslint/eslintrc",
|
||||
@ -327,6 +326,5 @@
|
||||
"325": "@types/react-dom",
|
||||
"326": "@types/supertest",
|
||||
"327": "eslint-plugin-react-refresh",
|
||||
"328": "tailwindcss",
|
||||
"329": "typescript-eslint"
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,26 +1,26 @@
|
||||
{
|
||||
"0": "Roles",
|
||||
"1": "app.module.ts",
|
||||
"2": "payment.service.ts",
|
||||
"2": "getMediaUrl",
|
||||
"3": "productService.ts",
|
||||
"4": "UserDashboard.tsx",
|
||||
"4": "PetProfile.tsx",
|
||||
"5": "CmsController",
|
||||
"6": "tickets.controller.ts",
|
||||
"7": "SmsSettingsPage.tsx",
|
||||
"8": "SmsService",
|
||||
"9": "devDependencies",
|
||||
"10": "ReviewsService",
|
||||
"11": "ConfirmModal.tsx",
|
||||
"10": "reviews.controller.ts",
|
||||
"11": "UsersService",
|
||||
"12": "index.ts",
|
||||
"13": "app-audit-verification.e2e-spec.js",
|
||||
"14": "toPersian",
|
||||
"14": "UserDashboard.tsx",
|
||||
"15": "src/services/api.ts",
|
||||
"16": "DoctorQueryDto",
|
||||
"17": "schema.ts",
|
||||
"18": "JwtAuthGuard",
|
||||
"19": "admin.controller.ts",
|
||||
"20": "CreateVideoDto",
|
||||
"21": "auth.service.ts",
|
||||
"21": "auth.module.ts",
|
||||
"22": "ProductDto",
|
||||
"23": "MenuService",
|
||||
"24": "BE-001",
|
||||
@ -35,7 +35,7 @@
|
||||
"33": "WholesaleApplyDto",
|
||||
"34": "B2BService",
|
||||
"35": "ContactService",
|
||||
"36": "FaqService",
|
||||
"36": "FaqController",
|
||||
"37": "راهنمای تست سیستم (Software Testing)",
|
||||
"38": "Button",
|
||||
"39": "CategoriesController",
|
||||
@ -51,13 +51,13 @@
|
||||
"49": "devDependencies",
|
||||
"50": "devDependencies",
|
||||
"51": "BlogsController",
|
||||
"52": "PrescriptionsService",
|
||||
"52": "prescriptions.controller.ts",
|
||||
"53": "SmartAdvisorService",
|
||||
"54": "Button.tsx",
|
||||
"55": "UITexts.tsx",
|
||||
"56": "Orders.tsx",
|
||||
"57": "Role & Core Objective",
|
||||
"58": "AuthService",
|
||||
"58": "auth.service.ts",
|
||||
"59": "compilerOptions",
|
||||
"60": "CreateUserDto",
|
||||
"61": "ProductPage.tsx",
|
||||
@ -84,15 +84,15 @@
|
||||
"82": "scripts",
|
||||
"83": "dependencies",
|
||||
"84": "Role & Core Objective",
|
||||
"85": "RegisterDto",
|
||||
"85": "auth.controller.ts",
|
||||
"86": "zibal.service.ts",
|
||||
"87": "dependencies",
|
||||
"88": "CreateEBankCheckoutDto",
|
||||
"89": "seed-products.ts",
|
||||
"90": "useCartStore",
|
||||
"90": "orderService.ts",
|
||||
"91": "Reconciled Audit Roles & Assignments",
|
||||
"92": "OrdersService",
|
||||
"93": "ArchivePage.tsx",
|
||||
"93": "components/Skeleton.tsx",
|
||||
"94": "Phase 3.1 — Human Review Preparation and Master Backlog Critique",
|
||||
"95": "getSeoConfig",
|
||||
"96": "compilerOptions",
|
||||
@ -122,7 +122,7 @@
|
||||
"120": "compilerOptions",
|
||||
"121": "backend/README.md",
|
||||
"122": "AdminService",
|
||||
"123": "UsersService",
|
||||
"123": "UsersController",
|
||||
"124": "Repository Map",
|
||||
"125": "validate_integrity.js",
|
||||
"126": "admin-panel/package.json",
|
||||
@ -143,15 +143,15 @@
|
||||
"141": "application/package.json",
|
||||
"142": "start-dev.js",
|
||||
"143": "generate-openapi.js",
|
||||
"144": "PodcastPlayerModal.tsx",
|
||||
"145": "AdminLoginDto",
|
||||
"144": "lib/services/api.ts",
|
||||
"145": "orders.service.ts",
|
||||
"146": "System Discovery",
|
||||
"147": "HomeController",
|
||||
"148": "VerifyOtpDto",
|
||||
"148": "RouteErrorBoundary",
|
||||
"149": "wiki/[slug]/page.tsx",
|
||||
"150": "Product Requirement Document (PRD)",
|
||||
"151": "@types/node",
|
||||
"152": "RevalidationService",
|
||||
"151": "AddressDto",
|
||||
"152": "RedisService",
|
||||
"153": "exclude",
|
||||
"154": "Baseline Command Plan & Reconciled Command History",
|
||||
"155": "seo-backfill.ts",
|
||||
@ -183,8 +183,8 @@
|
||||
"181": "⚙️ Backend Technical Review (05_dev_backend)",
|
||||
"182": "🎨 Frontend & Admin Panel Technical Review (06_dev_frontend)",
|
||||
"183": "🚀 SEO & Content Strategy Review (12_seo_content)",
|
||||
"184": "AppModule",
|
||||
"185": "eslint-config-next",
|
||||
"184": "FaqService",
|
||||
"185": "Reviews.tsx",
|
||||
"186": "seed-ui-texts.ts",
|
||||
"187": "seed-wiki.ts",
|
||||
"188": "update-blog.dto.ts",
|
||||
@ -196,13 +196,14 @@
|
||||
"194": "Raw Finding Verification & Disposition Report",
|
||||
"195": "React + TypeScript + Vite",
|
||||
"196": "Select.tsx",
|
||||
"197": "userStore.ts",
|
||||
"197": "ClientLayout.tsx",
|
||||
"198": "@tailwindcss/postcss",
|
||||
"199": "SmsLogQueryDto",
|
||||
"199": "track/page.tsx",
|
||||
"200": "application/README.md",
|
||||
"201": "deploy.sh",
|
||||
"202": "🔒 Security & Performance Review (09_devops_security)",
|
||||
"203": "👁️ UX & Persona Interface Review (08_visual_qa)",
|
||||
"204": "bcrypt",
|
||||
"205": "prisma/scientificTerms.ts",
|
||||
"206": "seed-blogs.ts",
|
||||
"207": "seed-custom.ts",
|
||||
@ -218,9 +219,11 @@
|
||||
"217": "sync_honest_manifest.js",
|
||||
"218": "sync_manifest.js",
|
||||
"219": "FormField.tsx",
|
||||
"220": "class-transformer",
|
||||
"221": "Textarea.tsx",
|
||||
"222": "admin-panel/tsconfig.json",
|
||||
"223": "tailwindcss",
|
||||
"224": "helmet",
|
||||
"225": "next.config.ts",
|
||||
"226": "Shabnam Font README",
|
||||
"227": "AGENTS.md",
|
||||
@ -228,7 +231,8 @@
|
||||
"229": ".agents/workflows/graphify.md",
|
||||
"230": "instructions.md",
|
||||
"231": "@nestjs/schematics",
|
||||
"232": "prisma",
|
||||
"232": "js-yaml",
|
||||
"233": "@nestjs/core",
|
||||
"234": "source-map-support",
|
||||
"235": "ts-loader",
|
||||
"236": "ts-node",
|
||||
@ -260,6 +264,7 @@
|
||||
"262": "User Logout API",
|
||||
"263": "generate-openapi.d.ts",
|
||||
"264": "@types/compression",
|
||||
"265": "@nestjs/jwt",
|
||||
"266": "@types/express",
|
||||
"267": "@types/jest",
|
||||
"268": "@types/multer",
|
||||
@ -289,14 +294,23 @@
|
||||
"292": "Production Docker Compose",
|
||||
"293": "Staging Docker Compose",
|
||||
"294": "ZibalService",
|
||||
"295": "@nestjs/throttler",
|
||||
"296": "passport",
|
||||
"297": "ZibalEBankService",
|
||||
"298": ".initiateOrderPayment",
|
||||
"299": "@tailwindcss/postcss",
|
||||
"300": "typescript",
|
||||
"301": "reflect-metadata",
|
||||
"302": "typescript-eslint",
|
||||
"303": "swagger-ui-express",
|
||||
"304": "eslint",
|
||||
"305": "eslint-config-prettier",
|
||||
"306": "@eslint/js",
|
||||
"307": "@eslint/eslintrc",
|
||||
"308": "jest",
|
||||
"309": "axios",
|
||||
"310": "tailwindcss",
|
||||
"311": "@nestjs/cli",
|
||||
"312": "@types/passport-jwt",
|
||||
"313": "20260526160916_add_ui_texts_and_scientific_terms/migration.sql",
|
||||
"314": "eslint-plugin-prettier",
|
||||
@ -304,9 +318,15 @@
|
||||
"316": "globals",
|
||||
"317": "revalidate/route.ts",
|
||||
"318": "MaskableField.tsx",
|
||||
"319": "@nestjs/testing",
|
||||
"320": "prettier",
|
||||
"321": "orders/page.tsx",
|
||||
"322": "pets/page.tsx",
|
||||
"323": "ts-jest",
|
||||
"324": "@types/js-yaml",
|
||||
"325": "@types/react-dom",
|
||||
"326": "@types/supertest",
|
||||
"327": "eslint-plugin-react-refresh",
|
||||
"328": "tailwindcss",
|
||||
"329": "typescript-eslint"
|
||||
}
|
||||
|
||||
@ -1,42 +1,42 @@
|
||||
# Graph Report - canina (2026-09-05)
|
||||
|
||||
## Corpus Check
|
||||
- 601 files · ~1,114,020 words
|
||||
- 602 files · ~1,114,472 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
- 4234 nodes · 7717 edges · 310 communities (215 shown, 95 thin omitted)
|
||||
- 4240 nodes · 7765 edges · 330 communities (217 shown, 113 thin omitted)
|
||||
- Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 298 edges (avg confidence: 0.79)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Graph Freshness
|
||||
- Built from commit: `e15c25da`
|
||||
- Built from commit: `330d9605`
|
||||
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
|
||||
- Run `graphify update .` after code changes (no API cost).
|
||||
|
||||
## Community Hubs (Navigation)
|
||||
- Roles
|
||||
- app.module.ts
|
||||
- payment.service.ts
|
||||
- getMediaUrl
|
||||
- productService.ts
|
||||
- UserDashboard.tsx
|
||||
- PetProfile.tsx
|
||||
- CmsController
|
||||
- tickets.controller.ts
|
||||
- SmsSettingsPage.tsx
|
||||
- SmsService
|
||||
- devDependencies
|
||||
- ReviewsService
|
||||
- ConfirmModal.tsx
|
||||
- reviews.controller.ts
|
||||
- UsersService
|
||||
- index.ts
|
||||
- app-audit-verification.e2e-spec.js
|
||||
- toPersian
|
||||
- UserDashboard.tsx
|
||||
- src/services/api.ts
|
||||
- DoctorQueryDto
|
||||
- schema.ts
|
||||
- JwtAuthGuard
|
||||
- admin.controller.ts
|
||||
- CreateVideoDto
|
||||
- auth.service.ts
|
||||
- auth.module.ts
|
||||
- ProductDto
|
||||
- MenuService
|
||||
- BE-001
|
||||
@ -51,7 +51,7 @@
|
||||
- WholesaleApplyDto
|
||||
- B2BService
|
||||
- ContactService
|
||||
- FaqService
|
||||
- FaqController
|
||||
- راهنمای تست سیستم (Software Testing)
|
||||
- Button
|
||||
- CategoriesController
|
||||
@ -67,13 +67,13 @@
|
||||
- devDependencies
|
||||
- devDependencies
|
||||
- BlogsController
|
||||
- PrescriptionsService
|
||||
- prescriptions.controller.ts
|
||||
- SmartAdvisorService
|
||||
- Button.tsx
|
||||
- UITexts.tsx
|
||||
- Orders.tsx
|
||||
- Role & Core Objective
|
||||
- AuthService
|
||||
- auth.service.ts
|
||||
- compilerOptions
|
||||
- CreateUserDto
|
||||
- ProductPage.tsx
|
||||
@ -100,15 +100,15 @@
|
||||
- scripts
|
||||
- dependencies
|
||||
- Role & Core Objective
|
||||
- RegisterDto
|
||||
- auth.controller.ts
|
||||
- zibal.service.ts
|
||||
- dependencies
|
||||
- CreateEBankCheckoutDto
|
||||
- seed-products.ts
|
||||
- useCartStore
|
||||
- orderService.ts
|
||||
- Reconciled Audit Roles & Assignments
|
||||
- OrdersService
|
||||
- ArchivePage.tsx
|
||||
- components/Skeleton.tsx
|
||||
- Phase 3.1 — Human Review Preparation and Master Backlog Critique
|
||||
- getSeoConfig
|
||||
- compilerOptions
|
||||
@ -138,7 +138,7 @@
|
||||
- compilerOptions
|
||||
- backend/README.md
|
||||
- AdminService
|
||||
- UsersService
|
||||
- UsersController
|
||||
- Repository Map
|
||||
- validate_integrity.js
|
||||
- admin-panel/package.json
|
||||
@ -159,15 +159,15 @@
|
||||
- application/package.json
|
||||
- start-dev.js
|
||||
- generate-openapi.js
|
||||
- PodcastPlayerModal.tsx
|
||||
- AdminLoginDto
|
||||
- lib/services/api.ts
|
||||
- orders.service.ts
|
||||
- System Discovery
|
||||
- HomeController
|
||||
- VerifyOtpDto
|
||||
- RouteErrorBoundary
|
||||
- wiki/[slug]/page.tsx
|
||||
- Product Requirement Document (PRD)
|
||||
- @types/node
|
||||
- RevalidationService
|
||||
- AddressDto
|
||||
- RedisService
|
||||
- exclude
|
||||
- Baseline Command Plan & Reconciled Command History
|
||||
- seo-backfill.ts
|
||||
@ -198,8 +198,8 @@
|
||||
- ⚙️ Backend Technical Review (05_dev_backend)
|
||||
- 🎨 Frontend & Admin Panel Technical Review (06_dev_frontend)
|
||||
- 🚀 SEO & Content Strategy Review (12_seo_content)
|
||||
- AppModule
|
||||
- eslint-config-next
|
||||
- FaqService
|
||||
- Reviews.tsx
|
||||
- seed-ui-texts.ts
|
||||
- seed-wiki.ts
|
||||
- update-blog.dto.ts
|
||||
@ -211,13 +211,14 @@
|
||||
- Raw Finding Verification & Disposition Report
|
||||
- React + TypeScript + Vite
|
||||
- Select.tsx
|
||||
- userStore.ts
|
||||
- ClientLayout.tsx
|
||||
- @tailwindcss/postcss
|
||||
- SmsLogQueryDto
|
||||
- track/page.tsx
|
||||
- application/README.md
|
||||
- deploy.sh
|
||||
- 🔒 Security & Performance Review (09_devops_security)
|
||||
- 👁️ UX & Persona Interface Review (08_visual_qa)
|
||||
- bcrypt
|
||||
- prisma/scientificTerms.ts
|
||||
- seed-blogs.ts
|
||||
- seed-custom.ts
|
||||
@ -233,9 +234,11 @@
|
||||
- sync_honest_manifest.js
|
||||
- sync_manifest.js
|
||||
- FormField.tsx
|
||||
- class-transformer
|
||||
- Textarea.tsx
|
||||
- admin-panel/tsconfig.json
|
||||
- tailwindcss
|
||||
- helmet
|
||||
- next.config.ts
|
||||
- Shabnam Font README
|
||||
- AGENTS.md
|
||||
@ -243,7 +246,8 @@
|
||||
- .agents/workflows/graphify.md
|
||||
- instructions.md
|
||||
- @nestjs/schematics
|
||||
- prisma
|
||||
- js-yaml
|
||||
- @nestjs/core
|
||||
- source-map-support
|
||||
- ts-loader
|
||||
- ts-node
|
||||
@ -271,6 +275,7 @@
|
||||
- User Login API
|
||||
- User Logout API
|
||||
- @types/compression
|
||||
- @nestjs/jwt
|
||||
- @types/express
|
||||
- @types/jest
|
||||
- @types/multer
|
||||
@ -289,12 +294,21 @@
|
||||
- Production Docker Compose
|
||||
- Staging Docker Compose
|
||||
- ZibalService
|
||||
- @nestjs/throttler
|
||||
- passport
|
||||
- ZibalEBankService
|
||||
- .initiateOrderPayment
|
||||
- @tailwindcss/postcss
|
||||
- typescript
|
||||
- reflect-metadata
|
||||
- typescript-eslint
|
||||
- swagger-ui-express
|
||||
- eslint
|
||||
- eslint-config-prettier
|
||||
- @eslint/js
|
||||
- @eslint/eslintrc
|
||||
- jest
|
||||
- @nestjs/cli
|
||||
- @types/passport-jwt
|
||||
- 20260526160916_add_ui_texts_and_scientific_terms/migration.sql
|
||||
- eslint-plugin-prettier
|
||||
@ -302,8 +316,14 @@
|
||||
- globals
|
||||
- revalidate/route.ts
|
||||
- MaskableField.tsx
|
||||
- @nestjs/testing
|
||||
- prettier
|
||||
- ts-jest
|
||||
- @types/js-yaml
|
||||
- @types/react-dom
|
||||
- @types/supertest
|
||||
- eslint-plugin-react-refresh
|
||||
- tailwindcss
|
||||
- typescript-eslint
|
||||
|
||||
## God Nodes (most connected - your core abstractions)
|
||||
@ -331,11 +351,11 @@
|
||||
backend/src/orders/orders.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/store/cartStore.ts -> frontend/application/lib/services/api.ts`
|
||||
- 3-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/services/authService.ts -> frontend/application/lib/services/api.ts`
|
||||
- 3-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/store/cartStore.ts -> frontend/application/lib/services/api.ts`
|
||||
- 4-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/store/cartStore.ts -> frontend/application/lib/services/orderService.ts -> frontend/application/lib/services/api.ts`
|
||||
|
||||
## Communities (310 total, 95 thin omitted)
|
||||
## Communities (330 total, 113 thin omitted)
|
||||
|
||||
### Community 0 - "Roles"
|
||||
Cohesion: 0.24
|
||||
@ -343,19 +363,19 @@ Nodes (13): Roles(), PaymentController, ApiBearerAuth, ApiOperation, ApiTags, Bo
|
||||
|
||||
### Community 1 - "app.module.ts"
|
||||
Cohesion: 0.07
|
||||
Nodes (36): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+28 more)
|
||||
Nodes (34): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+26 more)
|
||||
|
||||
### Community 2 - "payment.service.ts"
|
||||
Cohesion: 0.20
|
||||
Nodes (8): AdminTransactionFilterDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type, ClientMetadata
|
||||
### Community 2 - "getMediaUrl"
|
||||
Cohesion: 0.10
|
||||
Nodes (23): buildTorobProductSpec(), buildTorobProductTitle(), dynamic, GET(), revalidate, dynamic, GET(), revalidate (+15 more)
|
||||
|
||||
### Community 3 - "productService.ts"
|
||||
Cohesion: 0.05
|
||||
Nodes (41): buildTorobProductSpec(), buildTorobProductTitle(), dynamic, GET(), revalidate, dynamic, GET(), revalidate (+33 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (32): DEFAULT_CATEGORIES, dynamic, revalidate, dynamic, revalidate, BlogCategory, BlogPostItem, CatalogPageSpread() (+24 more)
|
||||
|
||||
### Community 4 - "UserDashboard.tsx"
|
||||
Cohesion: 0.11
|
||||
Nodes (20): metadata, OrderDetailsModal(), PetProfile(), SearchResultsPage(), CURRENT_SYMPTOMS, MEDICAL_HISTORIES, SmartAdvisor(), SmartAdvisorProps (+12 more)
|
||||
### Community 4 - "PetProfile.tsx"
|
||||
Cohesion: 0.09
|
||||
Nodes (31): VerifyContent(), metadata, CartDrawer(), Header(), MENU_ICONS, OrderSuccess(), PetProfile(), PrescriptionUploadModal() (+23 more)
|
||||
|
||||
### Community 5 - "CmsController"
|
||||
Cohesion: 0.09
|
||||
@ -370,20 +390,20 @@ Cohesion: 0.20
|
||||
Nodes (10): PatternItem, SmsConfigState, SmsEventDefinition, SmsEventVariable, SmsLogItem, SmsLogStats, SmsRule, SmsSettingsPage() (+2 more)
|
||||
|
||||
### Community 8 - "SmsService"
|
||||
Cohesion: 0.06
|
||||
Nodes (20): SmsEventDefinition, SmsService, Injectable, SettingsController, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags (+12 more)
|
||||
Cohesion: 0.05
|
||||
Nodes (27): SmsEventDefinition, SmsService, Injectable, SmsLogQueryDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional (+19 more)
|
||||
|
||||
### Community 9 - "devDependencies"
|
||||
Cohesion: 0.08
|
||||
Nodes (25): devDependencies, eslint, eslint-config-prettier, @eslint/eslintrc, jest, @nestjs/cli, @nestjs/testing, prettier (+17 more)
|
||||
Cohesion: 0.22
|
||||
Nodes (9): devDependencies, prisma, @types/bcryptjs, @types/node, typescript, @types/node, typescript, prisma (+1 more)
|
||||
|
||||
### Community 10 - "ReviewsService"
|
||||
Cohesion: 0.09
|
||||
Nodes (22): ApiProperty, IsIn, IsOptional, IsString, UpdateReviewDto, ReviewsController, ApiBearerAuth, ApiOperation (+14 more)
|
||||
### Community 10 - "reviews.controller.ts"
|
||||
Cohesion: 0.07
|
||||
Nodes (32): CreateReviewDto, ApiProperty, IsInt, IsNotEmpty, IsOptional, IsString, Min, ApiProperty (+24 more)
|
||||
|
||||
### Community 11 - "ConfirmModal.tsx"
|
||||
Cohesion: 0.10
|
||||
Nodes (16): ConfirmModal(), ConfirmModalProps, Pagination(), PaginationProps, Category, Pet, DoctorOption, Video (+8 more)
|
||||
### Community 11 - "UsersService"
|
||||
Cohesion: 0.12
|
||||
Nodes (10): ApiPropertyOptional, IsEmail, IsOptional, IsString, MinLength, UpdateProfileDto, Injectable, Optional (+2 more)
|
||||
|
||||
### Community 12 - "index.ts"
|
||||
Cohesion: 0.06
|
||||
@ -393,13 +413,13 @@ Nodes (24): backend, frontend, playwright.config.ts, @playwright/test, tests/**/
|
||||
Cohesion: 0.07
|
||||
Nodes (26): EnvironmentVariables, IsNotEmpty, IsOptional, IsString, validateEnv(), CustomHttpExceptionFilter, Catch, PrismaExceptionFilter (+18 more)
|
||||
|
||||
### Community 14 - "toPersian"
|
||||
Cohesion: 0.17
|
||||
Nodes (19): VerifyContent(), AddressFormData, AddressModal(), AddressModalProps, normalizeDigits(), validateAddressForm(), BackButton(), BackButtonProps (+11 more)
|
||||
### Community 14 - "UserDashboard.tsx"
|
||||
Cohesion: 0.14
|
||||
Nodes (23): AddressFormData, AddressModal(), AddressModalProps, normalizeDigits(), validateAddressForm(), BackButton(), BackButtonProps, CheckoutPage() (+15 more)
|
||||
|
||||
### Community 15 - "src/services/api.ts"
|
||||
Cohesion: 0.06
|
||||
Nodes (38): Layout(), ProtectedRoute(), MenuGroup, Sidebar(), SidebarProps, SubMenuItem, LiveMonitoringSummary, SEARCHABLE_PAGES (+30 more)
|
||||
Nodes (36): Layout(), ProtectedRoute(), MenuGroup, Sidebar(), SidebarProps, SubMenuItem, LiveMonitoringSummary, SEARCHABLE_PAGES (+28 more)
|
||||
|
||||
### Community 16 - "DoctorQueryDto"
|
||||
Cohesion: 0.09
|
||||
@ -410,20 +430,20 @@ Cohesion: 0.14
|
||||
Nodes (18): B2BPage(), generateMetadata(), ContactPage(), generateMetadata(), generateMetadata(), getInitialVideos(), Videos(), ContactFormClient() (+10 more)
|
||||
|
||||
### Community 18 - "JwtAuthGuard"
|
||||
Cohesion: 0.10
|
||||
Nodes (19): JwtAuthGuard, Injectable, ROLES_KEY, RequestWithUser, RolesGuard, Injectable, ApiPropertyOptional, IsOptional (+11 more)
|
||||
Cohesion: 0.21
|
||||
Nodes (6): JwtAuthGuard, Injectable, ROLES_KEY, RequestWithUser, RolesGuard, Injectable
|
||||
|
||||
### Community 19 - "admin.controller.ts"
|
||||
Cohesion: 0.29
|
||||
Nodes (12): ApplyGlobalMarginsDto, BulkPriceAdjustmentDto, ApiProperty, ApiPropertyOptional, IsArray, IsBoolean, IsIn, IsNumber (+4 more)
|
||||
|
||||
### Community 20 - "CreateVideoDto"
|
||||
Cohesion: 0.07
|
||||
Nodes (32): CreateVideoDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString, UpdateVideoDto (+24 more)
|
||||
Cohesion: 0.09
|
||||
Nodes (24): CreateVideoDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString, UpdateVideoDto (+16 more)
|
||||
|
||||
### Community 21 - "auth.service.ts"
|
||||
Cohesion: 0.14
|
||||
Nodes (13): AdminLoginInput, LoginInput, RegisterInput, LoginDto, ApiProperty, IsNotEmpty, IsString, MinLength (+5 more)
|
||||
### Community 21 - "auth.module.ts"
|
||||
Cohesion: 0.15
|
||||
Nodes (10): DEFAULT_JWT_REFRESH_SECRET, DEFAULT_JWT_SECRET, getJwtSecret(), AuthModule, Module, JwtPayload, JwtStrategy, Injectable (+2 more)
|
||||
|
||||
### Community 22 - "ProductDto"
|
||||
Cohesion: 0.16
|
||||
@ -467,23 +487,23 @@ Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternati
|
||||
|
||||
### Community 32 - "adminRoutes.tsx"
|
||||
Cohesion: 0.07
|
||||
Nodes (16): App(), Props, RouteErrorBoundary, State, HeroBanner, VetTestimonial, SslStatus, AdminRouteConfig (+8 more)
|
||||
Nodes (21): App(), ContactInfoItem, ContactSubmission, CategoryDist, DashboardData, SslStatus, Ticket, TicketMessage (+13 more)
|
||||
|
||||
### Community 33 - "WholesaleApplyDto"
|
||||
Cohesion: 0.10
|
||||
Nodes (20): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto, ApiBearerAuth, ApiOperation (+12 more)
|
||||
|
||||
### Community 34 - "B2BService"
|
||||
Cohesion: 0.12
|
||||
Nodes (16): B2BController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+8 more)
|
||||
Cohesion: 0.13
|
||||
Nodes (15): B2BController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+7 more)
|
||||
|
||||
### Community 35 - "ContactService"
|
||||
Cohesion: 0.13
|
||||
Nodes (12): ContactController, Body, Controller, Get, Param, Post, Put, Query (+4 more)
|
||||
|
||||
### Community 36 - "FaqService"
|
||||
Cohesion: 0.12
|
||||
Nodes (16): FaqController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+8 more)
|
||||
### Community 36 - "FaqController"
|
||||
Cohesion: 0.14
|
||||
Nodes (12): FaqController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+4 more)
|
||||
|
||||
### Community 37 - "راهنمای تست سیستم (Software Testing)"
|
||||
Cohesion: 0.07
|
||||
@ -499,7 +519,7 @@ Nodes (16): CategoriesController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags
|
||||
|
||||
### Community 40 - "MediaController"
|
||||
Cohesion: 0.11
|
||||
Nodes (16): MediaController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+8 more)
|
||||
Nodes (14): MediaController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
|
||||
|
||||
### Community 41 - "What You Must Do When Invoked"
|
||||
Cohesion: 0.07
|
||||
@ -530,7 +550,7 @@ Cohesion: 0.13
|
||||
Nodes (14): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
|
||||
|
||||
### Community 48 - "AuthController"
|
||||
Cohesion: 0.25
|
||||
Cohesion: 0.23
|
||||
Nodes (13): AuthController, ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+5 more)
|
||||
|
||||
### Community 49 - "devDependencies"
|
||||
@ -539,23 +559,23 @@ Nodes (19): autoprefixer, devDependencies, autoprefixer, eslint, @eslint/js, glo
|
||||
|
||||
### Community 50 - "devDependencies"
|
||||
Cohesion: 0.12
|
||||
Nodes (17): devDependencies, eslint, jsdom, tailwindcss, @testing-library/jest-dom, @testing-library/react, @types/node, @types/react (+9 more)
|
||||
Nodes (17): eslint-config-next, devDependencies, eslint, eslint-config-next, jsdom, @testing-library/jest-dom, @testing-library/react, @types/node (+9 more)
|
||||
|
||||
### Community 51 - "BlogsController"
|
||||
Cohesion: 0.07
|
||||
Nodes (18): BlogsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+10 more)
|
||||
|
||||
### Community 52 - "PrescriptionsService"
|
||||
Cohesion: 0.14
|
||||
Nodes (14): PrescriptionsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+6 more)
|
||||
### Community 52 - "prescriptions.controller.ts"
|
||||
Cohesion: 0.11
|
||||
Nodes (17): PrescriptionsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+9 more)
|
||||
|
||||
### Community 53 - "SmartAdvisorService"
|
||||
Cohesion: 0.13
|
||||
Nodes (14): SmartAdvisorController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
|
||||
|
||||
### Community 54 - "Button.tsx"
|
||||
Cohesion: 0.07
|
||||
Nodes (24): ButtonProps, ButtonSize, ButtonVariant, maxWidthClasses, Modal(), ModalProps, ContactInfoItem, ContactSubmission (+16 more)
|
||||
Cohesion: 0.10
|
||||
Nodes (16): ButtonProps, ButtonSize, ButtonVariant, ConfirmModal(), ConfirmModalProps, HeroBanner, VetTestimonial, FAQ (+8 more)
|
||||
|
||||
### Community 55 - "UITexts.tsx"
|
||||
Cohesion: 0.08
|
||||
@ -569,9 +589,9 @@ Nodes (15): Badge(), BadgeProps, BadgeVariant, variantStyles, Skeleton(), Monito
|
||||
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 58 - "AuthService"
|
||||
Cohesion: 0.19
|
||||
Nodes (3): AuthService, Injectable, normalizeMobile()
|
||||
### Community 58 - "auth.service.ts"
|
||||
Cohesion: 0.09
|
||||
Nodes (17): AdminLoginInput, AuthService, LoginInput, RegisterInput, Injectable, SendOtpDto, ApiProperty, IsNotEmpty (+9 more)
|
||||
|
||||
### Community 59 - "compilerOptions"
|
||||
Cohesion: 0.06
|
||||
@ -582,16 +602,16 @@ Cohesion: 0.21
|
||||
Nodes (10): CreateUserDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty, IsNumber, IsOptional, IsString (+2 more)
|
||||
|
||||
### Community 61 - "ProductPage.tsx"
|
||||
Cohesion: 0.09
|
||||
Nodes (20): ProductImageZoomModalProps, CalculatorState, GalleryMediaItem, ICON_MAP, isVideoUrl(), ProductImageZoomModal, ProductPage(), ProductReviews (+12 more)
|
||||
Cohesion: 0.18
|
||||
Nodes (21): ArchiveProductCard(), CATEGORY_MAP, ICON_MAP, FeaturedProducts(), ProductCard(), ProductImageZoomModalProps, CalculatorState, GalleryMediaItem (+13 more)
|
||||
|
||||
### Community 62 - "torob.controller.ts"
|
||||
Cohesion: 0.22
|
||||
Nodes (8): buildTorobProductSpec(), buildTorobProductTitle(), TorobController, ApiOperation, ApiTags, Controller, Get, Query
|
||||
|
||||
### Community 63 - "dependencies"
|
||||
Cohesion: 0.05
|
||||
Nodes (43): dependencies, bcrypt, bcryptjs, class-transformer, class-validator, compression, helmet, ioredis (+35 more)
|
||||
Cohesion: 0.09
|
||||
Nodes (23): dependencies, bcryptjs, class-validator, compression, ioredis, @nestjs/common, @nestjs/passport, @nestjs/platform-express (+15 more)
|
||||
|
||||
### Community 64 - "compilerOptions"
|
||||
Cohesion: 0.10
|
||||
@ -606,12 +626,12 @@ Cohesion: 0.18
|
||||
Nodes (7): ApiQuery, Query, AdminProductQueryDto, AdminQueryDto, ApiPropertyOptional, IsOptional, IsString
|
||||
|
||||
### Community 67 - "admin.module.ts"
|
||||
Cohesion: 0.08
|
||||
Nodes (17): AdminModule, Module, ReportsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller (+9 more)
|
||||
Cohesion: 0.06
|
||||
Nodes (23): AdminModule, Module, CategoryQuery, MediaService, Injectable, PetQuery, PetsService, Injectable (+15 more)
|
||||
|
||||
### Community 68 - "useSettingsStore"
|
||||
Cohesion: 0.08
|
||||
Nodes (36): HomeClient(), HomeClientProps, B2BLandingClient(), BlogPostClientProps, BlogPost, BlogPreviewSection(), ContactInfoItem, EnamadBadge() (+28 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (34): HomeClient(), HomeClientProps, ArchivePage(), B2BLandingClient(), BannerPlacement(), BannerPlacementProps, BrandLogo(), BrandLogoProps (+26 more)
|
||||
|
||||
### Community 69 - "Required Review Group Closures"
|
||||
Cohesion: 0.10
|
||||
@ -622,8 +642,8 @@ Cohesion: 0.08
|
||||
Nodes (23): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, jsx, lib, module, moduleDetection, moduleResolution (+15 more)
|
||||
|
||||
### Community 71 - "getPageMetadata"
|
||||
Cohesion: 0.08
|
||||
Nodes (16): generateMetadata(), CatalogClient(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata() (+8 more)
|
||||
Cohesion: 0.09
|
||||
Nodes (15): generateMetadata(), CatalogClient(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata(), generateMetadata() (+7 more)
|
||||
|
||||
### Community 72 - "Operational Rules & Boundaries"
|
||||
Cohesion: 0.11
|
||||
@ -677,9 +697,9 @@ Nodes (21): dependencies, axios, lucide-react, react, react-dom, react-hot-toast
|
||||
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 85 - "RegisterDto"
|
||||
Cohesion: 0.22
|
||||
Nodes (8): RegisterDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty, IsOptional, IsString, MinLength
|
||||
### Community 85 - "auth.controller.ts"
|
||||
Cohesion: 0.10
|
||||
Nodes (19): AdminLoginDto, ApiProperty, IsEmail, IsNotEmpty, IsString, MinLength, LoginDto, ApiProperty (+11 more)
|
||||
|
||||
### Community 86 - "zibal.service.ts"
|
||||
Cohesion: 0.16
|
||||
@ -697,21 +717,21 @@ Nodes (8): CreateEBankCheckoutDto, ApiProperty, ApiPropertyOptional, IsNotEmpty,
|
||||
Cohesion: 0.17
|
||||
Nodes (12): prisma, main(), prisma, determineSuitableFor(), findOrCreateCategory(), getProductImageUrl(), main(), parseSize() (+4 more)
|
||||
|
||||
### Community 90 - "useCartStore"
|
||||
Cohesion: 0.09
|
||||
Nodes (19): B2BPortal, CartDrawer, B2BPortal(), CartDrawer(), DeleteConfirmModal(), DeleteConfirmModalProps, OrderSuccess(), OrderTracking() (+11 more)
|
||||
### Community 90 - "orderService.ts"
|
||||
Cohesion: 0.18
|
||||
Nodes (5): ApiErr, Order, OrderItem, OrderService, mockProduct
|
||||
|
||||
### Community 91 - "Reconciled Audit Roles & Assignments"
|
||||
Cohesion: 0.12
|
||||
Nodes (15): 10. Documentation Engineer, 1. Lead Architect / Orchestrator, 2. React / Vite Storefront Auditor, 3. NestJS Backend Auditor, 4. Admin Features Auditor, 5. Database & Data Integrity Auditor, 6. Security Auditor, 7. TypeScript & Code Quality Auditor (+7 more)
|
||||
|
||||
### Community 92 - "OrdersService"
|
||||
Cohesion: 0.06
|
||||
Nodes (35): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+27 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (29): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+21 more)
|
||||
|
||||
### Community 93 - "ArchivePage.tsx"
|
||||
Cohesion: 0.08
|
||||
Nodes (21): ArchivePage(), ArchiveProductCard(), CATEGORY_MAP, ICON_MAP, BannerPlacement(), BannerPlacementProps, OrderRowSkeleton(), PetProfileSkeleton() (+13 more)
|
||||
### Community 93 - "components/Skeleton.tsx"
|
||||
Cohesion: 0.24
|
||||
Nodes (4): OrderRowSkeleton(), PetProfileSkeleton(), Skeleton(), SkeletonProps
|
||||
|
||||
### Community 94 - "Phase 3.1 — Human Review Preparation and Master Backlog Critique"
|
||||
Cohesion: 0.13
|
||||
@ -725,6 +745,10 @@ Nodes (11): BlogPostPage(), generateMetadata(), getBlog(), revalidate, safeIso()
|
||||
Cohesion: 0.06
|
||||
Nodes (32): compilerOptions, allowJs, esModuleInterop, incremental, isolatedModules, jsx, lib, module (+24 more)
|
||||
|
||||
### Community 97 - "PaymentService"
|
||||
Cohesion: 0.10
|
||||
Nodes (9): AdminTransactionFilterDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type, PaymentService (+1 more)
|
||||
|
||||
### Community 98 - "scripts"
|
||||
Cohesion: 0.13
|
||||
Nodes (15): scripts, build, build:nest, docs:generate, lint, seo:backfill, start, start:debug (+7 more)
|
||||
@ -750,8 +774,8 @@ Cohesion: 0.15
|
||||
Nodes (12): 10. `TASK-VERIFY-001`, 1. `TASK-SEC-001`, 2. `TASK-SEC-002`, 3. `TASK-SEC-003`, 4. `TASK-FIN-001`, 5. `TASK-BUILD-001`, 6. `TASK-AUTH-001`, 7. `TASK-FE-001` (+4 more)
|
||||
|
||||
### Community 104 - "Products.tsx"
|
||||
Cohesion: 0.09
|
||||
Nodes (25): Input, InputProps, formatPriceWithCommas(), PriceInput(), PriceInputProps, toEnglishDigits(), Coupon, CouponFormData (+17 more)
|
||||
Cohesion: 0.10
|
||||
Nodes (24): Input, InputProps, formatPriceWithCommas(), PriceInput(), PriceInputProps, toEnglishDigits(), Coupon, CouponFormData (+16 more)
|
||||
|
||||
### Community 105 - "Operational Rules & Boundaries"
|
||||
Cohesion: 0.17
|
||||
@ -762,12 +786,12 @@ Cohesion: 0.43
|
||||
Nodes (7): InitiatePaymentDto, InitiateWalletTopupDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString
|
||||
|
||||
### Community 107 - "PaginationDto"
|
||||
Cohesion: 0.06
|
||||
Nodes (27): BlogsModule, Module, BlogFilterDto, BlogsService, Injectable, PaginationDto, SortOrder, ApiPropertyOptional (+19 more)
|
||||
Cohesion: 0.05
|
||||
Nodes (32): BlogsModule, Module, BlogFilterDto, BlogsService, Injectable, PaginationDto, SortOrder, ApiPropertyOptional (+24 more)
|
||||
|
||||
### Community 108 - "PrismaService"
|
||||
Cohesion: 0.07
|
||||
Nodes (23): CategoryQuery, DEFAULT_SMS_RULES, SMS_EVENT_DEFINITIONS, SmsEventVariable, SmsRule, MeliPayamakPattern, MeliPayamakResponse, SendPatternSmsOptions (+15 more)
|
||||
Cohesion: 0.04
|
||||
Nodes (35): ApiExcludeController, Optional, B2BWholesaleOrderItem, MetricsController, Controller, Get, Res, RevalidationModule (+27 more)
|
||||
|
||||
### Community 109 - "1. Summary of Integrity Repairs Performed"
|
||||
Cohesion: 0.17
|
||||
@ -786,16 +810,16 @@ Cohesion: 0.18
|
||||
Nodes (10): 1. Pre-Deployment Checklist, 2. Build Verification, 3. Deployment Strategy (Based on Target), 4. Post-Deployment Health Check, 5. Forbidden Actions, Expected JSON Output Schema, Operational Rules & Boundaries, Required Output Artifacts (What files to write/update) (+2 more)
|
||||
|
||||
### Community 113 - "PetsController"
|
||||
Cohesion: 0.10
|
||||
Nodes (14): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+6 more)
|
||||
Cohesion: 0.15
|
||||
Nodes (11): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+3 more)
|
||||
|
||||
### Community 114 - "AppService"
|
||||
Cohesion: 0.29
|
||||
Nodes (5): AppController, Controller, Get, AppService, Injectable
|
||||
|
||||
### Community 115 - "Spinner.tsx"
|
||||
Cohesion: 0.10
|
||||
Nodes (22): ImagePreviewModal(), ImagePreviewModalProps, getFileType(), Media, MediaSelector(), MediaSelectorProps, Spinner(), Doctor (+14 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (36): ImagePreviewModal(), ImagePreviewModalProps, getFileType(), Media, MediaSelector(), MediaSelectorProps, maxWidthClasses, Modal() (+28 more)
|
||||
|
||||
### Community 116 - "Vazirmatn Changelog"
|
||||
Cohesion: 0.18
|
||||
@ -825,9 +849,9 @@ Nodes (9): Compile and run the project, Deployment, Description, License, Projec
|
||||
Cohesion: 0.09
|
||||
Nodes (12): AdminController, ApiBearerAuth, ApiOperation, ApiTags, Controller, Delete, Get, Param (+4 more)
|
||||
|
||||
### Community 123 - "UsersService"
|
||||
Cohesion: 0.05
|
||||
Nodes (42): DEFAULT_JWT_REFRESH_SECRET, DEFAULT_JWT_SECRET, getJwtSecret(), AuthModule, Module, JwtPayload, JwtStrategy, Injectable (+34 more)
|
||||
### Community 123 - "UsersController"
|
||||
Cohesion: 0.21
|
||||
Nodes (16): ApiBadRequestResponse, ApiBearerAuth, ApiCreatedResponse, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+8 more)
|
||||
|
||||
### Community 124 - "Repository Map"
|
||||
Cohesion: 0.20
|
||||
@ -909,13 +933,13 @@ Nodes (7): backend, distMainPath, fs, http, path, { spawn, execSync }, waitForBa
|
||||
Cohesion: 0.25
|
||||
Nodes (6): app_module_1, core_1, fs, path, swagger_1, yaml
|
||||
|
||||
### Community 144 - "PodcastPlayerModal.tsx"
|
||||
Cohesion: 0.40
|
||||
Nodes (3): PLAYBACK_RATES, PodcastPlayerModal(), PodcastPlayerModalProps
|
||||
### Community 144 - "lib/services/api.ts"
|
||||
Cohesion: 0.08
|
||||
Nodes (24): B2BPortal(), BlogPostClientProps, BlogPost, BlogPreviewSection(), ContactInfoItem, OrderDetailsModal(), OrderDetailsModalProps, PLAYBACK_RATES (+16 more)
|
||||
|
||||
### Community 145 - "AdminLoginDto"
|
||||
Cohesion: 0.29
|
||||
Nodes (6): AdminLoginDto, ApiProperty, IsEmail, IsNotEmpty, IsString, MinLength
|
||||
### Community 145 - "orders.service.ts"
|
||||
Cohesion: 0.24
|
||||
Nodes (6): IsNotEmpty, IsNumber, IsString, ValidateCouponDto, OrdersModule, Module
|
||||
|
||||
### Community 146 - "System Discovery"
|
||||
Cohesion: 0.25
|
||||
@ -925,9 +949,9 @@ Nodes (7): Active Core Applications, Current Architecture, Evidence-Based Status
|
||||
Cohesion: 0.16
|
||||
Nodes (10): HomeController, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, HomeModule, Module (+2 more)
|
||||
|
||||
### Community 148 - "VerifyOtpDto"
|
||||
Cohesion: 0.33
|
||||
Nodes (6): ApiProperty, IsNotEmpty, IsString, Matches, VerifyOtpDto, Length
|
||||
### Community 148 - "RouteErrorBoundary"
|
||||
Cohesion: 0.22
|
||||
Nodes (3): Props, RouteErrorBoundary, State
|
||||
|
||||
### Community 149 - "wiki/[slug]/page.tsx"
|
||||
Cohesion: 0.60
|
||||
@ -937,9 +961,13 @@ Nodes (5): generateMetadata(), getRelatedProducts(), getWikiTerm(), WikiTermPage
|
||||
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 152 - "RevalidationService"
|
||||
Cohesion: 0.10
|
||||
Nodes (11): Optional, RevalidationModule, Global, Module, RevalidationService, Injectable, RedisModule, Global (+3 more)
|
||||
### Community 151 - "AddressDto"
|
||||
Cohesion: 0.25
|
||||
Nodes (7): AddressDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString
|
||||
|
||||
### Community 152 - "RedisService"
|
||||
Cohesion: 0.11
|
||||
Nodes (7): AppModule, Module, RedisModule, Global, Module, RedisService, Injectable
|
||||
|
||||
### Community 153 - "exclude"
|
||||
Cohesion: 0.22
|
||||
@ -1057,9 +1085,13 @@ 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 184 - "AppModule"
|
||||
Cohesion: 0.12
|
||||
Nodes (7): ApiExcludeController, AppModule, Module, MetricsController, Controller, Get, Res
|
||||
### Community 184 - "FaqService"
|
||||
Cohesion: 0.33
|
||||
Nodes (4): FaqModule, Module, FaqService, Injectable
|
||||
|
||||
### Community 185 - "Reviews.tsx"
|
||||
Cohesion: 0.40
|
||||
Nodes (5): BlogCommentItem, ProductReview, Reviews(), toPersianDigits(), Reviews
|
||||
|
||||
### Community 191 - "graphify reference: add a URL and watch a folder"
|
||||
Cohesion: 0.50
|
||||
@ -1085,13 +1117,9 @@ Nodes (3): Expanding the ESLint configuration, React Compiler, React + TypeScrip
|
||||
Cohesion: 0.50
|
||||
Nodes (3): Select, SelectOption, SelectProps
|
||||
|
||||
### Community 197 - "userStore.ts"
|
||||
Cohesion: 0.06
|
||||
Nodes (33): AuthModal, ClientLayout(), LoginModal, AuthModal(), AuthModalProps, extractOtpFromText(), BrandLogo(), BrandLogoProps (+25 more)
|
||||
|
||||
### Community 199 - "SmsLogQueryDto"
|
||||
Cohesion: 0.25
|
||||
Nodes (7): SmsLogQueryDto, ApiPropertyOptional, IsIn, IsNumber, IsOptional, IsString, Type
|
||||
### Community 197 - "ClientLayout.tsx"
|
||||
Cohesion: 0.08
|
||||
Nodes (19): AuthModal, B2BPortal, CartDrawer, ClientLayout(), LoginModal, AuthModal(), AuthModalProps, extractOtpFromText() (+11 more)
|
||||
|
||||
### Community 200 - "application/README.md"
|
||||
Cohesion: 0.50
|
||||
@ -1110,8 +1138,8 @@ Cohesion: 0.67
|
||||
Nodes (3): Shabnam Font README, Shabnam Font Sample, Vazir Font
|
||||
|
||||
### Community 298 - ".initiateOrderPayment"
|
||||
Cohesion: 0.28
|
||||
Nodes (6): ApiBadRequestResponse, ApiOkResponse, Req, Res, Headers, Ip
|
||||
Cohesion: 0.20
|
||||
Nodes (10): ApiPropertyOptional, IsOptional, IsString, ZibalCallbackQueryDto, ApiBadRequestResponse, ApiOkResponse, Req, Res (+2 more)
|
||||
|
||||
### Community 317 - "revalidate/route.ts"
|
||||
Cohesion: 0.83
|
||||
@ -1120,22 +1148,22 @@ Nodes (3): GET(), handleRevalidate(), POST()
|
||||
## Knowledge Gaps
|
||||
- **1352 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1347 more)
|
||||
These have ≤1 connection - possible missing edges or undocumented components.
|
||||
- **95 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
|
||||
- **113 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 `Roles()` connect `Roles` to `WholesaleApplyDto`, `B2BService`, `ContactService`, `FaqService`, `CmsController`, `tickets.controller.ts`, `SmsService`, `SslController`, `BannersService`, `ProductsService`, `ReviewsService`, `TestimonialsService`, `IngredientsService`, `JwtAuthGuard`, `PrescriptionsService`, `SmartAdvisorService`, `MenuService`?**
|
||||
- **Why does `Roles()` connect `Roles` to `WholesaleApplyDto`, `B2BService`, `ContactService`, `FaqController`, `CmsController`, `tickets.controller.ts`, `SmsService`, `SslController`, `BannersService`, `ProductsService`, `reviews.controller.ts`, `TestimonialsService`, `IngredientsService`, `JwtAuthGuard`, `prescriptions.controller.ts`, `SmartAdvisorService`, `MenuService`?**
|
||||
_High betweenness centrality (0.094) - this node is a cross-community bridge._
|
||||
- **Why does `ApiResponse` connect `src/services/api.ts` to `BlogsController`, `PetsController`, `ProductsService`, `PaginationDto`, `AuthController`, `HomeController`, `UsersService`, `OrdersService`?**
|
||||
- **Why does `ApiResponse` connect `src/services/api.ts` to `BlogsController`, `PetsController`, `ProductsService`, `PaginationDto`, `AuthController`, `HomeController`, `UsersController`, `OrdersService`?**
|
||||
_High betweenness centrality (0.066) - this node is a cross-community bridge._
|
||||
- **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `admin.module.ts`, `CmsController`, `tickets.controller.ts`, `PaginationDto`, `PetsController`, `ProductsService`, `DoctorQueryDto`, `PetsController`, `admin.controller.ts`, `CreateVideoDto`, `auth.service.ts`, `UsersService`, `OrdersService`?**
|
||||
- **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `admin.module.ts`, `CmsController`, `tickets.controller.ts`, `reviews.controller.ts`, `PaginationDto`, `PetsController`, `ProductsService`, `UsersService`, `DoctorQueryDto`, `orders.service.ts`, `admin.controller.ts`, `prescriptions.controller.ts`, `auth.controller.ts`?**
|
||||
_High betweenness centrality (0.030) - this node is a cross-community bridge._
|
||||
- **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?**
|
||||
_1352 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||
- **Should `app.module.ts` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.06988120195667366 - nodes in this community are weakly interconnected._
|
||||
_Cohesion score 0.07215686274509804 - nodes in this community are weakly interconnected._
|
||||
- **Should `getMediaUrl` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.09848484848484848 - nodes in this community are weakly interconnected._
|
||||
- **Should `productService.ts` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.05472837022132797 - nodes in this community are weakly interconnected._
|
||||
- **Should `UserDashboard.tsx` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.10752688172043011 - nodes in this community are weakly interconnected._
|
||||
_Cohesion score 0.06654567453115548 - 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,25 +1,25 @@
|
||||
# Graph Report - canina (2026-09-05)
|
||||
|
||||
## Corpus Check
|
||||
- 602 files · ~1,114,472 words
|
||||
- 603 files · ~1,115,636 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
- 4240 nodes · 7765 edges · 330 communities (217 shown, 113 thin omitted)
|
||||
- 4245 nodes · 7776 edges · 328 communities (215 shown, 113 thin omitted)
|
||||
- Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 298 edges (avg confidence: 0.79)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Graph Freshness
|
||||
- Built from commit: `330d9605`
|
||||
- Built from commit: `00cfd1a2`
|
||||
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
|
||||
- Run `graphify update .` after code changes (no API cost).
|
||||
|
||||
## Community Hubs (Navigation)
|
||||
- Roles
|
||||
- app.module.ts
|
||||
- getMediaUrl
|
||||
- VetGallery.tsx
|
||||
- productService.ts
|
||||
- PetProfile.tsx
|
||||
- useSettingsStore
|
||||
- CmsController
|
||||
- tickets.controller.ts
|
||||
- SmsSettingsPage.tsx
|
||||
@ -36,7 +36,7 @@
|
||||
- JwtAuthGuard
|
||||
- admin.controller.ts
|
||||
- CreateVideoDto
|
||||
- auth.module.ts
|
||||
- pets/pets.controller.ts
|
||||
- ProductDto
|
||||
- MenuService
|
||||
- BE-001
|
||||
@ -49,7 +49,7 @@
|
||||
- DOC-001
|
||||
- adminRoutes.tsx
|
||||
- WholesaleApplyDto
|
||||
- B2BService
|
||||
- B2BController
|
||||
- ContactService
|
||||
- FaqController
|
||||
- راهنمای تست سیستم (Software Testing)
|
||||
@ -58,12 +58,12 @@
|
||||
- MediaController
|
||||
- What You Must Do When Invoked
|
||||
- SslController
|
||||
- BannersService
|
||||
- TestimonialsService
|
||||
- BannersController
|
||||
- TestimonialsController
|
||||
- What You Must Do When Invoked
|
||||
- 20260526145407_init/migration.sql
|
||||
- IngredientsService
|
||||
- AuthController
|
||||
- IngredientsController
|
||||
- WikiController
|
||||
- devDependencies
|
||||
- devDependencies
|
||||
- BlogsController
|
||||
@ -73,17 +73,17 @@
|
||||
- UITexts.tsx
|
||||
- Orders.tsx
|
||||
- Role & Core Objective
|
||||
- auth.service.ts
|
||||
- AuthService
|
||||
- compilerOptions
|
||||
- CreateUserDto
|
||||
- ProductPage.tsx
|
||||
- torob.controller.ts
|
||||
- ReportsController
|
||||
- dependencies
|
||||
- compilerOptions
|
||||
- admin.service.ts
|
||||
- AdminQueryDto
|
||||
- ApiOperation
|
||||
- admin.module.ts
|
||||
- useSettingsStore
|
||||
- HomeClient.tsx
|
||||
- Required Review Group Closures
|
||||
- compilerOptions
|
||||
- getPageMetadata
|
||||
@ -100,12 +100,12 @@
|
||||
- scripts
|
||||
- dependencies
|
||||
- Role & Core Objective
|
||||
- auth.controller.ts
|
||||
- auth.service.ts
|
||||
- zibal.service.ts
|
||||
- dependencies
|
||||
- CreateEBankCheckoutDto
|
||||
- seed-products.ts
|
||||
- orderService.ts
|
||||
- cartStore.ts
|
||||
- Reconciled Audit Roles & Assignments
|
||||
- OrdersService
|
||||
- components/Skeleton.tsx
|
||||
@ -128,7 +128,7 @@
|
||||
- Operational Rules & Boundaries
|
||||
- Operational Rules & Boundaries
|
||||
- Operational Rules & Boundaries
|
||||
- PetsController
|
||||
- MetricsController
|
||||
- AppService
|
||||
- Spinner.tsx
|
||||
- Vazirmatn Changelog
|
||||
@ -138,12 +138,12 @@
|
||||
- compilerOptions
|
||||
- backend/README.md
|
||||
- AdminService
|
||||
- UsersController
|
||||
- B2BService
|
||||
- Repository Map
|
||||
- validate_integrity.js
|
||||
- admin-panel/package.json
|
||||
- Sahel-Font
|
||||
- Body
|
||||
- zibal-ebank.service.ts
|
||||
- Reports.tsx
|
||||
- Sahel-Font
|
||||
- Role & Core Objective
|
||||
@ -160,14 +160,14 @@
|
||||
- start-dev.js
|
||||
- generate-openapi.js
|
||||
- lib/services/api.ts
|
||||
- orders.service.ts
|
||||
- trust-seals/page.tsx
|
||||
- System Discovery
|
||||
- HomeController
|
||||
- RouteErrorBoundary
|
||||
- wiki/[slug]/page.tsx
|
||||
- Product Requirement Document (PRD)
|
||||
- AddressDto
|
||||
- RedisService
|
||||
- @nestjs/swagger
|
||||
- RevalidationService
|
||||
- exclude
|
||||
- Baseline Command Plan & Reconciled Command History
|
||||
- seo-backfill.ts
|
||||
@ -211,9 +211,9 @@
|
||||
- Raw Finding Verification & Disposition Report
|
||||
- React + TypeScript + Vite
|
||||
- Select.tsx
|
||||
- ClientLayout.tsx
|
||||
- toPersian
|
||||
- @tailwindcss/postcss
|
||||
- track/page.tsx
|
||||
- prisma
|
||||
- application/README.md
|
||||
- deploy.sh
|
||||
- 🔒 Security & Performance Review (09_devops_security)
|
||||
@ -234,7 +234,7 @@
|
||||
- sync_honest_manifest.js
|
||||
- sync_manifest.js
|
||||
- FormField.tsx
|
||||
- class-transformer
|
||||
- eslint-config-next
|
||||
- Textarea.tsx
|
||||
- admin-panel/tsconfig.json
|
||||
- tailwindcss
|
||||
@ -303,7 +303,6 @@
|
||||
- reflect-metadata
|
||||
- typescript-eslint
|
||||
- swagger-ui-express
|
||||
- eslint
|
||||
- eslint-config-prettier
|
||||
- @eslint/js
|
||||
- @eslint/eslintrc
|
||||
@ -323,7 +322,6 @@
|
||||
- @types/react-dom
|
||||
- @types/supertest
|
||||
- eslint-plugin-react-refresh
|
||||
- tailwindcss
|
||||
- typescript-eslint
|
||||
|
||||
## God Nodes (most connected - your core abstractions)
|
||||
@ -351,11 +349,11 @@
|
||||
backend/src/orders/orders.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`
|
||||
- 3-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/store/cartStore.ts -> frontend/application/lib/services/api.ts`
|
||||
- 3-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/services/authService.ts -> frontend/application/lib/services/api.ts`
|
||||
- 4-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/store/cartStore.ts -> frontend/application/lib/services/orderService.ts -> frontend/application/lib/services/api.ts`
|
||||
|
||||
## Communities (330 total, 113 thin omitted)
|
||||
## Communities (328 total, 113 thin omitted)
|
||||
|
||||
### Community 0 - "Roles"
|
||||
Cohesion: 0.24
|
||||
@ -363,19 +361,19 @@ Nodes (13): Roles(), PaymentController, ApiBearerAuth, ApiOperation, ApiTags, Bo
|
||||
|
||||
### Community 1 - "app.module.ts"
|
||||
Cohesion: 0.07
|
||||
Nodes (34): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+26 more)
|
||||
Nodes (32): BannersModule, Module, CmsModule, Module, SmsModule, Global, Module, ContactModule (+24 more)
|
||||
|
||||
### Community 2 - "getMediaUrl"
|
||||
Cohesion: 0.10
|
||||
Nodes (23): buildTorobProductSpec(), buildTorobProductTitle(), dynamic, GET(), revalidate, dynamic, GET(), revalidate (+15 more)
|
||||
### Community 2 - "VetGallery.tsx"
|
||||
Cohesion: 0.15
|
||||
Nodes (13): BackButton(), BackButtonProps, VideoModalPlayer, DisplayVideoItem, FALLBACK_VIDEOS, TestimonialItem, VetGallery(), PLAYBACK_RATES (+5 more)
|
||||
|
||||
### Community 3 - "productService.ts"
|
||||
Cohesion: 0.07
|
||||
Nodes (32): DEFAULT_CATEGORIES, dynamic, revalidate, dynamic, revalidate, BlogCategory, BlogPostItem, CatalogPageSpread() (+24 more)
|
||||
Cohesion: 0.06
|
||||
Nodes (40): buildTorobProductSpec(), buildTorobProductTitle(), dynamic, GET(), revalidate, dynamic, GET(), revalidate (+32 more)
|
||||
|
||||
### Community 4 - "PetProfile.tsx"
|
||||
Cohesion: 0.09
|
||||
Nodes (31): VerifyContent(), metadata, CartDrawer(), Header(), MENU_ICONS, OrderSuccess(), PetProfile(), PrescriptionUploadModal() (+23 more)
|
||||
### Community 4 - "useSettingsStore"
|
||||
Cohesion: 0.08
|
||||
Nodes (28): AuthModal, B2BPortal, CartDrawer, ClientLayout(), LoginModal, metadata, ArchivePage(), BrandLogo() (+20 more)
|
||||
|
||||
### Community 5 - "CmsController"
|
||||
Cohesion: 0.09
|
||||
@ -395,27 +393,27 @@ Nodes (27): SmsEventDefinition, SmsService, Injectable, SmsLogQueryDto, ApiPrope
|
||||
|
||||
### Community 9 - "devDependencies"
|
||||
Cohesion: 0.22
|
||||
Nodes (9): devDependencies, prisma, @types/bcryptjs, @types/node, typescript, @types/node, typescript, prisma (+1 more)
|
||||
Nodes (9): devDependencies, eslint, @types/bcryptjs, @types/node, typescript, eslint, @types/node, typescript (+1 more)
|
||||
|
||||
### Community 10 - "reviews.controller.ts"
|
||||
Cohesion: 0.07
|
||||
Nodes (32): CreateReviewDto, ApiProperty, IsInt, IsNotEmpty, IsOptional, IsString, Min, ApiProperty (+24 more)
|
||||
|
||||
### Community 11 - "UsersService"
|
||||
Cohesion: 0.12
|
||||
Nodes (10): ApiPropertyOptional, IsEmail, IsOptional, IsString, MinLength, UpdateProfileDto, Injectable, Optional (+2 more)
|
||||
Cohesion: 0.05
|
||||
Nodes (43): DEFAULT_JWT_REFRESH_SECRET, DEFAULT_JWT_SECRET, getJwtSecret(), AuthModule, Module, JwtPayload, JwtStrategy, Injectable (+35 more)
|
||||
|
||||
### Community 12 - "index.ts"
|
||||
Cohesion: 0.06
|
||||
Nodes (24): backend, frontend, playwright.config.ts, @playwright/test, tests/**/*.ts, authFile, test, compilerOptions (+16 more)
|
||||
|
||||
### Community 13 - "app-audit-verification.e2e-spec.js"
|
||||
Cohesion: 0.07
|
||||
Nodes (26): EnvironmentVariables, IsNotEmpty, IsOptional, IsString, validateEnv(), CustomHttpExceptionFilter, Catch, PrismaExceptionFilter (+18 more)
|
||||
Cohesion: 0.06
|
||||
Nodes (28): AppModule, Module, EnvironmentVariables, IsNotEmpty, IsOptional, IsString, validateEnv(), CustomHttpExceptionFilter (+20 more)
|
||||
|
||||
### Community 14 - "UserDashboard.tsx"
|
||||
Cohesion: 0.14
|
||||
Nodes (23): AddressFormData, AddressModal(), AddressModalProps, normalizeDigits(), validateAddressForm(), BackButton(), BackButtonProps, CheckoutPage() (+15 more)
|
||||
Cohesion: 0.13
|
||||
Nodes (22): AddressFormData, AddressModal(), AddressModalProps, normalizeDigits(), validateAddressForm(), CheckoutPage(), DeleteConfirmModal(), DeleteConfirmModalProps (+14 more)
|
||||
|
||||
### Community 15 - "src/services/api.ts"
|
||||
Cohesion: 0.06
|
||||
@ -430,20 +428,20 @@ Cohesion: 0.14
|
||||
Nodes (18): B2BPage(), generateMetadata(), ContactPage(), generateMetadata(), generateMetadata(), getInitialVideos(), Videos(), ContactFormClient() (+10 more)
|
||||
|
||||
### Community 18 - "JwtAuthGuard"
|
||||
Cohesion: 0.21
|
||||
Nodes (6): JwtAuthGuard, Injectable, ROLES_KEY, RequestWithUser, RolesGuard, Injectable
|
||||
Cohesion: 0.18
|
||||
Nodes (7): JwtAuthGuard, Injectable, ROLES_KEY, RequestWithUser, RolesGuard, Injectable, ScientificTermData
|
||||
|
||||
### Community 19 - "admin.controller.ts"
|
||||
Cohesion: 0.29
|
||||
Cohesion: 0.35
|
||||
Nodes (12): ApplyGlobalMarginsDto, BulkPriceAdjustmentDto, ApiProperty, ApiPropertyOptional, IsArray, IsBoolean, IsIn, IsNumber (+4 more)
|
||||
|
||||
### Community 20 - "CreateVideoDto"
|
||||
Cohesion: 0.09
|
||||
Nodes (24): CreateVideoDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString, UpdateVideoDto (+16 more)
|
||||
|
||||
### Community 21 - "auth.module.ts"
|
||||
Cohesion: 0.15
|
||||
Nodes (10): DEFAULT_JWT_REFRESH_SECRET, DEFAULT_JWT_SECRET, getJwtSecret(), AuthModule, Module, JwtPayload, JwtStrategy, Injectable (+2 more)
|
||||
### Community 21 - "pets/pets.controller.ts"
|
||||
Cohesion: 0.13
|
||||
Nodes (15): CreatePetDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional, IsString (+7 more)
|
||||
|
||||
### Community 22 - "ProductDto"
|
||||
Cohesion: 0.16
|
||||
@ -493,9 +491,9 @@ Nodes (21): App(), ContactInfoItem, ContactSubmission, CategoryDist, DashboardDa
|
||||
Cohesion: 0.10
|
||||
Nodes (20): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto, ApiBearerAuth, ApiOperation (+12 more)
|
||||
|
||||
### Community 34 - "B2BService"
|
||||
Cohesion: 0.13
|
||||
Nodes (15): B2BController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+7 more)
|
||||
### Community 34 - "B2BController"
|
||||
Cohesion: 0.14
|
||||
Nodes (13): B2BController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+5 more)
|
||||
|
||||
### Community 35 - "ContactService"
|
||||
Cohesion: 0.13
|
||||
@ -529,13 +527,13 @@ Nodes (26): For /graphify add and --watch, For /graphify query, For the commit h
|
||||
Cohesion: 0.13
|
||||
Nodes (14): SslController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Post (+6 more)
|
||||
|
||||
### Community 43 - "BannersService"
|
||||
### Community 43 - "BannersController"
|
||||
Cohesion: 0.13
|
||||
Nodes (15): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+7 more)
|
||||
Nodes (13): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+5 more)
|
||||
|
||||
### Community 44 - "TestimonialsService"
|
||||
### Community 44 - "TestimonialsController"
|
||||
Cohesion: 0.13
|
||||
Nodes (14): TestimonialsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
|
||||
Nodes (12): TestimonialsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+4 more)
|
||||
|
||||
### Community 45 - "What You Must Do When Invoked"
|
||||
Cohesion: 0.07
|
||||
@ -545,13 +543,13 @@ Nodes (26): For /graphify add and --watch, For /graphify query, For the commit h
|
||||
Cohesion: 0.27
|
||||
Nodes (14): "coupons", "health_logs", "order_items", "orders", "pet_medical_conditions", "pets", "product_ingredients", "product_symptoms" (+6 more)
|
||||
|
||||
### Community 47 - "IngredientsService"
|
||||
### Community 47 - "IngredientsController"
|
||||
Cohesion: 0.13
|
||||
Nodes (14): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
|
||||
Nodes (12): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+4 more)
|
||||
|
||||
### Community 48 - "AuthController"
|
||||
Cohesion: 0.23
|
||||
Nodes (13): AuthController, ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+5 more)
|
||||
### Community 48 - "WikiController"
|
||||
Cohesion: 0.13
|
||||
Nodes (13): ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param, Query (+5 more)
|
||||
|
||||
### Community 49 - "devDependencies"
|
||||
Cohesion: 0.11
|
||||
@ -559,7 +557,7 @@ Nodes (19): autoprefixer, devDependencies, autoprefixer, eslint, @eslint/js, glo
|
||||
|
||||
### Community 50 - "devDependencies"
|
||||
Cohesion: 0.12
|
||||
Nodes (17): eslint-config-next, devDependencies, eslint, eslint-config-next, jsdom, @testing-library/jest-dom, @testing-library/react, @types/node (+9 more)
|
||||
Nodes (17): devDependencies, eslint, jsdom, tailwindcss, @testing-library/jest-dom, @testing-library/react, @types/node, @types/react (+9 more)
|
||||
|
||||
### Community 51 - "BlogsController"
|
||||
Cohesion: 0.07
|
||||
@ -589,9 +587,9 @@ Nodes (15): Badge(), BadgeProps, BadgeVariant, variantStyles, Skeleton(), Monito
|
||||
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 58 - "auth.service.ts"
|
||||
Cohesion: 0.09
|
||||
Nodes (17): AdminLoginInput, AuthService, LoginInput, RegisterInput, Injectable, SendOtpDto, ApiProperty, IsNotEmpty (+9 more)
|
||||
### Community 58 - "AuthService"
|
||||
Cohesion: 0.22
|
||||
Nodes (3): AuthService, Injectable, normalizeMobile()
|
||||
|
||||
### Community 59 - "compilerOptions"
|
||||
Cohesion: 0.06
|
||||
@ -602,36 +600,36 @@ Cohesion: 0.21
|
||||
Nodes (10): CreateUserDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty, IsNumber, IsOptional, IsString (+2 more)
|
||||
|
||||
### Community 61 - "ProductPage.tsx"
|
||||
Cohesion: 0.18
|
||||
Nodes (21): ArchiveProductCard(), CATEGORY_MAP, ICON_MAP, FeaturedProducts(), ProductCard(), ProductImageZoomModalProps, CalculatorState, GalleryMediaItem (+13 more)
|
||||
Cohesion: 0.11
|
||||
Nodes (32): ArchiveProductCard(), CATEGORY_MAP, ICON_MAP, FeaturedProducts(), ProductCard(), Header(), OrderSuccess(), OrderTracking() (+24 more)
|
||||
|
||||
### Community 62 - "torob.controller.ts"
|
||||
Cohesion: 0.22
|
||||
Nodes (8): buildTorobProductSpec(), buildTorobProductTitle(), TorobController, ApiOperation, ApiTags, Controller, Get, Query
|
||||
### Community 62 - "ReportsController"
|
||||
Cohesion: 0.14
|
||||
Nodes (11): ReportsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Get, Query (+3 more)
|
||||
|
||||
### Community 63 - "dependencies"
|
||||
Cohesion: 0.09
|
||||
Nodes (23): dependencies, bcryptjs, class-validator, compression, ioredis, @nestjs/common, @nestjs/passport, @nestjs/platform-express (+15 more)
|
||||
Nodes (23): dependencies, bcryptjs, class-transformer, class-validator, compression, ioredis, @nestjs/common, @nestjs/passport (+15 more)
|
||||
|
||||
### Community 64 - "compilerOptions"
|
||||
Cohesion: 0.10
|
||||
Nodes (20): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, lib, module, moduleDetection, moduleResolution, noEmit (+12 more)
|
||||
|
||||
### Community 65 - "admin.service.ts"
|
||||
Cohesion: 0.33
|
||||
Cohesion: 0.21
|
||||
Nodes (8): CouponTargetInput, PaginationQuery, applyRounding(), calculateSellingPrice(), DEFAULT_PRICING_SETTINGS, PricingSettings, RoundingMode, CANONICAL_ALIASES
|
||||
|
||||
### Community 66 - "AdminQueryDto"
|
||||
Cohesion: 0.18
|
||||
Nodes (7): ApiQuery, Query, AdminProductQueryDto, AdminQueryDto, ApiPropertyOptional, IsOptional, IsString
|
||||
### Community 66 - "ApiOperation"
|
||||
Cohesion: 0.13
|
||||
Nodes (9): ApiOperation, ApiQuery, Get, Query, AdminProductQueryDto, AdminQueryDto, ApiPropertyOptional, IsOptional (+1 more)
|
||||
|
||||
### Community 67 - "admin.module.ts"
|
||||
Cohesion: 0.06
|
||||
Nodes (23): AdminModule, Module, CategoryQuery, MediaService, Injectable, PetQuery, PetsService, Injectable (+15 more)
|
||||
Nodes (23): AdminModule, Module, MediaService, Injectable, PetsController, ApiBearerAuth, ApiOperation, ApiQuery (+15 more)
|
||||
|
||||
### Community 68 - "useSettingsStore"
|
||||
Cohesion: 0.07
|
||||
Nodes (34): HomeClient(), HomeClientProps, ArchivePage(), B2BLandingClient(), BannerPlacement(), BannerPlacementProps, BrandLogo(), BrandLogoProps (+26 more)
|
||||
### Community 68 - "HomeClient.tsx"
|
||||
Cohesion: 0.11
|
||||
Nodes (19): HomeClient(), HomeClientProps, BannerPlacement(), BannerPlacementProps, BlogPreviewSection(), FAQSection(), Hero(), StatCounter() (+11 more)
|
||||
|
||||
### Community 69 - "Required Review Group Closures"
|
||||
Cohesion: 0.10
|
||||
@ -658,12 +656,12 @@ Cohesion: 0.13
|
||||
Nodes (14): ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete, Get (+6 more)
|
||||
|
||||
### Community 75 - "PetsController"
|
||||
Cohesion: 0.05
|
||||
Nodes (47): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, CreatePetDto, ApiProperty (+39 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (32): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, CreateReminderDto, ApiProperty (+24 more)
|
||||
|
||||
### Community 76 - "ProductsService"
|
||||
Cohesion: 0.10
|
||||
Nodes (19): GetProductsDto, ApiPropertyOptional, IsEnum, IsOptional, IsString, ProductsController, ApiOperation, ApiTags (+11 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (27): GetProductsDto, ApiPropertyOptional, IsEnum, IsOptional, IsString, ProductsController, ApiOperation, ApiTags (+19 more)
|
||||
|
||||
### Community 77 - "seo.module.ts"
|
||||
Cohesion: 0.16
|
||||
@ -697,9 +695,9 @@ Nodes (21): dependencies, axios, lucide-react, react, react-dom, react-hot-toast
|
||||
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 85 - "auth.controller.ts"
|
||||
Cohesion: 0.10
|
||||
Nodes (19): AdminLoginDto, ApiProperty, IsEmail, IsNotEmpty, IsString, MinLength, LoginDto, ApiProperty (+11 more)
|
||||
### Community 85 - "auth.service.ts"
|
||||
Cohesion: 0.06
|
||||
Nodes (46): AuthController, ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+38 more)
|
||||
|
||||
### Community 86 - "zibal.service.ts"
|
||||
Cohesion: 0.16
|
||||
@ -717,17 +715,17 @@ Nodes (8): CreateEBankCheckoutDto, ApiProperty, ApiPropertyOptional, IsNotEmpty,
|
||||
Cohesion: 0.17
|
||||
Nodes (12): prisma, main(), prisma, determineSuitableFor(), findOrCreateCategory(), getProductImageUrl(), main(), parseSize() (+4 more)
|
||||
|
||||
### Community 90 - "orderService.ts"
|
||||
Cohesion: 0.18
|
||||
Nodes (5): ApiErr, Order, OrderItem, OrderService, mockProduct
|
||||
### Community 90 - "cartStore.ts"
|
||||
Cohesion: 0.15
|
||||
Nodes (8): ApiErr, Order, OrderItem, OrderService, CartItem, CartStore, Order, mockProduct
|
||||
|
||||
### Community 91 - "Reconciled Audit Roles & Assignments"
|
||||
Cohesion: 0.12
|
||||
Nodes (15): 10. Documentation Engineer, 1. Lead Architect / Orchestrator, 2. React / Vite Storefront Auditor, 3. NestJS Backend Auditor, 4. Admin Features Auditor, 5. Database & Data Integrity Auditor, 6. Security Auditor, 7. TypeScript & Code Quality Auditor (+7 more)
|
||||
|
||||
### Community 92 - "OrdersService"
|
||||
Cohesion: 0.07
|
||||
Nodes (29): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+21 more)
|
||||
Cohesion: 0.06
|
||||
Nodes (35): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+27 more)
|
||||
|
||||
### Community 93 - "components/Skeleton.tsx"
|
||||
Cohesion: 0.24
|
||||
@ -786,12 +784,12 @@ Cohesion: 0.43
|
||||
Nodes (7): InitiatePaymentDto, InitiateWalletTopupDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString
|
||||
|
||||
### Community 107 - "PaginationDto"
|
||||
Cohesion: 0.05
|
||||
Nodes (32): BlogsModule, Module, BlogFilterDto, BlogsService, Injectable, PaginationDto, SortOrder, ApiPropertyOptional (+24 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (19): BlogsModule, Module, BlogFilterDto, BlogsService, Injectable, PaginationDto, SortOrder, ApiPropertyOptional (+11 more)
|
||||
|
||||
### Community 108 - "PrismaService"
|
||||
Cohesion: 0.04
|
||||
Nodes (35): ApiExcludeController, Optional, B2BWholesaleOrderItem, MetricsController, Controller, Get, Res, RevalidationModule (+27 more)
|
||||
Cohesion: 0.06
|
||||
Nodes (27): CategoryQuery, PetQuery, WikiQuery, BannersService, Injectable, DEFAULT_SMS_RULES, SMS_EVENT_DEFINITIONS, SmsEventVariable (+19 more)
|
||||
|
||||
### Community 109 - "1. Summary of Integrity Repairs Performed"
|
||||
Cohesion: 0.17
|
||||
@ -809,9 +807,9 @@ Nodes (10): 1. Mark Active Task as Complete, 2. Documentation Updates, 3. Dynami
|
||||
Cohesion: 0.18
|
||||
Nodes (10): 1. Pre-Deployment Checklist, 2. Build Verification, 3. Deployment Strategy (Based on Target), 4. Post-Deployment Health Check, 5. Forbidden Actions, Expected JSON Output Schema, Operational Rules & Boundaries, Required Output Artifacts (What files to write/update) (+2 more)
|
||||
|
||||
### Community 113 - "PetsController"
|
||||
Cohesion: 0.15
|
||||
Nodes (11): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+3 more)
|
||||
### Community 113 - "MetricsController"
|
||||
Cohesion: 0.20
|
||||
Nodes (5): ApiExcludeController, MetricsController, Controller, Get, Res
|
||||
|
||||
### Community 114 - "AppService"
|
||||
Cohesion: 0.29
|
||||
@ -847,11 +845,11 @@ Nodes (9): Compile and run the project, Deployment, Description, License, Projec
|
||||
|
||||
### Community 122 - "AdminService"
|
||||
Cohesion: 0.09
|
||||
Nodes (12): AdminController, ApiBearerAuth, ApiOperation, ApiTags, Controller, Delete, Get, Param (+4 more)
|
||||
Nodes (13): AdminController, ApiBearerAuth, ApiTags, Body, Controller, Delete, Param, Post (+5 more)
|
||||
|
||||
### Community 123 - "UsersController"
|
||||
Cohesion: 0.21
|
||||
Nodes (16): ApiBadRequestResponse, ApiBearerAuth, ApiCreatedResponse, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+8 more)
|
||||
### Community 123 - "B2BService"
|
||||
Cohesion: 0.33
|
||||
Nodes (5): B2BModule, Module, B2BService, B2BWholesaleOrderItem, Injectable
|
||||
|
||||
### Community 124 - "Repository Map"
|
||||
Cohesion: 0.20
|
||||
@ -869,9 +867,9 @@ Nodes (9): name, private, scripts, build, dev, lint, preview, type (+1 more)
|
||||
Cohesion: 0.20
|
||||
Nodes (9): Arch Linux, Contributors, Install, Known problems for variable version, License, Sahel-Font, To Do (variable), طریقه استفاده از نسخه متغیر variable (+1 more)
|
||||
|
||||
### Community 128 - "Body"
|
||||
Cohesion: 0.17
|
||||
Nodes (3): Body, Post, CouponInput
|
||||
### Community 128 - "zibal-ebank.service.ts"
|
||||
Cohesion: 0.40
|
||||
Nodes (4): EBankCheckoutListFilter, EBankCheckoutOptions, EBankIdentifiedPaymentFilter, EBankStatementFilter
|
||||
|
||||
### Community 129 - "Reports.tsx"
|
||||
Cohesion: 0.20
|
||||
@ -934,12 +932,8 @@ Cohesion: 0.25
|
||||
Nodes (6): app_module_1, core_1, fs, path, swagger_1, yaml
|
||||
|
||||
### Community 144 - "lib/services/api.ts"
|
||||
Cohesion: 0.08
|
||||
Nodes (24): B2BPortal(), BlogPostClientProps, BlogPost, BlogPreviewSection(), ContactInfoItem, OrderDetailsModal(), OrderDetailsModalProps, PLAYBACK_RATES (+16 more)
|
||||
|
||||
### Community 145 - "orders.service.ts"
|
||||
Cohesion: 0.24
|
||||
Nodes (6): IsNotEmpty, IsNumber, IsString, ValidateCouponDto, OrdersModule, Module
|
||||
Cohesion: 0.09
|
||||
Nodes (21): B2BLandingClient(), BlogPostClientProps, BlogPost, ContactInfoItem, FAQItem, OrderDetailsModalProps, PLAYBACK_RATES, PodcastInlinePlayer() (+13 more)
|
||||
|
||||
### Community 146 - "System Discovery"
|
||||
Cohesion: 0.25
|
||||
@ -961,13 +955,9 @@ Nodes (5): generateMetadata(), getRelatedProducts(), getWikiTerm(), WikiTermPage
|
||||
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 151 - "AddressDto"
|
||||
Cohesion: 0.25
|
||||
Nodes (7): AddressDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString
|
||||
|
||||
### Community 152 - "RedisService"
|
||||
Cohesion: 0.11
|
||||
Nodes (7): AppModule, Module, RedisModule, Global, Module, RedisService, Injectable
|
||||
### Community 152 - "RevalidationService"
|
||||
Cohesion: 0.12
|
||||
Nodes (8): Optional, RevalidationModule, Global, Module, RevalidationService, Injectable, RedisService, Injectable
|
||||
|
||||
### Community 153 - "exclude"
|
||||
Cohesion: 0.22
|
||||
@ -1117,9 +1107,9 @@ Nodes (3): Expanding the ESLint configuration, React Compiler, React + TypeScrip
|
||||
Cohesion: 0.50
|
||||
Nodes (3): Select, SelectOption, SelectProps
|
||||
|
||||
### Community 197 - "ClientLayout.tsx"
|
||||
Cohesion: 0.08
|
||||
Nodes (19): AuthModal, B2BPortal, CartDrawer, ClientLayout(), LoginModal, AuthModal(), AuthModalProps, extractOtpFromText() (+11 more)
|
||||
### Community 197 - "toPersian"
|
||||
Cohesion: 0.07
|
||||
Nodes (33): VerifyContent(), AuthModal(), AuthModalProps, extractOtpFromText(), otpCooldownExpiries, B2BPortal(), CartDrawer(), HeaderButton() (+25 more)
|
||||
|
||||
### Community 200 - "application/README.md"
|
||||
Cohesion: 0.50
|
||||
@ -1146,24 +1136,24 @@ Cohesion: 0.83
|
||||
Nodes (3): GET(), handleRevalidate(), POST()
|
||||
|
||||
## Knowledge Gaps
|
||||
- **1352 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1347 more)
|
||||
- **1355 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1350 more)
|
||||
These have ≤1 connection - possible missing edges or undocumented components.
|
||||
- **113 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 `Roles()` connect `Roles` to `WholesaleApplyDto`, `B2BService`, `ContactService`, `FaqController`, `CmsController`, `tickets.controller.ts`, `SmsService`, `SslController`, `BannersService`, `ProductsService`, `reviews.controller.ts`, `TestimonialsService`, `IngredientsService`, `JwtAuthGuard`, `prescriptions.controller.ts`, `SmartAdvisorService`, `MenuService`?**
|
||||
_High betweenness centrality (0.094) - this node is a cross-community bridge._
|
||||
- **Why does `ApiResponse` connect `src/services/api.ts` to `BlogsController`, `PetsController`, `ProductsService`, `PaginationDto`, `AuthController`, `HomeController`, `UsersController`, `OrdersService`?**
|
||||
- **Why does `Roles()` connect `Roles` to `WholesaleApplyDto`, `B2BController`, `ContactService`, `FaqController`, `CmsController`, `tickets.controller.ts`, `SmsService`, `SslController`, `BannersController`, `ProductsService`, `reviews.controller.ts`, `TestimonialsController`, `IngredientsController`, `JwtAuthGuard`, `prescriptions.controller.ts`, `SmartAdvisorService`, `MenuService`, `B2BService`?**
|
||||
_High betweenness centrality (0.093) - this node is a cross-community bridge._
|
||||
- **Why does `ApiResponse` connect `src/services/api.ts` to `BlogsController`, `PetsController`, `ProductsService`, `UsersService`, `WikiController`, `HomeController`, `auth.service.ts`, `OrdersService`?**
|
||||
_High betweenness centrality (0.066) - this node is a cross-community bridge._
|
||||
- **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `admin.module.ts`, `CmsController`, `tickets.controller.ts`, `reviews.controller.ts`, `PaginationDto`, `PetsController`, `ProductsService`, `UsersService`, `DoctorQueryDto`, `orders.service.ts`, `admin.controller.ts`, `prescriptions.controller.ts`, `auth.controller.ts`?**
|
||||
- **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `app.module.ts`, `admin.module.ts`, `CmsController`, `tickets.controller.ts`, `reviews.controller.ts`, `PaginationDto`, `ProductsService`, `UsersService`, `admin.controller.ts`, `prescriptions.controller.ts`, `auth.service.ts`, `pets/pets.controller.ts`, `B2BService`, `OrdersService`?**
|
||||
_High betweenness centrality (0.030) - this node is a cross-community bridge._
|
||||
- **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?**
|
||||
_1352 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||
_1355 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||
- **Should `app.module.ts` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.07215686274509804 - nodes in this community are weakly interconnected._
|
||||
- **Should `getMediaUrl` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.09848484848484848 - nodes in this community are weakly interconnected._
|
||||
_Cohesion score 0.07137254901960784 - nodes in this community are weakly interconnected._
|
||||
- **Should `productService.ts` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.06654567453115548 - nodes in this community are weakly interconnected._
|
||||
_Cohesion score 0.05839727195225917 - nodes in this community are weakly interconnected._
|
||||
- **Should `useSettingsStore` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.0782608695652174 - 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
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