Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
340 changes: 340 additions & 0 deletions HrBarChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,340 @@
import { Box, Flex, Text } from '@chakra-ui/react';
import {
BarChart,
Bar,
XAxis,
YAxis,
ResponsiveContainer,
Tooltip,
CartesianGrid,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The CartesianGrid component is imported but not used.

} from 'recharts';
Comment on lines +1 to +10
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate Component Definition

Complete component definition duplicated starting at line 167, creating identical imports, interfaces, and component implementations. This duplication will cause compilation errors due to duplicate symbol definitions and violates DRY principles. The second definition overwrites the first, making the initial 166 lines unreachable dead code.

Standards
  • Algorithm-Correctness-Code-Structure
  • Logic-Verification-Symbol-Uniqueness
  • Org-Guideline-Keep pull requests small and focused

import { useTheme } from '@chakra-ui/react';

interface HrBarChartProps {
data: any;
keys: any;
chartMetadata: any;
Comment on lines +13 to +16
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weak Type Definitions

Interface uses 'any' types eliminating TypeScript benefits for type safety and IntelliSense. Weak typing reduces maintainability by hiding data structure contracts and preventing compile-time error detection. Proper interface definitions would improve code documentation and catch integration errors early.

Standards
  • Clean-Code-Meaningful-Names
  • Maintainability-Quality-Type-Safety

}
Comment on lines +13 to +17

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

To improve type safety and code clarity, avoid using any. Please define specific types for the component's props. Additionally, the keys prop is declared but never used in the component and should be removed.

interface HrBarChartProps {
  data: { data?: Record<string, any> }; // It's highly recommended to replace 'any' with a specific interface for stats.
  chartMetadata: { xlabel?: string; ylabel?: string };
}


const CustomTooltip = ({ active, payload, label }: any) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The props for CustomTooltip are typed as any. You can use TooltipProps from recharts for proper typing. You'll need to add these imports:

import { TooltipProps } from 'recharts';
import { ValueType, NameType } from 'recharts/types/component/DefaultTooltipContent';
const CustomTooltip = ({ active, payload, label }: TooltipProps<ValueType, NameType>) => {

if (active && payload && payload.length) {
return (
<Box bg="white" p={2} boxShadow="md" borderRadius="md" border="none">
<Flex gap={0.5} flexDirection={'column'} fontSize={'sm'}>
<Text fontWeight={'bold'}>{label}</Text>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XSS via Dynamic Labels

User-controlled label data rendered directly in JSX without sanitization enables XSS attacks. Malicious language names in data could inject scripts into tooltip display. Attackers can execute arbitrary JavaScript in user browsers through crafted chart data.

          <Text fontWeight={'bold'}>{String(label).replace(/<[^>]*>/g, '')}</Text>
Commitable Suggestion
Suggested change
<Text fontWeight={'bold'}>{label}</Text>
<Text fontWeight={'bold'}>{String(label).replace(/<[^>]*>/g, '')}</Text>
Standards
  • CWE-79
  • OWASP-A03
  • NIST-SSDF-PW.1

<Text color="text.secondary2">
Acceptance rate:{' '}
<Text as="span" color="text.primary">
{payload[0]?.value}%
</Text>
</Text>
<Text color="text.secondary2">
Acceptance Count:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.acceptanceCount}
</Text>
</Text>
<Text color="text.secondary2">
Avg Active Users:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.avgActiveUsers}
</Text>
</Text>
<Text color="text.secondary2">
Line Accepted:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.lineAccepted}
</Text>
</Text>
<Text color="text.secondary2">
Line Suggested:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.lineSuggested}
</Text>
</Text>
<Text color="text.secondary2">
Max Active Users:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.maxActiveUsers}
</Text>
</Text>
<Text color="text.secondary2">
Suggestion Count:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.suggestionCount}
</Text>
</Text>
</Flex>
</Box>
);
}
return null;
};

