@karimov-labs/backstage-plugin-devxp 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { useState, useCallback, useEffect } from 'react';
1
+ import React__default, { useState, useCallback, useEffect } from 'react';
2
2
  import { Box, Tooltip, IconButton, Typography, Grid, TableContainer, Paper, Table, TableHead, TableRow, TableCell, TableBody, CircularProgress, Chip, TextField, Button } from '@material-ui/core';
3
3
  import { makeStyles } from '@material-ui/core/styles';
4
4
  import ArrowBackIcon from '@material-ui/icons/ArrowBack';
@@ -171,13 +171,13 @@ const DeveloperComparison = ({ api, initialUserIds, onBack }) => {
171
171
  const renderSlotHeader = (index) => {
172
172
  const slot = slots[index];
173
173
  const color = index === 0 ? "#3f51b5" : "#e91e63";
174
- return /* @__PURE__ */ React.createElement(
174
+ return /* @__PURE__ */ React__default.createElement(
175
175
  Box,
176
176
  {
177
177
  className: `${classes.slotCard} ${slot.data ? classes.loadedSlot : ""}`,
178
178
  style: { borderColor: slot.data ? color : void 0 }
179
179
  },
180
- slot.loading ? /* @__PURE__ */ React.createElement(CircularProgress, { size: 24 }) : slot.data ? /* @__PURE__ */ React.createElement(Box, { display: "flex", alignItems: "center", style: { gap: 8 }, width: "100%" }, /* @__PURE__ */ React.createElement("span", { className: classes.legendDot, style: { backgroundColor: color } }), /* @__PURE__ */ React.createElement(Typography, { className: classes.userIdLabel, style: { flex: 1, textAlign: "left" } }, slot.userId), /* @__PURE__ */ React.createElement(Chip, { label: `${slot.data.uniqueSkills.length} skills`, size: "small" }), /* @__PURE__ */ React.createElement(Tooltip, { title: "Remove" }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", onClick: () => clearSlot(index) }, /* @__PURE__ */ React.createElement(CloseIcon, { fontSize: "small" })))) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
180
+ slot.loading ? /* @__PURE__ */ React__default.createElement(CircularProgress, { size: 24 }) : slot.data ? /* @__PURE__ */ React__default.createElement(Box, { display: "flex", alignItems: "center", style: { gap: 8 }, width: "100%" }, /* @__PURE__ */ React__default.createElement("span", { className: classes.legendDot, style: { backgroundColor: color } }), /* @__PURE__ */ React__default.createElement(Typography, { className: classes.userIdLabel, style: { flex: 1, textAlign: "left" } }, slot.userId), /* @__PURE__ */ React__default.createElement(Chip, { label: `${slot.data.uniqueSkills.length} skills`, size: "small" }), /* @__PURE__ */ React__default.createElement(Tooltip, { title: "Remove" }, /* @__PURE__ */ React__default.createElement(IconButton, { size: "small", onClick: () => clearSlot(index) }, /* @__PURE__ */ React__default.createElement(CloseIcon, { fontSize: "small" })))) : /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
181
181
  TextField,
182
182
  {
183
183
  size: "small",
@@ -197,12 +197,12 @@ const DeveloperComparison = ({ api, initialUserIds, onBack }) => {
197
197
  },
198
198
  style: { width: "100%" }
199
199
  }
200
- ), slot.error && /* @__PURE__ */ React.createElement(Typography, { variant: "caption", color: "error" }, slot.error), /* @__PURE__ */ React.createElement(
200
+ ), slot.error && /* @__PURE__ */ React__default.createElement(Typography, { variant: "caption", color: "error" }, slot.error), /* @__PURE__ */ React__default.createElement(
201
201
  Button,
202
202
  {
203
203
  size: "small",
204
204
  variant: "outlined",
205
- startIcon: /* @__PURE__ */ React.createElement(PersonAddIcon, null),
205
+ startIcon: /* @__PURE__ */ React__default.createElement(PersonAddIcon, null),
206
206
  onClick: () => loadSlot(index, inputValues[index]),
207
207
  disabled: !inputValues[index].trim()
208
208
  },
@@ -211,32 +211,32 @@ const DeveloperComparison = ({ api, initialUserIds, onBack }) => {
211
211
  );
212
212
  };
213
213
  const bothLoaded = !!slot0Data && !!slot1Data;
214
- return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Box, { className: classes.header }, /* @__PURE__ */ React.createElement(Tooltip, { title: "Back to leaderboard" }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", onClick: onBack }, /* @__PURE__ */ React.createElement(ArrowBackIcon, null))), /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, "Developer Comparison")), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2, style: { marginBottom: 16 } }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, sm: 6 }, renderSlotHeader(0)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, sm: 6 }, renderSlotHeader(1))), (slot0Data || slot1Data) && /* @__PURE__ */ React.createElement(InfoCard, { title: "Skill Radar Comparison" }, /* @__PURE__ */ React.createElement(
214
+ return /* @__PURE__ */ React__default.createElement(Box, null, /* @__PURE__ */ React__default.createElement(Box, { className: classes.header }, /* @__PURE__ */ React__default.createElement(Tooltip, { title: "Back to leaderboard" }, /* @__PURE__ */ React__default.createElement(IconButton, { size: "small", onClick: onBack }, /* @__PURE__ */ React__default.createElement(ArrowBackIcon, null))), /* @__PURE__ */ React__default.createElement(Typography, { variant: "h6" }, "Developer Comparison")), /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 2, style: { marginBottom: 16 } }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12, sm: 6 }, renderSlotHeader(0)), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12, sm: 6 }, renderSlotHeader(1))), (slot0Data || slot1Data) && /* @__PURE__ */ React__default.createElement(InfoCard, { title: "Skill Radar Comparison" }, /* @__PURE__ */ React__default.createElement(
215
215
  SpiderChart,
216
216
  {
217
217
  primary: slot0Data ? { categoryAverages: slot0Data.categoryAverages } : { categoryAverages: [] },
218
218
  compare: slot1Data ? { categoryAverages: slot1Data.categoryAverages } : void 0
219
219
  }
220
- ), /* @__PURE__ */ React.createElement(Box, { className: classes.legend }, slot0Data && /* @__PURE__ */ React.createElement(Box, { className: classes.legendItem }, /* @__PURE__ */ React.createElement("span", { className: classes.legendDot, style: { backgroundColor: "#3f51b5" } }), /* @__PURE__ */ React.createElement(Typography, { variant: "caption" }, slots[0].userId)), slot1Data && /* @__PURE__ */ React.createElement(Box, { className: classes.legendItem }, /* @__PURE__ */ React.createElement("span", { className: classes.legendDot, style: { backgroundColor: "#e91e63" } }), /* @__PURE__ */ React.createElement(Typography, { variant: "caption" }, slots[1].userId)), average && /* @__PURE__ */ React.createElement(Box, { className: classes.legendItem }, /* @__PURE__ */ React.createElement("span", { className: classes.legendDot, style: { backgroundColor: "#ccc" } }), /* @__PURE__ */ React.createElement(Typography, { variant: "caption" }, "Platform avg (", average.developerCount, " devs)"))), /* @__PURE__ */ React.createElement(Typography, { className: classes.chartSubtitle }, "Blue = ", slots[0].userId || "Developer 1", " \xB7 Pink = ", slots[1].userId || "Developer 2")), bothLoaded && /* @__PURE__ */ React.createElement(Box, { mt: 2 }, /* @__PURE__ */ React.createElement(InfoCard, { title: "Category Breakdown" }, /* @__PURE__ */ React.createElement(TableContainer, { component: Paper, variant: "outlined" }, /* @__PURE__ */ React.createElement(Table, { size: "small" }, /* @__PURE__ */ React.createElement(TableHead, null, /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, "Category"), /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, slots[0].userId), /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, slots[1].userId), average && /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, "Platform Avg"), /* @__PURE__ */ React.createElement(TableCell, { align: "center" }, "Winner"))), /* @__PURE__ */ React.createElement(TableBody, null, CATEGORIES.map((cat) => {
220
+ ), /* @__PURE__ */ React__default.createElement(Box, { className: classes.legend }, slot0Data && /* @__PURE__ */ React__default.createElement(Box, { className: classes.legendItem }, /* @__PURE__ */ React__default.createElement("span", { className: classes.legendDot, style: { backgroundColor: "#3f51b5" } }), /* @__PURE__ */ React__default.createElement(Typography, { variant: "caption" }, slots[0].userId)), slot1Data && /* @__PURE__ */ React__default.createElement(Box, { className: classes.legendItem }, /* @__PURE__ */ React__default.createElement("span", { className: classes.legendDot, style: { backgroundColor: "#e91e63" } }), /* @__PURE__ */ React__default.createElement(Typography, { variant: "caption" }, slots[1].userId)), average && /* @__PURE__ */ React__default.createElement(Box, { className: classes.legendItem }, /* @__PURE__ */ React__default.createElement("span", { className: classes.legendDot, style: { backgroundColor: "#ccc" } }), /* @__PURE__ */ React__default.createElement(Typography, { variant: "caption" }, "Platform avg (", average.developerCount, " devs)"))), /* @__PURE__ */ React__default.createElement(Typography, { className: classes.chartSubtitle }, "Blue = ", slots[0].userId || "Developer 1", " \xB7 Pink = ", slots[1].userId || "Developer 2")), bothLoaded && /* @__PURE__ */ React__default.createElement(Box, { mt: 2 }, /* @__PURE__ */ React__default.createElement(InfoCard, { title: "Category Breakdown" }, /* @__PURE__ */ React__default.createElement(TableContainer, { component: Paper, variant: "outlined" }, /* @__PURE__ */ React__default.createElement(Table, { size: "small" }, /* @__PURE__ */ React__default.createElement(TableHead, null, /* @__PURE__ */ React__default.createElement(TableRow, null, /* @__PURE__ */ React__default.createElement(TableCell, null, "Category"), /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, slots[0].userId), /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, slots[1].userId), average && /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, "Platform Avg"), /* @__PURE__ */ React__default.createElement(TableCell, { align: "center" }, "Winner"))), /* @__PURE__ */ React__default.createElement(TableBody, null, CATEGORIES.map((cat) => {
221
221
  const v0 = getCategoryValue(slot0Data, cat) ?? 0;
222
222
  const v1 = getCategoryValue(slot1Data, cat) ?? 0;
223
223
  const avg = getAvgValue(cat);
224
224
  const winner = v0 > v1 ? 0 : v1 > v0 ? 1 : -1;
225
- return /* @__PURE__ */ React.createElement(TableRow, { key: cat }, /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, SHORT_NAMES[cat] ?? cat)), /* @__PURE__ */ React.createElement(
225
+ return /* @__PURE__ */ React__default.createElement(TableRow, { key: cat }, /* @__PURE__ */ React__default.createElement(TableCell, null, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2" }, SHORT_NAMES[cat] ?? cat)), /* @__PURE__ */ React__default.createElement(
226
226
  TableCell,
227
227
  {
228
228
  align: "right",
229
229
  className: winner === 0 ? classes.betterCell : classes.worseCell
230
230
  },
231
231
  v0.toFixed(2)
232
- ), /* @__PURE__ */ React.createElement(
232
+ ), /* @__PURE__ */ React__default.createElement(
233
233
  TableCell,
234
234
  {
235
235
  align: "right",
236
236
  className: winner === 1 ? classes.betterCell : classes.worseCell
237
237
  },
238
238
  v1.toFixed(2)
239
- ), average && /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, /* @__PURE__ */ React.createElement(Typography, { variant: "caption", color: "textSecondary" }, avg !== null ? avg.toFixed(2) : "\u2013")), /* @__PURE__ */ React.createElement(TableCell, { align: "center" }, winner === -1 ? /* @__PURE__ */ React.createElement(Typography, { variant: "caption", color: "textSecondary" }, "Tie") : /* @__PURE__ */ React.createElement(
239
+ ), average && /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "caption", color: "textSecondary" }, avg !== null ? avg.toFixed(2) : "\u2013")), /* @__PURE__ */ React__default.createElement(TableCell, { align: "center" }, winner === -1 ? /* @__PURE__ */ React__default.createElement(Typography, { variant: "caption", color: "textSecondary" }, "Tie") : /* @__PURE__ */ React__default.createElement(
240
240
  Typography,
241
241
  {
242
242
  variant: "caption",
@@ -244,7 +244,7 @@ const DeveloperComparison = ({ api, initialUserIds, onBack }) => {
244
244
  },
245
245
  winner === 0 ? slots[0].userId : slots[1].userId
246
246
  )));
247
- })))))), !slot0Data && !slot1Data && /* @__PURE__ */ React.createElement(
247
+ })))))), !slot0Data && !slot1Data && /* @__PURE__ */ React__default.createElement(
248
248
  EmptyState,
249
249
  {
250
250
  missing: "data",
@@ -1 +1 @@
1
- {"version":3,"file":"DeveloperComparison.esm.js","sources":["../../src/components/DeveloperComparison.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\nimport {\n Box,\n Typography,\n Grid,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Paper,\n TextField,\n Button,\n CircularProgress,\n IconButton,\n Tooltip,\n Chip,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport ArrowBackIcon from '@material-ui/icons/ArrowBack';\nimport PersonAddIcon from '@material-ui/icons/PersonAdd';\nimport CloseIcon from '@material-ui/icons/Close';\nimport { InfoCard, EmptyState } from '@backstage/core-components';\nimport type { DevxpApi } from '../api';\nimport type { DeveloperPerformance, DeveloperAveragePerformance } from '../types';\nimport { SpiderChart } from './SpiderChart';\n\nconst CATEGORIES = [\n 'Frontend Engineering',\n 'Backend Systems',\n 'Database & Data',\n 'Infrastructure (DevOps)',\n 'Mobile Development',\n 'AI & Machine Learning',\n 'Testing & QA',\n 'Security & Auth',\n 'Distributed Systems',\n 'Documentation',\n];\n\nconst SHORT_NAMES: Record<string, string> = {\n 'Frontend Engineering': 'Frontend',\n 'Backend Systems': 'Backend',\n 'Database & Data': 'Database',\n 'Infrastructure (DevOps)': 'DevOps',\n 'Mobile Development': 'Mobile',\n 'AI & Machine Learning': 'AI/ML',\n 'Testing & QA': 'Testing',\n 'Security & Auth': 'Security',\n 'Distributed Systems': 'Distributed',\n 'Documentation': 'Docs',\n};\n\nconst useStyles = makeStyles(theme => ({\n header: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n marginBottom: theme.spacing(2),\n },\n slotCard: {\n border: `2px dashed ${theme.palette.divider}`,\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(2),\n textAlign: 'center',\n minHeight: 80,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.spacing(1),\n },\n loadedSlot: {\n borderStyle: 'solid',\n borderColor: theme.palette.primary.main,\n },\n userIdLabel: {\n fontFamily: 'monospace',\n fontWeight: 700,\n },\n legendDot: {\n width: 12,\n height: 12,\n borderRadius: '50%',\n display: 'inline-block',\n marginRight: 6,\n flexShrink: 0,\n },\n scoreCell: {\n fontWeight: 600,\n },\n betterCell: {\n color: theme.palette.success.main,\n fontWeight: 700,\n },\n worseCell: {\n color: theme.palette.error.main,\n },\n chartSubtitle: {\n textAlign: 'center',\n color: theme.palette.text.secondary,\n fontSize: '0.75rem',\n marginTop: theme.spacing(1),\n },\n legend: {\n display: 'flex',\n gap: theme.spacing(3),\n justifyContent: 'center',\n marginTop: theme.spacing(1),\n flexWrap: 'wrap',\n },\n legendItem: {\n display: 'flex',\n alignItems: 'center',\n },\n}));\n\ninterface DeveloperSlot {\n userId: string;\n data: DeveloperPerformance | null;\n loading: boolean;\n error: string | null;\n}\n\ninterface DeveloperComparisonProps {\n api: DevxpApi;\n initialUserIds: string[];\n onBack: () => void;\n}\n\nexport const DeveloperComparison = ({ api, initialUserIds, onBack }: DeveloperComparisonProps) => {\n const classes = useStyles();\n\n const makeSlot = (userId = ''): DeveloperSlot => ({\n userId,\n data: null,\n loading: false,\n error: null,\n });\n\n const [slots, setSlots] = useState<[DeveloperSlot, DeveloperSlot]>([\n makeSlot(initialUserIds[0] ?? ''),\n makeSlot(initialUserIds[1] ?? ''),\n ]);\n const [inputValues, setInputValues] = useState<[string, string]>([\n initialUserIds[0] ?? '',\n initialUserIds[1] ?? '',\n ]);\n const [average, setAverage] = useState<DeveloperAveragePerformance | null>(null);\n\n const loadSlot = useCallback(\n async (index: 0 | 1, userId: string) => {\n if (!userId.trim()) return;\n setSlots(prev => {\n const updated = [...prev] as [DeveloperSlot, DeveloperSlot];\n updated[index] = { userId, data: null, loading: true, error: null };\n return updated;\n });\n try {\n const data = await api.getDeveloperPerformance(userId.trim());\n setSlots(prev => {\n const updated = [...prev] as [DeveloperSlot, DeveloperSlot];\n updated[index] = { userId, data, loading: false, error: null };\n return updated;\n });\n } catch (e: any) {\n setSlots(prev => {\n const updated = [...prev] as [DeveloperSlot, DeveloperSlot];\n updated[index] = { userId, data: null, loading: false, error: e.message ?? 'Failed to load' };\n return updated;\n });\n }\n },\n [api],\n );\n\n // Load average performance for baseline\n useEffect(() => {\n api.getDeveloperAveragePerformance().then(setAverage).catch(() => {});\n }, [api]);\n\n // Auto-load initially provided userIds\n useEffect(() => {\n if (initialUserIds[0]) loadSlot(0, initialUserIds[0]);\n if (initialUserIds[1]) loadSlot(1, initialUserIds[1]);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const clearSlot = (index: 0 | 1) => {\n setSlots(prev => {\n const updated = [...prev] as [DeveloperSlot, DeveloperSlot];\n updated[index] = makeSlot('');\n return updated;\n });\n setInputValues(prev => {\n const updated = [...prev] as [string, string];\n updated[index] = '';\n return updated;\n });\n };\n\n // Build combined chart data\n const slot0Data = slots[0].data;\n const slot1Data = slots[1].data;\n\n const getCategoryValue = (perf: DeveloperPerformance | null, category: string) => {\n if (!perf) return null;\n const found = perf.categoryAverages.find(c => c.category === category);\n return found ? found.averageProficiency : 0;\n };\n\n const getAvgValue = (category: string) => {\n if (!average) return null;\n const found = average.categoryAverages.find(c => c.category === category);\n return found ? found.averageProficiency : 0;\n };\n\n const renderSlotHeader = (index: 0 | 1) => {\n const slot = slots[index];\n const color = index === 0 ? '#3f51b5' : '#e91e63';\n\n return (\n <Box className={`${classes.slotCard} ${slot.data ? classes.loadedSlot : ''}`}\n style={{ borderColor: slot.data ? color : undefined }}>\n {slot.loading ? (\n <CircularProgress size={24} />\n ) : slot.data ? (\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }} width=\"100%\">\n <span className={classes.legendDot} style={{ backgroundColor: color }} />\n <Typography className={classes.userIdLabel} style={{ flex: 1, textAlign: 'left' }}>\n {slot.userId}\n </Typography>\n <Chip label={`${slot.data.uniqueSkills.length} skills`} size=\"small\" />\n <Tooltip title=\"Remove\">\n <IconButton size=\"small\" onClick={() => clearSlot(index)}>\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Box>\n ) : (\n <>\n <TextField\n size=\"small\"\n label={`Developer ${index + 1}`}\n variant=\"outlined\"\n value={inputValues[index]}\n onChange={e => {\n const val = e.target.value;\n setInputValues(prev => {\n const updated = [...prev] as [string, string];\n updated[index] = val;\n return updated;\n });\n }}\n onKeyDown={e => {\n if (e.key === 'Enter') loadSlot(index, inputValues[index]);\n }}\n style={{ width: '100%' }}\n />\n {slot.error && (\n <Typography variant=\"caption\" color=\"error\">{slot.error}</Typography>\n )}\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<PersonAddIcon />}\n onClick={() => loadSlot(index, inputValues[index])}\n disabled={!inputValues[index].trim()}\n >\n Load\n </Button>\n </>\n )}\n </Box>\n );\n };\n\n const bothLoaded = !!slot0Data && !!slot1Data;\n\n return (\n <Box>\n <Box className={classes.header}>\n <Tooltip title=\"Back to leaderboard\">\n <IconButton size=\"small\" onClick={onBack}>\n <ArrowBackIcon />\n </IconButton>\n </Tooltip>\n <Typography variant=\"h6\">Developer Comparison</Typography>\n </Box>\n\n {/* Slot selectors */}\n <Grid container spacing={2} style={{ marginBottom: 16 }}>\n <Grid item xs={12} sm={6}>{renderSlotHeader(0)}</Grid>\n <Grid item xs={12} sm={6}>{renderSlotHeader(1)}</Grid>\n </Grid>\n\n {/* Overlaid spider chart */}\n {(slot0Data || slot1Data) && (\n <InfoCard title=\"Skill Radar Comparison\">\n <SpiderChart\n primary={\n slot0Data\n ? { categoryAverages: slot0Data.categoryAverages }\n : { categoryAverages: [] }\n }\n compare={\n slot1Data\n ? { categoryAverages: slot1Data.categoryAverages }\n : undefined\n }\n />\n <Box className={classes.legend}>\n {slot0Data && (\n <Box className={classes.legendItem}>\n <span className={classes.legendDot} style={{ backgroundColor: '#3f51b5' }} />\n <Typography variant=\"caption\">{slots[0].userId}</Typography>\n </Box>\n )}\n {slot1Data && (\n <Box className={classes.legendItem}>\n <span className={classes.legendDot} style={{ backgroundColor: '#e91e63' }} />\n <Typography variant=\"caption\">{slots[1].userId}</Typography>\n </Box>\n )}\n {average && (\n <Box className={classes.legendItem}>\n <span className={classes.legendDot} style={{ backgroundColor: '#ccc' }} />\n <Typography variant=\"caption\">Platform avg ({average.developerCount} devs)</Typography>\n </Box>\n )}\n </Box>\n <Typography className={classes.chartSubtitle}>\n Blue = {slots[0].userId || 'Developer 1'} · Pink = {slots[1].userId || 'Developer 2'}\n </Typography>\n </InfoCard>\n )}\n\n {/* Category breakdown table */}\n {bothLoaded && (\n <Box mt={2}>\n <InfoCard title=\"Category Breakdown\">\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Category</TableCell>\n <TableCell align=\"right\">{slots[0].userId}</TableCell>\n <TableCell align=\"right\">{slots[1].userId}</TableCell>\n {average && <TableCell align=\"right\">Platform Avg</TableCell>}\n <TableCell align=\"center\">Winner</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {CATEGORIES.map(cat => {\n const v0 = getCategoryValue(slot0Data, cat) ?? 0;\n const v1 = getCategoryValue(slot1Data, cat) ?? 0;\n const avg = getAvgValue(cat);\n const winner = v0 > v1 ? 0 : v1 > v0 ? 1 : -1;\n return (\n <TableRow key={cat}>\n <TableCell>\n <Typography variant=\"body2\">{SHORT_NAMES[cat] ?? cat}</Typography>\n </TableCell>\n <TableCell\n align=\"right\"\n className={winner === 0 ? classes.betterCell : classes.worseCell}\n >\n {v0.toFixed(2)}\n </TableCell>\n <TableCell\n align=\"right\"\n className={winner === 1 ? classes.betterCell : classes.worseCell}\n >\n {v1.toFixed(2)}\n </TableCell>\n {average && (\n <TableCell align=\"right\">\n <Typography variant=\"caption\" color=\"textSecondary\">\n {avg !== null ? avg.toFixed(2) : '–'}\n </Typography>\n </TableCell>\n )}\n <TableCell align=\"center\">\n {winner === -1 ? (\n <Typography variant=\"caption\" color=\"textSecondary\">Tie</Typography>\n ) : (\n <Typography\n variant=\"caption\"\n style={{ fontFamily: 'monospace', fontWeight: 600 }}\n >\n {winner === 0 ? slots[0].userId : slots[1].userId}\n </Typography>\n )}\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </TableContainer>\n </InfoCard>\n </Box>\n )}\n\n {!slot0Data && !slot1Data && (\n <EmptyState\n missing=\"data\"\n title=\"No developers selected\"\n description=\"Enter developer usernames above to start comparing.\"\n />\n )}\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DeveloperComparison.esm.js","sources":["../../src/components/DeveloperComparison.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport {\n Box,\n Typography,\n Grid,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Paper,\n TextField,\n Button,\n CircularProgress,\n IconButton,\n Tooltip,\n Chip,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport ArrowBackIcon from '@material-ui/icons/ArrowBack';\nimport PersonAddIcon from '@material-ui/icons/PersonAdd';\nimport CloseIcon from '@material-ui/icons/Close';\nimport { InfoCard, EmptyState } from '@backstage/core-components';\nimport type { DevxpApi } from '../api';\nimport type { DeveloperPerformance, DeveloperAveragePerformance } from '../types';\nimport { SpiderChart } from './SpiderChart';\n\nconst CATEGORIES = [\n 'Frontend Engineering',\n 'Backend Systems',\n 'Database & Data',\n 'Infrastructure (DevOps)',\n 'Mobile Development',\n 'AI & Machine Learning',\n 'Testing & QA',\n 'Security & Auth',\n 'Distributed Systems',\n 'Documentation',\n];\n\nconst SHORT_NAMES: Record<string, string> = {\n 'Frontend Engineering': 'Frontend',\n 'Backend Systems': 'Backend',\n 'Database & Data': 'Database',\n 'Infrastructure (DevOps)': 'DevOps',\n 'Mobile Development': 'Mobile',\n 'AI & Machine Learning': 'AI/ML',\n 'Testing & QA': 'Testing',\n 'Security & Auth': 'Security',\n 'Distributed Systems': 'Distributed',\n 'Documentation': 'Docs',\n};\n\nconst useStyles = makeStyles(theme => ({\n header: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n marginBottom: theme.spacing(2),\n },\n slotCard: {\n border: `2px dashed ${theme.palette.divider}`,\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(2),\n textAlign: 'center',\n minHeight: 80,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.spacing(1),\n },\n loadedSlot: {\n borderStyle: 'solid',\n borderColor: theme.palette.primary.main,\n },\n userIdLabel: {\n fontFamily: 'monospace',\n fontWeight: 700,\n },\n legendDot: {\n width: 12,\n height: 12,\n borderRadius: '50%',\n display: 'inline-block',\n marginRight: 6,\n flexShrink: 0,\n },\n scoreCell: {\n fontWeight: 600,\n },\n betterCell: {\n color: theme.palette.success.main,\n fontWeight: 700,\n },\n worseCell: {\n color: theme.palette.error.main,\n },\n chartSubtitle: {\n textAlign: 'center',\n color: theme.palette.text.secondary,\n fontSize: '0.75rem',\n marginTop: theme.spacing(1),\n },\n legend: {\n display: 'flex',\n gap: theme.spacing(3),\n justifyContent: 'center',\n marginTop: theme.spacing(1),\n flexWrap: 'wrap',\n },\n legendItem: {\n display: 'flex',\n alignItems: 'center',\n },\n}));\n\ninterface DeveloperSlot {\n userId: string;\n data: DeveloperPerformance | null;\n loading: boolean;\n error: string | null;\n}\n\ninterface DeveloperComparisonProps {\n api: DevxpApi;\n initialUserIds: string[];\n onBack: () => void;\n}\n\nexport const DeveloperComparison = ({ api, initialUserIds, onBack }: DeveloperComparisonProps) => {\n const classes = useStyles();\n\n const makeSlot = (userId = ''): DeveloperSlot => ({\n userId,\n data: null,\n loading: false,\n error: null,\n });\n\n const [slots, setSlots] = useState<[DeveloperSlot, DeveloperSlot]>([\n makeSlot(initialUserIds[0] ?? ''),\n makeSlot(initialUserIds[1] ?? ''),\n ]);\n const [inputValues, setInputValues] = useState<[string, string]>([\n initialUserIds[0] ?? '',\n initialUserIds[1] ?? '',\n ]);\n const [average, setAverage] = useState<DeveloperAveragePerformance | null>(null);\n\n const loadSlot = useCallback(\n async (index: 0 | 1, userId: string) => {\n if (!userId.trim()) return;\n setSlots(prev => {\n const updated = [...prev] as [DeveloperSlot, DeveloperSlot];\n updated[index] = { userId, data: null, loading: true, error: null };\n return updated;\n });\n try {\n const data = await api.getDeveloperPerformance(userId.trim());\n setSlots(prev => {\n const updated = [...prev] as [DeveloperSlot, DeveloperSlot];\n updated[index] = { userId, data, loading: false, error: null };\n return updated;\n });\n } catch (e: any) {\n setSlots(prev => {\n const updated = [...prev] as [DeveloperSlot, DeveloperSlot];\n updated[index] = { userId, data: null, loading: false, error: e.message ?? 'Failed to load' };\n return updated;\n });\n }\n },\n [api],\n );\n\n // Load average performance for baseline\n useEffect(() => {\n api.getDeveloperAveragePerformance().then(setAverage).catch(() => {});\n }, [api]);\n\n // Auto-load initially provided userIds\n useEffect(() => {\n if (initialUserIds[0]) loadSlot(0, initialUserIds[0]);\n if (initialUserIds[1]) loadSlot(1, initialUserIds[1]);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const clearSlot = (index: 0 | 1) => {\n setSlots(prev => {\n const updated = [...prev] as [DeveloperSlot, DeveloperSlot];\n updated[index] = makeSlot('');\n return updated;\n });\n setInputValues(prev => {\n const updated = [...prev] as [string, string];\n updated[index] = '';\n return updated;\n });\n };\n\n // Build combined chart data\n const slot0Data = slots[0].data;\n const slot1Data = slots[1].data;\n\n const getCategoryValue = (perf: DeveloperPerformance | null, category: string) => {\n if (!perf) return null;\n const found = perf.categoryAverages.find(c => c.category === category);\n return found ? found.averageProficiency : 0;\n };\n\n const getAvgValue = (category: string) => {\n if (!average) return null;\n const found = average.categoryAverages.find(c => c.category === category);\n return found ? found.averageProficiency : 0;\n };\n\n const renderSlotHeader = (index: 0 | 1) => {\n const slot = slots[index];\n const color = index === 0 ? '#3f51b5' : '#e91e63';\n\n return (\n <Box className={`${classes.slotCard} ${slot.data ? classes.loadedSlot : ''}`}\n style={{ borderColor: slot.data ? color : undefined }}>\n {slot.loading ? (\n <CircularProgress size={24} />\n ) : slot.data ? (\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }} width=\"100%\">\n <span className={classes.legendDot} style={{ backgroundColor: color }} />\n <Typography className={classes.userIdLabel} style={{ flex: 1, textAlign: 'left' }}>\n {slot.userId}\n </Typography>\n <Chip label={`${slot.data.uniqueSkills.length} skills`} size=\"small\" />\n <Tooltip title=\"Remove\">\n <IconButton size=\"small\" onClick={() => clearSlot(index)}>\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Box>\n ) : (\n <React.Fragment>\n <TextField\n size=\"small\"\n label={`Developer ${index + 1}`}\n variant=\"outlined\"\n value={inputValues[index]}\n onChange={e => {\n const val = e.target.value;\n setInputValues(prev => {\n const updated = [...prev] as [string, string];\n updated[index] = val;\n return updated;\n });\n }}\n onKeyDown={e => {\n if (e.key === 'Enter') loadSlot(index, inputValues[index]);\n }}\n style={{ width: '100%' }}\n />\n {slot.error && (\n <Typography variant=\"caption\" color=\"error\">{slot.error}</Typography>\n )}\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<PersonAddIcon />}\n onClick={() => loadSlot(index, inputValues[index])}\n disabled={!inputValues[index].trim()}\n >\n Load\n </Button>\n </React.Fragment>\n )}\n </Box>\n );\n };\n\n const bothLoaded = !!slot0Data && !!slot1Data;\n\n return (\n <Box>\n <Box className={classes.header}>\n <Tooltip title=\"Back to leaderboard\">\n <IconButton size=\"small\" onClick={onBack}>\n <ArrowBackIcon />\n </IconButton>\n </Tooltip>\n <Typography variant=\"h6\">Developer Comparison</Typography>\n </Box>\n\n {/* Slot selectors */}\n <Grid container spacing={2} style={{ marginBottom: 16 }}>\n <Grid item xs={12} sm={6}>{renderSlotHeader(0)}</Grid>\n <Grid item xs={12} sm={6}>{renderSlotHeader(1)}</Grid>\n </Grid>\n\n {/* Overlaid spider chart */}\n {(slot0Data || slot1Data) && (\n <InfoCard title=\"Skill Radar Comparison\">\n <SpiderChart\n primary={\n slot0Data\n ? { categoryAverages: slot0Data.categoryAverages }\n : { categoryAverages: [] }\n }\n compare={\n slot1Data\n ? { categoryAverages: slot1Data.categoryAverages }\n : undefined\n }\n />\n <Box className={classes.legend}>\n {slot0Data && (\n <Box className={classes.legendItem}>\n <span className={classes.legendDot} style={{ backgroundColor: '#3f51b5' }} />\n <Typography variant=\"caption\">{slots[0].userId}</Typography>\n </Box>\n )}\n {slot1Data && (\n <Box className={classes.legendItem}>\n <span className={classes.legendDot} style={{ backgroundColor: '#e91e63' }} />\n <Typography variant=\"caption\">{slots[1].userId}</Typography>\n </Box>\n )}\n {average && (\n <Box className={classes.legendItem}>\n <span className={classes.legendDot} style={{ backgroundColor: '#ccc' }} />\n <Typography variant=\"caption\">Platform avg ({average.developerCount} devs)</Typography>\n </Box>\n )}\n </Box>\n <Typography className={classes.chartSubtitle}>\n Blue = {slots[0].userId || 'Developer 1'} · Pink = {slots[1].userId || 'Developer 2'}\n </Typography>\n </InfoCard>\n )}\n\n {/* Category breakdown table */}\n {bothLoaded && (\n <Box mt={2}>\n <InfoCard title=\"Category Breakdown\">\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Category</TableCell>\n <TableCell align=\"right\">{slots[0].userId}</TableCell>\n <TableCell align=\"right\">{slots[1].userId}</TableCell>\n {average && <TableCell align=\"right\">Platform Avg</TableCell>}\n <TableCell align=\"center\">Winner</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {CATEGORIES.map(cat => {\n const v0 = getCategoryValue(slot0Data, cat) ?? 0;\n const v1 = getCategoryValue(slot1Data, cat) ?? 0;\n const avg = getAvgValue(cat);\n const winner = v0 > v1 ? 0 : v1 > v0 ? 1 : -1;\n return (\n <TableRow key={cat}>\n <TableCell>\n <Typography variant=\"body2\">{SHORT_NAMES[cat] ?? cat}</Typography>\n </TableCell>\n <TableCell\n align=\"right\"\n className={winner === 0 ? classes.betterCell : classes.worseCell}\n >\n {v0.toFixed(2)}\n </TableCell>\n <TableCell\n align=\"right\"\n className={winner === 1 ? classes.betterCell : classes.worseCell}\n >\n {v1.toFixed(2)}\n </TableCell>\n {average && (\n <TableCell align=\"right\">\n <Typography variant=\"caption\" color=\"textSecondary\">\n {avg !== null ? avg.toFixed(2) : '–'}\n </Typography>\n </TableCell>\n )}\n <TableCell align=\"center\">\n {winner === -1 ? (\n <Typography variant=\"caption\" color=\"textSecondary\">Tie</Typography>\n ) : (\n <Typography\n variant=\"caption\"\n style={{ fontFamily: 'monospace', fontWeight: 600 }}\n >\n {winner === 0 ? slots[0].userId : slots[1].userId}\n </Typography>\n )}\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </TableContainer>\n </InfoCard>\n </Box>\n )}\n\n {!slot0Data && !slot1Data && (\n <EmptyState\n missing=\"data\"\n title=\"No developers selected\"\n description=\"Enter developer usernames above to start comparing.\"\n />\n )}\n </Box>\n );\n};\n"],"names":["React"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"DeveloperLeaderboard.esm.js","sources":["../../src/components/DeveloperLeaderboard.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect } from 'react';\nimport {\n Box,\n Typography,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Paper,\n TextField,\n Select,\n MenuItem,\n FormControl,\n InputLabel,\n Chip,\n IconButton,\n Button,\n CircularProgress,\n LinearProgress,\n Tooltip,\n} from '@material-ui/core';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport { makeStyles } from '@material-ui/core/styles';\nimport SearchIcon from '@material-ui/icons/Search';\nimport ArrowUpwardIcon from '@material-ui/icons/ArrowUpward';\nimport ArrowDownwardIcon from '@material-ui/icons/ArrowDownward';\nimport CompareArrowsIcon from '@material-ui/icons/CompareArrows';\nimport PersonIcon from '@material-ui/icons/Person';\nimport { InfoCard, EmptyState } from '@backstage/core-components';\nimport type { DevxpApi } from '../api';\nimport type { LeaderboardDeveloper, LeaderboardFilters } from '../types';\n\nconst CATEGORIES = [\n 'Frontend Engineering',\n 'Backend Systems',\n 'Database & Data',\n 'Infrastructure (DevOps)',\n 'Mobile Development',\n 'AI & Machine Learning',\n 'Testing & QA',\n 'Security & Auth',\n 'Distributed Systems',\n 'Documentation',\n];\n\nconst CATEGORY_COLORS: Record<string, string> = {\n 'Frontend Engineering': '#e91e63',\n 'Backend Systems': '#3f51b5',\n 'Database & Data': '#9c27b0',\n 'Infrastructure (DevOps)': '#ff9800',\n 'Mobile Development': '#4caf50',\n 'AI & Machine Learning': '#607d8b',\n 'Testing & QA': '#00bcd4',\n 'Security & Auth': '#f44336',\n 'Distributed Systems': '#795548',\n 'Documentation': '#9e9e9e',\n};\n\nconst useStyles = makeStyles(theme => ({\n filters: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(2),\n alignItems: 'flex-end',\n },\n searchField: {\n minWidth: 200,\n flex: 1,\n },\n repoField: {\n minWidth: 240,\n flex: 2,\n },\n selectField: {\n minWidth: 160,\n },\n categorySelect: {\n minWidth: 200,\n flex: 1,\n },\n rankCell: {\n fontWeight: 700,\n color: theme.palette.text.secondary,\n width: 48,\n },\n userIdCell: {\n fontFamily: 'monospace',\n fontWeight: 600,\n },\n scoreBar: {\n height: 6,\n borderRadius: 3,\n marginTop: 4,\n },\n categoryChip: {\n margin: theme.spacing(0.25),\n fontSize: '0.65rem',\n height: 18,\n },\n clickableRow: {\n cursor: 'pointer',\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n },\n pagination: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: theme.spacing(1, 0),\n marginTop: theme.spacing(1),\n },\n medalGold: { color: '#FFD700', fontWeight: 700 },\n medalSilver: { color: '#C0C0C0', fontWeight: 700 },\n medalBronze: { color: '#CD7F32', fontWeight: 700 },\n actionButtons: {\n display: 'flex',\n gap: theme.spacing(0.5),\n },\n}));\n\ninterface DeveloperLeaderboardProps {\n api: DevxpApi;\n onViewDeveloper: (userId: string) => void;\n onCompareDeveloper: (userId: string) => void;\n compareList: string[];\n /** Pre-loaded repo names from the parent. When provided the component skips its own fetch. */\n repoOptions?: string[];\n}\n\nexport const DeveloperLeaderboard = ({\n api,\n onViewDeveloper,\n onCompareDeveloper,\n compareList,\n repoOptions: repoOptionsProp,\n}: DeveloperLeaderboardProps) => {\n const classes = useStyles();\n\n const [developers, setDevelopers] = useState<LeaderboardDeveloper[]>([]);\n const [totalCount, setTotalCount] = useState(0);\n const [totalPages, setTotalPages] = useState(1);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // Use parent-provided options when available, otherwise fetch own\n const [ownRepoOptions, setOwnRepoOptions] = useState<string[]>([]);\n const repoOptions = repoOptionsProp ?? ownRepoOptions;\n\n const [filters, setFilters] = useState<LeaderboardFilters>({\n page: 1,\n pageSize: 20,\n categories: [],\n repoNames: [],\n sortBy: 'avgProficiency',\n sortOrder: 'desc',\n searchQuery: '',\n });\n const [searchInput, setSearchInput] = useState('');\n\n // Only fetch repo names ourselves if the parent didn't supply them\n useEffect(() => {\n if (repoOptionsProp !== undefined) return;\n api\n .getRepositories({ pageSize: 200 })\n .then(data => setOwnRepoOptions(data.repositories.map(r => r.repoName)))\n .catch(() => {});\n }, [api, repoOptionsProp]);\n\n const load = useCallback(\n async (f: LeaderboardFilters) => {\n setLoading(true);\n setError(null);\n try {\n const data = await api.getDeveloperLeaderboard(f);\n setDevelopers(data.developers);\n setTotalCount(data.totalCount);\n setTotalPages(data.totalPages);\n } catch (e: any) {\n setError(e.message ?? 'Failed to load leaderboard');\n } finally {\n setLoading(false);\n }\n },\n [api],\n );\n\n useEffect(() => {\n load(filters);\n }, [load, filters]);\n\n const applySearch = () => {\n setFilters(f => ({ ...f, page: 1, searchQuery: searchInput }));\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') applySearch();\n };\n\n const toggleSort = (field: 'avgProficiency' | 'domainSkillsScore') => {\n setFilters(f => ({\n ...f,\n page: 1,\n sortBy: field,\n sortOrder: f.sortBy === field && f.sortOrder === 'desc' ? 'asc' : 'desc',\n }));\n };\n\n const SortIcon = ({ field }: { field: 'avgProficiency' | 'domainSkillsScore' }) => {\n if (filters.sortBy !== field) return null;\n return filters.sortOrder === 'desc' ? (\n <ArrowDownwardIcon style={{ fontSize: 14, verticalAlign: 'middle' }} />\n ) : (\n <ArrowUpwardIcon style={{ fontSize: 14, verticalAlign: 'middle' }} />\n );\n };\n\n const rankLabel = (rank: number) => {\n if (rank === 1) return <span className={classes.medalGold}>🥇 1</span>;\n if (rank === 2) return <span className={classes.medalSilver}>🥈 2</span>;\n if (rank === 3) return <span className={classes.medalBronze}>🥉 3</span>;\n return <span>{rank}</span>;\n };\n\n const globalRank = (idx: number) => (filters.page - 1) * filters.pageSize + idx + 1;\n\n return (\n <InfoCard title={`Developer Leaderboard (${totalCount})`} noPadding={false}>\n {/* Filters */}\n <Box className={classes.filters}>\n <TextField\n className={classes.searchField}\n size=\"small\"\n label=\"Search developer\"\n variant=\"outlined\"\n value={searchInput}\n onChange={e => setSearchInput(e.target.value)}\n onKeyDown={handleKeyDown}\n InputProps={{\n endAdornment: (\n <IconButton size=\"small\" onClick={applySearch}>\n <SearchIcon fontSize=\"small\" />\n </IconButton>\n ),\n }}\n />\n <Autocomplete\n className={classes.repoField}\n multiple\n options={repoOptions}\n value={filters.repoNames}\n onChange={(_e, value) =>\n setFilters(f => ({ ...f, page: 1, repoNames: value }))\n }\n renderTags={(value, getTagProps) =>\n value.map((option, index) => (\n <Chip\n key={option}\n label={option.split('/').pop() ?? option}\n size=\"small\"\n {...getTagProps({ index })}\n />\n ))\n }\n renderInput={params => (\n <TextField\n {...params}\n variant=\"outlined\"\n size=\"small\"\n label=\"Repositories\"\n placeholder={filters.repoNames.length === 0 ? 'Filter by repo…' : ''}\n />\n )}\n />\n <FormControl variant=\"outlined\" size=\"small\" className={classes.categorySelect}>\n <InputLabel>Expertise domain</InputLabel>\n <Select\n multiple\n value={filters.categories}\n onChange={e =>\n setFilters(f => ({ ...f, page: 1, categories: e.target.value as string[] }))\n }\n label=\"Expertise domain\"\n renderValue={(selected: any) =>\n (selected as string[])\n .map(s => s.split(' ')[0])\n .join(', ')\n }\n >\n {CATEGORIES.map(cat => (\n <MenuItem key={cat} value={cat}>\n {cat}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n <FormControl variant=\"outlined\" size=\"small\" className={classes.selectField}>\n <InputLabel>Sort by</InputLabel>\n <Select\n value={filters.sortBy}\n onChange={e =>\n setFilters(f => ({ ...f, page: 1, sortBy: e.target.value as any }))\n }\n label=\"Sort by\"\n >\n <MenuItem value=\"avgProficiency\">Avg Proficiency</MenuItem>\n <MenuItem value=\"domainSkillsScore\">Domain Score</MenuItem>\n </Select>\n </FormControl>\n </Box>\n\n {loading ? (\n <Box display=\"flex\" justifyContent=\"center\" py={4}>\n <CircularProgress />\n </Box>\n ) : error ? (\n <EmptyState\n missing=\"data\"\n title=\"Leaderboard unavailable\"\n description={error}\n />\n ) : developers.length === 0 ? (\n <EmptyState\n missing=\"data\"\n title=\"No developers found\"\n description=\"Try adjusting the filters.\"\n />\n ) : (\n <>\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell className={classes.rankCell}>#</TableCell>\n <TableCell>Developer</TableCell>\n <TableCell>\n <span\n style={{ cursor: 'pointer' }}\n onClick={() => toggleSort('avgProficiency')}\n >\n Avg Proficiency <SortIcon field=\"avgProficiency\" />\n </span>\n </TableCell>\n <TableCell>\n <span\n style={{ cursor: 'pointer' }}\n onClick={() => toggleSort('domainSkillsScore')}\n >\n Domain Score <SortIcon field=\"domainSkillsScore\" />\n </span>\n </TableCell>\n <TableCell>Skills</TableCell>\n <TableCell>Top Domains</TableCell>\n <TableCell align=\"right\">Actions</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {developers.map((dev, idx) => (\n <TableRow\n key={dev.userId}\n className={classes.clickableRow}\n onClick={() => onViewDeveloper(dev.userId)}\n >\n <TableCell className={classes.rankCell}>\n {rankLabel(globalRank(idx))}\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\" className={classes.userIdCell}>\n {dev.userId}\n </Typography>\n </TableCell>\n <TableCell style={{ minWidth: 120 }}>\n <Typography variant=\"body2\" style={{ fontWeight: 600 }}>\n {(dev.averageProficiency * 10).toFixed(1)}%\n </Typography>\n <LinearProgress\n variant=\"determinate\"\n value={dev.averageProficiency * 10}\n className={classes.scoreBar}\n style={{ color: '#3f51b5' }}\n />\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\">\n {dev.sumOfAveragedSkillsProficiency.toFixed(2)}\n </Typography>\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\">{dev.skillCount}</Typography>\n </TableCell>\n <TableCell style={{ maxWidth: 200 }}>\n {dev.categoryBreakdown\n .sort((a, b) => b.averageProficiency - a.averageProficiency)\n .slice(0, 3)\n .map(cat => (\n <Chip\n key={cat.category}\n label={cat.category.split(' ')[0]}\n size=\"small\"\n className={classes.categoryChip}\n style={{\n backgroundColor: `${CATEGORY_COLORS[cat.category] ?? '#9e9e9e'}20`,\n color: CATEGORY_COLORS[cat.category] ?? '#9e9e9e',\n }}\n />\n ))}\n </TableCell>\n <TableCell align=\"right\" onClick={e => e.stopPropagation()}>\n <Box className={classes.actionButtons}>\n <Tooltip title=\"View details\">\n <IconButton\n size=\"small\"\n onClick={() => onViewDeveloper(dev.userId)}\n >\n <PersonIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n <Tooltip\n title={\n compareList.includes(dev.userId)\n ? 'Added to comparison'\n : 'Add to comparison'\n }\n >\n <IconButton\n size=\"small\"\n color={compareList.includes(dev.userId) ? 'primary' : 'default'}\n onClick={() => onCompareDeveloper(dev.userId)}\n >\n <CompareArrowsIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Box>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n\n {/* Pagination */}\n <Box className={classes.pagination}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Showing {(filters.page - 1) * filters.pageSize + 1}–\n {Math.min(filters.page * filters.pageSize, totalCount)} of {totalCount}\n </Typography>\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <Button\n size=\"small\"\n disabled={filters.page <= 1}\n onClick={() => setFilters(f => ({ ...f, page: f.page - 1 }))}\n >\n Prev\n </Button>\n <Typography variant=\"caption\">\n {filters.page} / {totalPages}\n </Typography>\n <Button\n size=\"small\"\n disabled={filters.page >= totalPages}\n onClick={() => setFilters(f => ({ ...f, page: f.page + 1 }))}\n >\n Next\n </Button>\n </Box>\n </Box>\n </>\n )}\n </InfoCard>\n );\n};\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"DeveloperLeaderboard.esm.js","sources":["../../src/components/DeveloperLeaderboard.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect } from 'react';\nimport {\n Box,\n Typography,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Paper,\n TextField,\n Select,\n MenuItem,\n FormControl,\n InputLabel,\n Chip,\n IconButton,\n Button,\n CircularProgress,\n LinearProgress,\n Tooltip,\n} from '@material-ui/core';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport { makeStyles } from '@material-ui/core/styles';\nimport SearchIcon from '@material-ui/icons/Search';\nimport ArrowUpwardIcon from '@material-ui/icons/ArrowUpward';\nimport ArrowDownwardIcon from '@material-ui/icons/ArrowDownward';\nimport CompareArrowsIcon from '@material-ui/icons/CompareArrows';\nimport PersonIcon from '@material-ui/icons/Person';\nimport { InfoCard, EmptyState } from '@backstage/core-components';\nimport type { DevxpApi } from '../api';\nimport type { LeaderboardDeveloper, LeaderboardFilters } from '../types';\n\nconst CATEGORIES = [\n 'Frontend Engineering',\n 'Backend Systems',\n 'Database & Data',\n 'Infrastructure (DevOps)',\n 'Mobile Development',\n 'AI & Machine Learning',\n 'Testing & QA',\n 'Security & Auth',\n 'Distributed Systems',\n 'Documentation',\n];\n\nconst CATEGORY_COLORS: Record<string, string> = {\n 'Frontend Engineering': '#e91e63',\n 'Backend Systems': '#3f51b5',\n 'Database & Data': '#9c27b0',\n 'Infrastructure (DevOps)': '#ff9800',\n 'Mobile Development': '#4caf50',\n 'AI & Machine Learning': '#607d8b',\n 'Testing & QA': '#00bcd4',\n 'Security & Auth': '#f44336',\n 'Distributed Systems': '#795548',\n 'Documentation': '#9e9e9e',\n};\n\nconst useStyles = makeStyles(theme => ({\n filters: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(2),\n alignItems: 'flex-end',\n },\n searchField: {\n minWidth: 200,\n flex: 1,\n },\n repoField: {\n minWidth: 240,\n flex: 2,\n },\n selectField: {\n minWidth: 160,\n },\n categorySelect: {\n minWidth: 200,\n flex: 1,\n },\n rankCell: {\n fontWeight: 700,\n color: theme.palette.text.secondary,\n width: 48,\n },\n userIdCell: {\n fontFamily: 'monospace',\n fontWeight: 600,\n },\n scoreBar: {\n height: 6,\n borderRadius: 3,\n marginTop: 4,\n },\n categoryChip: {\n margin: theme.spacing(0.25),\n fontSize: '0.65rem',\n height: 18,\n },\n clickableRow: {\n cursor: 'pointer',\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n },\n pagination: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: theme.spacing(1, 0),\n marginTop: theme.spacing(1),\n },\n medalGold: { color: '#FFD700', fontWeight: 700 },\n medalSilver: { color: '#C0C0C0', fontWeight: 700 },\n medalBronze: { color: '#CD7F32', fontWeight: 700 },\n actionButtons: {\n display: 'flex',\n gap: theme.spacing(0.5),\n },\n}));\n\ninterface DeveloperLeaderboardProps {\n api: DevxpApi;\n onViewDeveloper: (userId: string) => void;\n onCompareDeveloper: (userId: string) => void;\n compareList: string[];\n /** Pre-loaded repo names from the parent. When provided the component skips its own fetch. */\n repoOptions?: string[];\n}\n\nexport const DeveloperLeaderboard = ({\n api,\n onViewDeveloper,\n onCompareDeveloper,\n compareList,\n repoOptions: repoOptionsProp,\n}: DeveloperLeaderboardProps) => {\n const classes = useStyles();\n\n const [developers, setDevelopers] = useState<LeaderboardDeveloper[]>([]);\n const [totalCount, setTotalCount] = useState(0);\n const [totalPages, setTotalPages] = useState(1);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // Use parent-provided options when available, otherwise fetch own\n const [ownRepoOptions, setOwnRepoOptions] = useState<string[]>([]);\n const repoOptions = repoOptionsProp ?? ownRepoOptions;\n\n const [filters, setFilters] = useState<LeaderboardFilters>({\n page: 1,\n pageSize: 20,\n categories: [],\n repoNames: [],\n sortBy: 'avgProficiency',\n sortOrder: 'desc',\n searchQuery: '',\n });\n const [searchInput, setSearchInput] = useState('');\n\n // Only fetch repo names ourselves if the parent didn't supply them\n useEffect(() => {\n if (repoOptionsProp !== undefined) return;\n api\n .getRepositories({ pageSize: 200 })\n .then(data => setOwnRepoOptions(data.repositories.map(r => r.repoName)))\n .catch(() => {});\n }, [api, repoOptionsProp]);\n\n const load = useCallback(\n async (f: LeaderboardFilters) => {\n setLoading(true);\n setError(null);\n try {\n const data = await api.getDeveloperLeaderboard(f);\n setDevelopers(data.developers);\n setTotalCount(data.totalCount);\n setTotalPages(data.totalPages);\n } catch (e: any) {\n setError(e.message ?? 'Failed to load leaderboard');\n } finally {\n setLoading(false);\n }\n },\n [api],\n );\n\n useEffect(() => {\n load(filters);\n }, [load, filters]);\n\n const applySearch = () => {\n setFilters(f => ({ ...f, page: 1, searchQuery: searchInput }));\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') applySearch();\n };\n\n const toggleSort = (field: 'avgProficiency' | 'domainSkillsScore') => {\n setFilters(f => ({\n ...f,\n page: 1,\n sortBy: field,\n sortOrder: f.sortBy === field && f.sortOrder === 'desc' ? 'asc' : 'desc',\n }));\n };\n\n const SortIcon = ({ field }: { field: 'avgProficiency' | 'domainSkillsScore' }) => {\n if (filters.sortBy !== field) return null;\n return filters.sortOrder === 'desc' ? (\n <ArrowDownwardIcon style={{ fontSize: 14, verticalAlign: 'middle' }} />\n ) : (\n <ArrowUpwardIcon style={{ fontSize: 14, verticalAlign: 'middle' }} />\n );\n };\n\n const rankLabel = (rank: number) => {\n if (rank === 1) return <span className={classes.medalGold}>🥇 1</span>;\n if (rank === 2) return <span className={classes.medalSilver}>🥈 2</span>;\n if (rank === 3) return <span className={classes.medalBronze}>🥉 3</span>;\n return <span>{rank}</span>;\n };\n\n const globalRank = (idx: number) => (filters.page - 1) * filters.pageSize + idx + 1;\n\n return (\n <InfoCard title={`Developer Leaderboard (${totalCount})`} noPadding={false}>\n {/* Filters */}\n <Box className={classes.filters}>\n <TextField\n className={classes.searchField}\n size=\"small\"\n label=\"Search developer\"\n variant=\"outlined\"\n value={searchInput}\n onChange={e => setSearchInput(e.target.value)}\n onKeyDown={handleKeyDown}\n InputProps={{\n endAdornment: (\n <IconButton size=\"small\" onClick={applySearch}>\n <SearchIcon fontSize=\"small\" />\n </IconButton>\n ),\n }}\n />\n <Autocomplete\n className={classes.repoField}\n multiple\n options={repoOptions}\n value={filters.repoNames}\n onChange={(_e, value) =>\n setFilters(f => ({ ...f, page: 1, repoNames: value }))\n }\n renderTags={(value, getTagProps) =>\n value.map((option, index) => (\n <Chip\n key={option}\n label={option.split('/').pop() ?? option}\n size=\"small\"\n {...getTagProps({ index })}\n />\n ))\n }\n renderInput={params => (\n <TextField\n {...params}\n variant=\"outlined\"\n size=\"small\"\n label=\"Repositories\"\n placeholder={filters.repoNames.length === 0 ? 'Filter by repo…' : ''}\n />\n )}\n />\n <FormControl variant=\"outlined\" size=\"small\" className={classes.categorySelect}>\n <InputLabel>Expertise domain</InputLabel>\n <Select\n multiple\n value={filters.categories}\n onChange={e =>\n setFilters(f => ({ ...f, page: 1, categories: e.target.value as string[] }))\n }\n label=\"Expertise domain\"\n renderValue={(selected: any) =>\n (selected as string[])\n .map(s => s.split(' ')[0])\n .join(', ')\n }\n >\n {CATEGORIES.map(cat => (\n <MenuItem key={cat} value={cat}>\n {cat}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n <FormControl variant=\"outlined\" size=\"small\" className={classes.selectField}>\n <InputLabel>Sort by</InputLabel>\n <Select\n value={filters.sortBy}\n onChange={e =>\n setFilters(f => ({ ...f, page: 1, sortBy: e.target.value as any }))\n }\n label=\"Sort by\"\n >\n <MenuItem value=\"avgProficiency\">Avg Proficiency</MenuItem>\n <MenuItem value=\"domainSkillsScore\">Domain Score</MenuItem>\n </Select>\n </FormControl>\n </Box>\n\n {loading ? (\n <Box display=\"flex\" justifyContent=\"center\" py={4}>\n <CircularProgress />\n </Box>\n ) : error ? (\n <EmptyState\n missing=\"data\"\n title=\"Leaderboard unavailable\"\n description={error}\n />\n ) : developers.length === 0 ? (\n <EmptyState\n missing=\"data\"\n title=\"No developers found\"\n description=\"Try adjusting the filters.\"\n />\n ) : (\n <React.Fragment>\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell className={classes.rankCell}>#</TableCell>\n <TableCell>Developer</TableCell>\n <TableCell>\n <span\n style={{ cursor: 'pointer' }}\n onClick={() => toggleSort('avgProficiency')}\n >\n Avg Proficiency <SortIcon field=\"avgProficiency\" />\n </span>\n </TableCell>\n <TableCell>\n <span\n style={{ cursor: 'pointer' }}\n onClick={() => toggleSort('domainSkillsScore')}\n >\n Domain Score <SortIcon field=\"domainSkillsScore\" />\n </span>\n </TableCell>\n <TableCell>Skills</TableCell>\n <TableCell>Top Domains</TableCell>\n <TableCell align=\"right\">Actions</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {developers.map((dev, idx) => (\n <TableRow\n key={dev.userId}\n className={classes.clickableRow}\n onClick={() => onViewDeveloper(dev.userId)}\n >\n <TableCell className={classes.rankCell}>\n {rankLabel(globalRank(idx))}\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\" className={classes.userIdCell}>\n {dev.userId}\n </Typography>\n </TableCell>\n <TableCell style={{ minWidth: 120 }}>\n <Typography variant=\"body2\" style={{ fontWeight: 600 }}>\n {(dev.averageProficiency * 10).toFixed(1)}%\n </Typography>\n <LinearProgress\n variant=\"determinate\"\n value={dev.averageProficiency * 10}\n className={classes.scoreBar}\n style={{ color: '#3f51b5' }}\n />\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\">\n {dev.sumOfAveragedSkillsProficiency.toFixed(2)}\n </Typography>\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\">{dev.skillCount}</Typography>\n </TableCell>\n <TableCell style={{ maxWidth: 200 }}>\n {dev.categoryBreakdown\n .sort((a, b) => b.averageProficiency - a.averageProficiency)\n .slice(0, 3)\n .map(cat => (\n <Chip\n key={cat.category}\n label={cat.category.split(' ')[0]}\n size=\"small\"\n className={classes.categoryChip}\n style={{\n backgroundColor: `${CATEGORY_COLORS[cat.category] ?? '#9e9e9e'}20`,\n color: CATEGORY_COLORS[cat.category] ?? '#9e9e9e',\n }}\n />\n ))}\n </TableCell>\n <TableCell align=\"right\" onClick={e => e.stopPropagation()}>\n <Box className={classes.actionButtons}>\n <Tooltip title=\"View details\">\n <IconButton\n size=\"small\"\n onClick={() => onViewDeveloper(dev.userId)}\n >\n <PersonIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n <Tooltip\n title={\n compareList.includes(dev.userId)\n ? 'Added to comparison'\n : 'Add to comparison'\n }\n >\n <IconButton\n size=\"small\"\n color={compareList.includes(dev.userId) ? 'primary' : 'default'}\n onClick={() => onCompareDeveloper(dev.userId)}\n >\n <CompareArrowsIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Box>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n\n {/* Pagination */}\n <Box className={classes.pagination}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Showing {(filters.page - 1) * filters.pageSize + 1}–\n {Math.min(filters.page * filters.pageSize, totalCount)} of {totalCount}\n </Typography>\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <Button\n size=\"small\"\n disabled={filters.page <= 1}\n onClick={() => setFilters(f => ({ ...f, page: f.page - 1 }))}\n >\n Prev\n </Button>\n <Typography variant=\"caption\">\n {filters.page} / {totalPages}\n </Typography>\n <Button\n size=\"small\"\n disabled={filters.page >= totalPages}\n onClick={() => setFilters(f => ({ ...f, page: f.page + 1 }))}\n >\n Next\n </Button>\n </Box>\n </Box>\n </React.Fragment>\n )}\n </InfoCard>\n );\n};\n"],"names":["React"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { useState, useCallback, useEffect } from 'react';
1
+ import React__default, { useState, useCallback, useEffect } from 'react';
2
2
  import { Box, TextField, IconButton, CircularProgress, TableContainer, Paper, Table, TableHead, TableRow, TableCell, TableBody, Typography, LinearProgress, Button, Tooltip, Chip } from '@material-ui/core';
3
3
  import { makeStyles } from '@material-ui/core/styles';
4
4
  import SearchIcon from '@material-ui/icons/Search';
@@ -84,7 +84,7 @@ const useStyles = makeStyles((theme) => ({
84
84
  const RepositoriesContent = ({ api, onViewDeveloper }) => {
85
85
  const [view, setView] = useState("list");
86
86
  const [selectedRepo, setSelectedRepo] = useState("");
87
- return /* @__PURE__ */ React.createElement(Box, null, view === "list" ? /* @__PURE__ */ React.createElement(
87
+ return /* @__PURE__ */ React__default.createElement(Box, null, view === "list" ? /* @__PURE__ */ React__default.createElement(
88
88
  RepositoryList,
89
89
  {
90
90
  api,
@@ -93,7 +93,7 @@ const RepositoriesContent = ({ api, onViewDeveloper }) => {
93
93
  setView("details");
94
94
  }
95
95
  }
96
- ) : /* @__PURE__ */ React.createElement(
96
+ ) : /* @__PURE__ */ React__default.createElement(
97
97
  RepositoryDetailsView,
98
98
  {
99
99
  api,
@@ -149,7 +149,7 @@ const RepositoryList = ({ api, onViewRepo }) => {
149
149
  return iso;
150
150
  }
151
151
  };
152
- return /* @__PURE__ */ React.createElement(InfoCard, { title: `Repositories (${totalCount})`, noPadding: false }, /* @__PURE__ */ React.createElement(Box, { className: classes.searchRow }, /* @__PURE__ */ React.createElement(
152
+ return /* @__PURE__ */ React__default.createElement(InfoCard, { title: `Repositories (${totalCount})`, noPadding: false }, /* @__PURE__ */ React__default.createElement(Box, { className: classes.searchRow }, /* @__PURE__ */ React__default.createElement(
153
153
  TextField,
154
154
  {
155
155
  className: classes.searchField,
@@ -160,20 +160,20 @@ const RepositoryList = ({ api, onViewRepo }) => {
160
160
  onChange: (e) => setSearchInput(e.target.value),
161
161
  onKeyDown: (e) => e.key === "Enter" && applySearch(),
162
162
  InputProps: {
163
- endAdornment: /* @__PURE__ */ React.createElement(IconButton, { size: "small", onClick: applySearch }, /* @__PURE__ */ React.createElement(SearchIcon, { fontSize: "small" }))
163
+ endAdornment: /* @__PURE__ */ React__default.createElement(IconButton, { size: "small", onClick: applySearch }, /* @__PURE__ */ React__default.createElement(SearchIcon, { fontSize: "small" }))
164
164
  }
165
165
  }
166
- )), loading ? /* @__PURE__ */ React.createElement(Box, { display: "flex", justifyContent: "center", py: 4 }, /* @__PURE__ */ React.createElement(CircularProgress, null)) : error ? /* @__PURE__ */ React.createElement(EmptyState, { missing: "data", title: "Repositories unavailable", description: error }) : repositories.length === 0 ? /* @__PURE__ */ React.createElement(EmptyState, { missing: "data", title: "No repositories found", description: "Try a different search." }) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(TableContainer, { component: Paper, variant: "outlined" }, /* @__PURE__ */ React.createElement(Table, { size: "small" }, /* @__PURE__ */ React.createElement(TableHead, null, /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, "Repository"), /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, "Developers"), /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, "Events"), /* @__PURE__ */ React.createElement(TableCell, { style: { minWidth: 140 } }, "Avg Proficiency"), /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, "Last Activity"))), /* @__PURE__ */ React.createElement(TableBody, null, repositories.map((repo) => /* @__PURE__ */ React.createElement(
166
+ )), loading ? /* @__PURE__ */ React__default.createElement(Box, { display: "flex", justifyContent: "center", py: 4 }, /* @__PURE__ */ React__default.createElement(CircularProgress, null)) : error ? /* @__PURE__ */ React__default.createElement(EmptyState, { missing: "data", title: "Repositories unavailable", description: error }) : repositories.length === 0 ? /* @__PURE__ */ React__default.createElement(EmptyState, { missing: "data", title: "No repositories found", description: "Try a different search." }) : /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(TableContainer, { component: Paper, variant: "outlined" }, /* @__PURE__ */ React__default.createElement(Table, { size: "small" }, /* @__PURE__ */ React__default.createElement(TableHead, null, /* @__PURE__ */ React__default.createElement(TableRow, null, /* @__PURE__ */ React__default.createElement(TableCell, null, "Repository"), /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, "Developers"), /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, "Events"), /* @__PURE__ */ React__default.createElement(TableCell, { style: { minWidth: 140 } }, "Avg Proficiency"), /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, "Last Activity"))), /* @__PURE__ */ React__default.createElement(TableBody, null, repositories.map((repo) => /* @__PURE__ */ React__default.createElement(
167
167
  TableRow,
168
168
  {
169
169
  key: repo.repoName,
170
170
  className: classes.clickableRow,
171
171
  onClick: () => onViewRepo(repo.repoName)
172
172
  },
173
- /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Box, { display: "flex", alignItems: "center", style: { gap: 8 } }, /* @__PURE__ */ React.createElement(StorageIcon, { fontSize: "small", color: "action" }), /* @__PURE__ */ React.createElement(Typography, { variant: "body2", className: classes.repoName }, repo.repoName))),
174
- /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, repo.developerCount)),
175
- /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, repo.eventCount.toLocaleString())),
176
- /* @__PURE__ */ React.createElement(TableCell, { style: { minWidth: 140 } }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", style: { fontWeight: 600 } }, (repo.avgProficiency * 10).toFixed(1), "%"), /* @__PURE__ */ React.createElement(
173
+ /* @__PURE__ */ React__default.createElement(TableCell, null, /* @__PURE__ */ React__default.createElement(Box, { display: "flex", alignItems: "center", style: { gap: 8 } }, /* @__PURE__ */ React__default.createElement(StorageIcon, { fontSize: "small", color: "action" }), /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2", className: classes.repoName }, repo.repoName))),
174
+ /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2" }, repo.developerCount)),
175
+ /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2" }, repo.eventCount.toLocaleString())),
176
+ /* @__PURE__ */ React__default.createElement(TableCell, { style: { minWidth: 140 } }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2", style: { fontWeight: 600 } }, (repo.avgProficiency * 10).toFixed(1), "%"), /* @__PURE__ */ React__default.createElement(
177
177
  LinearProgress,
178
178
  {
179
179
  variant: "determinate",
@@ -181,8 +181,8 @@ const RepositoryList = ({ api, onViewRepo }) => {
181
181
  className: classes.scoreBar
182
182
  }
183
183
  )),
184
- /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, /* @__PURE__ */ React.createElement(Typography, { variant: "caption", color: "textSecondary" }, formatDate(repo.lastActivity)))
185
- ))))), /* @__PURE__ */ React.createElement(Box, { className: classes.pagination }, /* @__PURE__ */ React.createElement(Typography, { variant: "caption", color: "textSecondary" }, "Showing ", (page - 1) * pageSize + 1, "\u2013", Math.min(page * pageSize, totalCount), " of ", totalCount), /* @__PURE__ */ React.createElement(Box, { display: "flex", alignItems: "center", style: { gap: 8 } }, /* @__PURE__ */ React.createElement(Button, { size: "small", disabled: page <= 1, onClick: () => setPage((p) => p - 1) }, "Prev"), /* @__PURE__ */ React.createElement(Typography, { variant: "caption" }, page, " / ", totalPages), /* @__PURE__ */ React.createElement(Button, { size: "small", disabled: page >= totalPages, onClick: () => setPage((p) => p + 1) }, "Next")))));
184
+ /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "caption", color: "textSecondary" }, formatDate(repo.lastActivity)))
185
+ ))))), /* @__PURE__ */ React__default.createElement(Box, { className: classes.pagination }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "caption", color: "textSecondary" }, "Showing ", (page - 1) * pageSize + 1, "\u2013", Math.min(page * pageSize, totalCount), " of ", totalCount), /* @__PURE__ */ React__default.createElement(Box, { display: "flex", alignItems: "center", style: { gap: 8 } }, /* @__PURE__ */ React__default.createElement(Button, { size: "small", disabled: page <= 1, onClick: () => setPage((p) => p - 1) }, "Prev"), /* @__PURE__ */ React__default.createElement(Typography, { variant: "caption" }, page, " / ", totalPages), /* @__PURE__ */ React__default.createElement(Button, { size: "small", disabled: page >= totalPages, onClick: () => setPage((p) => p + 1) }, "Next")))));
186
186
  };
