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

Review Result ?

solutionbowl/super-admin · 6c2ec1b3
This commit adds a comprehensive Excel export feature for bets with multiple layouts accommodating different report styles. The code modularizes the export functionality and dynamically builds Excel sheets with relevant headers and rows based on layout. It also integrates linking between main bets and their legs. However, it lacks comments and type safety checks that could improve maintainability and reduce risks. No security-critical functionality was changed, but exporting potentially sensitive info (like IP addresses) requires careful consideration. The commit message is vague and lacks detail on changes.
Quality ?
85%
Security ?
50%
Business Value ?
80%
Maintainability ?
78%
Issues & Suggested Fixes ?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Poor Description
Where commit message
Issue / Evidence poor description
Suggested Fix improve commit message to clearly describe the added features and changes
Lack Of Comments
Where src/components/common/BetsExcelExportButton.tsx:94
Issue / Evidence lack of comments
Suggested Fix add inline comments explaining critical functions and data structures for maintainability
Missing Validation
Where src/components/common/BetsExcelExportButton.tsx:104
Issue / Evidence no validation on bets or leg data
Suggested Fix add type checks or validation to avoid runtime errors
Cell Link Setting
Where src/components/common/BetsExcelExportButton.tsx:126
Issue / Evidence cell link setting
Suggested Fix add check to ensure target row exists to avoid broken internal links in Excel
Sensitive Info Exposed
Where src/components/common/BetsExcelExportButton.tsx:189
Issue / Evidence sensitive info exposed
Suggested Fix verify proper handling/permission for exporting user IP addresses
Duplicate Logic
Where src/components/common/BetsExcelExportButton.tsx:247
Issue / Evidence repeated similar code patterns in getMainRow and getLegRow
Suggested Fix refactor to reduce duplication
Excel Sheet Creation
Where src/components/common/BetsExcelExportButton.tsx:121
Issue / Evidence Excel sheet creation
Suggested Fix add error handling around XLSX library calls to gracefully handle failures
Code Change Preview · src/components/common/BetsExcelExportButton.tsx ?
Removed / Before Commit
- diff --git a/src/components/common/BetsExcelExportButton.tsx b/src/components/common/BetsExcelExportButton.tsx
- index 38fb882..07aac68 100644
- filename: string;
- rows: TRow[];
- getBet: (row: TRow) => BetsExcelBet;
- onExport?: (rows: number) => void;
- children?: ReactNode;
- };
- filename,
- rows,
- getBet,
- children = "Download XLSX",
- disabled,
- className,
- setIsExporting(true);
- const XLSX = await import("xlsx");
- 
-       exportBetsExcel(XLSX, rows.map(getBet), filename);
Added / After Commit
+ diff --git a/src/components/common/BetsExcelExportButton.tsx b/src/components/common/BetsExcelExportButton.tsx
+ index 38fb882..07aac68 100644
+ filename: string;
+ rows: TRow[];
+ getBet: (row: TRow) => BetsExcelBet;
+   layout?: "default" | "bet-ticket" | "bet-list";
+ onExport?: (rows: number) => void;
+ children?: ReactNode;
+ };
+ filename,
+ rows,
+ getBet,
+   layout = "default",
+ children = "Download XLSX",
+ disabled,
+ className,
+ setIsExporting(true);
+ const XLSX = await import("xlsx");
Removed / Before Commit
- diff --git a/src/components/common/NetExposureExcelExportButton.tsx b/src/components/common/NetExposureExcelExportButton.tsx
- new file mode 100644
- index 0000000..ad81f10
Added / After Commit
+ diff --git a/src/components/common/NetExposureExcelExportButton.tsx b/src/components/common/NetExposureExcelExportButton.tsx
+ new file mode 100644
+ index 0000000..ad81f10
+ import { useState } from "react";
+ import { Download } from "lucide-react";
+ import { toast } from "sonner";
+ import { Button } from "@/components/ui/button";
+ import { tenantApiClient } from "@/services/api/apiClient";
+ 
+ type ExposureMarket = {
+   marketId: string;
+   marketName: string;
+   totalStake: number;
+   worstBook: number;
+   bestBook: number;
+ };
+ 
+ type ExposureRace = {
Removed / Before Commit
- diff --git a/src/components/common/ProfitLossExcelExportButton.tsx b/src/components/common/ProfitLossExcelExportButton.tsx
- new file mode 100644
- index 0000000..c5726d3
Added / After Commit
+ diff --git a/src/components/common/ProfitLossExcelExportButton.tsx b/src/components/common/ProfitLossExcelExportButton.tsx
+ new file mode 100644
+ index 0000000..c5726d3
+ import { useState } from "react";
+ import { Download } from "lucide-react";
+ import { toast } from "sonner";
+ import { Button } from "@/components/ui/button";
+ 
+ type CellValue = string | number | boolean | null | undefined;
+ 
+ export type ProfitLossExcelDetail = {
+   rowIndex: number;
+   sheetName: string;
+   loadBets: () => Promise<unknown>;
+ };
+ 
+ export default function ProfitLossExcelExportButton({
+   filename,
Removed / Before Commit
- diff --git a/src/components/common/XlsxExportButton.tsx b/src/components/common/XlsxExportButton.tsx
- new file mode 100644
- index 0000000..49f7eb5
Added / After Commit
+ diff --git a/src/components/common/XlsxExportButton.tsx b/src/components/common/XlsxExportButton.tsx
+ new file mode 100644
+ index 0000000..49f7eb5
+ import { useState, type ComponentProps, type ReactNode } from "react";
+ import { Download } from "lucide-react";
+ import { Button } from "@/components/ui/button";
+ import type { CsvColumn } from "@/utils/csv/types";
+ 
+ export default function XlsxExportButton<TRow>({
+   filename,
+   rows,
+   columns,
+   children = "Download XLSX",
+   disabled,
+   ...buttonProps
+ }: Omit<ComponentProps<typeof Button>, "onClick"> & {
+   filename: string;
+   rows: TRow[];
Removed / Before Commit
- diff --git a/src/routes/bet-list.tsx b/src/routes/bet-list.tsx
- index 48696cb..f363642 100644
- filename={`bets-list-${formatApiDate(new Date())}.xlsx`}
- rows={bets}
- getBet={getBetExcelRow}
- disabled={activeIsLoading || Boolean(activeError)}
- className="ml-auto h-9 rounded-md bg-emerald-600 px-4 text-white hover:bg-emerald-700"
- />
Added / After Commit
+ diff --git a/src/routes/bet-list.tsx b/src/routes/bet-list.tsx
+ index 48696cb..f363642 100644
+ filename={`bets-list-${formatApiDate(new Date())}.xlsx`}
+ rows={bets}
+ getBet={getBetExcelRow}
+             layout="bet-list"
+ disabled={activeIsLoading || Boolean(activeError)}
+ className="ml-auto h-9 rounded-md bg-emerald-600 px-4 text-white hover:bg-emerald-700"
+ />
Removed / Before Commit
- diff --git a/src/routes/bet-ticket.tsx b/src/routes/bet-ticket.tsx
- index 9c39012..2c7b934 100644
- filename={`bet-ticket-${new Date().toISOString().slice(0, 10)}.xlsx`}
- rows={bets}
- getBet={getBetTickerExcelRow}
- disabled={isLoading}
- className="h-9 rounded-lg bg-emerald-600 px-4 text-white hover:bg-emerald-700"
- />
- <table className="w-full min-w-[780px] border-collapse text-left text-xs">
- <thead className="bg-background">
- <tr>
-               {["Leg", "Race", "Market", "Market ID", "Runner", "Selection", "Status"].map((h) => (
- <th key={h} className="whitespace-nowrap px-3 py-2 font-bold text-muted-foreground">
- {h}
- </th>
Added / After Commit
+ diff --git a/src/routes/bet-ticket.tsx b/src/routes/bet-ticket.tsx
+ index 9c39012..2c7b934 100644
+ filename={`bet-ticket-${new Date().toISOString().slice(0, 10)}.xlsx`}
+ rows={bets}
+ getBet={getBetTickerExcelRow}
+               layout="bet-ticket"
+ disabled={isLoading}
+ className="h-9 rounded-lg bg-emerald-600 px-4 text-white hover:bg-emerald-700"
+ />
+ <table className="w-full min-w-[780px] border-collapse text-left text-xs">
+ <thead className="bg-background">
+ <tr>
+               {["Leg", "Race", "Market", "Market ID", "Runner", "Odds","Selection", "Status"].map((h) => (
+ <th key={h} className="whitespace-nowrap px-3 py-2 font-bold text-muted-foreground">
+ {h}
+ </th>
Removed / Before Commit
- diff --git a/src/routes/net-exposure.tsx b/src/routes/net-exposure.tsx
- index 63d4d39..b09ed7b 100644
- import { internalServices } from "@/services/api/internalServices";
- import { setExposureParams } from "@/lib/nav-params";
- import { useRefreshToggle } from "@/hooks/useRefreshToggle";
- 
- export const Route = createFileRoute("/net-exposure")({
- component: NetExposurePage,
- "Greyhound Racing",
- ];
- 
-   const { data: rawData, isLoading, error, refetch, isFetching } = useQuery({
- queryKey: ["net-exposure"],
- queryFn: fetchNetExposure,
- refetchOnMount: "always",
- {/* Title + Refresh */}
- <div className="flex flex-col gap-4 border-b border-border/60 p-5 lg:flex-row lg:items-center lg:justify-between">
- <h2 className="text-xl font-bold tracking-tight">Net Exposure</h2>
Added / After Commit
+ diff --git a/src/routes/net-exposure.tsx b/src/routes/net-exposure.tsx
+ index 63d4d39..b09ed7b 100644
+ import { internalServices } from "@/services/api/internalServices";
+ import { setExposureParams } from "@/lib/nav-params";
+ import { useRefreshToggle } from "@/hooks/useRefreshToggle";
+ import NetExposureExcelExportButton from "@/components/common/NetExposureExcelExportButton";
+ 
+ export const Route = createFileRoute("/net-exposure")({
+ component: NetExposurePage,
+ "Greyhound Racing",
+ ];
+ 
+   const {
+     data: rawData,
+     isLoading,
+     error,
+     refetch,
+     isFetching,
Removed / Before Commit
- diff --git a/src/routes/pl-by-agent.tsx b/src/routes/pl-by-agent.tsx
- index 940a3d9..1cc2e50 100644
- import { Card } from "@/components/ui/card";
- import { Button } from "@/components/ui/button";
- import DateRangePicker from "@/components/common/DateRangePicker";
- import CsvExportButton from "@/components/common/CsvExportButton";
- import {
- Table,
- TableBody,
- agent: string;
- market: string;
- totals: ProfitLossTotals;
- };
- 
- const defaultFilters = {
- Race: row.race,
- Agent: row.agent,
- Market: row.market,
Added / After Commit
+ diff --git a/src/routes/pl-by-agent.tsx b/src/routes/pl-by-agent.tsx
+ index 940a3d9..1cc2e50 100644
+ import { Card } from "@/components/ui/card";
+ import { Button } from "@/components/ui/button";
+ import DateRangePicker from "@/components/common/DateRangePicker";
+ import ProfitLossExcelExportButton from "@/components/common/ProfitLossExcelExportButton";
+ import {
+ Table,
+ TableBody,
+ agent: string;
+ market: string;
+ totals: ProfitLossTotals;
+   raceId: string;
+   agentId: string;
+ };
+ 
+ const defaultFilters = {
+ Race: row.race,
Removed / Before Commit
- diff --git a/src/routes/pl-by-market.tsx b/src/routes/pl-by-market.tsx
- index 63f4500..d7b7ff2 100644
- import { Card } from "@/components/ui/card";
- import { Button } from "@/components/ui/button";
- import DateRangePicker from "@/components/common/DateRangePicker";
- import CsvExportButton from "@/components/common/CsvExportButton";
- import {
- Table,
- TableBody,
- date: string;
- race: string;
- market: string;
- totals: ProfitLossTotals;
- };
- 
- 
- useReportSocket({ onProfitLoss: refreshFromSocket });
- 
Added / After Commit
+ diff --git a/src/routes/pl-by-market.tsx b/src/routes/pl-by-market.tsx
+ index 63f4500..d7b7ff2 100644
+ import { Card } from "@/components/ui/card";
+ import { Button } from "@/components/ui/button";
+ import DateRangePicker from "@/components/common/DateRangePicker";
+ import ProfitLossExcelExportButton from "@/components/common/ProfitLossExcelExportButton";
+ import {
+ Table,
+ TableBody,
+ date: string;
+ race: string;
+ market: string;
+   marketId: string;
+ totals: ProfitLossTotals;
+ };
+ 
+ 
+ useReportSocket({ onProfitLoss: refreshFromSocket });
Removed / Before Commit
- diff --git a/src/routes/transfer.tsx b/src/routes/transfer.tsx
- index dd93b4f..e7bd987 100644
- loginName: string;
- action: TransferAction;
- amount: string;
- };
- 
- function StatCell({
- loginName: row.loginName,
- action: getTransferAction(row) as TransferAction,
- amount: getTransferAmount(row),
- })),
- );
- };
- };
- 
- const focusBulkTransferAmount = (rowKey: string) => {
-     bulkAmountInputRefs.current[rowKey]?.focus();
Added / After Commit
+ diff --git a/src/routes/transfer.tsx b/src/routes/transfer.tsx
+ index dd93b4f..e7bd987 100644
+ loginName: string;
+ action: TransferAction;
+ amount: string;
+   isEditing: boolean;
+ };
+ 
+ function StatCell({
+ loginName: row.loginName,
+ action: getTransferAction(row) as TransferAction,
+ amount: getTransferAmount(row),
+         isEditing: false,
+ })),
+ );
+ };
+ };
+ 
Removed / Before Commit
- diff --git a/src/routes/user-details.$userId.tsx b/src/routes/user-details.$userId.tsx
- index 1985931..8dcabf0 100644
- import { format } from "date-fns";
- 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")({
- component: UserDetailsPage,
- 
- return (
- <Card className="overflow-hidden rounded-2xl border-border/60 bg-card shadow-elegant">
- <div className="overflow-x-auto">
- <Table>
- <TableHeader>
- 
Added / After Commit
+ diff --git a/src/routes/user-details.$userId.tsx b/src/routes/user-details.$userId.tsx
+ index 1985931..8dcabf0 100644
+ import { format } from "date-fns";
+ import { setExposureParams } from "@/lib/nav-params";
+ import type { MultiBetLeg } from "@/services/api/betTypes";
+ import BetsExcelExportButton from "@/components/common/BetsExcelExportButton";
+ import XlsxExportButton from "@/components/common/XlsxExportButton";
+ import type { CsvColumn } from "@/utils/csv/types";
+ import NetExposureExcelExportButton from "@/components/common/NetExposureExcelExportButton";
+ 
+ export const Route = createFileRoute("/user-details/$userId")({
+ component: UserDetailsPage,
+ 
+ return (
+ <Card className="overflow-hidden rounded-2xl border-border/60 bg-card shadow-elegant">
+       <div className="flex justify-end border-b border-border/60 p-4">
+         <XlsxExportButton
+           filename={`user-activity-${new Date().toISOString().slice(0, 10)}.xlsx`}
Removed / Before Commit
- diff --git a/src/routes/user-exposure-detail.tsx b/src/routes/user-exposure-detail.tsx
- index 1e82173..7aa0a9d 100644
- return (Array.isArray(data) ? data : []) as OddsMarket[];
- }
- 
- async function fetchHierarchy(
- raceId: string,
- marketId: string,
Added / After Commit
+ diff --git a/src/routes/user-exposure-detail.tsx b/src/routes/user-exposure-detail.tsx
+ index 1e82173..7aa0a9d 100644
+ return (Array.isArray(data) ? data : []) as OddsMarket[];
+ }
+ 
+ 
+ 
+ async function fetchHierarchy(
+ raceId: string,
+ marketId: string,
Removed / Before Commit
- diff --git a/src/routes/user-listing.tsx b/src/routes/user-listing.tsx
- index 2b8a7d1..8bf8c22 100644
- Pencil,
- Plus,
- RefreshCw,
- Unlock,
- } from "lucide-react";
- import {
- DownlineUser,
- UserBlockStatusResult,
- } from "@/services/api/internalTypes";
- import CsvExportButton from "@/components/common/CsvExportButton";
- import type { CsvColumn } from "@/utils/csv/types";
- import { cn } from "@/lib/utils";
- 
- const statusFilterValues = ["ACTIVE", "INACTIVE", "CLOSED"] as const;
- const [selectedDownlineTab, setSelectedDownlineTab] = useState<DownlineTab>("all");
- const [drillDownlineUserId, setDrillDownlineUserId] = useState<string | null>(null);
Added / After Commit
+ diff --git a/src/routes/user-listing.tsx b/src/routes/user-listing.tsx
+ index 2b8a7d1..8bf8c22 100644
+ Pencil,
+ Plus,
+ RefreshCw,
+   Download,
+ Unlock,
+ } from "lucide-react";
+ import {
+ DownlineUser,
+ UserBlockStatusResult,
+ } from "@/services/api/internalTypes";
+ import type { CsvCellValue, CsvColumn } from "@/utils/csv/types";
+ import { cn } from "@/lib/utils";
+ 
+ const statusFilterValues = ["ACTIVE", "INACTIVE", "CLOSED"] as const;
+ const [selectedDownlineTab, setSelectedDownlineTab] = useState<DownlineTab>("all");
+ const [drillDownlineUserId, setDrillDownlineUserId] = useState<string | null>(null);
Removed / Before Commit
- diff --git a/src/services/api/internalServices.ts b/src/services/api/internalServices.ts
- index 5a0fc1f..13a7a72 100644
- return unwrapData<DownlineUser[]>(
- await authApiClient.get<unknown>(
- `${authConfig.panelAuthEndpoints.downlineUsers}${queryString}`,
- ),
- );
- },
Added / After Commit
+ diff --git a/src/services/api/internalServices.ts b/src/services/api/internalServices.ts
+ index 5a0fc1f..13a7a72 100644
+ return unwrapData<DownlineUser[]>(
+ await authApiClient.get<unknown>(
+ `${authConfig.panelAuthEndpoints.downlineUsers}${queryString}`,
+           { cache: "no-store" },
+ ),
+ );
+ },