Showing AI reviews for super-admin
Project AI Score ?
72%
Quality Avg ?
77%
Security Avg ?
64%
Reviews ?
91

Review Result ?

solutionbowl/super-admin · 41b3563d
This commit adds a new Excel export feature for bets with detailed type definitions and UI integration, improving business value by enabling users to export data easily. The implementation is mostly clean and user-friendly. Dynamic import of the xlsx library is appropriate to reduce initial load. The risk of bugs is low because there is defensive handling of empty datasets. However, security improvements could be made regarding the handling of potentially sensitive data (like IP addresses) and sanitizing data before export. Minor improvements on error handling and clearer commit message would help overall quality and maintainability.
Quality ?
85%
Security ?
30%
Business Value ?
90%
Maintainability ?
88%
Issues & Suggested Fixes ?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Poor Detail
Where commit message
Issue / Evidence poor detail
Suggested Fix write a more descriptive commit message explaining the purpose and key changes
Error Message Is Generic
Where src/components/common/BetsExcelExportButton.tsx:63
Issue / Evidence error message is generic
Suggested Fix consider providing more user context or guidance
Dynamic Import Usage
Where src/components/common/BetsExcelExportButton.tsx:69
Issue / Evidence dynamic import usage
Suggested Fix ensure proper error handling in case the import fails
Includes Ip Addresses In Export
Where src/components/common/BetsExcelExportButton.tsx:134
Issue / Evidence includes IP addresses in export
Suggested Fix consider anonymizing or omitting sensitive data to improve security
Tocelltext Does Minimal Sanitization
Where src/components/common/BetsExcelExportButton.tsx:186
Issue / Evidence toCellText does minimal sanitization
Suggested Fix add sanitization or escaping to avoid injection in excel files
Displaying Username Or User Info
Where src/routes/bet-list.tsx:674
Issue / Evidence displaying username or user info
Suggested Fix ensure no PII is leaked unintentionally in exported data or UI
Code Change Preview · package.json ?
Removed / Before Commit
- diff --git a/package.json b/package.json
- index 4aa3e60..f7a01c0 100644
- "input-otp": "^1.4.2",
- "lucide-react": "^0.575.0",
- "motion": "^12.38.0",
- "react": "^19.2.0",
- "react-day-picker": "^9.14.0",
- "react-dom": "^19.2.0",
- "tw-animate-css": "^1.3.4",
- "vaul": "^1.1.2",
- "vite-tsconfig-paths": "^6.0.2",
- "zod": "^3.24.2"
- },
- "devDependencies": {
Added / After Commit
+ diff --git a/package.json b/package.json
+ index 4aa3e60..f7a01c0 100644
+ "input-otp": "^1.4.2",
+ "lucide-react": "^0.575.0",
+ "motion": "^12.38.0",
+     "number-to-words": "^1.2.4",
+ "react": "^19.2.0",
+ "react-day-picker": "^9.14.0",
+ "react-dom": "^19.2.0",
+ "tw-animate-css": "^1.3.4",
+ "vaul": "^1.1.2",
+ "vite-tsconfig-paths": "^6.0.2",
+     "xlsx": "^0.18.5",
+ "zod": "^3.24.2"
+ },
+ "devDependencies": {
Removed / Before Commit
- diff --git a/src/components/common/BetsExcelExportButton.tsx b/src/components/common/BetsExcelExportButton.tsx
- new file mode 100644
- index 0000000..38fb882
Added / After Commit
+ diff --git a/src/components/common/BetsExcelExportButton.tsx b/src/components/common/BetsExcelExportButton.tsx
+ new file mode 100644
+ index 0000000..38fb882
+ import { useState, type ComponentProps, type ReactNode } from "react";
+ import { Download } from "lucide-react";
+ import { toast } from "sonner";
+ import { Button } from "@/components/ui/button";
+ 
+ type CellValue = string | number | boolean | null | undefined;
+ type XlsxModule = typeof import("xlsx");
+ 
+ export type BetsExcelLeg = {
+   raceId?: CellValue;
+   market?: CellValue;
+   marketId?: CellValue;
+   runnerId?: CellValue;
+   selectionNo?: CellValue;
+   runnerName?: CellValue;
Removed / Before Commit
- diff --git a/src/routes/bet-list.tsx b/src/routes/bet-list.tsx
- index c6d13a2..9f3be0b 100644
- import type { DateRange } from "react-day-picker";
- import { Button } from "@/components/ui/button";
- import { Input } from "@/components/ui/input";
- import CsvExportButton from "@/components/common/CsvExportButton";
- import {
- Select,
- SelectContent,
- } from "@/components/ui/select";
- import { internalServices } from "@/services/api/internalServices";
- import type { Bet, MultiBetLeg } from "@/services/api/betTypes";
- import type { CsvColumn } from "@/utils/csv/types";
- import { cn } from "@/lib/utils";
- 
- export const Route = createFileRoute("/bet-list")({
- const activeIsLoading = isAgentMode ? agentBetsQuery.isLoading : isLoading;
- const activeIsFetching = isAgentMode ? agentBetsQuery.isFetching : isFetching;
Added / After Commit
+ diff --git a/src/routes/bet-list.tsx b/src/routes/bet-list.tsx
+ index c6d13a2..9f3be0b 100644
+ import type { DateRange } from "react-day-picker";
+ import { Button } from "@/components/ui/button";
+ import { Input } from "@/components/ui/input";
+ import BetsExcelExportButton from "@/components/common/BetsExcelExportButton";
+ import {
+ Select,
+ SelectContent,
+ } from "@/components/ui/select";
+ import { internalServices } from "@/services/api/internalServices";
+ import type { Bet, MultiBetLeg } from "@/services/api/betTypes";
+ import { cn } from "@/lib/utils";
+ 
+ export const Route = createFileRoute("/bet-list")({
+ const activeIsLoading = isAgentMode ? agentBetsQuery.isLoading : isLoading;
+ const activeIsFetching = isAgentMode ? agentBetsQuery.isFetching : isFetching;
+ const activeError = isAgentMode ? agentBetsQuery.error : error;
Removed / Before Commit
- diff --git a/src/routes/bet-ticket.tsx b/src/routes/bet-ticket.tsx
- index cacc2ea..8bee2a3 100644
- import { cn } from "@/lib/utils";
- import { format } from "date-fns";
- import { useAutoRefresh } from "@/hooks/useAutoRefresh";
- import CsvExportButton from "@/components/common/CsvExportButton";
- import type { CsvColumn } from "@/utils/csv/types";
- 
- export const Route = createFileRoute("/bet-ticket")({
- component: BetTicketPage,
- const total = data?.total ?? 0;
- const totalItems = data?.total ?? 0;
- const totalPages = data?.totalPages ?? 1;
-   const csvColumns = useMemo(
-     () =>
-       [
-         { header: "Legs", accessor: (bet) => bet.totalLegs ?? bet.legs?.length ?? "" },
-         { header: "User", accessor: (bet) => bet.username || "-" },
Added / After Commit
+ diff --git a/src/routes/bet-ticket.tsx b/src/routes/bet-ticket.tsx
+ index cacc2ea..8bee2a3 100644
+ import { cn } from "@/lib/utils";
+ import { format } from "date-fns";
+ import { useAutoRefresh } from "@/hooks/useAutoRefresh";
+ import BetsExcelExportButton from "@/components/common/BetsExcelExportButton";
+ 
+ export const Route = createFileRoute("/bet-ticket")({
+ component: BetTicketPage,
+ const total = data?.total ?? 0;
+ const totalItems = data?.total ?? 0;
+ const totalPages = data?.totalPages ?? 1;
+ 
+ const [currentPage, setCurrentPage] = useState(1);
+ // const PAGE_SIZE = 20;
+ <RefreshCw className={cn("mr-2 h-4 w-4", isFetching && "animate-spin")} />
+ Refresh {countdown}s
+ </Button>
Removed / Before Commit
- diff --git a/src/routes/transfer.tsx b/src/routes/transfer.tsx
- index 1c5baa2..d1e0c96 100644
- import { createFileRoute } from "@tanstack/react-router";
- import { useEffect, useMemo, useState, type ReactNode } from "react";
- import { useMutation, useQuery } from "@tanstack/react-query";
- import { motion } from "motion/react";
- import { toast } from "sonner";
- 
- type TransferTabValue = "all" | CreatableRole;
- type TransferTab = { value: TransferTabValue; label: string };
- 
- function StatCell({
- label,
- const [selectedRows, setSelectedRows] = useState<string[]>([]);
- const [transferTarget, setTransferTarget] = useState<TransferRow | null>(null);
- const [transferAmount, setTransferAmount] = useState("");
- const pageSize = 20;
- 
Added / After Commit
+ diff --git a/src/routes/transfer.tsx b/src/routes/transfer.tsx
+ index 1c5baa2..d1e0c96 100644
+ import { createFileRoute } from "@tanstack/react-router";
+ import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
+ import { useMutation, useQuery } from "@tanstack/react-query";
+ import { motion } from "motion/react";
+ import { toast } from "sonner";
+ 
+ type TransferTabValue = "all" | CreatableRole;
+ type TransferTab = { value: TransferTabValue; label: string };
+ type BulkTransferRow = {
+   key: string;
+   childUserId: string;
+   loginName: string;
+   action: TransferAction;
+   amount: string;
+ };
+ 
Removed / Before Commit
- diff --git a/src/routes/user-details.$userId.tsx b/src/routes/user-details.$userId.tsx
- index 8e90c94..f659b5c 100644
- import { setExposureParams } from "@/lib/nav-params";
- import type { MultiBetLeg } from "@/services/api/betTypes";
- import CsvExportButton from "@/components/common/CsvExportButton";
- import type { CsvColumn } from "@/utils/csv/types";
- 
- export const Route = createFileRoute("/user-details/$userId")({
- () => bets.slice((currentPage - 1) * pageSize, currentPage * pageSize),
- [bets, currentPage],
- );
-   const csvColumns = useMemo(
-     () =>
-       [
-         { header: "Legs", accessor: (bet) => getUserBetTotalLegs(bet) },
-         { header: "Bet ID", accessor: (bet) => bet.bet_id ?? "" },
-         { header: "Market", accessor: (bet) => bet.market_name ?? "" },
-         { header: "Selection", accessor: (bet) => bet.selection ?? "" },
Added / After Commit
+ diff --git a/src/routes/user-details.$userId.tsx b/src/routes/user-details.$userId.tsx
+ index 8e90c94..f659b5c 100644
+ import { setExposureParams } from "@/lib/nav-params";
+ import type { MultiBetLeg } from "@/services/api/betTypes";
+ import CsvExportButton from "@/components/common/CsvExportButton";
+ import BetsExcelExportButton from "@/components/common/BetsExcelExportButton";
+ import type { CsvColumn } from "@/utils/csv/types";
+ 
+ export const Route = createFileRoute("/user-details/$userId")({
+ () => bets.slice((currentPage - 1) * pageSize, currentPage * pageSize),
+ [bets, currentPage],
+ );
+ return (
+ <Card className="overflow-hidden rounded-2xl border-border/60 bg-card shadow-elegant">
+ {/* Filters */}
+ {f}
+ </Button>
+ ))}
Removed / Before Commit
- diff --git a/src/routes/user-exposure-bet.tsx b/src/routes/user-exposure-bet.tsx
- new file mode 100644
- index 0000000..87ea24c
Added / After Commit
+ diff --git a/src/routes/user-exposure-bet.tsx b/src/routes/user-exposure-bet.tsx
+ new file mode 100644
+ index 0000000..87ea24c
+ import { createFileRoute } from '@tanstack/react-router'
+ 
+ export const Route = createFileRoute('/user-exposure-bet')({
+   component: RouteComponent,
+ })
+ 
+ function RouteComponent() {
+   return <div>Hello "/user-exposure-bet"!</div>
+ }
Removed / Before Commit
- diff --git a/src/routes/user-listing.tsx b/src/routes/user-listing.tsx
- index 472568d..e3e0b1d 100644
- const [editCreditRefUser, setEditCreditRefUser] = useState<DownlineUser | null>(null);
- const [newCreditRefValue, setNewCreditRefValue] = useState("");
- const [creditRefError, setCreditRefError] = useState("");
- 
- useEffect(() => {
- setPageInput(String(currentPage));
- <div className="flex flex-wrap items-center divide-x divide-black/10 ">
- <StatCell
- label="Credit Limit"
-                 value={<div style={{ marginTop: "20px" }}>{fmt(creditSummary.creditLimit)} </div>}
- />
- <StatCell
- label="Distributed to downline"
- </span>
- )}
- </div>
Added / After Commit
+ diff --git a/src/routes/user-listing.tsx b/src/routes/user-listing.tsx
+ index 472568d..e3e0b1d 100644
+ const [editCreditRefUser, setEditCreditRefUser] = useState<DownlineUser | null>(null);
+ const [newCreditRefValue, setNewCreditRefValue] = useState("");
+ const [creditRefError, setCreditRefError] = useState("");
+   const createCreditLimitWords = formatRupeesInWords(formData.creditLimit);
+ 
+ useEffect(() => {
+ setPageInput(String(currentPage));
+ <div className="flex flex-wrap items-center divide-x divide-black/10 ">
+ <StatCell
+ label="Credit Limit"
+                 value={
+                   <div className="mt-5">
+                     <div>{fmt(creditSummary.creditLimit)}</div>
+ 
+                     <div className="mt-1 text-xs font-semibold text-green-600">
+                       {creditSummary.creditLimit
Removed / Before Commit
- diff --git a/src/services/api/internalServices.ts b/src/services/api/internalServices.ts
- index 9d5d297..5a0fc1f 100644
- CreatePanelUserRequest,
- CreditTransferRequest,
- CreditTransferResult,
- TransferSubmitRequest,
- TransferListResponse,
- DownlineUser,
- const root = asRecord(payload);
- return asRecord(root.data ?? payload) as TransferListResponse;
- },
-     async submitTransfer(payload: TransferSubmitRequest) {
- return authApiClient.post<unknown>(authConfig.panelAuthEndpoints.transferList, payload);
- },
- async balance() {
Added / After Commit
+ diff --git a/src/services/api/internalServices.ts b/src/services/api/internalServices.ts
+ index 9d5d297..5a0fc1f 100644
+ CreatePanelUserRequest,
+ CreditTransferRequest,
+ CreditTransferResult,
+   BulkTransferSubmitRequest,
+ TransferSubmitRequest,
+ TransferListResponse,
+ DownlineUser,
+ const root = asRecord(payload);
+ return asRecord(root.data ?? payload) as TransferListResponse;
+ },
+     async submitTransfer(payload: TransferSubmitRequest | BulkTransferSubmitRequest) {
+ return authApiClient.post<unknown>(authConfig.panelAuthEndpoints.transferList, payload);
+ },
+ async balance() {
Removed / Before Commit
- diff --git a/src/services/api/internalTypes.ts b/src/services/api/internalTypes.ts
- index f9031fc..93e3c52 100644
- action: TransferAction;
- }
- 
- export interface TransferListProfile {
- id?: string;
- username?: string;
- id?: string;
- username?: string;
- role?: string;
-     isBetBlocked: boolean,
-     isTransferBlocked: boolean,
- };
- credit?: {
- creditLimit?: number;
- redirect_link?: string;
- publish_time?: string;
Added / After Commit
+ diff --git a/src/services/api/internalTypes.ts b/src/services/api/internalTypes.ts
+ index f9031fc..93e3c52 100644
+ action: TransferAction;
+ }
+ 
+ export interface BulkTransferSubmitRequest {
+   data: Array<{
+     childUserId: string;
+     action: TransferAction;
+     amount: number;
+   }>;
+ }
+ 
+ export interface TransferListProfile {
+ id?: string;
+ username?: string;
+ id?: string;
+ username?: string;