187
187
  const RepositoryDetailsView = ({ api, repoName, onBack, onViewDeveloper }) => {
188
188
  const classes = useStyles();
@@ -205,7 +205,7 @@ const RepositoryDetailsView = ({ api, repoName, onBack, onViewDeveloper }) => {
205
205
  return iso;
206
206
  }
207
207
  };
208
- return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Box, { className: classes.header }, /* @__PURE__ */ React.createElement(Tooltip, { title: "Back to repositories" }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", onClick: onBack }, /* @__PURE__ */ React.createElement(ArrowBackIcon, null))), /* @__PURE__ */ React.createElement(StorageIcon, { color: "action" }), /* @__PURE__ */ React.createElement(Typography, { variant: "h6", className: classes.repoName }, repoName)), loading ? /* @__PURE__ */ React.createElement(Box, { display: "flex", justifyContent: "center", py: 6 }, /* @__PURE__ */ React.createElement(CircularProgress, null)) : error ? /* @__PURE__ */ React.createElement(EmptyState, { missing: "data", title: "Details unavailable", description: error }) : details ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(InfoCard, { title: "Overview" }, /* @__PURE__ */ React.createElement(Box, { display: "flex", justifyContent: "space-around", flexWrap: "wrap" }, /* @__PURE__ */ React.createElement(Box, { className: classes.statBox }, /* @__PURE__ */ React.createElement(Typography, { className: classes.statValue }, details.developerCount), /* @__PURE__ */ React.createElement(Typography, { className: classes.statLabel }, "Developers")), /* @__PURE__ */ React.createElement(Box, { className: classes.statBox }, /* @__PURE__ */ React.createElement(Typography, { className: classes.statValue }, details.eventCount.toLocaleString()), /* @__PURE__ */ React.createElement(Typography, { className: classes.statLabel }, "Skill Events")), /* @__PURE__ */ React.createElement(Box, { className: classes.statBox }, /* @__PURE__ */ React.createElement(Typography, { className: classes.statValue }, (details.avgProficiency * 10).toFixed(1), "%"), /* @__PURE__ */ React.createElement(Typography, { className: classes.statLabel }, "Avg Proficiency")), /* @__PURE__ */ React.createElement(Box, { className: classes.statBox }, /* @__PURE__ */ React.createElement(Typography, { className: classes.statValue, style: { fontSize: "1rem" } }, formatDate(details.lastActivity)), /* @__PURE__ */ React.createElement(Typography, { className: classes.statLabel }, "Last Activity")))), details.categoryBreakdown.length > 0 && /* @__PURE__ */ React.createElement(Box, { mt: 2 }, /* @__PURE__ */ React.createElement(InfoCard, { title: "Skill Categories" }, /* @__PURE__ */ React.createElement(TableContainer, { component: Paper, variant: "outlined" }, /* @__PURE__ */ React.createElement(Table, { size: "small" }, /* @__PURE__ */ React.createElement(TableHead, null, /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, "Category"), /* @__PURE__ */ React.createElement(TableCell, { style: { minWidth: 160 } }, "Avg Proficiency"))), /* @__PURE__ */ React.createElement(TableBody, null, details.categoryBreakdown.map((cat) => /* @__PURE__ */ React.createElement(TableRow, { key: cat.category }, /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(
208
+ return /* @__PURE__ */ React__default.createElement(Box, null, /* @__PURE__ */ React__default.createElement(Box, { className: classes.header }, /* @__PURE__ */ React__default.createElement(Tooltip, { title: "Back to repositories" }, /* @__PURE__ */ React__default.createElement(IconButton, { size: "small", onClick: onBack }, /* @__PURE__ */ React__default.createElement(ArrowBackIcon, null))), /* @__PURE__ */ React__default.createElement(StorageIcon, { color: "action" }), /* @__PURE__ */ React__default.createElement(Typography, { variant: "h6", className: classes.repoName }, repoName)), loading ? /* @__PURE__ */ React__default.createElement(Box, { display: "flex", justifyContent: "center", py: 6 }, /* @__PURE__ */ React__default.createElement(CircularProgress, null)) : error ? /* @__PURE__ */ React__default.createElement(EmptyState, { missing: "data", title: "Details unavailable", description: error }) : details ? /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(InfoCard, { title: "Overview" }, /* @__PURE__ */ React__default.createElement(Box, { display: "flex", justifyContent: "space-around", flexWrap: "wrap" }, /* @__PURE__ */ React__default.createElement(Box, { className: classes.statBox }, /* @__PURE__ */ React__default.createElement(Typography, { className: classes.statValue }, details.developerCount), /* @__PURE__ */ React__default.createElement(Typography, { className: classes.statLabel }, "Developers")), /* @__PURE__ */ React__default.createElement(Box, { className: classes.statBox }, /* @__PURE__ */ React__default.createElement(Typography, { className: classes.statValue }, details.eventCount.toLocaleString()), /* @__PURE__ */ React__default.createElement(Typography, { className: classes.statLabel }, "Skill Events")), /* @__PURE__ */ React__default.createElement(Box, { className: classes.statBox }, /* @__PURE__ */ React__default.createElement(Typography, { className: classes.statValue }, (details.avgProficiency * 10).toFixed(1), "%"), /* @__PURE__ */ React__default.createElement(Typography, { className: classes.statLabel }, "Avg Proficiency")), /* @__PURE__ */ React__default.createElement(Box, { className: classes.statBox }, /* @__PURE__ */ React__default.createElement(Typography, { className: classes.statValue, style: { fontSize: "1rem" } }, formatDate(details.lastActivity)), /* @__PURE__ */ React__default.createElement(Typography, { className: classes.statLabel }, "Last Activity")))), details.categoryBreakdown.length > 0 && /* @__PURE__ */ React__default.createElement(Box, { mt: 2 }, /* @__PURE__ */ React__default.createElement(InfoCard, { title: "Skill Categories" }, /* @__PURE__ */ React__default.createElement(TableContainer, { component: Paper, variant: "outlined" }, /* @__PURE__ */ React__default.createElement(Table, { size: "small" }, /* @__PURE__ */ React__default.createElement(TableHead, null, /* @__PURE__ */ React__default.createElement(TableRow, null, /* @__PURE__ */ React__default.createElement(TableCell, null, "Category"), /* @__PURE__ */ React__default.createElement(TableCell, { style: { minWidth: 160 } }, "Avg Proficiency"))), /* @__PURE__ */ React__default.createElement(TableBody, null, details.categoryBreakdown.map((cat) => /* @__PURE__ */ React__default.createElement(TableRow, { key: cat.category }, /* @__PURE__ */ React__default.createElement(TableCell, null, /* @__PURE__ */ React__default.createElement(
209
209
  Chip,
210
210
  {
211
211
  label: cat.category,
@@ -217,7 +217,7 @@ const RepositoryDetailsView = ({ api, repoName, onBack, onViewDeveloper }) => {
217
217
  height: 20
218
218
  }
219
219
  }
220
- )), /* @__PURE__ */ React.createElement(TableCell, { style: { minWidth: 160 } }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", style: { fontWeight: 600 } }, (cat.averageProficiency * 10).toFixed(1), "%"), /* @__PURE__ */ React.createElement(
220
+ )), /* @__PURE__ */ React__default.createElement(TableCell, { style: { minWidth: 160 } }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2", style: { fontWeight: 600 } }, (cat.averageProficiency * 10).toFixed(1), "%"), /* @__PURE__ */ React__default.createElement(
221
221
  LinearProgress,
222
222
  {
223
223
  variant: "determinate",
@@ -225,16 +225,16 @@ const RepositoryDetailsView = ({ api, repoName, onBack, onViewDeveloper }) => {
225
225
  className: classes.scoreBar,
226
226
  style: { backgroundColor: `${CATEGORY_COLORS[cat.category] ?? "#9e9e9e"}30` }
227
227
  }
228
- ))))))))), details.topDevelopers.length > 0 && /* @__PURE__ */ React.createElement(Box, { mt: 2 }, /* @__PURE__ */ React.createElement(InfoCard, { title: "Top Developers" }, /* @__PURE__ */ React.createElement(TableContainer, { component: Paper, variant: "outlined" }, /* @__PURE__ */ React.createElement(Table, { size: "small" }, /* @__PURE__ */ React.createElement(TableHead, null, /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, "#"), /* @__PURE__ */ React.createElement(TableCell, null, "Developer"), /* @__PURE__ */ React.createElement(TableCell, { style: { minWidth: 140 } }, "Avg Proficiency"), /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, "Skills"), onViewDeveloper && /* @__PURE__ */ React.createElement(TableCell, { align: "right" }))), /* @__PURE__ */ React.createElement(TableBody, null, details.topDevelopers.map((dev, idx) => /* @__PURE__ */ React.createElement(
228
+ ))))))))), details.topDevelopers.length > 0 && /* @__PURE__ */ React__default.createElement(Box, { mt: 2 }, /* @__PURE__ */ React__default.createElement(InfoCard, { title: "Top Developers" }, /* @__PURE__ */ React__default.createElement(TableContainer, { component: Paper, variant: "outlined" }, /* @__PURE__ */ React__default.createElement(Table, { size: "small" }, /* @__PURE__ */ React__default.createElement(TableHead, null, /* @__PURE__ */ React__default.createElement(TableRow, null, /* @__PURE__ */ React__default.createElement(TableCell, null, "#"), /* @__PURE__ */ React__default.createElement(TableCell, null, "Developer"), /* @__PURE__ */ React__default.createElement(TableCell, { style: { minWidth: 140 } }, "Avg Proficiency"), /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, "Skills"), onViewDeveloper && /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }))), /* @__PURE__ */ React__default.createElement(TableBody, null, details.topDevelopers.map((dev, idx) => /* @__PURE__ */ React__default.createElement(
229
229
  TableRow,
230
230
  {
231
231
  key: dev.userId,
232
232
  className: onViewDeveloper ? classes.clickableRow : void 0,
233
233
  onClick: () => onViewDeveloper?.(dev.userId)
234
234
  },
235
- /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, idx + 1)),
236
- /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", style: { fontFamily: "monospace", fontWeight: 600 } }, dev.userId)),
237
- /* @__PURE__ */ React.createElement(TableCell, { style: { minWidth: 140 } }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", style: { fontWeight: 600 } }, (dev.averageProficiency * 10).toFixed(1), "%"), /* @__PURE__ */ React.createElement(
235
+ /* @__PURE__ */ React__default.createElement(TableCell, null, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2", color: "textSecondary" }, idx + 1)),
236
+ /* @__PURE__ */ React__default.createElement(TableCell, null, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2", style: { fontFamily: "monospace", fontWeight: 600 } }, dev.userId)),
237
+ /* @__PURE__ */ React__default.createElement(TableCell, { style: { minWidth: 140 } }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2", style: { fontWeight: 600 } }, (dev.averageProficiency * 10).toFixed(1), "%"), /* @__PURE__ */ React__default.createElement(
238
238
  LinearProgress,
239
239
  {
240
240
  variant: "determinate",
@@ -242,8 +242,8 @@ const RepositoryDetailsView = ({ api, repoName, onBack, onViewDeveloper }) => {
242
242
  className: classes.scoreBar
243
243
  }
244
244
  )),
245
- /* @__PURE__ */ React.createElement(TableCell, { align: "right" }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, dev.skillCount)),
246
- onViewDeveloper && /* @__PURE__ */ React.createElement(TableCell, { align: "right", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React.createElement(Tooltip, { title: "View developer details" }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", onClick: () => onViewDeveloper(dev.userId) }, /* @__PURE__ */ React.createElement(PersonIcon, { fontSize: "small" }))))
245
+ /* @__PURE__ */ React__default.createElement(TableCell, { align: "right" }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2" }, dev.skillCount)),
246
+ onViewDeveloper && /* @__PURE__ */ React__default.createElement(TableCell, { align: "right", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React__default.createElement(Tooltip, { title: "View developer details" }, /* @__PURE__ */ React__default.createElement(IconButton, { size: "small", onClick: () => onViewDeveloper(dev.userId) }, /* @__PURE__ */ React__default.createElement(PersonIcon, { fontSize: "small" }))))
247
247
  )))))))) : null);