export const HrBarChart = ({ data, chartMetadata }: HrBarChartProps) => {
const { colors } = useTheme();
const transformedData = Object.entries(data?.data)?.map(
([language, stats]: [string, any]) => ({
language: language.charAt(0).toUpperCase() + language.slice(1),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XSS via Language Names

Language names from external data transformed and displayed without sanitization creates XSS vulnerability. Malicious language identifiers containing script tags could execute when rendered in chart labels. User browsers vulnerable to code injection through chart data manipulation.

      language: String(language).replace(/<[^>]*>/g, '').charAt(0).toUpperCase() + String(language).replace(/<[^>]*>/g, '').slice(1),
Commitable Suggestion
Suggested change
language: language.charAt(0).toUpperCase() + language.slice(1),
language: String(language).replace(/<[^>]*>/g, '').charAt(0).toUpperCase() + String(language).replace(/<[^>]*>/g, '').slice(1),
Standards
  • CWE-79
  • OWASP-A03
  • NIST-SSDF-PW.1

acceptanceRate: parseFloat(stats.acceptanceRate),
Comment on lines +76 to +79
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsafe Data Access

Data transformation lacks null safety checks for nested properties causing runtime TypeError exceptions. Missing validation for stats object properties leads to parseFloat(undefined) returning NaN values. Chart rendering fails with invalid data producing blank or corrupted visualizations.

Standards
  • ISO-IEC-25010-Reliability-Fault-Tolerance
  • ISO-IEC-25010-Functional-Correctness-Appropriateness
  • DbC-Preconditions

acceptanceCount: parseInt(stats.acceptanceCount),
avgActiveUsers: parseFloat(stats.avgActiveUsers).toFixed(2),
lineAccepted: parseInt(stats.lineAccepted),
lineSuggested: parseInt(stats.lineSuggested),
maxActiveUsers: parseInt(stats.maxActiveUsers),
suggestionCount: parseInt(stats.suggestionCount),
Comment on lines +80 to +85
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add an explicit radix (10) to all parseInt calls inside the data transformation to ensure decimal parsing. [best practice]

Severity Level: Minor ⚠️

Suggested change
acceptanceCount: parseInt(stats.acceptanceCount),
avgActiveUsers: parseFloat(stats.avgActiveUsers).toFixed(2),
lineAccepted: parseInt(stats.lineAccepted),
lineSuggested: parseInt(stats.lineSuggested),
maxActiveUsers: parseInt(stats.maxActiveUsers),
suggestionCount: parseInt(stats.suggestionCount),
acceptanceCount: parseInt(stats.acceptanceCount, 10),
lineAccepted: parseInt(stats.lineAccepted, 10),
lineSuggested: parseInt(stats.lineSuggested, 10),
maxActiveUsers: parseInt(stats.maxActiveUsers, 10),
suggestionCount: parseInt(stats.suggestionCount, 10),
Why it matters? ⭐

The file currently calls parseInt(...) without an explicit radix in multiple places (e.g. lines shown by grep). While modern engines default to base 10 for most inputs, explicitly passing 10 is a simple, standard best practice that avoids surprising behavior for strings with leading zeros or non-decimal contexts. This change is low risk and improves clarity.

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** HrBarChart.tsx
**Line:** 80:85
**Comment:**
	*Best Practice: Add an explicit radix (10) to all parseInt calls inside the data transformation to ensure decimal parsing.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.

})
);
transformedData?.sort((a, b) => b.acceptanceRate - a.acceptanceRate);
Comment on lines +76 to +88

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This data transformation logic has a couple of issues:

  1. Performance: It runs on every render. This should be wrapped in a useMemo hook to memoize the result and avoid re-computation. You will need to import useMemo from 'react'.
  2. Robustness: Object.entries(data?.data) will crash if data.data is nullish. It should be Object.entries(data?.data || {}).
  3. Readability: The optional chaining on .map() and transformedData?.sort() can be removed if you handle the nullish case for data.data correctly.


const CustomBarLabel = (props: any) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Avoid using any for props. You can define a specific interface for the props passed to CustomBarLabel by recharts for better type safety.

  const CustomBarLabel = (props: { x: number; y: number; width: number; value: number }) => {

const { x, y, width, value } = props;
return (
<text
x={x + width + 10}
y={y + 10}
fill="#667085"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The fill color for the bar label is hardcoded. It's better to use a color from the Chakra UI theme (e.g., colors.text.secondary or colors.gray.600) to ensure consistency and support for different themes like dark mode.

        fill={colors.text.primary} /* Or another appropriate color from your theme */

fontSize={11}
fontWeight={500}
textAnchor="start"
>
{`${value}%`}
</text>
);
};

return (
<Box height="100%" width="100%">
<ResponsiveContainer width="100%" height="100%">
<BarChart
layout="vertical"
data={transformedData}
margin={{ top: 10, right: 10, left: 60, bottom: 10 }}
>
<XAxis
type="number"
domain={[0, 100]}
unit="%"
axisLine={{ stroke: '#E2E8F0', strokeWidth: 1 }}
tickLine={false}
style={{ fontSize: 11, fontWeight: 400, fill: colors.text.primary }}
label={{
value: chartMetadata?.xlabel,
position: 'bottom',
offset: 0,
style: {
textAnchor: 'middle',
fontSize: 11,
},
}}
/>
<YAxis
type="category"
dataKey="language"
axisLine={{ stroke: '#E2E8F0', strokeWidth: 1 }}
tickLine={false}
interval={0}
style={{ fontSize: 13, fontWeight: 400, fill: colors.text.primary }}
label={{
value: chartMetadata?.ylabel,
angle: -90,
position: 'outsideLeft',
fontSize: 11,
fontWeight: 400,
dy: 40,
dx: -60,
zIndex: 1000,
}}
/>
<Tooltip
cursor={false}
content={<CustomTooltip />}
wrapperStyle={{ outline: 'none' }}
/>
<Bar
dataKey="acceptanceRate"
fill={colors.primary}
radius={[0, 4, 4, 0]}
barSize={20}
label={<CustomBarLabel />}
animationDuration={1000}
animationBegin={0}
/>
</BarChart>
</ResponsiveContainer>
</Box>
);
};import { Box, Flex, Text } from '@chakra-ui/react';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This file appears to be corrupted. It contains a duplicated implementation of the HrBarChart component, with the second one starting on this line. This causes a syntax error and prevents the code from being used. Please remove the duplicated code from line 167 to 340. Note that the duplicated code contains some useful changes (e.g., in CustomTooltip and CustomBarLabel) which should be integrated into the primary component definition before deleting this block.

