AI Review Center
Commit Review Workspace ?
Select a commit on the left to inspect quality, security, business value, findings, and suggested code changes.
Project AI Score
?
63%
Quality Avg
?
68%
Security Avg
?
45%
Reviews
?
56
Review Result ?
jattin01/avriti · 4c8515a5
This commit introduces frontend enhancements including a banner and service-related features. It adds service support in the checkout and my-order pages, fetches and displays banners, and builds a detailed service detail page with tabs and consultation fee display. The code generally follows React and Next.js conventions with appropriate type usage and state handling. Some parts use dangerouslySetInnerHTML which presents potential security risks if data isn't sanitized server-side. There is no explicit input validation or error handling in fetch calls beyond basic try/catch. Shipping logic update for all-service orders is a good business optimization.
Quality
?
85%
Security
?
60%
Business Value
?
90%
Maintainability
?
83%
Issues & Suggested Fixes
?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Usage Of Dangerouslysetinnerhtml
Where
app/services/[slug]/page.tsx:100
Issue / Evidence
usage of dangerouslySetInnerHTML
Suggested Fix
ensure server-side sanitization of HTML to prevent XSS vulnerabilities
Fetch Error Handling
Where
app/services/[slug]/page.tsx:42
Issue / Evidence
fetch error handling
Suggested Fix
add user-visible error feedback in UI on fetch failure to improve UX
Empty Catch Block In Banner Fetch
Where
app/page.tsx:123
Issue / Evidence
empty catch block in banner fetch
Suggested Fix
log or handle error to aid debugging and user experience
Shipping Logic
Where
app/checkout/page.tsx:388-391
Issue / Evidence
shipping logic
Suggested Fix
consider adding unit tests to cover the isAllService branch for reliability
Button Disabling Logic
Where
app/checkout/page.tsx:840
Issue / Evidence
button disabling logic
Suggested Fix
confirm all conditions correctly disable placement to prevent invalid state
Minor Issue
Where
commit message
Issue / Evidence
minor issue
Suggested Fix
expand message with more details about changes to assist reviewers and future maintenance
Code Change Preview · app/checkout/page.tsx
?
Removed / Before Commit
- type CheckoutItem = { - product_id: number | null; - combo_product_id?: number | null; - is_combo?: boolean; - title: string; - thumbnail?: string; - attribute_name: string; - setItems([{ - product_id: parsed.product_id ?? null, - combo_product_id: parsed.combo_product_id ?? null, - is_combo: !!parsed.is_combo, - title: parsed.title, - thumbnail: parsed.thumbnail ?? "", - attribute_name: parsed.attribute_name, - attribute_value: parsed.attribute_value, - variant_name: parsed.variant_name, - sku: parsed.sku ?? "", - selling_price: parsed.selling_price ?? 0,
Added / After Commit
+ type CheckoutItem = { + product_id: number | null; + combo_product_id?: number | null; + service_detail_id?: number | null; + is_combo?: boolean; + is_service?: boolean; + title: string; + thumbnail?: string; + attribute_name: string; + setItems([{ + product_id: parsed.product_id ?? null, + combo_product_id: parsed.combo_product_id ?? null, + service_detail_id: parsed.service_detail_id ?? null, + is_combo: !!parsed.is_combo, + is_service: !!parsed.is_service, + title: parsed.title, + thumbnail: parsed.thumbnail ?? "", + attribute_name: parsed.attribute_name ?? "",
Removed / Before Commit
- quantity: number; - total: number; - product_image: string | null; - } - - interface OrderData { - - <div className="min-w-0"> - <p className="truncate text-[15px] font-semibold text-[#111827]"> - {item.product_name} - </p> - {formatAttributeLabel(item) && ( - <p className="mt-1 text-[12px] text-[#7A7A7A]">
Added / After Commit
+ quantity: number; + total: number; + product_image: string | null; + is_service?: boolean; + } + + interface OrderData { + + <div className="min-w-0"> + <p className="truncate text-[15px] font-semibold text-[#111827]"> + {item.product_name}{item.is_service ? " (Service)" : ""} + </p> + {formatAttributeLabel(item) && ( + <p className="mt-1 text-[12px] text-[#7A7A7A]">
Removed / Before Commit
- "from-[#F4F0E8] to-[#EDE4DC]", - ]; - - const offerBanners = ["/offerBanner1.png", "/offerBanner1.png", "/offerBanner1.png"]; - - export default function Home() { - const [home, setHome] = useState<HomeData | null>(null); - const [featuredProducts, setFeaturedProducts] = useState<FeaturedProduct[]>([]); - const [activeOfferIndex, setActiveOfferIndex] = useState(0); - - useEffect(() => { - Promise.all([ - }, []); - - useEffect(() => { - const intervalId = window.setInterval(() => { - setActiveOfferIndex((current) => (current + 1) % offerBanners.length); - }, 4000);
Added / After Commit
+ "from-[#F4F0E8] to-[#EDE4DC]", + ]; + + type BannerItem = { id: number; image: string; url: string }; + + export default function Home() { + const [home, setHome] = useState<HomeData | null>(null); + const [featuredProducts, setFeaturedProducts] = useState<FeaturedProduct[]>([]); + const [activeOfferIndex, setActiveOfferIndex] = useState(0); + const [banners, setBanners] = useState<BannerItem[]>([]); + + useEffect(() => { + Promise.all([ + }, []); + + useEffect(() => { + fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/banners`) + .then((res) => res.json())
Removed / Before Commit
- import Link from "next/link"; - import { notFound } from "next/navigation"; - import { CalendarDays, Check, MessageCircle } from "lucide-react"; - import { Badge } from "@/components/ui/badge"; - import { Button } from "@/components/ui/button"; - import { Card } from "@/components/ui/card"; - import { services } from "@/lib/data"; - - export function generateStaticParams() { - return services.map((service) => ({ slug: service.slug })); - } - - export default async function ServiceDetailPage({ - params, - }: { - params: Promise<{ slug: string }>; - }) { - const { slug } = await params;
Added / After Commit
+ "use client"; + + import { useEffect, useState } from "react"; + import { useParams } from "next/navigation"; + import Link from "next/link"; + import { isLoggedIn } from "@/lib/cart"; + + type OtherDetail = { + sno: number; + section_name: string; + details: string; + }; + + type ServiceDetail = { + id: number; + name: string; + slug: string; + short_description: string;
Removed / Before Commit
- - import { useEffect, useState } from "react"; - import Image from "next/image"; - import { PdfBrowserFrame } from "@/components/pdf-browser-frame"; - - type ServiceCard = { - cards: ServiceCard[]; - }; - - export default function ServicesPage() { - const [serviceData, setServiceData] = useState<ServiceData | null>(null); - const cards = serviceData?.cards ?? []; - - useEffect(() => { - fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/services`) - .then((res) => res.json()) - .then((data) => { - if (data.success && data.data) {
Added / After Commit
+ + import { useEffect, useState } from "react"; + import Image from "next/image"; + import Link from "next/link"; + import { PdfBrowserFrame } from "@/components/pdf-browser-frame"; + + type ServiceCard = { + cards: ServiceCard[]; + }; + + type ServiceDetailCard = { + id: number; + name: string; + slug: string; + short_description: string; + icon: string | null; + image: string | null; + consultation_fee: string;
Removed / Before Commit
- whatToExpect, - }: ProductAccordionProps) { - const sections: AccordionItem[] = [ - ...(disclaimer - ? [ - { - title: "Disclaimer", - defaultOpen: false, - content: ( - <div - className="prose prose-sm max-w-none [&_p]:mb-3 [&_p:last-child]:mb-0" - dangerouslySetInnerHTML={{ __html: disclaimer }} - /> - ), - }, - ] - : []), - ...(chakraAlignment
Added / After Commit
+ whatToExpect, + }: ProductAccordionProps) { + const sections: AccordionItem[] = [ + ...(chakraAlignment + ? [{ title: "Chakra Alignment", defaultOpen: false, content: <p>{chakraAlignment}</p> }] + : []), + </div> + ), + }, + ...(disclaimer + ? [ + { + title: "Disclaimer", + defaultOpen: false, + content: ( + <div + className="prose prose-sm max-w-none [&_p]:mb-3 [&_p:last-child]:mb-0" + dangerouslySetInnerHTML={{ __html: disclaimer }}
Removed / Before Commit
- - - - - - - // "use client"; - - // import { useState } from "react"; - - // const tabs = ["Description", "Reviews", "Shipping"]; - - // const tabContent = (description?: string): Record<string, React.ReactNode> => ({ - // Description: ( - // <div - // className="text-gray-600 text-sm leading-relaxed" - // dangerouslySetInnerHTML={{ __html: description || "No description available." }} - // />
Added / After Commit
+ + +
Removed / Before Commit
- export type LocalCartItem = { - product_id?: number | null; - combo_product_id?: number | null; - slug: string; - title: string; - thumbnail: string; - mrp: number; - quantity: number; - is_combo?: boolean; - }; - - const CART_KEY = "avriti_cart"; - export async function apiAddToCart(item: { - product_id?: number; - combo_product_id?: number; - attribute_name?: string; - attribute_value?: string; - quantity: number;
Added / After Commit
+ export type LocalCartItem = { + product_id?: number | null; + combo_product_id?: number | null; + service_detail_id?: number | null; + slug: string; + title: string; + thumbnail: string; + mrp: number; + quantity: number; + is_combo?: boolean; + is_service?: boolean; + }; + + const CART_KEY = "avriti_cart"; + export async function apiAddToCart(item: { + product_id?: number; + combo_product_id?: number; + service_detail_id?: number;