248
248
  };
249
249
 
@@ -1 +1 @@
1
- {"version":3,"file":"RepositoriesContent.esm.js","sources":["../../src/components/RepositoriesContent.tsx"],"sourcesContent":["import { useState, useCallback, useEffect } from 'react';\nimport {\n Box,\n Typography,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Paper,\n TextField,\n Chip,\n IconButton,\n Button,\n CircularProgress,\n Tooltip,\n LinearProgress,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport SearchIcon from '@material-ui/icons/Search';\nimport ArrowBackIcon from '@material-ui/icons/ArrowBack';\nimport StorageIcon from '@material-ui/icons/Storage';\nimport PersonIcon from '@material-ui/icons/Person';\nimport { InfoCard, EmptyState } from '@backstage/core-components';\nimport type { DevxpApi } from '../api';\nimport type { RepositoryStats, RepositoryDetails } from '../types';\n\nconst CATEGORY_COLORS: Record<string, string> = {\n 'Frontend Engineering': '#e91e63',\n 'Backend Systems': '#3f51b5',\n 'Database & Data': '#9c27b0',\n 'Infrastructure (DevOps)': '#ff9800',\n 'Mobile Development': '#4caf50',\n 'AI & Machine Learning': '#607d8b',\n 'Testing & QA': '#00bcd4',\n 'Security & Auth': '#f44336',\n 'Distributed Systems': '#795548',\n 'Documentation': '#9e9e9e',\n};\n\nconst useStyles = makeStyles(theme => ({\n header: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n marginBottom: theme.spacing(2),\n },\n searchRow: {\n display: 'flex',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(2),\n alignItems: 'center',\n },\n searchField: {\n flex: 1,\n maxWidth: 400,\n },\n clickableRow: {\n cursor: 'pointer',\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n },\n repoName: {\n fontFamily: 'monospace',\n fontWeight: 600,\n },\n pagination: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: theme.spacing(1, 0),\n marginTop: theme.spacing(1),\n },\n categoryChip: {\n margin: theme.spacing(0.25),\n fontSize: '0.65rem',\n height: 18,\n },\n scoreBar: {\n height: 6,\n borderRadius: 3,\n marginTop: 4,\n },\n sectionTitle: {\n fontWeight: 600,\n marginBottom: theme.spacing(1),\n marginTop: theme.spacing(2),\n },\n statValue: {\n fontWeight: 700,\n fontSize: '1.5rem',\n },\n statLabel: {\n color: theme.palette.text.secondary,\n fontSize: '0.75rem',\n },\n statBox: {\n textAlign: 'center',\n padding: theme.spacing(1.5),\n },\n}));\n\ninterface RepositoriesContentProps {\n api: DevxpApi;\n onViewDeveloper?: (userId: string) => void;\n}\n\nexport const RepositoriesContent = ({ api, onViewDeveloper }: RepositoriesContentProps) => {\n const [view, setView] = useState<'list' | 'details'>('list');\n const [selectedRepo, setSelectedRepo] = useState('');\n\n return (\n <Box>\n {view === 'list' ? (\n <RepositoryList\n api={api}\n onViewRepo={repoName => {\n setSelectedRepo(repoName);\n setView('details');\n }}\n />\n ) : (\n <RepositoryDetailsView\n api={api}\n repoName={selectedRepo}\n onBack={() => setView('list')}\n onViewDeveloper={onViewDeveloper}\n />\n )}\n </Box>\n );\n};\n\n// ─── Repository List ──────────────────────────────────────────────────────────\n\ninterface RepositoryListProps {\n api: DevxpApi;\n onViewRepo: (repoName: string) => void;\n}\n\nconst RepositoryList = ({ api, onViewRepo }: RepositoryListProps) => {\n const classes = useStyles();\n\n const [repositories, setRepositories] = useState<RepositoryStats[]>([]);\n const [totalCount, setTotalCount] = useState(0);\n const [totalPages, setTotalPages] = useState(1);\n const [page, setPage] = useState(1);\n const pageSize = 25;\n\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [searchInput, setSearchInput] = useState('');\n const [appliedSearch, setAppliedSearch] = useState('');\n\n const load = useCallback(\n async (pg: number, search: string) => {\n setLoading(true);\n setError(null);\n try {\n const data = await api.getRepositories({ page: pg, pageSize, searchQuery: search });\n setRepositories(data.repositories);\n setTotalCount(data.totalCount);\n setTotalPages(data.totalPages);\n } catch (e: any) {\n setError(e.message ?? 'Failed to load repositories');\n } finally {\n setLoading(false);\n }\n },\n [api],\n );\n\n useEffect(() => {\n load(page, appliedSearch);\n }, [load, page, appliedSearch]);\n\n const applySearch = () => {\n setPage(1);\n setAppliedSearch(searchInput);\n };\n\n const formatDate = (iso: string) => {\n try {\n return new Date(iso).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n } catch {\n return iso;\n }\n };\n\n return (\n <InfoCard title={`Repositories (${totalCount})`} noPadding={false}>\n <Box className={classes.searchRow}>\n <TextField\n className={classes.searchField}\n size=\"small\"\n variant=\"outlined\"\n label=\"Search repositories\"\n value={searchInput}\n onChange={e => setSearchInput(e.target.value)}\n onKeyDown={e => e.key === 'Enter' && applySearch()}\n InputProps={{\n endAdornment: (\n <IconButton size=\"small\" onClick={applySearch}>\n <SearchIcon fontSize=\"small\" />\n </IconButton>\n ),\n }}\n />\n </Box>\n\n {loading ? (\n <Box display=\"flex\" justifyContent=\"center\" py={4}>\n <CircularProgress />\n </Box>\n ) : error ? (\n <EmptyState missing=\"data\" title=\"Repositories unavailable\" description={error} />\n ) : repositories.length === 0 ? (\n <EmptyState missing=\"data\" title=\"No repositories found\" description=\"Try a different search.\" />\n ) : (\n <>\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Repository</TableCell>\n <TableCell align=\"right\">Developers</TableCell>\n <TableCell align=\"right\">Events</TableCell>\n <TableCell style={{ minWidth: 140 }}>Avg Proficiency</TableCell>\n <TableCell align=\"right\">Last Activity</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {repositories.map(repo => (\n <TableRow\n key={repo.repoName}\n className={classes.clickableRow}\n onClick={() => onViewRepo(repo.repoName)}\n >\n <TableCell>\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <StorageIcon fontSize=\"small\" color=\"action\" />\n <Typography variant=\"body2\" className={classes.repoName}>\n {repo.repoName}\n </Typography>\n </Box>\n </TableCell>\n <TableCell align=\"right\">\n <Typography variant=\"body2\">{repo.developerCount}</Typography>\n </TableCell>\n <TableCell align=\"right\">\n <Typography variant=\"body2\">{repo.eventCount.toLocaleString()}</Typography>\n </TableCell>\n <TableCell style={{ minWidth: 140 }}>\n <Typography variant=\"body2\" style={{ fontWeight: 600 }}>\n {(repo.avgProficiency * 10).toFixed(1)}%\n </Typography>\n <LinearProgress\n variant=\"determinate\"\n value={repo.avgProficiency * 10}\n className={classes.scoreBar}\n />\n </TableCell>\n <TableCell align=\"right\">\n <Typography variant=\"caption\" color=\"textSecondary\">\n {formatDate(repo.lastActivity)}\n </Typography>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n\n <Box className={classes.pagination}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Showing {(page - 1) * pageSize + 1}–{Math.min(page * pageSize, totalCount)} of {totalCount}\n </Typography>\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <Button size=\"small\" disabled={page <= 1} onClick={() => setPage(p => p - 1)}>\n Prev\n </Button>\n <Typography variant=\"caption\">\n {page} / {totalPages}\n </Typography>\n <Button size=\"small\" disabled={page >= totalPages} onClick={() => setPage(p => p + 1)}>\n Next\n </Button>\n </Box>\n </Box>\n </>\n )}\n </InfoCard>\n );\n};\n\n// ─── Repository Details ───────────────────────────────────────────────────────\n\ninterface RepositoryDetailsViewProps {\n api: DevxpApi;\n repoName: string;\n onBack: () => void;\n onViewDeveloper?: (userId: string) => void;\n}\n\nconst RepositoryDetailsView = ({ api, repoName, onBack, onViewDeveloper }: RepositoryDetailsViewProps) => {\n const classes = useStyles();\n\n const [details, setDetails] = useState<RepositoryDetails | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n setLoading(true);\n setError(null);\n api\n .getRepositoryDetails(repoName)\n .then(setDetails)\n .catch((e: any) => setError(e.message ?? 'Failed to load repository details'))\n .finally(() => setLoading(false));\n }, [api, repoName]);\n\n const formatDate = (iso: string) => {\n try {\n return new Date(iso).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n } catch {\n return iso;\n }\n };\n\n return (\n <Box>\n <Box className={classes.header}>\n <Tooltip title=\"Back to repositories\">\n <IconButton size=\"small\" onClick={onBack}>\n <ArrowBackIcon />\n </IconButton>\n </Tooltip>\n <StorageIcon color=\"action\" />\n <Typography variant=\"h6\" className={classes.repoName}>\n {repoName}\n </Typography>\n </Box>\n\n {loading ? (\n <Box display=\"flex\" justifyContent=\"center\" py={6}>\n <CircularProgress />\n </Box>\n ) : error ? (\n <EmptyState missing=\"data\" title=\"Details unavailable\" description={error} />\n ) : details ? (\n <>\n {/* Summary stats */}\n <InfoCard title=\"Overview\">\n <Box display=\"flex\" justifyContent=\"space-around\" flexWrap=\"wrap\">\n <Box className={classes.statBox}>\n <Typography className={classes.statValue}>{details.developerCount}</Typography>\n <Typography className={classes.statLabel}>Developers</Typography>\n </Box>\n <Box className={classes.statBox}>\n <Typography className={classes.statValue}>{details.eventCount.toLocaleString()}</Typography>\n <Typography className={classes.statLabel}>Skill Events</Typography>\n </Box>\n <Box className={classes.statBox}>\n <Typography className={classes.statValue}>\n {(details.avgProficiency * 10).toFixed(1)}%\n </Typography>\n <Typography className={classes.statLabel}>Avg Proficiency</Typography>\n </Box>\n <Box className={classes.statBox}>\n <Typography className={classes.statValue} style={{ fontSize: '1rem' }}>\n {formatDate(details.lastActivity)}\n </Typography>\n <Typography className={classes.statLabel}>Last Activity</Typography>\n </Box>\n </Box>\n </InfoCard>\n\n {/* Category breakdown */}\n {details.categoryBreakdown.length > 0 && (\n <Box mt={2}>\n <InfoCard title=\"Skill Categories\">\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Category</TableCell>\n <TableCell style={{ minWidth: 160 }}>Avg Proficiency</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {details.categoryBreakdown.map(cat => (\n <TableRow key={cat.category}>\n <TableCell>\n <Chip\n label={cat.category}\n size=\"small\"\n className={classes.categoryChip}\n style={{\n backgroundColor: `${CATEGORY_COLORS[cat.category] ?? '#9e9e9e'}20`,\n color: CATEGORY_COLORS[cat.category] ?? '#9e9e9e',\n height: 20,\n }}\n />\n </TableCell>\n <TableCell style={{ minWidth: 160 }}>\n <Typography variant=\"body2\" style={{ fontWeight: 600 }}>\n {(cat.averageProficiency * 10).toFixed(1)}%\n </Typography>\n <LinearProgress\n variant=\"determinate\"\n value={cat.averageProficiency * 10}\n className={classes.scoreBar}\n style={{ backgroundColor: `${CATEGORY_COLORS[cat.category] ?? '#9e9e9e'}30` }}\n />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n </InfoCard>\n </Box>\n )}\n\n {/* Top developers */}\n {details.topDevelopers.length > 0 && (\n <Box mt={2}>\n <InfoCard title=\"Top Developers\">\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>#</TableCell>\n <TableCell>Developer</TableCell>\n <TableCell style={{ minWidth: 140 }}>Avg Proficiency</TableCell>\n <TableCell align=\"right\">Skills</TableCell>\n {onViewDeveloper && <TableCell align=\"right\" />}\n </TableRow>\n </TableHead>\n <TableBody>\n {details.topDevelopers.map((dev, idx) => (\n <TableRow\n key={dev.userId}\n className={onViewDeveloper ? classes.clickableRow : undefined}\n onClick={() => onViewDeveloper?.(dev.userId)}\n >\n <TableCell>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {idx + 1}\n </Typography>\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\" style={{ fontFamily: 'monospace', fontWeight: 600 }}>\n {dev.userId}\n </Typography>\n </TableCell>\n <TableCell style={{ minWidth: 140 }}>\n <Typography variant=\"body2\" style={{ fontWeight: 600 }}>\n {(dev.averageProficiency * 10).toFixed(1)}%\n </Typography>\n <LinearProgress\n variant=\"determinate\"\n value={dev.averageProficiency * 10}\n className={classes.scoreBar}\n />\n </TableCell>\n <TableCell align=\"right\">\n <Typography variant=\"body2\">{dev.skillCount}</Typography>\n </TableCell>\n {onViewDeveloper && (\n <TableCell align=\"right\" onClick={e => e.stopPropagation()}>\n <Tooltip title=\"View developer details\">\n <IconButton size=\"small\" onClick={() => onViewDeveloper(dev.userId)}>\n <PersonIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </TableCell>\n )}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n </InfoCard>\n </Box>\n )}\n </>\n ) : null}\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AA4BA,MAAM,eAAA,GAA0C;AAAA,EAC9C,sBAAA,EAAwB,SAAA;AAAA,EACxB,iBAAA,EAAmB,SAAA;AAAA,EACnB,iBAAA,EAAmB,SAAA;AAAA,EACnB,yBAAA,EAA2B,SAAA;AAAA,EAC3B,oBAAA,EAAsB,SAAA;AAAA,EACtB,uBAAA,EAAyB,SAAA;AAAA,EACzB,cAAA,EAAgB,SAAA;AAAA,EAChB,iBAAA,EAAmB,SAAA;AAAA,EACnB,qBAAA,EAAuB,SAAA;AAAA,EACvB,eAAA,EAAiB;AACnB,CAAA;AAEA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,MAAA,EAAQ;AAAA,IACN,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IACpB,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA,GAC/B;AAAA,EACA,SAAA,EAAW;AAAA,IACT,OAAA,EAAS,MAAA;AAAA,IACT,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IACpB,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC7B,UAAA,EAAY;AAAA,GACd;AAAA,EACA,WAAA,EAAa;AAAA,IACX,IAAA,EAAM,CAAA;AAAA,IACN,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,MAAA,EAAQ,SAAA;AAAA,IACR,SAAA,EAAW;AAAA,MACT,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO;AAAA;AACxC,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR,UAAA,EAAY,WAAA;AAAA,IACZ,UAAA,EAAY;AAAA,GACd;AAAA,EACA,UAAA,EAAY;AAAA,IACV,OAAA,EAAS,MAAA;AAAA,IACT,cAAA,EAAgB,eAAA;AAAA,IAChB,UAAA,EAAY,QAAA;AAAA,IACZ,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,CAAA,EAAG,CAAC,CAAA;AAAA,IAC3B,SAAA,EAAW,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA,GAC5B;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,MAAA,EAAQ,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,IAC1B,QAAA,EAAU,SAAA;AAAA,IACV,MAAA,EAAQ;AAAA,GACV;AAAA,EACA,QAAA,EAAU;AAAA,IACR,MAAA,EAAQ,CAAA;AAAA,IACR,YAAA,EAAc,CAAA;AAAA,IACd,SAAA,EAAW;AAAA,GACb;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,UAAA,EAAY,GAAA;AAAA,IACZ,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC7B,SAAA,EAAW,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA,GAC5B;AAAA,EACA,SAAA,EAAW;AAAA,IACT,UAAA,EAAY,GAAA;AAAA,IACZ,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,SAAA,EAAW;AAAA,IACT,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,SAAA;AAAA,IAC1B,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,OAAA,EAAS;AAAA,IACP,SAAA,EAAW,QAAA;AAAA,IACX,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,GAAG;AAAA;AAE9B,CAAA,CAAE,CAAA;AAOK,MAAM,mBAAA,GAAsB,CAAC,EAAE,GAAA,EAAK,iBAAgB,KAAgC;AACzF,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAA6B,MAAM,CAAA;AAC3D,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,EAAE,CAAA;AAEnD,EAAA,uBACE,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,IAAA,EACE,IAAA,KAAS,MAAA,mBACR,KAAA,CAAA,aAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,YAAY,CAAA,QAAA,KAAY;AACtB,QAAA,eAAA,CAAgB,QAAQ,CAAA;AACxB,QAAA,OAAA,CAAQ,SAAS,CAAA;AAAA,MACnB;AAAA;AAAA,GACF,mBAEA,KAAA,CAAA,aAAA;AAAA,IAAC,qBAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,QAAA,EAAU,YAAA;AAAA,MACV,MAAA,EAAQ,MAAM,OAAA,CAAQ,MAAM,CAAA;AAAA,MAC5B;AAAA;AAAA,GAGN,CAAA;AAEJ;AASA,MAAM,cAAA,GAAiB,CAAC,EAAE,GAAA,EAAK,YAAW,KAA2B;AACnE,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,QAAA,CAA4B,EAAE,CAAA;AACtE,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAS,CAAC,CAAA;AAC9C,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAS,CAAC,CAAA;AAC9C,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,CAAC,CAAA;AAClC,EAAA,MAAM,QAAA,GAAW,EAAA;AAEjB,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AACtD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,EAAE,CAAA;AACjD,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,EAAE,CAAA;AAErD,EAAA,MAAM,IAAA,GAAO,WAAA;AAAA,IACX,OAAO,IAAY,MAAA,KAAmB;AACpC,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,eAAA,CAAgB,EAAE,MAAM,EAAA,EAAI,QAAA,EAAU,WAAA,EAAa,MAAA,EAAQ,CAAA;AAClF,QAAA,eAAA,CAAgB,KAAK,YAAY,CAAA;AACjC,QAAA,aAAA,CAAc,KAAK,UAAU,CAAA;AAC7B,QAAA,aAAA,CAAc,KAAK,UAAU,CAAA;AAAA,MAC/B,SAAS,CAAA,EAAQ;AACf,QAAA,QAAA,CAAS,CAAA,CAAE,WAAW,6BAA6B,CAAA;AAAA,MACrD,CAAA,SAAE;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,GAAG;AAAA,GACN;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAA,CAAK,MAAM,aAAa,CAAA;AAAA,EAC1B,CAAA,EAAG,CAAC,IAAA,EAAM,IAAA,EAAM,aAAa,CAAC,CAAA;AAE9B,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,OAAA,CAAQ,CAAC,CAAA;AACT,IAAA,gBAAA,CAAiB,WAAW,CAAA;AAAA,EAC9B,CAAA;AAEA,EAAA,MAAM,UAAA,GAAa,CAAC,GAAA,KAAgB;AAClC,IAAA,IAAI;AACF,MAAA,OAAO,IAAI,IAAA,CAAK,GAAG,CAAA,CAAE,mBAAmB,KAAA,CAAA,EAAW;AAAA,QACjD,IAAA,EAAM,SAAA;AAAA,QACN,KAAA,EAAO,OAAA;AAAA,QACP,GAAA,EAAK;AAAA,OACN,CAAA;AAAA,IACH,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,GAAA;AAAA,IACT;AAAA,EACF,CAAA;AAEA,EAAA,uBACE,KAAA,CAAA,aAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAO,CAAA,cAAA,EAAiB,UAAU,CAAA,CAAA,CAAA,EAAK,SAAA,EAAW,KAAA,EAAA,kBAC1D,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAA,kBACtB,KAAA,CAAA,aAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,WAAW,OAAA,CAAQ,WAAA;AAAA,MACnB,IAAA,EAAK,OAAA;AAAA,MACL,OAAA,EAAQ,UAAA;AAAA,MACR,KAAA,EAAM,qBAAA;AAAA,MACN,KAAA,EAAO,WAAA;AAAA,MACP,QAAA,EAAU,CAAA,CAAA,KAAK,cAAA,CAAe,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,MAC5C,SAAA,EAAW,CAAA,CAAA,KAAK,CAAA,CAAE,GAAA,KAAQ,WAAW,WAAA,EAAY;AAAA,MACjD,UAAA,EAAY;AAAA,QACV,YAAA,kBACE,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,IAAA,EAAK,OAAA,EAAQ,OAAA,EAAS,WAAA,EAAA,kBAChC,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,QAAA,EAAS,OAAA,EAAQ,CAC/B;AAAA;AAEJ;AAAA,GAEJ,CAAA,EAEC,OAAA,uCACE,GAAA,EAAA,EAAI,OAAA,EAAQ,QAAO,cAAA,EAAe,QAAA,EAAS,IAAI,CAAA,EAAA,kBAC9C,KAAA,CAAA,aAAA,CAAC,sBAAiB,CACpB,CAAA,GACE,wBACF,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAQ,MAAA,EAAO,KAAA,EAAM,0BAAA,EAA2B,WAAA,EAAa,OAAO,CAAA,GAC9E,YAAA,CAAa,WAAW,CAAA,mBAC1B,KAAA,CAAA,aAAA,CAAC,cAAW,OAAA,EAAQ,MAAA,EAAO,OAAM,uBAAA,EAAwB,WAAA,EAAY,2BAA0B,CAAA,mBAE/F,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,sCACG,cAAA,EAAA,EAAe,SAAA,EAAW,OAAO,OAAA,EAAQ,UAAA,EAAA,kBACxC,KAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAM,MAAK,OAAA,EAAA,kBACV,KAAA,CAAA,aAAA,CAAC,iCACC,KAAA,CAAA,aAAA,CAAC,QAAA,EAAA,IAAA,sCACE,SAAA,EAAA,IAAA,EAAU,YAAU,mBACrB,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,OAAM,OAAA,EAAA,EAAQ,YAAU,mBACnC,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,OAAM,OAAA,EAAA,EAAQ,QAAM,mBAC/B,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,OAAO,EAAE,QAAA,EAAU,KAAI,EAAA,EAAG,iBAAe,mBACpD,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,OAAM,OAAA,EAAA,EAAQ,eAAa,CACxC,CACF,CAAA,sCACC,SAAA,EAAA,IAAA,EACE,YAAA,CAAa,IAAI,CAAA,IAAA,qBAChB,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAK,IAAA,CAAK,QAAA;AAAA,MACV,WAAW,OAAA,CAAQ,YAAA;AAAA,MACnB,OAAA,EAAS,MAAM,UAAA,CAAW,IAAA,CAAK,QAAQ;AAAA,KAAA;AAAA,oBAEvC,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,IAAA,kBACC,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,OAAA,EAAQ,MAAA,EAAO,UAAA,EAAW,QAAA,EAAS,KAAA,EAAO,EAAE,GAAA,EAAK,CAAA,sBACpD,KAAA,CAAA,aAAA,CAAC,WAAA,EAAA,EAAY,QAAA,EAAS,OAAA,EAAQ,KAAA,EAAM,QAAA,EAAS,CAAA,kBAC7C,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,SAAA,EAAW,OAAA,CAAQ,QAAA,EAAA,EAC5C,IAAA,CAAK,QACR,CACF,CACF,CAAA;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAM,OAAA,EAAA,kBACf,KAAA,CAAA,aAAA,CAAC,cAAW,OAAA,EAAQ,OAAA,EAAA,EAAS,IAAA,CAAK,cAAe,CACnD,CAAA;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAM,OAAA,EAAA,kBACf,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAA,EAAS,IAAA,CAAK,UAAA,CAAW,cAAA,EAAiB,CAChE,CAAA;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,aAAU,KAAA,EAAO,EAAE,UAAU,GAAA,EAAI,EAAA,kBAChC,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,OAAO,EAAE,UAAA,EAAY,GAAA,EAAI,EAAA,EAAA,CACjD,IAAA,CAAK,cAAA,GAAiB,IAAI,OAAA,CAAQ,CAAC,CAAA,EAAE,GACzC,CAAA,kBACA,KAAA,CAAA,aAAA;AAAA,MAAC,cAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,aAAA;AAAA,QACR,KAAA,EAAO,KAAK,cAAA,GAAiB,EAAA;AAAA,QAC7B,WAAW,OAAA,CAAQ;AAAA;AAAA,KAEvB,CAAA;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAM,OAAA,EAAA,sCACd,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,eAAA,EAAA,EACjC,UAAA,CAAW,IAAA,CAAK,YAAY,CAC/B,CACF;AAAA,GAEH,CACH,CACF,CACF,CAAA,kBAEA,KAAA,CAAA,aAAA,CAAC,OAAI,SAAA,EAAW,OAAA,CAAQ,UAAA,EAAA,kBACtB,KAAA,CAAA,aAAA,CAAC,cAAW,OAAA,EAAQ,SAAA,EAAU,OAAM,eAAA,EAAA,EAAgB,UAAA,EAAA,CACxC,OAAO,CAAA,IAAK,QAAA,GAAW,CAAA,EAAE,QAAA,EAAE,KAAK,GAAA,CAAI,IAAA,GAAO,UAAU,UAAU,CAAA,EAAE,QAAK,UAClF,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,SAAQ,MAAA,EAAO,UAAA,EAAW,UAAS,KAAA,EAAO,EAAE,KAAK,CAAA,EAAE,EAAA,kBACtD,KAAA,CAAA,aAAA,CAAC,MAAA,EAAA,EAAO,MAAK,OAAA,EAAQ,QAAA,EAAU,QAAQ,CAAA,EAAG,OAAA,EAAS,MAAM,OAAA,CAAQ,CAAA,CAAA,KAAK,CAAA,GAAI,CAAC,KAAG,MAE9E,CAAA,sCACC,UAAA,EAAA,EAAW,OAAA,EAAQ,aACjB,IAAA,EAAK,KAAA,EAAI,UACZ,CAAA,sCACC,MAAA,EAAA,EAAO,IAAA,EAAK,SAAQ,QAAA,EAAU,IAAA,IAAQ,YAAY,OAAA,EAAS,MAAM,OAAA,CAAQ,CAAA,CAAA,KAAK,IAAI,CAAC,CAAA,EAAA,EAAG,MAEvF,CACF,CACF,CACF,CAEJ,CAAA;AAEJ,CAAA;AAWA,MAAM,wBAAwB,CAAC,EAAE,KAAK,QAAA,EAAU,MAAA,EAAQ,iBAAgB,KAAkC;AACxG,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAmC,IAAI,CAAA;AACrE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AAEtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAA,GAAA,CACG,qBAAqB,QAAQ,CAAA,CAC7B,KAAK,UAAU,CAAA,CACf,MAAM,CAAC,CAAA,KAAW,SAAS,CAAA,CAAE,OAAA,IAAW,mCAAmC,CAAC,CAAA,CAC5E,QAAQ,MAAM,UAAA,CAAW,KAAK,CAAC,CAAA;AAAA,EACpC,CAAA,EAAG,CAAC,GAAA,EAAK,QAAQ,CAAC,CAAA;AAElB,EAAA,MAAM,UAAA,GAAa,CAAC,GAAA,KAAgB;AAClC,IAAA,IAAI;AACF,MAAA,OAAO,IAAI,IAAA,CAAK,GAAG,CAAA,CAAE,mBAAmB,KAAA,CAAA,EAAW;AAAA,QACjD,IAAA,EAAM,SAAA;AAAA,QACN,KAAA,EAAO,OAAA;AAAA,QACP,GAAA,EAAK;AAAA,OACN,CAAA;AAAA,IACH,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,GAAA;AAAA,IACT;AAAA,EACF,CAAA;AAEA,EAAA,uBACE,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,IAAA,kBACC,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,QAAQ,MAAA,EAAA,kBACtB,KAAA,CAAA,aAAA,CAAC,OAAA,EAAA,EAAQ,KAAA,EAAM,sBAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAC,cAAW,IAAA,EAAK,OAAA,EAAQ,OAAA,EAAS,MAAA,EAAA,kBAChC,KAAA,CAAA,aAAA,CAAC,aAAA,EAAA,IAAc,CACjB,CACF,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,WAAA,EAAA,EAAY,KAAA,EAAM,QAAA,EAAS,mBAC5B,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,IAAA,EAAK,SAAA,EAAW,OAAA,CAAQ,YACzC,QACH,CACF,CAAA,EAEC,OAAA,mBACC,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,SAAQ,MAAA,EAAO,cAAA,EAAe,QAAA,EAAS,EAAA,EAAI,CAAA,EAAA,kBAC9C,KAAA,CAAA,aAAA,CAAC,gBAAA,EAAA,IAAiB,CACpB,CAAA,GACE,KAAA,mBACF,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,MAAA,EAAO,OAAM,qBAAA,EAAsB,WAAA,EAAa,KAAA,EAAO,CAAA,GACzE,OAAA,mBACF,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,sCAEG,QAAA,EAAA,EAAS,KAAA,EAAM,UAAA,EAAA,kBACd,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,OAAA,EAAQ,QAAO,cAAA,EAAe,cAAA,EAAe,QAAA,EAAS,MAAA,EAAA,kBACzD,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,OAAA,EAAA,kBACtB,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAA,EAAY,QAAQ,cAAe,CAAA,kBAClE,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,OAAA,CAAQ,aAAW,YAAU,CACtD,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,QAAQ,OAAA,EAAA,kBACtB,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAA,EAAY,OAAA,CAAQ,UAAA,CAAW,cAAA,EAAiB,CAAA,kBAC/E,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,QAAQ,SAAA,EAAA,EAAW,cAAY,CACxD,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,WAAW,OAAA,CAAQ,OAAA,EAAA,kBACtB,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,OAAA,CAAQ,cAC3B,OAAA,CAAQ,cAAA,GAAiB,EAAA,EAAI,OAAA,CAAQ,CAAC,CAAA,EAAE,GAC5C,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAA,EAAW,iBAAe,CAC3D,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,OAAA,EAAA,sCACrB,UAAA,EAAA,EAAW,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAW,KAAA,EAAO,EAAE,UAAU,MAAA,EAAO,EAAA,EACjE,UAAA,CAAW,OAAA,CAAQ,YAAY,CAClC,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAA,EAAW,eAAa,CACzD,CACF,CACF,CAAA,EAGC,OAAA,CAAQ,iBAAA,CAAkB,MAAA,GAAS,CAAA,wCACjC,GAAA,EAAA,EAAI,EAAA,EAAI,CAAA,EAAA,kBACP,KAAA,CAAA,aAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,sCACd,KAAA,CAAA,aAAA,CAAC,cAAA,EAAA,EAAe,SAAA,EAAW,KAAA,EAAO,OAAA,EAAQ,UAAA,EAAA,kBACxC,KAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAM,IAAA,EAAK,OAAA,EAAA,kBACV,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,IAAA,kBACC,KAAA,CAAA,aAAA,CAAC,QAAA,EAAA,IAAA,sCACE,SAAA,EAAA,IAAA,EAAU,UAAQ,CAAA,kBACnB,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAO,EAAE,QAAA,EAAU,GAAA,EAAI,EAAA,EAAG,iBAAe,CACtD,CACF,mBACA,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,IAAA,EACE,OAAA,CAAQ,iBAAA,CAAkB,GAAA,CAAI,CAAA,GAAA,qBAC7B,KAAA,CAAA,aAAA,CAAC,QAAA,EAAA,EAAS,GAAA,EAAK,GAAA,CAAI,QAAA,EAAA,kBACjB,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,IAAA,kBACC,KAAA,CAAA,aAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,OAAO,GAAA,CAAI,QAAA;AAAA,MACX,IAAA,EAAK,OAAA;AAAA,MACL,WAAW,OAAA,CAAQ,YAAA;AAAA,MACnB,KAAA,EAAO;AAAA,QACL,iBAAiB,CAAA,EAAG,eAAA,CAAgB,GAAA,CAAI,QAAQ,KAAK,SAAS,CAAA,EAAA,CAAA;AAAA,QAC9D,KAAA,EAAO,eAAA,CAAgB,GAAA,CAAI,QAAQ,CAAA,IAAK,SAAA;AAAA,QACxC,MAAA,EAAQ;AAAA;AACV;AAAA,GAEJ,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAO,EAAE,QAAA,EAAU,GAAA,EAAI,EAAA,kBAChC,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAQ,KAAA,EAAO,EAAE,UAAA,EAAY,GAAA,EAAI,EAAA,EAAA,CACjD,GAAA,CAAI,kBAAA,GAAqB,EAAA,EAAI,OAAA,CAAQ,CAAC,CAAA,EAAE,GAC5C,CAAA,kBACA,KAAA,CAAA,aAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,aAAA;AAAA,MACR,KAAA,EAAO,IAAI,kBAAA,GAAqB,EAAA;AAAA,MAChC,WAAW,OAAA,CAAQ,QAAA;AAAA,MACnB,KAAA,EAAO,EAAE,eAAA,EAAiB,CAAA,EAAG,gBAAgB,GAAA,CAAI,QAAQ,CAAA,IAAK,SAAS,CAAA,EAAA,CAAA;AAAK;AAAA,GAEhF,CACF,CACD,CACH,CACF,CACF,CACF,CACF,CAAA,EAID,QAAQ,aAAA,CAAc,MAAA,GAAS,CAAA,oBAC9B,KAAA,CAAA,aAAA,CAAC,OAAI,EAAA,EAAI,CAAA,EAAA,kBACP,KAAA,CAAA,aAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,gBAAA,EAAA,kBACd,KAAA,CAAA,aAAA,CAAC,cAAA,EAAA,EAAe,WAAW,KAAA,EAAO,OAAA,EAAQ,UAAA,EAAA,kBACxC,KAAA,CAAA,aAAA,CAAC,SAAM,IAAA,EAAK,OAAA,EAAA,kBACV,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,IAAA,sCACE,QAAA,EAAA,IAAA,kBACC,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,IAAA,EAAU,GAAC,CAAA,kBACZ,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,IAAA,EAAU,WAAS,mBACpB,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAO,EAAE,UAAU,GAAA,EAAI,EAAA,EAAG,iBAAe,CAAA,sCACnD,SAAA,EAAA,EAAU,KAAA,EAAM,OAAA,EAAA,EAAQ,QAAM,GAC9B,eAAA,oBAAmB,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAM,SAAQ,CAC/C,CACF,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,iBACE,OAAA,CAAQ,aAAA,CAAc,GAAA,CAAI,CAAC,KAAK,GAAA,qBAC/B,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAK,GAAA,CAAI,MAAA;AAAA,MACT,SAAA,EAAW,eAAA,GAAkB,OAAA,CAAQ,YAAA,GAAe,MAAA;AAAA,MACpD,OAAA,EAAS,MAAM,eAAA,GAAkB,GAAA,CAAI,MAAM;AAAA,KAAA;AAAA,oBAE3C,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,IAAA,kBACC,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAQ,KAAA,EAAM,eAAA,EAAA,EAC/B,GAAA,GAAM,CACT,CACF,CAAA;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,IAAA,kBACC,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAQ,OAAA,EAAQ,KAAA,EAAO,EAAE,UAAA,EAAY,aAAa,UAAA,EAAY,GAAA,EAAI,EAAA,EAC3E,GAAA,CAAI,MACP,CACF,CAAA;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,aAAU,KAAA,EAAO,EAAE,UAAU,GAAA,EAAI,EAAA,kBAChC,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,OAAO,EAAE,UAAA,EAAY,GAAA,EAAI,EAAA,EAAA,CACjD,GAAA,CAAI,kBAAA,GAAqB,IAAI,OAAA,CAAQ,CAAC,CAAA,EAAE,GAC5C,CAAA,kBACA,KAAA,CAAA,aAAA;AAAA,MAAC,cAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,aAAA;AAAA,QACR,KAAA,EAAO,IAAI,kBAAA,GAAqB,EAAA;AAAA,QAChC,WAAW,OAAA,CAAQ;AAAA;AAAA,KAEvB,CAAA;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAM,OAAA,EAAA,kBACf,KAAA,CAAA,aAAA,CAAC,cAAW,OAAA,EAAQ,OAAA,EAAA,EAAS,GAAA,CAAI,UAAW,CAC9C,CAAA;AAAA,IACC,eAAA,oBACC,KAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAM,OAAA,EAAQ,OAAA,EAAS,CAAA,CAAA,KAAK,CAAA,CAAE,eAAA,EAAgB,EAAA,kBACvD,KAAA,CAAA,aAAA,CAAC,OAAA,EAAA,EAAQ,OAAM,wBAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,IAAA,EAAK,OAAA,EAAQ,OAAA,EAAS,MAAM,eAAA,CAAgB,GAAA,CAAI,MAAM,CAAA,EAAA,kBAChE,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,QAAA,EAAS,OAAA,EAAQ,CAC/B,CACF,CACF;AAAA,GAGL,CACH,CACF,CACF,CACF,CACF,CAEJ,IACE,IACN,CAAA;AAEJ,CAAA;;;;"}
1
+ {"version":3,"file":"RepositoriesContent.esm.js","sources":["../../src/components/RepositoriesContent.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect } from 'react';\nimport {\n Box,\n Typography,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Paper,\n TextField,\n Chip,\n IconButton,\n Button,\n CircularProgress,\n Tooltip,\n LinearProgress,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport SearchIcon from '@material-ui/icons/Search';\nimport ArrowBackIcon from '@material-ui/icons/ArrowBack';\nimport StorageIcon from '@material-ui/icons/Storage';\nimport PersonIcon from '@material-ui/icons/Person';\nimport { InfoCard, EmptyState } from '@backstage/core-components';\nimport type { DevxpApi } from '../api';\nimport type { RepositoryStats, RepositoryDetails } from '../types';\n\nconst CATEGORY_COLORS: Record<string, string> = {\n 'Frontend Engineering': '#e91e63',\n 'Backend Systems': '#3f51b5',\n 'Database & Data': '#9c27b0',\n 'Infrastructure (DevOps)': '#ff9800',\n 'Mobile Development': '#4caf50',\n 'AI & Machine Learning': '#607d8b',\n 'Testing & QA': '#00bcd4',\n 'Security & Auth': '#f44336',\n 'Distributed Systems': '#795548',\n 'Documentation': '#9e9e9e',\n};\n\nconst useStyles = makeStyles(theme => ({\n header: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n marginBottom: theme.spacing(2),\n },\n searchRow: {\n display: 'flex',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(2),\n alignItems: 'center',\n },\n searchField: {\n flex: 1,\n maxWidth: 400,\n },\n clickableRow: {\n cursor: 'pointer',\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n },\n repoName: {\n fontFamily: 'monospace',\n fontWeight: 600,\n },\n pagination: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: theme.spacing(1, 0),\n marginTop: theme.spacing(1),\n },\n categoryChip: {\n margin: theme.spacing(0.25),\n fontSize: '0.65rem',\n height: 18,\n },\n scoreBar: {\n height: 6,\n borderRadius: 3,\n marginTop: 4,\n },\n sectionTitle: {\n fontWeight: 600,\n marginBottom: theme.spacing(1),\n marginTop: theme.spacing(2),\n },\n statValue: {\n fontWeight: 700,\n fontSize: '1.5rem',\n },\n statLabel: {\n color: theme.palette.text.secondary,\n fontSize: '0.75rem',\n },\n statBox: {\n textAlign: 'center',\n padding: theme.spacing(1.5),\n },\n}));\n\ninterface RepositoriesContentProps {\n api: DevxpApi;\n onViewDeveloper?: (userId: string) => void;\n}\n\nexport const RepositoriesContent = ({ api, onViewDeveloper }: RepositoriesContentProps) => {\n const [view, setView] = useState<'list' | 'details'>('list');\n const [selectedRepo, setSelectedRepo] = useState('');\n\n return (\n <Box>\n {view === 'list' ? (\n <RepositoryList\n api={api}\n onViewRepo={repoName => {\n setSelectedRepo(repoName);\n setView('details');\n }}\n />\n ) : (\n <RepositoryDetailsView\n api={api}\n repoName={selectedRepo}\n onBack={() => setView('list')}\n onViewDeveloper={onViewDeveloper}\n />\n )}\n </Box>\n );\n};\n\n// ─── Repository List ──────────────────────────────────────────────────────────\n\ninterface RepositoryListProps {\n api: DevxpApi;\n onViewRepo: (repoName: string) => void;\n}\n\nconst RepositoryList = ({ api, onViewRepo }: RepositoryListProps) => {\n const classes = useStyles();\n\n const [repositories, setRepositories] = useState<RepositoryStats[]>([]);\n const [totalCount, setTotalCount] = useState(0);\n const [totalPages, setTotalPages] = useState(1);\n const [page, setPage] = useState(1);\n const pageSize = 25;\n\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [searchInput, setSearchInput] = useState('');\n const [appliedSearch, setAppliedSearch] = useState('');\n\n const load = useCallback(\n async (pg: number, search: string) => {\n setLoading(true);\n setError(null);\n try {\n const data = await api.getRepositories({ page: pg, pageSize, searchQuery: search });\n setRepositories(data.repositories);\n setTotalCount(data.totalCount);\n setTotalPages(data.totalPages);\n } catch (e: any) {\n setError(e.message ?? 'Failed to load repositories');\n } finally {\n setLoading(false);\n }\n },\n [api],\n );\n\n useEffect(() => {\n load(page, appliedSearch);\n }, [load, page, appliedSearch]);\n\n const applySearch = () => {\n setPage(1);\n setAppliedSearch(searchInput);\n };\n\n const formatDate = (iso: string) => {\n try {\n return new Date(iso).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n } catch {\n return iso;\n }\n };\n\n return (\n <InfoCard title={`Repositories (${totalCount})`} noPadding={false}>\n <Box className={classes.searchRow}>\n <TextField\n className={classes.searchField}\n size=\"small\"\n variant=\"outlined\"\n label=\"Search repositories\"\n value={searchInput}\n onChange={e => setSearchInput(e.target.value)}\n onKeyDown={e => e.key === 'Enter' && applySearch()}\n InputProps={{\n endAdornment: (\n <IconButton size=\"small\" onClick={applySearch}>\n <SearchIcon fontSize=\"small\" />\n </IconButton>\n ),\n }}\n />\n </Box>\n\n {loading ? (\n <Box display=\"flex\" justifyContent=\"center\" py={4}>\n <CircularProgress />\n </Box>\n ) : error ? (\n <EmptyState missing=\"data\" title=\"Repositories unavailable\" description={error} />\n ) : repositories.length === 0 ? (\n <EmptyState missing=\"data\" title=\"No repositories found\" description=\"Try a different search.\" />\n ) : (\n <React.Fragment>\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Repository</TableCell>\n <TableCell align=\"right\">Developers</TableCell>\n <TableCell align=\"right\">Events</TableCell>\n <TableCell style={{ minWidth: 140 }}>Avg Proficiency</TableCell>\n <TableCell align=\"right\">Last Activity</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {repositories.map(repo => (\n <TableRow\n key={repo.repoName}\n className={classes.clickableRow}\n onClick={() => onViewRepo(repo.repoName)}\n >\n <TableCell>\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <StorageIcon fontSize=\"small\" color=\"action\" />\n <Typography variant=\"body2\" className={classes.repoName}>\n {repo.repoName}\n </Typography>\n </Box>\n </TableCell>\n <TableCell align=\"right\">\n <Typography variant=\"body2\">{repo.developerCount}</Typography>\n </TableCell>\n <TableCell align=\"right\">\n <Typography variant=\"body2\">{repo.eventCount.toLocaleString()}</Typography>\n </TableCell>\n <TableCell style={{ minWidth: 140 }}>\n <Typography variant=\"body2\" style={{ fontWeight: 600 }}>\n {(repo.avgProficiency * 10).toFixed(1)}%\n </Typography>\n <LinearProgress\n variant=\"determinate\"\n value={repo.avgProficiency * 10}\n className={classes.scoreBar}\n />\n </TableCell>\n <TableCell align=\"right\">\n <Typography variant=\"caption\" color=\"textSecondary\">\n {formatDate(repo.lastActivity)}\n </Typography>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n\n <Box className={classes.pagination}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Showing {(page - 1) * pageSize + 1}–{Math.min(page * pageSize, totalCount)} of {totalCount}\n </Typography>\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <Button size=\"small\" disabled={page <= 1} onClick={() => setPage(p => p - 1)}>\n Prev\n </Button>\n <Typography variant=\"caption\">\n {page} / {totalPages}\n </Typography>\n <Button size=\"small\" disabled={page >= totalPages} onClick={() => setPage(p => p + 1)}>\n Next\n </Button>\n </Box>\n </Box>\n </React.Fragment>\n )}\n </InfoCard>\n );\n};\n\n// ─── Repository Details ───────────────────────────────────────────────────────\n\ninterface RepositoryDetailsViewProps {\n api: DevxpApi;\n repoName: string;\n onBack: () => void;\n onViewDeveloper?: (userId: string) => void;\n}\n\nconst RepositoryDetailsView = ({ api, repoName, onBack, onViewDeveloper }: RepositoryDetailsViewProps) => {\n const classes = useStyles();\n\n const [details, setDetails] = useState<RepositoryDetails | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n setLoading(true);\n setError(null);\n api\n .getRepositoryDetails(repoName)\n .then(setDetails)\n .catch((e: any) => setError(e.message ?? 'Failed to load repository details'))\n .finally(() => setLoading(false));\n }, [api, repoName]);\n\n const formatDate = (iso: string) => {\n try {\n return new Date(iso).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n } catch {\n return iso;\n }\n };\n\n return (\n <Box>\n <Box className={classes.header}>\n <Tooltip title=\"Back to repositories\">\n <IconButton size=\"small\" onClick={onBack}>\n <ArrowBackIcon />\n </IconButton>\n </Tooltip>\n <StorageIcon color=\"action\" />\n <Typography variant=\"h6\" className={classes.repoName}>\n {repoName}\n </Typography>\n </Box>\n\n {loading ? (\n <Box display=\"flex\" justifyContent=\"center\" py={6}>\n <CircularProgress />\n </Box>\n ) : error ? (\n <EmptyState missing=\"data\" title=\"Details unavailable\" description={error} />\n ) : details ? (\n <React.Fragment>\n {/* Summary stats */}\n <InfoCard title=\"Overview\">\n <Box display=\"flex\" justifyContent=\"space-around\" flexWrap=\"wrap\">\n <Box className={classes.statBox}>\n <Typography className={classes.statValue}>{details.developerCount}</Typography>\n <Typography className={classes.statLabel}>Developers</Typography>\n </Box>\n <Box className={classes.statBox}>\n <Typography className={classes.statValue}>{details.eventCount.toLocaleString()}</Typography>\n <Typography className={classes.statLabel}>Skill Events</Typography>\n </Box>\n <Box className={classes.statBox}>\n <Typography className={classes.statValue}>\n {(details.avgProficiency * 10).toFixed(1)}%\n </Typography>\n <Typography className={classes.statLabel}>Avg Proficiency</Typography>\n </Box>\n <Box className={classes.statBox}>\n <Typography className={classes.statValue} style={{ fontSize: '1rem' }}>\n {formatDate(details.lastActivity)}\n </Typography>\n <Typography className={classes.statLabel}>Last Activity</Typography>\n </Box>\n </Box>\n </InfoCard>\n\n {/* Category breakdown */}\n {details.categoryBreakdown.length > 0 && (\n <Box mt={2}>\n <InfoCard title=\"Skill Categories\">\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Category</TableCell>\n <TableCell style={{ minWidth: 160 }}>Avg Proficiency</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {details.categoryBreakdown.map(cat => (\n <TableRow key={cat.category}>\n <TableCell>\n <Chip\n label={cat.category}\n size=\"small\"\n className={classes.categoryChip}\n style={{\n backgroundColor: `${CATEGORY_COLORS[cat.category] ?? '#9e9e9e'}20`,\n color: CATEGORY_COLORS[cat.category] ?? '#9e9e9e',\n height: 20,\n }}\n />\n </TableCell>\n <TableCell style={{ minWidth: 160 }}>\n <Typography variant=\"body2\" style={{ fontWeight: 600 }}>\n {(cat.averageProficiency * 10).toFixed(1)}%\n </Typography>\n <LinearProgress\n variant=\"determinate\"\n value={cat.averageProficiency * 10}\n className={classes.scoreBar}\n style={{ backgroundColor: `${CATEGORY_COLORS[cat.category] ?? '#9e9e9e'}30` }}\n />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n </InfoCard>\n </Box>\n )}\n\n {/* Top developers */}\n {details.topDevelopers.length > 0 && (\n <Box mt={2}>\n <InfoCard title=\"Top Developers\">\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>#</TableCell>\n <TableCell>Developer</TableCell>\n <TableCell style={{ minWidth: 140 }}>Avg Proficiency</TableCell>\n <TableCell align=\"right\">Skills</TableCell>\n {onViewDeveloper && <TableCell align=\"right\" />}\n </TableRow>\n </TableHead>\n <TableBody>\n {details.topDevelopers.map((dev, idx) => (\n <TableRow\n key={dev.userId}\n className={onViewDeveloper ? classes.clickableRow : undefined}\n onClick={() => onViewDeveloper?.(dev.userId)}\n >\n <TableCell>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {idx + 1}\n </Typography>\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\" style={{ fontFamily: 'monospace', fontWeight: 600 }}>\n {dev.userId}\n </Typography>\n </TableCell>\n <TableCell style={{ minWidth: 140 }}>\n <Typography variant=\"body2\" style={{ fontWeight: 600 }}>\n {(dev.averageProficiency * 10).toFixed(1)}%\n </Typography>\n <LinearProgress\n variant=\"determinate\"\n value={dev.averageProficiency * 10}\n className={classes.scoreBar}\n />\n </TableCell>\n <TableCell align=\"right\">\n <Typography variant=\"body2\">{dev.skillCount}</Typography>\n </TableCell>\n {onViewDeveloper && (\n <TableCell align=\"right\" onClick={e => e.stopPropagation()}>\n <Tooltip title=\"View developer details\">\n <IconButton size=\"small\" onClick={() => onViewDeveloper(dev.userId)}>\n <PersonIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </TableCell>\n )}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n </InfoCard>\n </Box>\n )}\n </React.Fragment>\n ) : null}\n </Box>\n );\n};\n"],"names":["React"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import React__default from 'react';
1
2
  import { makeStyles } from '@material-ui/core/styles';
2
3
 
3
4
  const CATEGORIES = [
@@ -97,14 +98,14 @@ const SpiderChart = ({ primary, compare, maxValue = 10 }) => {
97
98
  const primaryValues = CATEGORIES.map((cat) => Math.max(primaryMap.get(cat) ?? 0, 1));
98
99
  const compareValues = compareMap ? CATEGORIES.map((cat) => Math.max(compareMap.get(cat) ?? 0, 1)) : null;
99
100
  const step = 360 / CATEGORIES.length;
100
- return /* @__PURE__ */ React.createElement(
101
+ return /* @__PURE__ */ React__default.createElement(
101
102
  "svg",
102
103
  {
103
104
  viewBox: `0 0 ${SVG_SIZE} ${SVG_SIZE}`,
104
105
  className: classes.svg,
105
106
  "aria-label": "Skill radar chart"
106
107
  },
107
- Array.from({ length: NUM_LEVELS }, (_, i) => i + 1).map((level) => /* @__PURE__ */ React.createElement(
108
+ Array.from({ length: NUM_LEVELS }, (_, i) => i + 1).map((level) => /* @__PURE__ */ React__default.createElement(
108
109
  "polygon",
109
110
  {
110
111
  key: level,
@@ -114,7 +115,7 @@ const SpiderChart = ({ primary, compare, maxValue = 10 }) => {
114
115
  )),
115
116
  CATEGORIES.map((_, i) => {
116
117
  const outer = polarToCartesian(CENTER_X, CENTER_Y, MAX_RADIUS, i * step);
117
- return /* @__PURE__ */ React.createElement(
118
+ return /* @__PURE__ */ React__default.createElement(
118
119
  "line",
119
120
  {
120
121
  key: i,
@@ -126,7 +127,7 @@ const SpiderChart = ({ primary, compare, maxValue = 10 }) => {
126
127
  }
127
128
  );
128
129
  }),
129
- compareValues && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
130
+ compareValues && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
130
131
  "polygon",
131
132
  {
132
133
  points: buildPolygon(compareValues, maxValue),
@@ -135,9 +136,9 @@ const SpiderChart = ({ primary, compare, maxValue = 10 }) => {
135
136
  ), compareValues.map((v, i) => {
136
137
  const r = Math.max(v, 0) / maxValue * MAX_RADIUS;
137
138
  const p = polarToCartesian(CENTER_X, CENTER_Y, r, i * step);
138
- return /* @__PURE__ */ React.createElement("circle", { key: i, cx: p.x, cy: p.y, r: 3, className: classes.comparePoint });
139
+ return /* @__PURE__ */ React__default.createElement("circle", { key: i, cx: p.x, cy: p.y, r: 3, className: classes.comparePoint });
139
140
  })),
140
- /* @__PURE__ */ React.createElement(
141
+ /* @__PURE__ */ React__default.createElement(
141
142
  "polygon",
142
143
  {
143
144
  points: buildPolygon(primaryValues, maxValue),
@@ -147,14 +148,14 @@ const SpiderChart = ({ primary, compare, maxValue = 10 }) => {
147
148
  primaryValues.map((v, i) => {
148
149
  const r = Math.max(v, 0) / maxValue * MAX_RADIUS;
149
150
  const p = polarToCartesian(CENTER_X, CENTER_Y, r, i * step);
150
- return /* @__PURE__ */ React.createElement("circle", { key: i, cx: p.x, cy: p.y, r: 4, className: classes.dataPoint });
151
+ return /* @__PURE__ */ React__default.createElement("circle", { key: i, cx: p.x, cy: p.y, r: 4, className: classes.dataPoint });
151
152
  }),
152
153
  CATEGORIES.map((cat, i) => {
153
154
  const pos = polarToCartesian(CENTER_X, CENTER_Y, LABEL_RADIUS, i * step);
154
155
  let anchor = "middle";
155
156
  if (pos.x < CENTER_X - 10) anchor = "end";
156
157
  else if (pos.x > CENTER_X + 10) anchor = "start";
157
- return /* @__PURE__ */ React.createElement(
158
+ return /* @__PURE__ */ React__default.createElement(
158
159
  "text",
159
160
  {
160
161
  key: cat,
@@ -1 +1 @@
1
- {"version":3,"file":"SpiderChart.esm.js","sources":["../../src/components/SpiderChart.tsx"],"sourcesContent":["import { makeStyles } from '@material-ui/core/styles';\n\nconst CATEGORIES = [\n 'Frontend Engineering',\n 'Backend Systems',\n 'Database & Data',\n 'Infrastructure (DevOps)',\n 'Mobile Development',\n 'AI & Machine Learning',\n 'Testing & QA',\n 'Security & Auth',\n 'Distributed Systems',\n 'Documentation',\n];\n\nconst SHORT_NAMES: Record<string, string> = {\n 'Frontend Engineering': 'Frontend',\n 'Backend Systems': 'Backend',\n 'Database & Data': 'Database',\n 'Infrastructure (DevOps)': 'DevOps',\n 'Mobile Development': 'Mobile',\n 'AI & Machine Learning': 'AI/ML',\n 'Testing & QA': 'Testing',\n 'Security & Auth': 'Security',\n 'Distributed Systems': 'Distributed',\n 'Documentation': 'Docs',\n};\n\nconst CENTER_X = 180;\nconst CENTER_Y = 180;\nconst MAX_RADIUS = 130;\nconst LABEL_RADIUS = 155;\nconst NUM_LEVELS = 5;\nconst SVG_SIZE = 360;\n\nfunction polarToCartesian(cx: number, cy: number, r: number, angleDeg: number) {\n const rad = ((angleDeg - 90) * Math.PI) / 180;\n return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) };\n}\n\nfunction buildPolygon(values: number[], maxVal: number): string {\n const step = 360 / values.length;\n const pts = values.map((v, i) => {\n const r = (Math.max(v, 0) / maxVal) * MAX_RADIUS;\n const p = polarToCartesian(CENTER_X, CENTER_Y, r, i * step);\n return `${p.x},${p.y}`;\n });\n return pts.join(' ');\n}\n\nfunction buildGridPolygon(level: number): string {\n const r = (level / NUM_LEVELS) * MAX_RADIUS;\n const step = 360 / CATEGORIES.length;\n return CATEGORIES.map((_, i) => {\n const p = polarToCartesian(CENTER_X, CENTER_Y, r, i * step);\n return `${p.x},${p.y}`;\n }).join(' ');\n}\n\nconst useStyles = makeStyles(theme => ({\n svg: {\n width: '100%',\n maxWidth: SVG_SIZE,\n display: 'block',\n margin: '0 auto',\n },\n gridPolygon: {\n fill: 'none',\n stroke: theme.palette.divider,\n strokeWidth: 1,\n },\n radialLine: {\n stroke: theme.palette.divider,\n strokeWidth: 1,\n },\n dataPolygon: {\n fill: 'rgba(63, 81, 181, 0.18)',\n stroke: '#3f51b5',\n strokeWidth: 2,\n },\n comparePolygon: {\n fill: 'rgba(233, 30, 99, 0.12)',\n stroke: '#e91e63',\n strokeWidth: 2,\n },\n dataPoint: {\n fill: '#3f51b5',\n },\n comparePoint: {\n fill: '#e91e63',\n },\n label: {\n fontSize: 10,\n fontWeight: 600,\n fill: theme.palette.text.primary,\n dominantBaseline: 'middle',\n },\n}));\n\nexport interface SpiderChartData {\n /** Map of category name → proficiency value (0-10 scale) */\n categoryAverages: Array<{ category: string; averageProficiency: number }>;\n}\n\ninterface SpiderChartProps {\n primary: SpiderChartData;\n /** Optional second dataset shown as overlay (e.g. platform average or second developer) */\n compare?: SpiderChartData;\n maxValue?: number;\n}\n\nexport const SpiderChart = ({ primary, compare, maxValue = 10 }: SpiderChartProps) => {\n const classes = useStyles();\n\n const primaryMap = new Map(primary.categoryAverages.map(c => [c.category, c.averageProficiency]));\n const compareMap = compare\n ? new Map(compare.categoryAverages.map(c => [c.category, c.averageProficiency]))\n : null;\n\n const primaryValues = CATEGORIES.map(cat => Math.max(primaryMap.get(cat) ?? 0, 1));\n const compareValues = compareMap ? CATEGORIES.map(cat => Math.max(compareMap.get(cat) ?? 0, 1)) : null;\n\n const step = 360 / CATEGORIES.length;\n\n return (\n <svg\n viewBox={`0 0 ${SVG_SIZE} ${SVG_SIZE}`}\n className={classes.svg}\n aria-label=\"Skill radar chart\"\n >\n {/* Grid */}\n {Array.from({ length: NUM_LEVELS }, (_, i) => i + 1).map(level => (\n <polygon\n key={level}\n points={buildGridPolygon(level)}\n className={classes.gridPolygon}\n />\n ))}\n\n {/* Radial lines */}\n {CATEGORIES.map((_, i) => {\n const outer = polarToCartesian(CENTER_X, CENTER_Y, MAX_RADIUS, i * step);\n return (\n <line\n key={i}\n x1={CENTER_X}\n y1={CENTER_Y}\n x2={outer.x}\n y2={outer.y}\n className={classes.radialLine}\n />\n );\n })}\n\n {/* Compare overlay */}\n {compareValues && (\n <>\n <polygon\n points={buildPolygon(compareValues, maxValue)}\n className={classes.comparePolygon}\n />\n {compareValues.map((v, i) => {\n const r = (Math.max(v, 0) / maxValue) * MAX_RADIUS;\n const p = polarToCartesian(CENTER_X, CENTER_Y, r, i * step);\n return <circle key={i} cx={p.x} cy={p.y} r={3} className={classes.comparePoint} />;\n })}\n </>\n )}\n\n {/* Primary data */}\n <polygon\n points={buildPolygon(primaryValues, maxValue)}\n className={classes.dataPolygon}\n />\n {primaryValues.map((v, i) => {\n const r = (Math.max(v, 0) / maxValue) * MAX_RADIUS;\n const p = polarToCartesian(CENTER_X, CENTER_Y, r, i * step);\n return <circle key={i} cx={p.x} cy={p.y} r={4} className={classes.dataPoint} />;\n })}\n\n {/* Category labels */}\n {CATEGORIES.map((cat, i) => {\n const pos = polarToCartesian(CENTER_X, CENTER_Y, LABEL_RADIUS, i * step);\n let anchor: 'inherit' | 'end' | 'start' | 'middle' = 'middle';\n if (pos.x < CENTER_X - 10) anchor = 'end';\n else if (pos.x > CENTER_X + 10) anchor = 'start';\n return (\n <text\n key={cat}\n x={pos.x}\n y={pos.y}\n textAnchor={anchor}\n className={classes.label}\n >\n {SHORT_NAMES[cat] ?? cat}\n </text>\n );\n })}\n </svg>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SpiderChart.esm.js","sources":["../../src/components/SpiderChart.tsx"],"sourcesContent":["import React from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\n\nconst CATEGORIES = [\n 'Frontend Engineering',\n 'Backend Systems',\n 'Database & Data',\n 'Infrastructure (DevOps)',\n 'Mobile Development',\n 'AI & Machine Learning',\n 'Testing & QA',\n 'Security & Auth',\n 'Distributed Systems',\n 'Documentation',\n];\n\nconst SHORT_NAMES: Record<string, string> = {\n 'Frontend Engineering': 'Frontend',\n 'Backend Systems': 'Backend',\n 'Database & Data': 'Database',\n 'Infrastructure (DevOps)': 'DevOps',\n 'Mobile Development': 'Mobile',\n 'AI & Machine Learning': 'AI/ML',\n 'Testing & QA': 'Testing',\n 'Security & Auth': 'Security',\n 'Distributed Systems': 'Distributed',\n 'Documentation': 'Docs',\n};\n\nconst CENTER_X = 180;\nconst CENTER_Y = 180;\nconst MAX_RADIUS = 130;\nconst LABEL_RADIUS = 155;\nconst NUM_LEVELS = 5;\nconst SVG_SIZE = 360;\n\nfunction polarToCartesian(cx: number, cy: number, r: number, angleDeg: number) {\n const rad = ((angleDeg - 90) * Math.PI) / 180;\n return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) };\n}\n\nfunction buildPolygon(values: number[], maxVal: number): string {\n const step = 360 / values.length;\n const pts = values.map((v, i) => {\n const r = (Math.max(v, 0) / maxVal) * MAX_RADIUS;\n const p = polarToCartesian(CENTER_X, CENTER_Y, r, i * step);\n return `${p.x},${p.y}`;\n });\n return pts.join(' ');\n}\n\nfunction buildGridPolygon(level: number): string {\n const r = (level / NUM_LEVELS) * MAX_RADIUS;\n const step = 360 / CATEGORIES.length;\n return CATEGORIES.map((_, i) => {\n const p = polarToCartesian(CENTER_X, CENTER_Y, r, i * step);\n return `${p.x},${p.y}`;\n }).join(' ');\n}\n\nconst useStyles = makeStyles(theme => ({\n svg: {\n width: '100%',\n maxWidth: SVG_SIZE,\n display: 'block',\n margin: '0 auto',\n },\n gridPolygon: {\n fill: 'none',\n stroke: theme.palette.divider,\n strokeWidth: 1,\n },\n radialLine: {\n stroke: theme.palette.divider,\n strokeWidth: 1,\n },\n dataPolygon: {\n fill: 'rgba(63, 81, 181, 0.18)',\n stroke: '#3f51b5',\n strokeWidth: 2,\n },\n comparePolygon: {\n fill: 'rgba(233, 30, 99, 0.12)',\n stroke: '#e91e63',\n strokeWidth: 2,\n },\n dataPoint: {\n fill: '#3f51b5',\n },\n comparePoint: {\n fill: '#e91e63',\n },\n label: {\n fontSize: 10,\n fontWeight: 600,\n fill: theme.palette.text.primary,\n dominantBaseline: 'middle',\n },\n}));\n\nexport interface SpiderChartData {\n /** Map of category name → proficiency value (0-10 scale) */\n categoryAverages: Array<{ category: string; averageProficiency: number }>;\n}\n\ninterface SpiderChartProps {\n primary: SpiderChartData;\n /** Optional second dataset shown as overlay (e.g. platform average or second developer) */\n compare?: SpiderChartData;\n maxValue?: number;\n}\n\nexport const SpiderChart = ({ primary, compare, maxValue = 10 }: SpiderChartProps) => {\n const classes = useStyles();\n\n const primaryMap = new Map(primary.categoryAverages.map(c => [c.category, c.averageProficiency]));\n const compareMap = compare\n ? new Map(compare.categoryAverages.map(c => [c.category, c.averageProficiency]))\n : null;\n\n const primaryValues = CATEGORIES.map(cat => Math.max(primaryMap.get(cat) ?? 0, 1));\n const compareValues = compareMap ? CATEGORIES.map(cat => Math.max(compareMap.get(cat) ?? 0, 1)) : null;\n\n const step = 360 / CATEGORIES.length;\n\n return (\n <svg\n viewBox={`0 0 ${SVG_SIZE} ${SVG_SIZE}`}\n className={classes.svg}\n aria-label=\"Skill radar chart\"\n >\n {/* Grid */}\n {Array.from({ length: NUM_LEVELS }, (_, i) => i + 1).map(level => (\n <polygon\n key={level}\n points={buildGridPolygon(level)}\n className={classes.gridPolygon}\n />\n ))}\n\n {/* Radial lines */}\n {CATEGORIES.map((_, i) => {\n const outer = polarToCartesian(CENTER_X, CENTER_Y, MAX_RADIUS, i * step);\n return (\n <line\n key={i}\n x1={CENTER_X}\n y1={CENTER_Y}\n x2={outer.x}\n y2={outer.y}\n className={classes.radialLine}\n />\n );\n })}\n\n {/* Compare overlay */}\n {compareValues && (\n <React.Fragment>\n <polygon\n points={buildPolygon(compareValues, maxValue)}\n className={classes.comparePolygon}\n />\n {compareValues.map((v, i) => {\n const r = (Math.max(v, 0) / maxValue) * MAX_RADIUS;\n const p = polarToCartesian(CENTER_X, CENTER_Y, r, i * step);\n return <circle key={i} cx={p.x} cy={p.y} r={3} className={classes.comparePoint} />;\n })}\n </React.Fragment>\n )}\n\n {/* Primary data */}\n <polygon\n points={buildPolygon(primaryValues, maxValue)}\n className={classes.dataPolygon}\n />\n {primaryValues.map((v, i) => {\n const r = (Math.max(v, 0) / maxValue) * MAX_RADIUS;\n const p = polarToCartesian(CENTER_X, CENTER_Y, r, i * step);\n return <circle key={i} cx={p.x} cy={p.y} r={4} className={classes.dataPoint} />;\n })}\n\n {/* Category labels */}\n {CATEGORIES.map((cat, i) => {\n const pos = polarToCartesian(CENTER_X, CENTER_Y, LABEL_RADIUS, i * step);\n let anchor: 'inherit' | 'end' | 'start' | 'middle' = 'middle';\n if (pos.x < CENTER_X - 10) anchor = 'end';\n else if (pos.x > CENTER_X + 10) anchor = 'start';\n return (\n <text\n key={cat}\n x={pos.x}\n y={pos.y}\n textAnchor={anchor}\n className={classes.label}\n >\n {SHORT_NAMES[cat] ?? cat}\n </text>\n );\n })}\n </svg>\n );\n};\n"],"names":["React"],"mappings":";;;AAGA,MAAM,UAAA,GAAa;AAAA,EACjB,sBAAA;AAAA,EACA,iBAAA;AAAA,EACA,iBAAA;AAAA,EACA,yBAAA;AAAA,EACA,oBAAA;AAAA,EACA,uBAAA;AAAA,EACA,cAAA;AAAA,EACA,iBAAA;AAAA,EACA,qBAAA;AAAA,EACA;AACF,CAAA;AAEA,MAAM,WAAA,GAAsC;AAAA,EAC1C,sBAAA,EAAwB,UAAA;AAAA,EACxB,iBAAA,EAAmB,SAAA;AAAA,EACnB,iBAAA,EAAmB,UAAA;AAAA,EACnB,yBAAA,EAA2B,QAAA;AAAA,EAC3B,oBAAA,EAAsB,QAAA;AAAA,EACtB,uBAAA,EAAyB,OAAA;AAAA,EACzB,cAAA,EAAgB,SAAA;AAAA,EAChB,iBAAA,EAAmB,UAAA;AAAA,EACnB,qBAAA,EAAuB,aAAA;AAAA,EACvB,eAAA,EAAiB;AACnB,CAAA;AAEA,MAAM,QAAA,GAAW,GAAA;AACjB,MAAM,QAAA,GAAW,GAAA;AACjB,MAAM,UAAA,GAAa,GAAA;AACnB,MAAM,YAAA,GAAe,GAAA;AACrB,MAAM,UAAA,GAAa,CAAA;AACnB,MAAM,QAAA,GAAW,GAAA;AAEjB,SAAS,gBAAA,CAAiB,EAAA,EAAY,EAAA,EAAY,CAAA,EAAW,QAAA,EAAkB;AAC7E,EAAA,MAAM,GAAA,GAAA,CAAQ,QAAA,GAAW,EAAA,IAAM,IAAA,CAAK,EAAA,GAAM,GAAA;AAC1C,EAAA,OAAO,EAAE,CAAA,EAAG,EAAA,GAAK,CAAA,GAAI,KAAK,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA,EAAG,EAAA,GAAK,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAE;AAChE;AAEA,SAAS,YAAA,CAAa,QAAkB,MAAA,EAAwB;AAC9D,EAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,MAAA;AAC1B,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AAC/B,IAAA,MAAM,IAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,IAAI,MAAA,GAAU,UAAA;AACtC,IAAA,MAAM,IAAI,gBAAA,CAAiB,QAAA,EAAU,QAAA,EAAU,CAAA,EAAG,IAAI,IAAI,CAAA;AAC1D,IAAA,OAAO,CAAA,EAAG,CAAA,CAAE,CAAC,CAAA,CAAA,EAAI,EAAE,CAAC,CAAA,CAAA;AAAA,EACtB,CAAC,CAAA;AACD,EAAA,OAAO,GAAA,CAAI,KAAK,GAAG,CAAA;AACrB;AAEA,SAAS,iBAAiB,KAAA,EAAuB;AAC/C,EAAA,MAAM,CAAA,GAAK,QAAQ,UAAA,GAAc,UAAA;AACjC,EAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,MAAA;AAC9B,EAAA,OAAO,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM;AAC9B,IAAA,MAAM,IAAI,gBAAA,CAAiB,QAAA,EAAU,QAAA,EAAU,CAAA,EAAG,IAAI,IAAI,CAAA;AAC1D,IAAA,OAAO,CAAA,EAAG,CAAA,CAAE,CAAC,CAAA,CAAA,EAAI,EAAE,CAAC,CAAA,CAAA;AAAA,EACtB,CAAC,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AACb;AAEA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,GAAA,EAAK;AAAA,IACH,KAAA,EAAO,MAAA;AAAA,IACP,QAAA,EAAU,QAAA;AAAA,IACV,OAAA,EAAS,OAAA;AAAA,IACT,MAAA,EAAQ;AAAA,GACV;AAAA,EACA,WAAA,EAAa;AAAA,IACX,IAAA,EAAM,MAAA;AAAA,IACN,MAAA,EAAQ,MAAM,OAAA,CAAQ,OAAA;AAAA,IACtB,WAAA,EAAa;AAAA,GACf;AAAA,EACA,UAAA,EAAY;AAAA,IACV,MAAA,EAAQ,MAAM,OAAA,CAAQ,OAAA;AAAA,IACtB,WAAA,EAAa;AAAA,GACf;AAAA,EACA,WAAA,EAAa;AAAA,IACX,IAAA,EAAM,yBAAA;AAAA,IACN,MAAA,EAAQ,SAAA;AAAA,IACR,WAAA,EAAa;AAAA,GACf;AAAA,EACA,cAAA,EAAgB;AAAA,IACd,IAAA,EAAM,yBAAA;AAAA,IACN,MAAA,EAAQ,SAAA;AAAA,IACR,WAAA,EAAa;AAAA,GACf;AAAA,EACA,SAAA,EAAW;AAAA,IACT,IAAA,EAAM;AAAA,GACR;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,IAAA,EAAM;AAAA,GACR;AAAA,EACA,KAAA,EAAO;AAAA,IACL,QAAA,EAAU,EAAA;AAAA,IACV,UAAA,EAAY,GAAA;AAAA,IACZ,IAAA,EAAM,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,OAAA;AAAA,IACzB,gBAAA,EAAkB;AAAA;AAEtB,CAAA,CAAE,CAAA;AAcK,MAAM,cAAc,CAAC,EAAE,SAAS,OAAA,EAAS,QAAA,GAAW,IAAG,KAAwB;AACpF,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,OAAA,CAAQ,gBAAA,CAAiB,GAAA,CAAI,CAAA,CAAA,KAAK,CAAC,CAAA,CAAE,QAAA,EAAU,CAAA,CAAE,kBAAkB,CAAC,CAAC,CAAA;AAChG,EAAA,MAAM,UAAA,GAAa,OAAA,GACf,IAAI,GAAA,CAAI,QAAQ,gBAAA,CAAiB,GAAA,CAAI,CAAA,CAAA,KAAK,CAAC,EAAE,QAAA,EAAU,CAAA,CAAE,kBAAkB,CAAC,CAAC,CAAA,GAC7E,IAAA;AAEJ,EAAA,MAAM,aAAA,GAAgB,UAAA,CAAW,GAAA,CAAI,CAAA,GAAA,KAAO,IAAA,CAAK,GAAA,CAAI,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA,IAAK,CAAA,EAAG,CAAC,CAAC,CAAA;AACjF,EAAA,MAAM,aAAA,GAAgB,UAAA,GAAa,UAAA,CAAW,GAAA,CAAI,SAAO,IAAA,CAAK,GAAA,CAAI,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA,IAAK,CAAA,EAAG,CAAC,CAAC,CAAA,GAAI,IAAA;AAElG,EAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,MAAA;AAE9B,EAAA,uBACEA,cAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAS,CAAA,IAAA,EAAO,QAAQ,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA;AAAA,MACpC,WAAW,OAAA,CAAQ,GAAA;AAAA,MACnB,YAAA,EAAW;AAAA,KAAA;AAAA,IAGV,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,UAAA,EAAW,EAAG,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAC,CAAA,CAAE,IAAI,CAAA,KAAA,qBACvDA,cAAA,CAAA,aAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,KAAA;AAAA,QACL,MAAA,EAAQ,iBAAiB,KAAK,CAAA;AAAA,QAC9B,WAAW,OAAA,CAAQ;AAAA;AAAA,KAEtB,CAAA;AAAA,IAGA,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM;AACxB,MAAA,MAAM,QAAQ,gBAAA,CAAiB,QAAA,EAAU,QAAA,EAAU,UAAA,EAAY,IAAI,IAAI,CAAA;AACvE,MAAA,uBACEA,cAAA,CAAA,aAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,GAAA,EAAK,CAAA;AAAA,UACL,EAAA,EAAI,QAAA;AAAA,UACJ,EAAA,EAAI,QAAA;AAAA,UACJ,IAAI,KAAA,CAAM,CAAA;AAAA,UACV,IAAI,KAAA,CAAM,CAAA;AAAA,UACV,WAAW,OAAA,CAAQ;AAAA;AAAA,OACrB;AAAA,IAEJ,CAAC,CAAA;AAAA,IAGA,aAAA,oBACCA,cAAA,CAAA,aAAA,CAACA,cAAA,CAAM,QAAA,EAAN,IAAA,kBACCA,cAAA,CAAA,aAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAQ,YAAA,CAAa,aAAA,EAAe,QAAQ,CAAA;AAAA,QAC5C,WAAW,OAAA,CAAQ;AAAA;AAAA,KACrB,EACC,aAAA,CAAc,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AAC3B,MAAA,MAAM,IAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,IAAI,QAAA,GAAY,UAAA;AACxC,MAAA,MAAM,IAAI,gBAAA,CAAiB,QAAA,EAAU,QAAA,EAAU,CAAA,EAAG,IAAI,IAAI,CAAA;AAC1D,MAAA,uBAAOA,cAAA,CAAA,aAAA,CAAC,QAAA,EAAA,EAAO,GAAA,EAAK,CAAA,EAAG,IAAI,CAAA,CAAE,CAAA,EAAG,EAAA,EAAI,CAAA,CAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,SAAA,EAAW,QAAQ,YAAA,EAAc,CAAA;AAAA,IAClF,CAAC,CACH,CAAA;AAAA,oBAIFA,cAAA,CAAA,aAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAQ,YAAA,CAAa,aAAA,EAAe,QAAQ,CAAA;AAAA,QAC5C,WAAW,OAAA,CAAQ;AAAA;AAAA,KACrB;AAAA,IACC,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM;AAC3B,MAAA,MAAM,IAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,IAAI,QAAA,GAAY,UAAA;AACxC,MAAA,MAAM,IAAI,gBAAA,CAAiB,QAAA,EAAU,QAAA,EAAU,CAAA,EAAG,IAAI,IAAI,CAAA;AAC1D,MAAA,uBAAOA,cAAA,CAAA,aAAA,CAAC,QAAA,EAAA,EAAO,GAAA,EAAK,CAAA,EAAG,IAAI,CAAA,CAAE,CAAA,EAAG,EAAA,EAAI,CAAA,CAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,SAAA,EAAW,QAAQ,SAAA,EAAW,CAAA;AAAA,IAC/E,CAAC,CAAA;AAAA,IAGA,UAAA,CAAW,GAAA,CAAI,CAAC,GAAA,EAAK,CAAA,KAAM;AAC1B,MAAA,MAAM,MAAM,gBAAA,CAAiB,QAAA,EAAU,QAAA,EAAU,YAAA,EAAc,IAAI,IAAI,CAAA;AACvE,MAAA,IAAI,MAAA,GAAiD,QAAA;AACrD,MAAA,IAAI,GAAA,CAAI,CAAA,GAAI,QAAA,GAAW,EAAA,EAAI,MAAA,GAAS,KAAA;AAAA,WAAA,IAC3B,GAAA,CAAI,CAAA,GAAI,QAAA,GAAW,EAAA,EAAI,MAAA,GAAS,OAAA;AACzC,MAAA,uBACEA,cAAA,CAAA,aAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,GAAA,EAAK,GAAA;AAAA,UACL,GAAG,GAAA,CAAI,CAAA;AAAA,UACP,GAAG,GAAA,CAAI,CAAA;AAAA,UACP,UAAA,EAAY,MAAA;AAAA,UACZ,WAAW,OAAA,CAAQ;AAAA,SAAA;AAAA,QAElB,WAAA,CAAY,GAAG,CAAA,IAAK;AAAA,OACvB;AAAA,IAEJ,CAAC;AAAA,GACH;AAEJ;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@karimov-labs/backstage-plugin-devxp",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Backstage frontend plugin for developer intelligence — masked identity management, CSV upload, and unmask tooling.",
5
5
  "main": "dist/index.esm.js",
6
6
  "module": "dist/index.esm.js",