import {
BarChart,
Bar,
XAxis,
YAxis,
ResponsiveContainer,
Tooltip,
CartesianGrid,
} from 'recharts';
import { useTheme } from '@chakra-ui/react';

interface HrBarChartProps {
data: any;
keys: any;
chartMetadata: any;
}
Comment on lines +179 to +183
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Replace any types with proper TypeScript interfaces and remove unused keys prop.

All props are typed as any, which eliminates type safety. The keys prop is defined but never used in the component, suggesting it may be unnecessary or the implementation is incomplete.

Consider defining proper types:

interface ChartStats {
  acceptanceRate: string | number;
  acceptanceCount: string | number;
  avgActiveUsers: string | number;
  lineAccepted: string | number;
  lineSuggested: string | number;
  maxActiveUsers: string | number;
  suggestionCount: string | number;
}

interface ChartData {
  data: Record<string, ChartStats>;
}

interface ChartMetadata {
  xlabel?: string;
  ylabel?: string;
}

interface HrBarChartProps {
  data: ChartData;
  chartMetadata: ChartMetadata;
  // Remove keys prop if not needed, or add implementation if required
}
🤖 Prompt for AI Agents
In HrBarChart.tsx around lines 179 to 183, replace the loose any types and
remove the unused keys prop: define and use specific interfaces for the incoming
props (e.g., ChartStats for each metric, ChartData for the data container and
ChartMetadata for chart labels) and update HrBarChartProps to accept data:
ChartData and chartMetadata: ChartMetadata (omit keys); update any internal
usages to match the new property shapes and run type checks to fix any type
errors that result.


const CustomTooltip = ({ active, payload, label }: any) => {
if (active && payload && payload.length) {
return (
<Box bg="white" p={2} boxShadow="md" borderRadius="md" border="none">
<Flex gap={0.5} flexDirection={'column'} fontSize={'sm'}>
<Text fontWeight={'bold'}>{label}</Text>
<Text color="text.secondary2">
Acceptance rate:{' '}
<Text as="span" color="text.primary">
{payload[0]?.value &&
!isNaN(payload[0]?.value) &&
payload[0]?.value > 0
? `${payload[0]?.value}%`
: '0'}
Comment on lines +194 to +198

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This logic for displaying the acceptance rate is a bit confusing. If the value is 0, it will display '0' instead of '0%'. If the value is invalid, it also displays '0'. It would be more consistent to always show the percentage sign for valid numbers (including 0) and handle invalid values differently, for example by showing 'N/A'.

              {typeof payload[0]?.value === 'number'
                ? `${payload[0].value}%`
                : 'N/A'}

Comment on lines +194 to +198
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent Validation Logic

Tooltip validation logic differs from bar label validation logic for the same data. Tooltip uses comprehensive validation (exists, not NaN, greater than 0) while bar label uses simpler validation (isNaN, null, <= 0). This inconsistency creates different display behaviors for identical edge cases, potentially confusing users when tooltip shows '0' but bar shows no label.

Standards
  • Logic-Verification-Consistency
  • Business-Rule-Display-Logic
  • Algorithm-Correctness-Validation-Patterns

</Text>
</Text>
<Text color="text.secondary2">
Acceptance Count:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.acceptanceCount}
</Text>
</Text>
<Text color="text.secondary2">
Avg Active Users:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.avgActiveUsers}
</Text>
</Text>
<Text color="text.secondary2">
Line Accepted:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.lineAccepted}
</Text>
</Text>
<Text color="text.secondary2">
Line Suggested:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.lineSuggested}
</Text>
</Text>
<Text color="text.secondary2">
Max Active Users:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.maxActiveUsers}
</Text>
</Text>
<Text color="text.secondary2">
Suggestion Count:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.suggestionCount}
</Text>
</Text>
</Flex>
</Box>
);
}
return null;
};

export const HrBarChart = ({ data, chartMetadata }: HrBarChartProps) => {
const { colors } = useTheme();
const transformedData = Object.entries(data?.data)?.map(
([language, stats]: [string, any]) => ({
language: language.charAt(0).toUpperCase() + language.slice(1),
acceptanceRate: parseFloat(stats.acceptanceRate),
acceptanceCount: parseInt(stats.acceptanceCount),
avgActiveUsers: parseFloat(stats.avgActiveUsers).toFixed(2),
lineAccepted: parseInt(stats.lineAccepted),
lineSuggested: parseInt(stats.lineSuggested),
maxActiveUsers: parseInt(stats.maxActiveUsers),
suggestionCount: parseInt(stats.suggestionCount),
})
);
transformedData?.sort((a, b) => b.acceptanceRate - a.acceptanceRate);
Comment on lines +246 to +258
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add null checks and error handling for data transformation.

The transformation assumes data?.data exists after optional chaining. If it's undefined, Object.entries(undefined) will throw. Additionally, the sort operation on transformedData will fail if it's undefined.

Apply this diff to add proper guards:

 export const HrBarChart = ({ data, chartMetadata }: HrBarChartProps) => {
   const { colors } = useTheme();
+  
+  if (!data?.data) {
+    return null; // or a fallback UI
+  }
+  
   const transformedData = Object.entries(data.data)?.map(
     ([language, stats]: [string, any]) => ({
       language: language.charAt(0).toUpperCase() + language.slice(1),
-      acceptanceRate: parseFloat(stats.acceptanceRate),
+      acceptanceRate: parseFloat(stats.acceptanceRate) || 0,
       acceptanceCount: parseInt(stats.acceptanceCount) || 0,
-      avgActiveUsers: parseFloat(stats.avgActiveUsers).toFixed(2),
+      avgActiveUsers: parseFloat(stats.avgActiveUsers || 0).toFixed(2),
       lineAccepted: parseInt(stats.lineAccepted) || 0,
       lineSuggested: parseInt(stats.lineSuggested) || 0,
       maxActiveUsers: parseInt(stats.maxActiveUsers) || 0,
       suggestionCount: parseInt(stats.suggestionCount) || 0,
     })
   );
-  transformedData?.sort((a, b) => b.acceptanceRate - a.acceptanceRate);
+  transformedData.sort((a, b) => b.acceptanceRate - a.acceptanceRate);

Committable suggestion skipped: line range outside the PR's diff.


const CustomBarLabel = (props: any) => {
const { x, y, width, value } = props;
if (isNaN(value) || value == null || value <= 0) {
return null;
}
return (
<text
x={x + width + 10}
y={y + 10}
fill="#667085"
fontSize={11}
fontWeight={500}
textAnchor="start"
>
{`${value}%`}
</text>
);
};

return (
<Box height="100%" width="100%">
<ResponsiveContainer width="100%" height="100%">
<BarChart
layout="vertical"
data={transformedData}
margin={{ top: 10, right: 10, left: 60, bottom: 10 }}
>
<XAxis
type="number"
domain={[0, 100]}
unit="%"
axisLine={{ stroke: '#E2E8F0', strokeWidth: 1 }}
tickLine={false}
style={{ fontSize: 11, fontWeight: 400, fill: colors.text.primary }}
label={{
value: chartMetadata?.xlabel,
position: 'bottom',
offset: 0,
style: {
textAnchor: 'middle',
fontSize: 11,
},
}}
/>
<YAxis
type="category"
dataKey="language"
axisLine={{ stroke: '#E2E8F0', strokeWidth: 1 }}
tickLine={false}
interval={0}
style={{ fontSize: 13, fontWeight: 400, fill: colors.text.primary }}
label={{
value: chartMetadata?.ylabel,
angle: -90,
position: 'outsideLeft',
fontSize: 11,
fontWeight: 400,
dy: 40,
dx: -60,
zIndex: 1000,
}}
/>
<Tooltip
cursor={false}
content={<CustomTooltip />}
wrapperStyle={{ outline: 'none' }}
/>
<Bar
dataKey="acceptanceRate"
fill={colors.primary}
radius={[0, 4, 4, 0]}
barSize={20}
label={<CustomBarLabel />}
animationDuration={1000}
animationBegin={0}
/>
</BarChart>
</ResponsiveContainer>
</Box>
);
};
Comment on lines +167 to +340
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Remove duplicate code - the entire file is repeated.

The entire file content is duplicated starting at line 167. This causes redeclaration errors for all imports, interfaces, and components. The second version (lines 167-340) includes improvements like NaN validation in the tooltip and bar label, so the first version (lines 1-166) should be removed.

Apply this diff to remove the duplicate:

-import { Box, Flex, Text } from '@chakra-ui/react';
-import {
-  BarChart,
-  Bar,
-  XAxis,
-  YAxis,
-  ResponsiveContainer,
-  Tooltip,
-  CartesianGrid,
-} from 'recharts';
-import { useTheme } from '@chakra-ui/react';
-
-interface HrBarChartProps {
-  data: any;
-  keys: any;
-  chartMetadata: any;
-}
-
-const CustomTooltip = ({ active, payload, label }: any) => {
-  if (active && payload && payload.length) {
-    return (
-      <Box bg="white" p={2} boxShadow="md" borderRadius="md" border="none">
-        <Flex gap={0.5} flexDirection={'column'} fontSize={'sm'}>
-          <Text fontWeight={'bold'}>{label}</Text>
-          <Text color="text.secondary2">
-            Acceptance rate:{' '}
-            <Text as="span" color="text.primary">
-              {payload[0]?.value}%
-            </Text>
-          </Text>
-          <Text color="text.secondary2">
-            Acceptance Count:{' '}
-            <Text as="span" color="text.primary">
-              {payload[0]?.payload.acceptanceCount}
-            </Text>
-          </Text>
-          <Text color="text.secondary2">
-            Avg Active Users:{' '}
-            <Text as="span" color="text.primary">
-              {payload[0]?.payload.avgActiveUsers}
-            </Text>
-          </Text>
-          <Text color="text.secondary2">
-            Line Accepted:{' '}
-            <Text as="span" color="text.primary">
-              {payload[0]?.payload.lineAccepted}
-            </Text>
-          </Text>
-          <Text color="text.secondary2">
-            Line Suggested:{' '}
-            <Text as="span" color="text.primary">
-              {payload[0]?.payload.lineSuggested}
-            </Text>
-          </Text>
-          <Text color="text.secondary2">
-            Max Active Users:{' '}
-            <Text as="span" color="text.primary">
-              {payload[0]?.payload.maxActiveUsers}
-            </Text>
-          </Text>
-          <Text color="text.secondary2">
-            Suggestion Count:{' '}
-            <Text as="span" color="text.primary">
-              {payload[0]?.payload.suggestionCount}
-            </Text>
-          </Text>
-        </Flex>
-      </Box>
-    );
-  }
-  return null;
-};
-
-export const HrBarChart = ({ data, chartMetadata }: HrBarChartProps) => {
-  const { colors } = useTheme();
-  const transformedData = Object.entries(data?.data)?.map(
-    ([language, stats]: [string, any]) => ({
-      language: language.charAt(0).toUpperCase() + language.slice(1),
-      acceptanceRate: parseFloat(stats.acceptanceRate),
-      acceptanceCount: parseInt(stats.acceptanceCount),
-      avgActiveUsers: parseFloat(stats.avgActiveUsers).toFixed(2),
-      lineAccepted: parseInt(stats.lineAccepted),
-      lineSuggested: parseInt(stats.lineSuggested),
-      maxActiveUsers: parseInt(stats.maxActiveUsers),
-      suggestionCount: parseInt(stats.suggestionCount),
-    })
-  );
-  transformedData?.sort((a, b) => b.acceptanceRate - a.acceptanceRate);
-
-  const CustomBarLabel = (props: any) => {
-    const { x, y, width, value } = props;
-    return (
-      <text
-        x={x + width + 10}
-        y={y + 10}
-        fill="#667085"
-        fontSize={11}
-        fontWeight={500}
-        textAnchor="start"
-      >
-        {`${value}%`}
-      </text>
-    );
-  };
-
-  return (
-    <Box height="100%" width="100%">
-      <ResponsiveContainer width="100%" height="100%">
-        <BarChart
-          layout="vertical"
-          data={transformedData}
-          margin={{ top: 10, right: 10, left: 60, bottom: 10 }}
-        >
-          <XAxis
-            type="number"
-            domain={[0, 100]}
-            unit="%"
-            axisLine={{ stroke: '#E2E8F0', strokeWidth: 1 }}
-            tickLine={false}
-            style={{ fontSize: 11, fontWeight: 400, fill: colors.text.primary }}
-            label={{
-              value: chartMetadata?.xlabel,
-              position: 'bottom',
-              offset: 0,
-              style: {
-                textAnchor: 'middle',
-                fontSize: 11,
-              },
-            }}
-          />
-          <YAxis
-            type="category"
-            dataKey="language"
-            axisLine={{ stroke: '#E2E8F0', strokeWidth: 1 }}
-            tickLine={false}
-            interval={0}
-            style={{ fontSize: 13, fontWeight: 400, fill: colors.text.primary }}
-            label={{
-              value: chartMetadata?.ylabel,
-              angle: -90,
-              position: 'outsideLeft',
-              fontSize: 11,
-              fontWeight: 400,
-              dy: 40,
-              dx: -60,
-              zIndex: 1000,
-            }}
-          />
-          <Tooltip
-            cursor={false}
-            content={<CustomTooltip />}
-            wrapperStyle={{ outline: 'none' }}
-          />
-          <Bar
-            dataKey="acceptanceRate"
-            fill={colors.primary}
-            radius={[0, 4, 4, 0]}
-            barSize={20}
-            label={<CustomBarLabel />}
-            animationDuration={1000}
-            animationBegin={0}
-          />
-        </BarChart>
-      </ResponsiveContainer>
-    </Box>
-  );
-};

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (2.1.2)

[error] 167-167: Shouldn't redeclare 'Box'. Consider to delete it or rename it.

'Box' is defined here:

(lint/suspicious/noRedeclare)


[error] 167-167: Shouldn't redeclare 'Flex'. Consider to delete it or rename it.

'Flex' is defined here:

(lint/suspicious/noRedeclare)


[error] 167-167: Shouldn't redeclare 'Text'. Consider to delete it or rename it.

'Text' is defined here:

(lint/suspicious/noRedeclare)


[error] 169-169: Shouldn't redeclare 'BarChart'. Consider to delete it or rename it.

'BarChart' is defined here:

(lint/suspicious/noRedeclare)


[error] 170-170: Shouldn't redeclare 'Bar'. Consider to delete it or rename it.

'Bar' is defined here:

(lint/suspicious/noRedeclare)


[error] 171-171: Shouldn't redeclare 'XAxis'. Consider to delete it or rename it.

'XAxis' is defined here:

(lint/suspicious/noRedeclare)


[error] 172-172: Shouldn't redeclare 'YAxis'. Consider to delete it or rename it.

'YAxis' is defined here:

(lint/suspicious/noRedeclare)


[error] 173-173: Shouldn't redeclare 'ResponsiveContainer'. Consider to delete it or rename it.

'ResponsiveContainer' is defined here:

(lint/suspicious/noRedeclare)


[error] 174-174: Shouldn't redeclare 'Tooltip'. Consider to delete it or rename it.

'Tooltip' is defined here:

(lint/suspicious/noRedeclare)


[error] 175-175: Shouldn't redeclare 'CartesianGrid'. Consider to delete it or rename it.

'CartesianGrid' is defined here:

(lint/suspicious/noRedeclare)


[error] 177-177: Shouldn't redeclare 'useTheme'. Consider to delete it or rename it.

'useTheme' is defined here:

(lint/suspicious/noRedeclare)


[error] 185-185: Shouldn't redeclare 'CustomTooltip'. Consider to delete it or rename it.

'CustomTooltip' is defined here:

(lint/suspicious/noRedeclare)


[error] 244-244: Shouldn't redeclare 'HrBarChart'. Consider to delete it or rename it.

'HrBarChart' is defined here:

(lint/suspicious/noRedeclare)

🤖 Prompt for AI Agents
In HrBarChart.tsx around lines 167-340 there is a duplicated copy of the file
(imports, interface and component re-declared), causing redeclaration errors;
remove the earlier duplicate (lines 1-166) so only the improved version (the one
with NaN validation in tooltip and bar label) remains, ensuring a single set of
imports, the HrBarChartProps interface, CustomTooltip, CustomBarLabel and
HrBarChart component; after removing, save and run build/lint to confirm no
redeclarations remain.

Comment on lines +167 to +340
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Remove the duplicated entire component block (the second copy) to avoid duplicate imports and duplicate HrBarChart declarations. [possible bug]

Severity Level: Critical 🚨

Suggested change
};import { Box, Flex, Text } from '@chakra-ui/react';
import {
BarChart,
Bar,
XAxis,
YAxis,
ResponsiveContainer,
Tooltip,
CartesianGrid,
} from 'recharts';
import { useTheme } from '@chakra-ui/react';
interface HrBarChartProps {
data: any;
keys: any;
chartMetadata: any;
}
const CustomTooltip = ({ active, payload, label }: any) => {
if (active && payload && payload.length) {
return (
<Box bg="white" p={2} boxShadow="md" borderRadius="md" border="none">
<Flex gap={0.5} flexDirection={'column'} fontSize={'sm'}>
<Text fontWeight={'bold'}>{label}</Text>
<Text color="text.secondary2">
Acceptance rate:{' '}
<Text as="span" color="text.primary">
{payload[0]?.value &&
!isNaN(payload[0]?.value) &&
payload[0]?.value > 0
? `${payload[0]?.value}%`
: '0'}
</Text>
</Text>
<Text color="text.secondary2">
Acceptance Count:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.acceptanceCount}
</Text>
</Text>
<Text color="text.secondary2">
Avg Active Users:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.avgActiveUsers}
</Text>
</Text>
<Text color="text.secondary2">
Line Accepted:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.lineAccepted}
</Text>
</Text>
<Text color="text.secondary2">
Line Suggested:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.lineSuggested}
</Text>
</Text>
<Text color="text.secondary2">
Max Active Users:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.maxActiveUsers}
</Text>
</Text>
<Text color="text.secondary2">
Suggestion Count:{' '}
<Text as="span" color="text.primary">
{payload[0]?.payload.suggestionCount}
</Text>
</Text>
</Flex>
</Box>
);
}
return null;
};
export const HrBarChart = ({ data, chartMetadata }: HrBarChartProps) => {
const { colors } = useTheme();
const transformedData = Object.entries(data?.data)?.map(
([language, stats]: [string, any]) => ({
language: language.charAt(0).toUpperCase() + language.slice(1),
acceptanceRate: parseFloat(stats.acceptanceRate),
acceptanceCount: parseInt(stats.acceptanceCount),
avgActiveUsers: parseFloat(stats.avgActiveUsers).toFixed(2),
lineAccepted: parseInt(stats.lineAccepted),
lineSuggested: parseInt(stats.lineSuggested),
maxActiveUsers: parseInt(stats.maxActiveUsers),
suggestionCount: parseInt(stats.suggestionCount),
})
);
transformedData?.sort((a, b) => b.acceptanceRate - a.acceptanceRate);
const CustomBarLabel = (props: any) => {
const { x, y, width, value } = props;
if (isNaN(value) || value == null || value <= 0) {
return null;
}
return (
<text
x={x + width + 10}
y={y + 10}
fill="#667085"
fontSize={11}
fontWeight={500}
textAnchor="start"
>
{`${value}%`}
</text>
);
};
return (
<Box height="100%" width="100%">
<ResponsiveContainer width="100%" height="100%">
<BarChart
layout="vertical"
data={transformedData}
margin={{ top: 10, right: 10, left: 60, bottom: 10 }}
>
<XAxis
type="number"
domain={[0, 100]}
unit="%"
axisLine={{ stroke: '#E2E8F0', strokeWidth: 1 }}
tickLine={false}
style={{ fontSize: 11, fontWeight: 400, fill: colors.text.primary }}
label={{
value: chartMetadata?.xlabel,
position: 'bottom',
offset: 0,
style: {
textAnchor: 'middle',
fontSize: 11,
},
}}
/>
<YAxis
type="category"
dataKey="language"
axisLine={{ stroke: '#E2E8F0', strokeWidth: 1 }}
tickLine={false}
interval={0}
style={{ fontSize: 13, fontWeight: 400, fill: colors.text.primary }}
label={{
value: chartMetadata?.ylabel,
angle: -90,
position: 'outsideLeft',
fontSize: 11,
fontWeight: 400,
dy: 40,
dx: -60,
zIndex: 1000,
}}
/>
<Tooltip
cursor={false}
content={<CustomTooltip />}
wrapperStyle={{ outline: 'none' }}
/>
<Bar
dataKey="acceptanceRate"
fill={colors.primary}
radius={[0, 4, 4, 0]}
barSize={20}
label={<CustomBarLabel />}
animationDuration={1000}
animationBegin={0}
/>
</BarChart>
</ResponsiveContainer>
</Box>
);
};
Why it matters? ⭐

The repository file HrBarChart.tsx currently contains two full copies of the component (I observed two export const HrBarChart declarations — at lines reported by grep). That produces duplicate imports/definitions and will cause conflicts / duplicate identifier errors in TypeScript. Removing the duplicated second block is the correct fix — it removes the redundant imports and the duplicate component declaration and leaves a single valid component.

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** HrBarChart.tsx
**Line:** 167:340
**Comment:**
	*Possible Bug: Remove the duplicated entire component block (the second copy) to avoid duplicate imports and duplicate `HrBarChart` declarations.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.