From 4532dab109299788eb1ad76316e04f5d3454485b Mon Sep 17 00:00:00 2001 From: Niklas Schneider Date: Sat, 15 Nov 2025 19:53:42 +0100 Subject: [PATCH 01/73] Renamed the current frontend-folder to frontendOld. Added the new frontend structure and folder for further migration and named it frontend. Fixed initial errors. --- .markdownlint-cli2.yaml | 3 +- apps/frontend/README.md | 62 +- apps/frontend/index.html | 28 +- apps/frontend/package.json | 90 +- apps/frontend/src/App.tsx | 140 +- apps/frontend/src/Attributions.md | 4 + apps/frontend/src/FEATURES.md | 253 + apps/frontend/src/MOCKUP_DATA.md | 336 ++ apps/frontend/src/QUICK_START.md | 202 + apps/frontend/src/components/AIInsights.tsx | 367 ++ .../frontend/src/components/ActivityChart.tsx | 97 + .../src/components/CodeChurnChart.tsx | 170 + .../frontend/src/components/CommitHeatmap.tsx | 150 + .../src/components/ContributionRanking.tsx | 192 + .../frontend/src/components/DashboardPage.tsx | 341 ++ .../src/components/FileDistributionChart.tsx | 73 + apps/frontend/src/components/FileTypeList.tsx | 125 + apps/frontend/src/components/Footer.tsx | 25 + .../frontend/src/components/GitDiffViewer.tsx | 265 + .../src/components/GraphViewTimeline.tsx | 307 ++ apps/frontend/src/components/Header.tsx | 113 + apps/frontend/src/components/InfoModal.tsx | 51 + apps/frontend/src/components/LandingPage.tsx | 121 + .../src/components/LoadingSpinner.tsx | 19 + apps/frontend/src/components/NewsDrawer.tsx | 91 + .../src/components/PremiumFeatures.tsx | 412 ++ .../src/components/SettingsDrawer.tsx | 184 + .../components/figma/ImageWithFallback.tsx | 41 + apps/frontend/src/components/ui/accordion.tsx | 66 + .../src/components/ui/alert-dialog.tsx | 157 + apps/frontend/src/components/ui/alert.tsx | 66 + .../src/components/ui/aspect-ratio.tsx | 11 + apps/frontend/src/components/ui/avatar.tsx | 53 + apps/frontend/src/components/ui/badge.tsx | 46 + .../frontend/src/components/ui/breadcrumb.tsx | 109 + apps/frontend/src/components/ui/button.tsx | 58 + apps/frontend/src/components/ui/calendar.tsx | 75 + apps/frontend/src/components/ui/card.tsx | 92 + apps/frontend/src/components/ui/carousel.tsx | 241 + apps/frontend/src/components/ui/chart.tsx | 353 ++ apps/frontend/src/components/ui/checkbox.tsx | 32 + .../src/components/ui/collapsible.tsx | 33 + apps/frontend/src/components/ui/command.tsx | 177 + .../src/components/ui/context-menu.tsx | 252 + apps/frontend/src/components/ui/dialog.tsx | 135 + apps/frontend/src/components/ui/drawer.tsx | 132 + .../src/components/ui/dropdown-menu.tsx | 257 + apps/frontend/src/components/ui/form.tsx | 168 + .../frontend/src/components/ui/hover-card.tsx | 44 + apps/frontend/src/components/ui/input-otp.tsx | 77 + apps/frontend/src/components/ui/input.tsx | 21 + apps/frontend/src/components/ui/label.tsx | 24 + apps/frontend/src/components/ui/menubar.tsx | 276 + .../src/components/ui/navigation-menu.tsx | 168 + .../frontend/src/components/ui/pagination.tsx | 127 + apps/frontend/src/components/ui/popover.tsx | 48 + apps/frontend/src/components/ui/progress.tsx | 31 + .../src/components/ui/radio-group.tsx | 45 + apps/frontend/src/components/ui/resizable.tsx | 56 + .../src/components/ui/scroll-area.tsx | 58 + apps/frontend/src/components/ui/select.tsx | 189 + apps/frontend/src/components/ui/separator.tsx | 28 + apps/frontend/src/components/ui/sheet.tsx | 139 + apps/frontend/src/components/ui/sidebar.tsx | 726 +++ apps/frontend/src/components/ui/skeleton.tsx | 13 + apps/frontend/src/components/ui/slider.tsx | 63 + apps/frontend/src/components/ui/sonner.tsx | 25 + apps/frontend/src/components/ui/switch.tsx | 31 + apps/frontend/src/components/ui/table.tsx | 116 + apps/frontend/src/components/ui/tabs.tsx | 66 + apps/frontend/src/components/ui/textarea.tsx | 18 + .../src/components/ui/toggle-group.tsx | 73 + apps/frontend/src/components/ui/toggle.tsx | 47 + apps/frontend/src/components/ui/tooltip.tsx | 61 + apps/frontend/src/components/ui/use-mobile.ts | 21 + apps/frontend/src/components/ui/utils.ts | 6 + apps/frontend/src/guidelines/Guidelines.md | 62 + apps/frontend/src/index.css | 3800 +++++++++++++- apps/frontend/src/main.tsx | 14 +- apps/frontend/src/styles/globals.css | 234 + apps/frontend/tsconfig.app.json | 7 +- apps/frontend/tsconfig.json | 8 +- apps/frontend/vite.config.ts | 61 +- apps/{frontend => frontendOld}/.gitignore | 0 apps/frontendOld/README.md | 61 + .../__tests__/App.test.tsx | 0 .../components/ActivityHeatmap.test.tsx | 0 .../__tests__/components/CommitList.test.tsx | 0 .../__tests__/components/RiveLoader.test.tsx | 0 .../__tests__/components/RiveLogo.test.tsx | 0 .../__tests__/main.test.tsx | 0 .../__tests__/pages/MainPage.test.tsx | 0 .../__tests__/services/api.test.tsx | 0 .../__tests__/services/apiExtended.test.tsx | 0 .../__tests__/utils/dateUtils.test.tsx | 0 .../eslint.config.js | 0 apps/frontendOld/index.html | 13 + apps/frontendOld/package.json | 46 + .../postcss.config.cjs | 0 .../Logo_Animation_StateMachine_DarkMode.riv | Bin .../Logo_Animation_StateMachine_LightMode.riv | Bin .../{frontend => frontendOld}/public/vite.svg | 0 apps/{frontend => frontendOld}/src/App.css | 0 apps/frontendOld/src/App.tsx | 16 + .../src/assets/react.svg | 0 .../src/components/ActivityHeatmap.tsx | 0 .../src/components/CommitList.tsx | 0 .../src/components/RepoInput.tsx | 0 .../src/components/RiveLoader.tsx | 0 .../src/components/RiveLogo.tsx | 0 apps/frontendOld/src/index.css | 94 + apps/frontendOld/src/main.tsx | 15 + .../src/pages/MainPage.tsx | 0 .../src/services/api.ts | 0 .../src/styles/heatmap.css | 0 .../src/test-setup.ts | 0 .../src/types/react-calendar-heatmap.d.ts | 0 .../src/utils/dateUtils.ts | 0 apps/frontendOld/src/vite-env.d.ts | 1 + .../tailwind.config.cjs | 0 apps/frontendOld/tsconfig.app.json | 37 + apps/frontendOld/tsconfig.json | 13 + apps/frontendOld/tsconfig.node.json | 24 + apps/frontendOld/vite.config.ts | 13 + .../vitest.config.ts | 0 eslint.config.mjs | 1 + pnpm-lock.yaml | 4602 +++++++++++++---- 127 files changed, 17277 insertions(+), 1217 deletions(-) create mode 100644 apps/frontend/src/Attributions.md create mode 100644 apps/frontend/src/FEATURES.md create mode 100644 apps/frontend/src/MOCKUP_DATA.md create mode 100644 apps/frontend/src/QUICK_START.md create mode 100644 apps/frontend/src/components/AIInsights.tsx create mode 100644 apps/frontend/src/components/ActivityChart.tsx create mode 100644 apps/frontend/src/components/CodeChurnChart.tsx create mode 100644 apps/frontend/src/components/CommitHeatmap.tsx create mode 100644 apps/frontend/src/components/ContributionRanking.tsx create mode 100644 apps/frontend/src/components/DashboardPage.tsx create mode 100644 apps/frontend/src/components/FileDistributionChart.tsx create mode 100644 apps/frontend/src/components/FileTypeList.tsx create mode 100644 apps/frontend/src/components/Footer.tsx create mode 100644 apps/frontend/src/components/GitDiffViewer.tsx create mode 100644 apps/frontend/src/components/GraphViewTimeline.tsx create mode 100644 apps/frontend/src/components/Header.tsx create mode 100644 apps/frontend/src/components/InfoModal.tsx create mode 100644 apps/frontend/src/components/LandingPage.tsx create mode 100644 apps/frontend/src/components/LoadingSpinner.tsx create mode 100644 apps/frontend/src/components/NewsDrawer.tsx create mode 100644 apps/frontend/src/components/PremiumFeatures.tsx create mode 100644 apps/frontend/src/components/SettingsDrawer.tsx create mode 100644 apps/frontend/src/components/figma/ImageWithFallback.tsx create mode 100644 apps/frontend/src/components/ui/accordion.tsx create mode 100644 apps/frontend/src/components/ui/alert-dialog.tsx create mode 100644 apps/frontend/src/components/ui/alert.tsx create mode 100644 apps/frontend/src/components/ui/aspect-ratio.tsx create mode 100644 apps/frontend/src/components/ui/avatar.tsx create mode 100644 apps/frontend/src/components/ui/badge.tsx create mode 100644 apps/frontend/src/components/ui/breadcrumb.tsx create mode 100644 apps/frontend/src/components/ui/button.tsx create mode 100644 apps/frontend/src/components/ui/calendar.tsx create mode 100644 apps/frontend/src/components/ui/card.tsx create mode 100644 apps/frontend/src/components/ui/carousel.tsx create mode 100644 apps/frontend/src/components/ui/chart.tsx create mode 100644 apps/frontend/src/components/ui/checkbox.tsx create mode 100644 apps/frontend/src/components/ui/collapsible.tsx create mode 100644 apps/frontend/src/components/ui/command.tsx create mode 100644 apps/frontend/src/components/ui/context-menu.tsx create mode 100644 apps/frontend/src/components/ui/dialog.tsx create mode 100644 apps/frontend/src/components/ui/drawer.tsx create mode 100644 apps/frontend/src/components/ui/dropdown-menu.tsx create mode 100644 apps/frontend/src/components/ui/form.tsx create mode 100644 apps/frontend/src/components/ui/hover-card.tsx create mode 100644 apps/frontend/src/components/ui/input-otp.tsx create mode 100644 apps/frontend/src/components/ui/input.tsx create mode 100644 apps/frontend/src/components/ui/label.tsx create mode 100644 apps/frontend/src/components/ui/menubar.tsx create mode 100644 apps/frontend/src/components/ui/navigation-menu.tsx create mode 100644 apps/frontend/src/components/ui/pagination.tsx create mode 100644 apps/frontend/src/components/ui/popover.tsx create mode 100644 apps/frontend/src/components/ui/progress.tsx create mode 100644 apps/frontend/src/components/ui/radio-group.tsx create mode 100644 apps/frontend/src/components/ui/resizable.tsx create mode 100644 apps/frontend/src/components/ui/scroll-area.tsx create mode 100644 apps/frontend/src/components/ui/select.tsx create mode 100644 apps/frontend/src/components/ui/separator.tsx create mode 100644 apps/frontend/src/components/ui/sheet.tsx create mode 100644 apps/frontend/src/components/ui/sidebar.tsx create mode 100644 apps/frontend/src/components/ui/skeleton.tsx create mode 100644 apps/frontend/src/components/ui/slider.tsx create mode 100644 apps/frontend/src/components/ui/sonner.tsx create mode 100644 apps/frontend/src/components/ui/switch.tsx create mode 100644 apps/frontend/src/components/ui/table.tsx create mode 100644 apps/frontend/src/components/ui/tabs.tsx create mode 100644 apps/frontend/src/components/ui/textarea.tsx create mode 100644 apps/frontend/src/components/ui/toggle-group.tsx create mode 100644 apps/frontend/src/components/ui/toggle.tsx create mode 100644 apps/frontend/src/components/ui/tooltip.tsx create mode 100644 apps/frontend/src/components/ui/use-mobile.ts create mode 100644 apps/frontend/src/components/ui/utils.ts create mode 100644 apps/frontend/src/guidelines/Guidelines.md create mode 100644 apps/frontend/src/styles/globals.css rename apps/{frontend => frontendOld}/.gitignore (100%) create mode 100644 apps/frontendOld/README.md rename apps/{frontend => frontendOld}/__tests__/App.test.tsx (100%) rename apps/{frontend => frontendOld}/__tests__/components/ActivityHeatmap.test.tsx (100%) rename apps/{frontend => frontendOld}/__tests__/components/CommitList.test.tsx (100%) rename apps/{frontend => frontendOld}/__tests__/components/RiveLoader.test.tsx (100%) rename apps/{frontend => frontendOld}/__tests__/components/RiveLogo.test.tsx (100%) rename apps/{frontend => frontendOld}/__tests__/main.test.tsx (100%) rename apps/{frontend => frontendOld}/__tests__/pages/MainPage.test.tsx (100%) rename apps/{frontend => frontendOld}/__tests__/services/api.test.tsx (100%) rename apps/{frontend => frontendOld}/__tests__/services/apiExtended.test.tsx (100%) rename apps/{frontend => frontendOld}/__tests__/utils/dateUtils.test.tsx (100%) rename apps/{frontend => frontendOld}/eslint.config.js (100%) create mode 100644 apps/frontendOld/index.html create mode 100644 apps/frontendOld/package.json rename apps/{frontend => frontendOld}/postcss.config.cjs (100%) rename apps/{frontend => frontendOld}/public/Logo_Animation_StateMachine_DarkMode.riv (100%) rename apps/{frontend => frontendOld}/public/Logo_Animation_StateMachine_LightMode.riv (100%) rename apps/{frontend => frontendOld}/public/vite.svg (100%) rename apps/{frontend => frontendOld}/src/App.css (100%) create mode 100644 apps/frontendOld/src/App.tsx rename apps/{frontend => frontendOld}/src/assets/react.svg (100%) rename apps/{frontend => frontendOld}/src/components/ActivityHeatmap.tsx (100%) rename apps/{frontend => frontendOld}/src/components/CommitList.tsx (100%) rename apps/{frontend => frontendOld}/src/components/RepoInput.tsx (100%) rename apps/{frontend => frontendOld}/src/components/RiveLoader.tsx (100%) rename apps/{frontend => frontendOld}/src/components/RiveLogo.tsx (100%) create mode 100644 apps/frontendOld/src/index.css create mode 100644 apps/frontendOld/src/main.tsx rename apps/{frontend => frontendOld}/src/pages/MainPage.tsx (100%) rename apps/{frontend => frontendOld}/src/services/api.ts (100%) rename apps/{frontend => frontendOld}/src/styles/heatmap.css (100%) rename apps/{frontend => frontendOld}/src/test-setup.ts (100%) rename apps/{frontend => frontendOld}/src/types/react-calendar-heatmap.d.ts (100%) rename apps/{frontend => frontendOld}/src/utils/dateUtils.ts (100%) create mode 100644 apps/frontendOld/src/vite-env.d.ts rename apps/{frontend => frontendOld}/tailwind.config.cjs (100%) create mode 100644 apps/frontendOld/tsconfig.app.json create mode 100644 apps/frontendOld/tsconfig.json create mode 100644 apps/frontendOld/tsconfig.node.json create mode 100644 apps/frontendOld/vite.config.ts rename apps/{frontend => frontendOld}/vitest.config.ts (100%) diff --git a/.markdownlint-cli2.yaml b/.markdownlint-cli2.yaml index 4d26384b..0a21b5cc 100644 --- a/.markdownlint-cli2.yaml +++ b/.markdownlint-cli2.yaml @@ -38,7 +38,8 @@ gitignore: true globs: - '**/*.{md,markdown}' -# 5) Ignore patterns - exclude prompts folder and Serena memories +# 5) Ignore patterns - exclude prompts folder, Serena memories, and new frontend docs ignores: - 'prompts/**/*.{md,markdown}' - '.serena/memories/**/*.{md,markdown}' + - 'apps/frontend/src/**/*.{md,markdown}' diff --git a/apps/frontend/README.md b/apps/frontend/README.md index b7a941b9..a7907c87 100644 --- a/apps/frontend/README.md +++ b/apps/frontend/README.md @@ -1,61 +1,11 @@ -# React + TypeScript + Vite -This template provides a minimal setup to get React working in Vite -with HMR and some ESLint rules. +# GitRay Web App Design -Currently, two official plugins are available: + This is a code bundle for GitRay Web App Design. The original project is available at . -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) - uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) - uses [SWC](https://swc.rs/) for Fast Refresh +## Running the code -## Expanding the ESLint configuration + Run `npm i` to install the dependencies. -If you are developing a production application, we recommend updating the -configuration to enable type-aware lint rules: - -```js -export default tseslint.config({ - extends: [ - // Remove ...tseslint.configs.recommended and replace with this - ...tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - ...tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - ...tseslint.configs.stylisticTypeChecked, - ], - languageOptions: { - // other options... - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - }, -}) - -You can also install -eslint-plugin-react-x -and -eslint-plugin-react-dom -for React‑specific lint rules: - -// eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' - -export default tseslint.config({ - plugins: { - // Add the react-x and react-dom plugins - 'react-x': reactX, - 'react-dom': reactDom, - }, - rules: { - // other rules... - // Enable its recommended typescript rules - ...reactX.configs['recommended-typescript'].rules, - ...reactDom.configs.recommended.rules, - }, -}) - -``` + Run `npm run dev` to start the development server. + \ No newline at end of file diff --git a/apps/frontend/index.html b/apps/frontend/index.html index e4b78eae..c08af1f2 100644 --- a/apps/frontend/index.html +++ b/apps/frontend/index.html @@ -1,13 +1,15 @@ - - - - - - - Vite + React + TS - - -
- - - + + + + + + + GitRay Web App Design + + + +
+ + + + \ No newline at end of file diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 5f6f288a..476119ec 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -1,46 +1,66 @@ { "name": "frontend", + "version": "0.1.0", "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "npx vite", - "build": "tsc -b", - "preview": "npx vite preview", - "test": "vitest run", - "test:watch": "vitest", - "test:coverage": "vitest run --coverage" - }, "dependencies": { - "@gitray/shared-types": "workspace:*", - "@rive-app/react-canvas": "^4.21.3", - "apexcharts": "^4.7.0", - "axios": "^1.9.0", - "date-fns": "^4.1.0", - "react": "^19.1.0", - "react-apexcharts": "^1.7.0", - "react-calendar-heatmap": "^1.10.0", - "react-dom": "^19.1.0", - "react-select": "^5.10.1", - "typescript": "~5.7.3" + "@radix-ui/react-accordion": "^1.2.3", + "@radix-ui/react-alert-dialog": "^1.1.6", + "@radix-ui/react-aspect-ratio": "^1.1.2", + "@radix-ui/react-avatar": "^1.1.3", + "@radix-ui/react-checkbox": "^1.1.4", + "@radix-ui/react-collapsible": "^1.1.3", + "@radix-ui/react-context-menu": "^2.2.6", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", + "@radix-ui/react-hover-card": "^1.1.6", + "@radix-ui/react-label": "^2.1.2", + "@radix-ui/react-menubar": "^1.1.6", + "@radix-ui/react-navigation-menu": "^1.2.5", + "@radix-ui/react-popover": "^1.1.6", + "@radix-ui/react-progress": "^1.1.2", + "@radix-ui/react-radio-group": "^1.2.3", + "@radix-ui/react-scroll-area": "^1.2.3", + "@radix-ui/react-select": "^2.1.6", + "@radix-ui/react-separator": "^1.1.2", + "@radix-ui/react-slider": "^1.2.3", + "@radix-ui/react-slot": "^1.1.2", + "@radix-ui/react-switch": "^1.1.3", + "@radix-ui/react-tabs": "^1.1.3", + "@radix-ui/react-toggle": "^1.1.2", + "@radix-ui/react-toggle-group": "^1.1.2", + "@radix-ui/react-tooltip": "^1.1.8", + "class-variance-authority": "^0.7.1", + "clsx": "*", + "cmdk": "^1.1.1", + "embla-carousel-react": "^8.6.0", + "input-otp": "^1.4.2", + "lucide-react": "^0.487.0", + "motion": "*", + "next-themes": "^0.4.6", + "react": "^18.3.1", + "react-day-picker": "^8.10.1", + "react-dom": "^18.3.1", + "react-hook-form": "^7.55.0", + "react-resizable-panels": "^2.1.7", + "recharts": "^2.15.2", + "sonner": "^2.0.3", + "tailwind-merge": "*", + "vaul": "^1.1.2" }, "devDependencies": { - "@tailwindcss/cli": "^4.1.7", - "@tailwindcss/postcss": "^4.1.7", - "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^14.3.1", - "@testing-library/user-event": "^14.6.1", - "@types/react": "^19.1.8", - "@types/react-dom": "^19.1.6", - "@vitejs/plugin-react": "^4.4.1", - "@vitest/coverage-v8": "^3.2.3", - "@vitest/ui": "^3.2.3", + "@types/node": "^20.10.0", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react-swc": "^3.10.2", "autoprefixer": "^10.4.21", - "eslint-plugin-react-refresh": "^0.4.20", - "jsdom": "^26.1.0", "postcss": "^8.5.3", "tailwindcss": "^4.1.7", - "vite": "^6.3.5", - "vitest": "^3.2.3" + "typescript": "~5.7.3", + "vite": "6.3.5" + }, + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "preview": "vite preview" } } diff --git a/apps/frontend/src/App.tsx b/apps/frontend/src/App.tsx index 07501230..8170614b 100644 --- a/apps/frontend/src/App.tsx +++ b/apps/frontend/src/App.tsx @@ -1,16 +1,126 @@ -import MainPage from './pages/MainPage'; -import './App.css'; - -/** - * Root component rendered by `main.tsx`. Acts as the entry point for the - * single-page application. - */ - -/** - * Simple wrapper component that renders the `MainPage` component. - */ -function App() { - return ; -} +import { useState, useEffect } from 'react'; +import { Header } from './components/Header'; +import { Footer } from './components/Footer'; +import { SettingsDrawer } from './components/SettingsDrawer'; +import { NewsDrawer } from './components/NewsDrawer'; +import { InfoModal } from './components/InfoModal'; +import { LandingPage } from './components/LandingPage'; +import { DashboardPage } from './components/DashboardPage'; +import { Toaster } from './components/ui/sonner'; +import { toast } from 'sonner@2.0.3'; + +type Page = 'landing' | 'dashboard'; +type InfoType = 'what' | 'private' | 'local' | null; + +export default function App() { + const [currentPage, setCurrentPage] = useState('landing'); + const [isSignedIn, setIsSignedIn] = useState(false); + const [theme, setTheme] = useState<'light' | 'dark' | 'system'>('dark'); + const [settingsOpen, setSettingsOpen] = useState(false); + const [newsOpen, setNewsOpen] = useState(false); + const [infoModalType, setInfoModalType] = useState(null); + const [hasUnreadNews, setHasUnreadNews] = useState(true); + + // Apply theme + useEffect(() => { + const root = window.document.documentElement; + root.classList.remove('light', 'dark'); + + if (theme === 'system') { + const systemTheme = window.matchMedia('(prefers-color-scheme: dark)') + .matches + ? 'dark' + : 'light'; + root.classList.add(systemTheme); + } else { + root.classList.add(theme); + } + }, [theme]); + + const handleAnalyze = (url: string, mode: string) => { + toast.success('Analysis started!', { + description: `Analyzing repository in ${mode} mode...`, + }); + + // Simulate analysis delay + setTimeout(() => { + setCurrentPage('dashboard'); + setIsSignedIn(true); + toast.success('Analysis complete!', { + description: 'Repository data has been processed.', + }); + }, 1500); + }; + + const handleSignOut = () => { + setIsSignedIn(false); + setCurrentPage('landing'); + toast.info('Signed out successfully'); + }; + + const handleNavigateHome = () => { + setCurrentPage('landing'); + }; -export default App; + const handleInfoClick = (type: 'what' | 'private' | 'local') => { + setInfoModalType(type); + }; + + const handleNewsClick = () => { + setNewsOpen(true); + setHasUnreadNews(false); + }; + + return ( +
+
setSettingsOpen(true)} + onNewsClick={handleNewsClick} + onSignOut={handleSignOut} + onNavigateHome={handleNavigateHome} + showNews={currentPage === 'dashboard'} + hasUnreadNews={hasUnreadNews} + title={currentPage === 'dashboard' ? 'GitRay' : undefined} + /> + +
+ {currentPage === 'landing' && ( + + )} + {currentPage === 'dashboard' && } +
+ +
+ + setSettingsOpen(false)} + theme={theme} + onThemeChange={setTheme} + /> + + setNewsOpen(false)} /> + + setInfoModalType(null)} + type={infoModalType} + /> + + +
+ ); +} diff --git a/apps/frontend/src/Attributions.md b/apps/frontend/src/Attributions.md new file mode 100644 index 00000000..21740022 --- /dev/null +++ b/apps/frontend/src/Attributions.md @@ -0,0 +1,4 @@ +/* eslint-disable */ +Diese Figma Make-Datei enthält Komponenten von [shadcn/ui](https://ui.shadcn.com/), verwendet unter [MIT-Lizenz](https://github.com/shadcn-ui/ui/blob/main/LICENSE.md). + +Diese Figma Make-Datei enthält Fotos von [Unsplash](https://unsplash.com), die unter [Lizenz](https://unsplash.com/license) verwendet werden. \ No newline at end of file diff --git a/apps/frontend/src/FEATURES.md b/apps/frontend/src/FEATURES.md new file mode 100644 index 00000000..6617a638 --- /dev/null +++ b/apps/frontend/src/FEATURES.md @@ -0,0 +1,253 @@ +/* eslint-disable */ +# GitRay Features Documentation + +## Overview +This document outlines all features implemented in GitRay, organized by priority and category as specified in the feature requirements. + +## Feature Organization + +### Dashboard Tabs Structure + +1. **Overview Tab** + - Repository Summary + - Contributors List + - File Distribution Chart + - Activity Snapshot (30 days) + - **Contribution Ranking** (NEW) + - Top contributors leaderboard + - Commit counts and code changes + - Percentage breakdown + - Badges and rankings + +2. **Heatmap Tab** + - 12-month commit activity heatmap + - **Filter Options** (NEW) + - Time range selection (3/6/12 months) + - Peak activity analysis + - Activity streaks + - Most active day/month statistics + +3. **Analytics Tab** (Priority 1 Features) + Sub-tabs: + - **Code Churn Analysis** + - Files with most changes + - Bug hotspot identification + - Risk categorization (High/Medium/Low) + - Visual bar chart representation + + - **File Types** + - Comprehensive file type distribution + - Count and percentage breakdown + - Language statistics + - Visual progress indicators + + - **Timeline** + - Graph View Timeline (Network Graph) + - Branch visualization + - Merge and commit tracking + - **Playback functionality** with controls + - Commit details on hover/click + - Recent activity feed + + - **Git Diff** + - Side-by-side diff viewer + - File-by-file comparison + - Addition/deletion statistics + - Expandable file views + - Syntax highlighting + +4. **AI Insights Tab** (Priority 3 Features) + Sub-tabs: + - **Overview** + - Project Health Score (0-100) + - AI-generated recommendations + - Architecture improvements + - Code quality suggestions + - Performance optimization tips + + - **Weekly** + - Weekly development summaries + - Iterative change tracking + - Key highlights per week + - Metrics (lines added/removed, files changed) + + - **Trends** + - Team productivity tracking + - Code quality metrics + - Collaboration scores + - 30-day performance indicators + +5. **Premium Tab** (Priority 1-4 Features) + Two sub-tabs: + - **Features** + - Time-lapse Animation (Gource visualization) + - Export capabilities (PNG, SVG, PDF) + - Advanced Zoom & Pan controls + - UML Diagram Generation (PlantUML) + - Project Efficiency Analysis + - Security Insights + - Multi-project Management + - Team Collaboration tools + - Team Chat Rooms + - Gamification System + - Desktop Application (Enterprise) + - Progressive Web App (PWA) + + - **Pricing** + - Four-tier pricing structure: + - Free: Basic features for individuals + - Premium ($15/mo): Advanced analytics and AI + - Team ($49/mo): Collaboration tools + - Enterprise (Custom): Full feature set + - Feature comparison table + - 14-day free trial + +## Settings Enhancements + +### Language Support (Priority 3) +- **Available Languages**: + - English (Default) ✓ + - Deutsch (German) + - Français (French) + - Español (Spanish) + - Português (Portuguese) + - 中文 (Mandarin) + - 日本語 (Japanese) + - Русский (Russian) + +- Location: Settings Drawer → General Tab +- Easy dropdown selection +- Persistent across sessions + +### Additional Settings +- Auto-analyze on paste +- Show notifications +- Enable export features +- Theme selection (Light/Dark/System) +- Account management +- API token storage (GitHub, AI) + +## Feature Implementation Status + +### ✅ Implemented Features + +#### Priority 1 +- [x] Code Churn Analysis with bug hotspot detection +- [x] Enhanced Heatmaps with filter functionality +- [x] File Type List with detailed categorization +- [x] Graph View Timeline with playback +- [x] Git Diff Viewer with comparison +- [x] Contribution Ranking +- [x] Export options (in Premium) +- [x] Zoom & Pan (in Premium) +- [x] Time-lapse/Gource (in Premium) + +#### Priority 2 +- [x] Account management (Settings) +- [x] URL field for repository input (Landing page) +- [x] Design template storage option (Settings) +- [x] Token storage (Settings → Connections) + +#### Priority 3 +- [x] AI-powered insights +- [x] Project structure recommendations +- [x] Weekly/Monthly summaries +- [x] Multi-language support with 8 languages +- [x] AI Insights page +- [x] Iterative change summaries + +#### Priority 4 +- [x] Multi-project Management (Premium) +- [x] Team Collaboration (Premium) +- [x] Team Chat (Premium) +- [x] Gamification Elements (Premium) +- [x] UML Feature (Premium) +- [x] Mobile PWA (Premium) +- [x] Desktop Application (Premium Enterprise) +- [x] Project Analysis Tool (Premium) + +## Mockup Data + +All features are populated with realistic mockup data: +- 3,482 total commits +- 24 contributors +- 590 total files across 6 file types +- 12 months of commit history +- 8 files with churn analysis +- 5 top contributors with detailed stats +- 4 branches with timeline visualization +- 3 files with Git diff comparison +- AI insights with 4 recommendation categories +- 2 weeks of development summaries +- 3 monthly trend metrics + +## User Workflows + +### 1. Basic Analysis Workflow +1. Enter GitHub repository URL on Landing page +2. View Overview tab for quick insights +3. Check Contribution Ranking +4. Explore Heatmap for activity patterns + +### 2. Deep Analysis Workflow +1. Navigate to Analytics tab +2. Review Code Churn for bug hotspots +3. Check File Type distribution +4. Use Timeline to understand project evolution +5. Compare versions with Git Diff viewer + +### 3. AI-Powered Insights Workflow +1. Open AI Insights tab +2. Review Project Health Score +3. Read AI recommendations +4. Check weekly summaries +5. Monitor monthly trends + +### 4. Premium Features Workflow +1. Navigate to Premium tab +2. Browse available features +3. Compare pricing plans +4. Start free trial or upgrade + +## Technical Implementation + +### Components Created +- `ContributionRanking.tsx` - Leaderboard with detailed contributor stats +- `CodeChurnChart.tsx` - Bug hotspot analysis with risk visualization +- `FileTypeList.tsx` - Comprehensive file categorization +- `GraphViewTimeline.tsx` - Interactive branch and commit timeline +- `GitDiffViewer.tsx` - Side-by-side code comparison +- `AIInsights.tsx` - AI-powered project analysis with tabs +- `PremiumFeatures.tsx` - Complete premium feature showcase + +### Enhanced Components +- `SettingsDrawer.tsx` - Added language selection dropdown +- `DashboardPage.tsx` - Reorganized with 5 main tabs +- `CommitHeatmap.tsx` - Enhanced with filter controls + +### Data Structure +All components use TypeScript interfaces for type safety with comprehensive mockup data that demonstrates real-world usage patterns. + +## Future Enhancements +- Real API integration with GitHub +- Backend implementation (Express + PostgreSQL) +- Live data updates +- Export functionality implementation +- Offline AI capabilities for Enterprise +- Mobile app development (Android) +- PWA deployment +- Desktop application packaging + +## Notes for Development +- All features are currently using mockup data +- AI insights are simulated (will require API integration) +- Premium features are locked behind upgrade prompts +- Language translations are placeholders (UI ready for i18n) +- Export buttons are UI-only (implementation pending) +- Team features require backend implementation + +--- + +**Last Updated**: November 8, 2024 +**Version**: 2.0.0 +**Status**: Feature Complete (with mockup data) diff --git a/apps/frontend/src/MOCKUP_DATA.md b/apps/frontend/src/MOCKUP_DATA.md new file mode 100644 index 00000000..168b05dd --- /dev/null +++ b/apps/frontend/src/MOCKUP_DATA.md @@ -0,0 +1,336 @@ +/* eslint-disable */ +# GitRay Mockup Data Reference + +This document details all the mockup data used throughout the GitRay application for demonstration purposes. + +## Repository Data + +**Repository**: `Octo Org/analytics-pro` +- Created: 2019-06-14 +- Age: 5.7 years +- Last Commit: 2 days ago +- Total Commits: 3,482 +- Contributors: 24 +- Status: Active + +## Contributors + +### Overview Tab - Quick List +1. John Doe (JD) +2. Jane Smith (JS) +3. Mike Johnson (MJ) +4. Sarah Williams (SW) +5. Tom Brown (TB) + +### Contribution Ranking - Detailed Leaders +1. **Sarah Chen** (SC) 🏆 + - Commits: 1,247 + - Additions: 45,632 + - Deletions: 12,340 + - Contribution: 35.8% + - Badge: Top Contributor + +2. **Marcus Johnson** (MJ) 🥈 + - Commits: 892 + - Additions: 32,145 + - Deletions: 9,876 + - Contribution: 25.6% + - Badge: Core Team + +3. **Emma Rodriguez** (ER) 🥉 + - Commits: 654 + - Additions: 24,567 + - Deletions: 7,654 + - Contribution: 18.8% + - Badge: Active + +4. **Alex Kim** (AK) ⭐ + - Commits: 423 + - Additions: 15,234 + - Deletions: 4,321 + - Contribution: 12.1% + - Badge: Regular + +5. **Jordan Taylor** (JT) ✨ + - Commits: 267 + - Additions: 8,932 + - Deletions: 2,345 + - Contribution: 7.7% + - Badge: Rising + +**Total Commits Shown**: 3,483 + +## File Distribution + +### Language Breakdown +1. **TypeScript** (42%) + - Extensions: .ts, .tsx + - Count: 247 files + - Color: Blue + +2. **JavaScript** (31%) + - Extensions: .js, .jsx + - Count: 183 files + - Color: Yellow + +3. **JSON** (12%) + - Extensions: .json + - Count: 72 files + - Color: Green + +4. **Markdown** (8%) + - Extensions: .md + - Count: 45 files + - Color: Purple + +5. **CSS/SCSS** (5%) + - Extensions: .css, .scss + - Count: 28 files + - Color: Pink + +6. **Images** (2%) + - Extensions: .png, .jpg, .svg + - Count: 15 files + - Color: Orange + +**Total Files**: 590 + +## Code Churn Analysis + +### Files with Most Changes (Bug Hotspots) + +1. **api/auth.ts** + - Changes: 47 + - Risk: High + - Category: High + +2. **components/Dashboard.tsx** + - Changes: 38 + - Risk: High + - Category: High + +3. **utils/helpers.ts** + - Changes: 32 + - Risk: Medium + - Category: High + +4. **pages/settings.tsx** + - Changes: 24 + - Risk: Medium + - Category: Medium + +5. **lib/api-client.ts** + - Changes: 19 + - Risk: Low + - Category: Medium + +6. **styles/globals.css** + - Changes: 15 + - Risk: Low + - Category: Medium + +7. **config/routes.ts** + - Changes: 12 + - Risk: Low + - Category: Low + +8. **types/index.ts** + - Changes: 8 + - Risk: Low + - Category: Low + +**Risk Thresholds**: +- High: 30+ changes +- Medium: 15-30 changes +- Low: <15 changes + +## Branch Structure + +### Active Branches +1. **main** + - Color: #5B9A8B (Primary) + - Commits: 247 + - Status: Active + +2. **develop** + - Color: #FFA69E (Secondary) + - Commits: 183 + - Status: Active + +3. **feature/analytics** + - Color: #FAE3B4 (Accent) + - Commits: 42 + - Status: Active + +4. **hotfix/auth** + - Color: #2E073F (Dark) + - Commits: 12 + - Status: Inactive + +## Timeline Events + +### Recent Activity +1. **Commit** on main + - Message: "feat: Add user authentication" + - Author: Sarah C. + - Time: 2 hours ago + - Hash: a3f4c21 + +2. **Merge** to main + - From: develop + - Message: "Merge develop into main" + - Author: Marcus J. + - Time: 5 hours ago + - Hash: b7e8d92 + +3. **Commit** on feature/analytics + - Message: "fix: Chart rendering issue" + - Author: Emma R. + - Time: 1 day ago + - Hash: c9f1a34 + +4. **Commit** on develop + - Message: "refactor: Code cleanup" + - Author: Alex K. + - Time: 2 days ago + - Hash: d2b5e67 + +## Git Diff Example + +### Files Changed: 3 + +1. **src/components/Dashboard.tsx** + - Additions: 45 lines + - Deletions: 12 lines + - Status: Modified + - Changes: Added Badge import, type safety, new Card components + +2. **src/lib/api.ts** + - Additions: 23 lines + - Deletions: 5 lines + - Status: Modified + - Changes: Updated API endpoint, added authentication headers + +3. **src/styles/globals.css** + - Additions: 8 lines + - Deletions: 2 lines + - Status: Modified + - Changes: Updated color scheme (primary, secondary) + +**Total Changes**: +- Additions: 76 lines +- Deletions: 19 lines + +## AI Insights + +### Project Health Score +- Overall Score: 78/100 +- Assessment: "This Angular project shows good architectural patterns with some areas for improvement" + +### Recommendations (4 Categories) + +1. **Architecture** (High Priority) + - Implement lazy loading for feature modules + - Impact: Reduce initial load time by ~35% + +2. **Code Quality** (Medium Priority) + - Increase test coverage from 62% + - Impact: Improve code reliability + +3. **Best Practices** (Medium Priority) + - Standardize component structure + - Impact: Better maintainability + +4. **Performance** (Low Priority) + - Optimize change detection with OnPush + - Impact: Reduce unnecessary re-renders by ~20% + +### Weekly Summaries + +**Week 47 (Nov 1-7, 2024)** +- Commits: 34 +- Lines Added: 2,340 +- Lines Removed: 876 +- Files Changed: 45 +- Highlights: + - Implemented new dashboard analytics + - Fixed 12 auth bugs + - Refactored API service layer + +**Week 46 (Oct 25-31, 2024)** +- Commits: 28 +- Lines Added: 1,823 +- Lines Removed: 654 +- Files Changed: 38 +- Highlights: + - Added user profile customization + - Upgraded dependencies + - Improved error handling + +### Monthly Trends (Last 30 Days) +- Team Productivity: 82% +- Code Quality: 75% +- Team Collaboration: 88% + +## Heatmap Statistics + +### Peak Activity +- **Most Active Day**: Wednesday (Avg. 12 commits) +- **Peak Month**: October 2024 (247 total commits) +- **Current Streak**: 14 days + +### Activity Distribution +- Generated for last 365 days +- Realistic patterns (weekdays > weekends) +- Average weekday commits: 10-15 +- Average weekend commits: 0-3 + +## Premium Features + +### Pricing Plans + +1. **Free** - $0/forever + - Up to 3 repositories + - 7-day data retention + - Basic analytics + +2. **Premium** - $15/month + - Unlimited repositories + - 30-day data retention + - AI insights + - Export features + +3. **Team** - $49/month + - Everything in Premium + - Multi-project management + - Team collaboration + - 90-day retention + - Up to 10 members + +4. **Enterprise** - Custom pricing + - Everything in Team + - Unlimited members + - Desktop app + - Offline AI + - On-premise deployment + +## Language Support + +### Available Languages (8) +1. English (Default) ✓ +2. Deutsch (German) +3. Français (French) +4. Español (Spanish) +5. Português (Portuguese) +6. 中文 (Mandarin) +7. 日本語 (Japanese) +8. Русский (Russian) + +--- + +**Note**: All data is simulated for demonstration purposes. Real integration would require: +- GitHub API connection +- Database for persistence +- AI service integration (OpenAI, etc.) +- Authentication system +- Real-time data processing diff --git a/apps/frontend/src/QUICK_START.md b/apps/frontend/src/QUICK_START.md new file mode 100644 index 00000000..3ab38d86 --- /dev/null +++ b/apps/frontend/src/QUICK_START.md @@ -0,0 +1,202 @@ +/* eslint-disable */ +# GitRay v2.0 - Quick Start Guide + +## 🎉 What's New in v2.0 + +### Major Features Added +- ✅ **AI-Powered Insights** - Project health scores and recommendations +- ✅ **Advanced Analytics** - Code churn, file types, timeline, and diff viewer +- ✅ **Contribution Ranking** - Detailed contributor leaderboards +- ✅ **Multi-Language Support** - 8 languages available +- ✅ **Premium Features** - Complete showcase with pricing +- ✅ **Enhanced Heatmap** - With filters and activity stats + +## 📍 Navigation Guide + +### Dashboard Tabs Overview + +``` +GitRay Dashboard +├── 📊 Overview Tab +│ ├── Repository Summary +│ ├── Contributors List +│ ├── File Distribution +│ ├── Activity Snapshot +│ └── 🆕 Contribution Ranking (new) +│ +├── 🔥 Heatmap Tab +│ ├── 12-Month Activity Heatmap +│ ├── 🆕 Time Range Filters (new) +│ └── 🆕 Peak Activity Stats (new) +│ +├── 📈 Analytics Tab (NEW) +│ ├── Code Churn (bug hotspots) +│ ├── File Types (distribution) +│ ├── Timeline (graph view with playback) +│ └── Git Diff (comparison viewer) +│ +├── ✨ AI Insights Tab (NEW) +│ ├── Overview (health score & recommendations) +│ ├── Weekly (development summaries) +│ └── Trends (monthly metrics) +│ +└── 💎 Premium Tab (ENHANCED) + ├── Features (comprehensive showcase) + └── Pricing (4-tier plans) +``` + +## 🚀 Quick Feature Access + +### For Code Quality Analysis +1. Go to **Analytics Tab** → **Code Churn** +2. View bug hotspots and risk categorization +3. Identify frequently changed files + +### For Team Insights +1. Go to **Overview Tab** +2. Scroll to **Contribution Ranking** +3. See detailed contributor stats with badges + +### For Project Health +1. Go to **AI Insights Tab** → **Overview** +2. View Project Health Score (0-100) +3. Read AI-generated recommendations + +### For Activity Patterns +1. Go to **Heatmap Tab** +2. Use time range filters (3/6/12 months) +3. Check peak activity statistics + +### For Code Changes +1. Go to **Analytics Tab** → **Git Diff** +2. Expand files to see changes +3. View additions/deletions side-by-side + +### For Timeline Visualization +1. Go to **Analytics Tab** → **Timeline** +2. Use playback controls +3. Hover commits for details + +## ⚙️ Settings Configuration + +### Change Language +1. Click burger menu (top-left) +2. Select **Settings** +3. Go to **General** tab +4. Choose from 8 languages: + - English (Default) + - Deutsch, Français, Español + - Português, 中文, 日本語, Русский + +### Manage Tokens +1. Open **Settings** +2. Go to **Connections** tab +3. Add GitHub Token (for private repos) +4. Add AI API Token (for AI features) + +### Customize Theme +1. Open **Settings** +2. Go to **Appearance** tab +3. Choose: Light / Dark / System + +## 📊 Understanding the Data + +### Contribution Ranking +- **🏆 Top Contributor**: Most commits and code changes +- **🥈 Core Team**: Consistent high contributions +- **🥉 Active**: Regular contributor +- **⭐ Regular**: Steady contributions +- **✨ Rising**: Growing contributor + +### Code Churn Risk Levels +- **High Risk** (Red): 30+ changes - likely bug hotspot +- **Medium Risk** (Yellow): 15-30 changes - moderate attention +- **Low Risk** (Green): <15 changes - stable code + +### AI Health Score +- **80-100**: Excellent - Well-maintained project +- **60-79**: Good - Some improvements needed +- **40-59**: Fair - Several areas need attention +- **0-39**: Poor - Significant improvements required + +## 💎 Premium Features + +### Available in Premium ($15/mo) +- Unlimited repositories +- AI-powered insights +- Export visualizations +- Advanced zoom & pan +- 30-day data retention + +### Team Features ($49/mo) +- Multi-project management +- Team collaboration tools +- Real-time chat +- Gamification system +- 90-day data retention + +### Enterprise (Custom) +- Desktop application +- Offline AI capabilities +- Unlimited team members +- On-premise deployment +- Custom integrations + +## 🎯 Best Practices + +### For Individual Developers +1. Check **Overview** for quick metrics +2. Use **Heatmap** to track consistency +3. Review **AI Insights** for improvement tips + +### For Team Leaders +1. Monitor **Contribution Ranking** regularly +2. Review **Code Churn** to identify problem areas +3. Use **Weekly Summaries** for team meetings +4. Check **Trends** for team health + +### For Code Reviews +1. Use **Git Diff** viewer before reviews +2. Check **Timeline** for context +3. Review **File Types** for balance + +## 📝 Keyboard Shortcuts + +| Action | Shortcut | +|--------|----------| +| Open Settings | Not yet implemented | +| Open News | Not yet implemented | +| Switch Tabs | Not yet implemented | + +*Note: Keyboard shortcuts will be added in future versions* + +## 🔗 Resources + +- Full documentation: See `FEATURES.md` +- Mockup data reference: See `MOCKUP_DATA.md` +- Changelog: Open News drawer (bell icon) + +## 🆘 Support + +For questions or issues: +1. Check this Quick Start Guide +2. Review `FEATURES.md` for details +3. Contact support (button in Settings) + +## 🚧 Coming Soon + +- Real GitHub API integration +- Backend implementation (Express + PostgreSQL) +- Live data updates +- Export functionality +- Mobile app (Android) +- Desktop application +- PWA deployment + +--- + +**Current Version**: v2.0.0 +**Status**: Feature Complete (Mockup Data) +**Next Steps**: Backend Integration & API Connection + +**Enjoy exploring GitRay! 🎉** diff --git a/apps/frontend/src/components/AIInsights.tsx b/apps/frontend/src/components/AIInsights.tsx new file mode 100644 index 00000000..fba3e169 --- /dev/null +++ b/apps/frontend/src/components/AIInsights.tsx @@ -0,0 +1,367 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from './ui/card'; +import { Badge } from './ui/badge'; +import { Button } from './ui/button'; +import { + Sparkles, + TrendingUp, + AlertTriangle, + CheckCircle, + Lightbulb, + Clock, + BookOpen, +} from 'lucide-react'; +import { Alert, AlertDescription } from './ui/alert'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'; +import { Progress } from './ui/progress'; + +const projectInsights = { + overallScore: 78, + summary: + 'This Angular project shows good architectural patterns with some areas for improvement in code organization and testing coverage.', + recommendations: [ + { + category: 'Architecture', + priority: 'high', + title: 'Implement lazy loading for feature modules', + description: + 'Several large modules are eagerly loaded, impacting initial bundle size. Consider implementing lazy loading for non-critical features.', + impact: 'Could reduce initial load time by ~35%', + }, + { + category: 'Code Quality', + priority: 'medium', + title: 'Increase test coverage', + description: + 'Current test coverage is at 62%. Focus on testing critical business logic in the authentication and payment modules.', + impact: 'Improve code reliability and maintainability', + }, + { + category: 'Best Practices', + priority: 'medium', + title: 'Standardize component structure', + description: + 'Some components use different organizational patterns. Follow Angular style guide consistently across all modules.', + impact: 'Better code maintainability and team collaboration', + }, + { + category: 'Performance', + priority: 'low', + title: 'Optimize change detection', + description: + "Consider using OnPush strategy for components that don't require frequent updates.", + impact: 'Reduce unnecessary re-renders by ~20%', + }, + ], +}; + +const weeklyInsights = [ + { + week: 'Week 47 (Nov 1-7)', + commits: 34, + highlights: [ + 'Implemented new dashboard analytics feature', + 'Fixed 12 reported bugs in the authentication flow', + 'Refactored API service layer for better maintainability', + ], + keyMetrics: { + linesAdded: 2340, + linesRemoved: 876, + filesChanged: 45, + }, + }, + { + week: 'Week 46 (Oct 25-31)', + commits: 28, + highlights: [ + 'Added user profile customization options', + 'Upgraded dependencies to latest versions', + 'Improved error handling across the application', + ], + keyMetrics: { + linesAdded: 1823, + linesRemoved: 654, + filesChanged: 38, + }, + }, +]; + +const monthlyTrends = { + productivity: 82, + codeQuality: 75, + collaboration: 88, +}; + +export function AIInsights() { + return ( +
+ + + + AI-powered insights are generated based on your project's structure, + commit history, and industry best practices. + + + + + + + + Overview + + + + Weekly + + + + Trends + + + + + + + + + Project Health Score + + + Overall assessment of your project + + + +
+
+ {projectInsights.overallScore} +
+
+ +

+ {projectInsights.summary} +

+
+
+
+
+ + + + Recommendations + + AI-generated suggestions to improve your project + + + + {projectInsights.recommendations.map((rec, index) => ( +
+
+
+ {rec.priority === 'high' ? ( + + ) : ( + + )} +
+
+
+ + {rec.category} + + + {rec.priority} priority + +
+
+

{rec.title}

+

+ {rec.description} +

+

+ + Impact: {rec.impact} +

+
+
+
+
+ ))} +
+
+
+ + + + + + + Weekly Development Summary + + + Iterative summary of changes and progress + + + + {weeklyInsights.map((week, index) => ( +
+
+

{week.week}

+ {week.commits} commits +
+ +
+
+

+ Lines Added +

+

+ +{week.keyMetrics.linesAdded.toLocaleString()} +

+
+
+

+ Lines Removed +

+

+ -{week.keyMetrics.linesRemoved.toLocaleString()} +

+
+
+

+ Files Changed +

+

+ {week.keyMetrics.filesChanged} +

+
+
+ +
+

Highlights:

+
    + {week.highlights.map((highlight, hIndex) => ( +
  • + + {highlight} +
  • + ))} +
+
+
+ ))} + +
+
+
+ + + + + Monthly Trends + + Key performance indicators for the last 30 days + + + +
+
+
+ + Team Productivity + + + {monthlyTrends.productivity}% + +
+ +

+ Based on commit frequency, code reviews, and task completion +

+
+ +
+
+ Code Quality + + {monthlyTrends.codeQuality}% + +
+ +

+ Measured by test coverage, code review feedback, and + refactoring efforts +

+
+ +
+
+ + Team Collaboration + + + {monthlyTrends.collaboration}% + +
+ +

+ Based on PR reviews, pair programming sessions, and code + contributions +

+
+
+ + + + + Your team's collaboration score has increased by 12% this + month. Keep up the great work! + + +
+
+
+
+
+ ); +} diff --git a/apps/frontend/src/components/ActivityChart.tsx b/apps/frontend/src/components/ActivityChart.tsx new file mode 100644 index 00000000..d8d121e0 --- /dev/null +++ b/apps/frontend/src/components/ActivityChart.tsx @@ -0,0 +1,97 @@ +import { + Area, + AreaChart, + CartesianGrid, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis, +} from 'recharts'; + +// Generate mock data for the last 30 days +function generateActivityData() { + const data = []; + const today = new Date(); + + for (let i = 29; i >= 0; i--) { + const date = new Date(today); + date.setDate(date.getDate() - i); + + // Generate realistic commit patterns + const dayOfWeek = date.getDay(); + const isWeekend = dayOfWeek === 0 || dayOfWeek === 6; + const baseCommits = isWeekend + ? Math.random() * 10 + : Math.random() * 30 + 10; + + data.push({ + date: date.toLocaleDateString('en-US', { + month: 'short', + day: 'numeric', + }), + commits: Math.floor(baseCommits), + }); + } + + return data; +} + +const data = generateActivityData(); + +export function ActivityChart() { + return ( +
+ + + + + + + + + + + + { + if (active && payload && payload.length) { + return ( +
+

{payload[0].payload.date}

+

+ {payload[0].value} commits +

+
+ ); + } + return null; + }} + /> + +
+
+
+ ); +} diff --git a/apps/frontend/src/components/CodeChurnChart.tsx b/apps/frontend/src/components/CodeChurnChart.tsx new file mode 100644 index 00000000..4ceb8ea4 --- /dev/null +++ b/apps/frontend/src/components/CodeChurnChart.tsx @@ -0,0 +1,170 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from './ui/card'; +import { + BarChart, + Bar, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + ResponsiveContainer, + Cell, +} from 'recharts'; +import { AlertTriangle, TrendingUp } from 'lucide-react'; +import { Badge } from './ui/badge'; + +const churnData = [ + { file: 'api/auth.ts', changes: 47, category: 'high', bugRisk: 'High' }, + { + file: 'components/Dashboard.tsx', + changes: 38, + category: 'high', + bugRisk: 'High', + }, + { + file: 'utils/helpers.ts', + changes: 32, + category: 'high', + bugRisk: 'Medium', + }, + { + file: 'pages/settings.tsx', + changes: 24, + category: 'medium', + bugRisk: 'Medium', + }, + { + file: 'lib/api-client.ts', + changes: 19, + category: 'medium', + bugRisk: 'Low', + }, + { + file: 'styles/globals.css', + changes: 15, + category: 'medium', + bugRisk: 'Low', + }, + { file: 'config/routes.ts', changes: 12, category: 'low', bugRisk: 'Low' }, + { file: 'types/index.ts', changes: 8, category: 'low', bugRisk: 'Low' }, +]; + +const COLORS = { + high: '#FFA69E', + medium: '#FAE3B4', + low: '#5B9A8B', +}; + +export function CodeChurnChart() { + return ( +
+
+ + + High Risk Files + 3 + + +

+ Files changed 30+ times +

+
+
+ + + + Medium Risk Files + 3 + + +

+ Files changed 15-30 times +

+
+
+ + + + Total Analyzed + 8 + + +

+ Most frequently changed +

+
+
+
+ + + + + + Code Churn by File + + + Files with the most changes - potential bug hotspots + + + + + + + + + + + {churnData.map((entry, index) => ( + + ))} + + + + +
+
+ Bug Hotspot Analysis +
+ {churnData.slice(0, 3).map((file, index) => ( +
+
+ +
+

{file.file}

+

+ {file.changes} changes detected +

+
+
+ + {file.bugRisk} Risk + +
+ ))} +
+
+
+
+ ); +} diff --git a/apps/frontend/src/components/CommitHeatmap.tsx b/apps/frontend/src/components/CommitHeatmap.tsx new file mode 100644 index 00000000..8202dff7 --- /dev/null +++ b/apps/frontend/src/components/CommitHeatmap.tsx @@ -0,0 +1,150 @@ +import { useState } from 'react'; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from './ui/tooltip'; + +interface CommitHeatmapProps { + data?: Array<{ date: string; count: number }>; +} + +// Generate mock data for the last 12 months +function generateHeatmapData() { + const data = []; + const today = new Date(); + + for (let i = 365; i >= 0; i--) { + const date = new Date(today); + date.setDate(date.getDate() - i); + + // Generate realistic commit patterns (more during weekdays, less on weekends) + const dayOfWeek = date.getDay(); + const isWeekend = dayOfWeek === 0 || dayOfWeek === 6; + const baseCount = isWeekend ? Math.random() * 3 : Math.random() * 15; + const count = Math.floor(baseCount); + + data.push({ + date: date.toISOString().split('T')[0], + count, + }); + } + + return data; +} + +export function CommitHeatmap({ + data = generateHeatmapData(), +}: CommitHeatmapProps) { + const [selectedDate, setSelectedDate] = useState(null); + + // Get intensity color based on count + const getColor = (count: number) => { + if (count === 0) return 'bg-muted/30'; + if (count < 3) return 'bg-primary/20'; + if (count < 6) return 'bg-primary/40'; + if (count < 9) return 'bg-primary/60'; + if (count < 12) return 'bg-primary/80'; + return 'bg-primary'; + }; + + // Group data by weeks + const weeks: Array> = []; + let currentWeek: Array<{ date: string; count: number }> = []; + + data.forEach((day, index) => { + const dayOfWeek = new Date(day.date).getDay(); + + if (dayOfWeek === 0 && currentWeek.length > 0) { + weeks.push(currentWeek); + currentWeek = []; + } + + currentWeek.push(day); + + if (index === data.length - 1 && currentWeek.length > 0) { + weeks.push(currentWeek); + } + }); + + const months = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec', + ]; + + const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; + + return ( +
+
+

Commit Activity

+
+ Less +
+
+
+
+
+
+
+ More +
+
+ +
+
+
+
+ {days.map((day, i) => ( +
+ {i % 2 === 1 ? day : ''} +
+ ))} +
+ + +
+ {weeks.map((week, weekIndex) => ( +
+ {weekIndex % 4 === 0 && ( +
+ {months[new Date(week[0].date).getMonth()]} +
+ )} + {weekIndex % 4 !== 0 &&
} + {week.map((day) => ( + + +
setSelectedDate(day.date)} + /> + + +

+ {day.count} {day.count === 1 ? 'commit' : 'commits'}{' '} + on {new Date(day.date).toLocaleDateString()} +

+
+ + ))} +
+ ))} +
+ +
+
+
+ ); +} diff --git a/apps/frontend/src/components/ContributionRanking.tsx b/apps/frontend/src/components/ContributionRanking.tsx new file mode 100644 index 00000000..fdc52ed8 --- /dev/null +++ b/apps/frontend/src/components/ContributionRanking.tsx @@ -0,0 +1,192 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from './ui/card'; +import { Avatar, AvatarFallback } from './ui/avatar'; +import { Badge } from './ui/badge'; +import { + Trophy, + Medal, + TrendingUp, + GitCommit, + Plus, + Minus, +} from 'lucide-react'; +import { Progress } from './ui/progress'; + +const contributors = [ + { + name: 'Sarah Chen', + initials: 'SC', + commits: 1247, + additions: 45632, + deletions: 12340, + rank: 1, + percentage: 35.8, + badge: '🏆 Top Contributor', + gradient: 'from-yellow-400 to-yellow-600', + }, + { + name: 'Marcus Johnson', + initials: 'MJ', + commits: 892, + additions: 32145, + deletions: 9876, + rank: 2, + percentage: 25.6, + badge: '🥈 Core Team', + gradient: 'from-gray-300 to-gray-500', + }, + { + name: 'Emma Rodriguez', + initials: 'ER', + commits: 654, + additions: 24567, + deletions: 7654, + rank: 3, + percentage: 18.8, + badge: '🥉 Active', + gradient: 'from-orange-400 to-orange-600', + }, + { + name: 'Alex Kim', + initials: 'AK', + commits: 423, + additions: 15234, + deletions: 4321, + rank: 4, + percentage: 12.1, + badge: '⭐ Regular', + gradient: 'from-primary to-secondary', + }, + { + name: 'Jordan Taylor', + initials: 'JT', + commits: 267, + additions: 8932, + deletions: 2345, + rank: 5, + percentage: 7.7, + badge: '✨ Rising', + gradient: 'from-purple-400 to-purple-600', + }, +]; + +const totalCommits = contributors.reduce((sum, c) => sum + c.commits, 0); + +export function ContributionRanking() { + return ( +
+
+ + + Top Contributor + {contributors[0].name} + + +

{contributors[0].commits}

+

commits

+
+
+ + + + Total Contributors + 24 + + +

+ {contributors.length} shown +

+
+
+ + + + Total Commits + + {totalCommits.toLocaleString()} + + + +

+ Across all contributors +

+
+
+
+ + + + + + Contribution Leaderboard + + + Top contributors ranked by commits and code changes + + + + {contributors.map((contributor, index) => ( +
+
+
+ + + {contributor.initials} + + +
+ #{contributor.rank} +
+
+ +
+
+

{contributor.name}

+ + {contributor.badge} + +
+ +
+
+ + {contributor.commits} commits +
+
+ + {contributor.additions.toLocaleString()} +
+
+ + {contributor.deletions.toLocaleString()} +
+
+ +
+
+ Contribution + {contributor.percentage}% +
+ +
+
+
+
+ ))} +
+
+
+ ); +} diff --git a/apps/frontend/src/components/DashboardPage.tsx b/apps/frontend/src/components/DashboardPage.tsx new file mode 100644 index 00000000..83b17a31 --- /dev/null +++ b/apps/frontend/src/components/DashboardPage.tsx @@ -0,0 +1,341 @@ +import { + Lock, + Users, + GitBranch, + Calendar, + FileCode, + TrendingUp, + AlertCircle, + Sparkles, + BarChart3, +} from 'lucide-react'; +import { motion } from 'motion/react'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from './ui/card'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'; +import { Badge } from './ui/badge'; +import { Button } from './ui/button'; +import { Avatar, AvatarFallback } from './ui/avatar'; +import { Alert, AlertDescription } from './ui/alert'; +import { CommitHeatmap } from './CommitHeatmap'; +import { FileDistributionChart } from './FileDistributionChart'; +import { ActivityChart } from './ActivityChart'; +import { ContributionRanking } from './ContributionRanking'; +import { CodeChurnChart } from './CodeChurnChart'; +import { FileTypeList } from './FileTypeList'; +import { GraphViewTimeline } from './GraphViewTimeline'; +import { GitDiffViewer } from './GitDiffViewer'; +import { AIInsights } from './AIInsights'; +import { PremiumFeatures } from './PremiumFeatures'; + +const repoData = { + name: 'analytics-pro', + owner: 'Octo Org', + created: '2019-06-14', + age: '5.7y', + lastCommit: '2 days ago', + totalCommits: 3482, + contributors: 24, +}; + +const contributors = [ + { name: 'John Doe', initials: 'JD' }, + { name: 'Jane Smith', initials: 'JS' }, + { name: 'Mike Johnson', initials: 'MJ' }, + { name: 'Sarah Williams', initials: 'SW' }, + { name: 'Tom Brown', initials: 'TB' }, +]; + +export function DashboardPage() { + return ( +
+
+
+
+ +
+
+

+ {repoData.owner}/{repoData.name} +

+

+ Repository Analytics +

+
+
+ + + + + Analysis complete. Data last updated {repoData.lastCommit}. + + +
+ + +
+ + + + Overview + Overview + + + + Heatmap + Heat + + + + Analytics + Analytics + + + + AI Insights + AI + + + + Premium + Pro + + +
+ + + + {/* Repo Summary Card */} + + + + Repository Summary + + + Key metrics and information + + + +
+
+

Repository

+

{repoData.name}

+
+
+

Owner

+

{repoData.owner}

+
+
+

Created

+

{repoData.created}

+
+
+

Age

+

{repoData.age}

+
+
+

Last Commit

+

{repoData.lastCommit}

+
+
+

+ Total Commits +

+

+ {repoData.totalCommits.toLocaleString()} +

+
+
+

+ Contributors +

+

{repoData.contributors}

+
+
+

Status

+ + Active + +
+
+
+
+ + {/* Contributors Card */} + + + + + Contributors + + + Top {contributors.length} contributors + + + +
+ {contributors.map((contributor, index) => ( +
+ + + {contributor.initials} + + + {contributor.name} +
+ ))} + +
+
+
+ + {/* File Distribution Card */} + + + File Distribution + Languages by percentage + + + + + + + {/* Activity Snapshot Card */} + + + Activity Snapshot + Commits over the last 30 days + + + + + +
+ + + + +
+ + + + +
+
+ Commit Heatmap + + Activity patterns over time with filters + +
+
+ + + +
+
+
+ + + +
+

Peak Activity Times

+
+ + +

+ Most Active Day +

+

Wednesday

+

+ Avg. 12 commits +

+
+
+ + +

+ Peak Month +

+

October 2024

+

+ 247 total commits +

+
+
+ + +

+ Current Streak +

+

14 days

+

+ Keep it up! +

+
+
+
+
+
+
+
+ + + + + Code Churn + File Types + Timeline + Git Diff + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ); +} diff --git a/apps/frontend/src/components/FileDistributionChart.tsx b/apps/frontend/src/components/FileDistributionChart.tsx new file mode 100644 index 00000000..3bc68fc2 --- /dev/null +++ b/apps/frontend/src/components/FileDistributionChart.tsx @@ -0,0 +1,73 @@ +import { + Cell, + Pie, + PieChart, + ResponsiveContainer, + Legend, + Tooltip, +} from 'recharts'; + +const COLORS = { + TypeScript: '#5B9A8B', + Go: '#FFA69E', + Python: '#2E073F', + JSON: '#7DB9A5', + Other: '#FFB8B1', +}; + +const data = [ + { name: 'TypeScript', value: 48, color: COLORS.TypeScript }, + { name: 'Go', value: 22, color: COLORS.Go }, + { name: 'Python', value: 18, color: COLORS.Python }, + { name: 'JSON', value: 7, color: COLORS.JSON }, + { name: 'Other', value: 5, color: COLORS.Other }, +]; + +export function FileDistributionChart() { + return ( +
+ + + + {data.map((entry, index) => ( + + ))} + + { + if (active && payload && payload.length) { + return ( +
+

+ {payload[0].name}:{' '} + {payload[0].value}% +

+
+ ); + } + return null; + }} + /> + ( + + {value} ({entry.payload.value}%) + + )} + /> +
+
+
+ ); +} diff --git a/apps/frontend/src/components/FileTypeList.tsx b/apps/frontend/src/components/FileTypeList.tsx new file mode 100644 index 00000000..a3df539b --- /dev/null +++ b/apps/frontend/src/components/FileTypeList.tsx @@ -0,0 +1,125 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from './ui/card'; +import { FileCode, FileJson, FileText, Image, File } from 'lucide-react'; +import { Progress } from './ui/progress'; + +const fileTypes = [ + { + type: 'TypeScript', + extension: '.ts, .tsx', + count: 247, + percentage: 42, + icon: FileCode, + color: 'bg-blue-500', + }, + { + type: 'JavaScript', + extension: '.js, .jsx', + count: 183, + percentage: 31, + icon: FileCode, + color: 'bg-yellow-500', + }, + { + type: 'JSON', + extension: '.json', + count: 72, + percentage: 12, + icon: FileJson, + color: 'bg-green-500', + }, + { + type: 'Markdown', + extension: '.md', + count: 45, + percentage: 8, + icon: FileText, + color: 'bg-purple-500', + }, + { + type: 'CSS/SCSS', + extension: '.css, .scss', + count: 28, + percentage: 5, + icon: FileText, + color: 'bg-pink-500', + }, + { + type: 'Images', + extension: '.png, .jpg, .svg', + count: 15, + percentage: 2, + icon: Image, + color: 'bg-orange-500', + }, +]; + +const totalFiles = fileTypes.reduce((sum, ft) => sum + ft.count, 0); + +export function FileTypeList() { + return ( + + + File Type Distribution + + Breakdown of {totalFiles.toLocaleString()} files by type + + + +
+ {fileTypes.map((fileType, index) => { + const Icon = fileType.icon; + return ( +
+
+
+
+ +
+
+

{fileType.type}

+

+ {fileType.extension} +

+
+
+
+

{fileType.count}

+

+ {fileType.percentage}% +

+
+
+ +
+ ); + })} +
+ +
+
+
+

Total Files

+

+ {totalFiles.toLocaleString()} +

+
+
+

File Types

+

{fileTypes.length}

+
+
+
+
+
+ ); +} diff --git a/apps/frontend/src/components/Footer.tsx b/apps/frontend/src/components/Footer.tsx new file mode 100644 index 00000000..4cf5197e --- /dev/null +++ b/apps/frontend/src/components/Footer.tsx @@ -0,0 +1,25 @@ +export function Footer() { + return ( + + ); +} diff --git a/apps/frontend/src/components/GitDiffViewer.tsx b/apps/frontend/src/components/GitDiffViewer.tsx new file mode 100644 index 00000000..586b459a --- /dev/null +++ b/apps/frontend/src/components/GitDiffViewer.tsx @@ -0,0 +1,265 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from './ui/card'; +import { Badge } from './ui/badge'; +import { Button } from './ui/button'; +import { FileCode, ChevronDown, ChevronRight, Plus, Minus } from 'lucide-react'; +import { useState } from 'react'; +import { ScrollArea } from './ui/scroll-area'; + +const diffFiles = [ + { + name: 'src/components/Dashboard.tsx', + additions: 45, + deletions: 12, + status: 'modified', + diff: [ + { type: 'context', line: "import { Card } from './ui/card';", number: 1 }, + { + type: 'context', + line: "import { Button } from './ui/button';", + number: 2, + }, + { type: 'add', line: "import { Badge } from './ui/badge';", number: 3 }, + { type: 'context', line: '', number: 4 }, + { type: 'context', line: 'export function Dashboard() {', number: 5 }, + { + type: 'remove', + line: ' const [data, setData] = useState(null);', + number: 6, + }, + { + type: 'add', + line: ' const [data, setData] = useState(null);', + number: 7, + }, + { + type: 'add', + line: ' const [loading, setLoading] = useState(false);', + number: 8, + }, + { type: 'context', line: '', number: 9 }, + { type: 'context', line: ' return (', number: 10 }, + { type: 'remove', line: '
Dashboard
', number: 11 }, + { type: 'add', line: "
", number: 12 }, + { type: 'add', line: '

Dashboard

', number: 13 }, + { type: 'add', line: ' ', number: 14 }, + { + type: 'add', + line: ' Analytics', + number: 15, + }, + { type: 'add', line: ' ', number: 16 }, + { type: 'add', line: '
', number: 17 }, + { type: 'context', line: ' );', number: 18 }, + { type: 'context', line: '}', number: 19 }, + ], + }, + { + name: 'src/lib/api.ts', + additions: 23, + deletions: 5, + status: 'modified', + diff: [ + { type: 'context', line: 'async function fetchData() {', number: 1 }, + { + type: 'remove', + line: " const response = await fetch('/api/data');", + number: 2, + }, + { + type: 'add', + line: " const response = await fetch('/api/v2/data', {", + number: 3, + }, + { + type: 'add', + line: " headers: { 'Authorization': `Bearer ${token}` }", + number: 4, + }, + { type: 'add', line: ' });', number: 5 }, + { type: 'context', line: ' return response.json();', number: 6 }, + { type: 'context', line: '}', number: 7 }, + ], + }, + { + name: 'src/styles/globals.css', + additions: 8, + deletions: 2, + status: 'modified', + diff: [ + { type: 'context', line: ':root {', number: 1 }, + { type: 'remove', line: ' --primary: #3b82f6;', number: 2 }, + { type: 'add', line: ' --primary: #5B9A8B;', number: 3 }, + { type: 'add', line: ' --secondary: #FFA69E;', number: 4 }, + { type: 'context', line: '}', number: 5 }, + ], + }, +]; + +export function GitDiffViewer() { + const [expandedFiles, setExpandedFiles] = useState>( + new Set([diffFiles[0].name]) + ); + + const toggleFile = (fileName: string) => { + const newExpanded = new Set(expandedFiles); + if (newExpanded.has(fileName)) { + newExpanded.delete(fileName); + } else { + newExpanded.add(fileName); + } + setExpandedFiles(newExpanded); + }; + + const totalAdditions = diffFiles.reduce( + (sum, file) => sum + file.additions, + 0 + ); + const totalDeletions = diffFiles.reduce( + (sum, file) => sum + file.deletions, + 0 + ); + + return ( +
+ + + + + Git Diff Viewer + + + Compare current version with previous commit + + + +
+
+ + + {totalAdditions} additions + + + + {totalDeletions} deletions + +
+
+
+
+ + {diffFiles.length} files changed + +
+ +
+ {diffFiles.map((file, index) => ( +
+ + + {expandedFiles.has(file.name) && ( + +
+ {file.diff.map((line, lineIndex) => ( +
+ + {line.number} + + + {line.type === 'add' + ? '+' + : line.type === 'remove' + ? '-' + : ' '} + + + {line.line} + +
+ ))} +
+
+ )} +
+ ))} +
+ +
+

+ Comparing with commit{' '} + + a3f4c21 + +

+
+ + +
+
+ + +
+ ); +} diff --git a/apps/frontend/src/components/GraphViewTimeline.tsx b/apps/frontend/src/components/GraphViewTimeline.tsx new file mode 100644 index 00000000..e9067732 --- /dev/null +++ b/apps/frontend/src/components/GraphViewTimeline.tsx @@ -0,0 +1,307 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from './ui/card'; +import { Button } from './ui/button'; +import { Badge } from './ui/badge'; +import { + GitBranch, + GitMerge, + GitCommit, + Play, + Pause, + RotateCcw, + Maximize2, +} from 'lucide-react'; +import { Slider } from './ui/slider'; +import { useState } from 'react'; +import { HoverCard, HoverCardContent, HoverCardTrigger } from './ui/hover-card'; + +const branches = [ + { name: 'main', color: '#5B9A8B', commits: 247, active: true }, + { name: 'develop', color: '#FFA69E', commits: 183, active: true }, + { name: 'feature/analytics', color: '#FAE3B4', commits: 42, active: true }, + { name: 'hotfix/auth', color: '#2E073F', commits: 12, active: false }, +]; + +const timelineEvents = [ + { + type: 'commit', + branch: 'main', + message: 'feat: Add user authentication', + author: 'Sarah C.', + date: '2 hours ago', + hash: 'a3f4c21', + }, + { + type: 'merge', + branch: 'main', + from: 'develop', + message: 'Merge develop into main', + author: 'Marcus J.', + date: '5 hours ago', + hash: 'b7e8d92', + }, + { + type: 'commit', + branch: 'feature/analytics', + message: 'fix: Chart rendering issue', + author: 'Emma R.', + date: '1 day ago', + hash: 'c9f1a34', + }, + { + type: 'commit', + branch: 'develop', + message: 'refactor: Code cleanup', + author: 'Alex K.', + date: '2 days ago', + hash: 'd2b5e67', + }, +]; + +export function GraphViewTimeline() { + const [playing, setPlaying] = useState(false); + const [timelinePosition, setTimelinePosition] = useState([50]); + + return ( +
+
+ {branches.map((branch, index) => ( + + +
+
+ + {branch.name} + +
+ + +

{branch.commits}

+

commits

+
+ + ))} +
+ + + +
+
+ + + Network Graph Timeline + + + Visual representation of branches, commits, and merges + +
+ +
+
+ + {/* Visual Timeline Graph */} +
+ + {/* Main branch line */} + + + {/* Develop branch line */} + + + + + {/* Feature branch line */} + + + + + {/* Commit dots */} + + + + + + + + + + + + + +
+ + {/* Playback Controls */} +
+
+ + +
+ +
+ + {timelinePosition[0]}% + +
+
+ + {/* Recent Events */} +
+

Recent Activity

+ {timelineEvents.map((event, index) => ( + + +
+
+ {event.type === 'merge' ? ( + + ) : ( + + )} +
+
+
+ + {event.branch} + + + {event.date} + +
+

{event.message}

+

+ by {event.author} · {event.hash} +

+
+
+
+ +
+
+ + {event.type} + + + {event.hash} + +
+

{event.message}

+
+ {event.author} + {event.date} +
+ {event.type === 'merge' && ( +

+ Merged {event.from} → {event.branch} +

+ )} +
+
+
+ ))} +
+
+
+
+ ); +} diff --git a/apps/frontend/src/components/Header.tsx b/apps/frontend/src/components/Header.tsx new file mode 100644 index 00000000..45813610 --- /dev/null +++ b/apps/frontend/src/components/Header.tsx @@ -0,0 +1,113 @@ +import { Menu, Bell } from 'lucide-react'; +import { Button } from './ui/button'; +import { Avatar, AvatarFallback } from './ui/avatar'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from './ui/dropdown-menu'; +import { Badge } from './ui/badge'; + +interface HeaderProps { + isSignedIn: boolean; + onMenuClick: () => void; + onNewsClick: () => void; + onSignOut?: () => void; + onNavigateHome: () => void; + showNews?: boolean; + hasUnreadNews?: boolean; + title?: string; +} + +export function Header({ + isSignedIn, + onMenuClick, + onNewsClick, + onSignOut, + onNavigateHome, + showNews = false, + hasUnreadNews = false, + title, +}: HeaderProps) { + return ( +
+
+
+ + + +
+ +
+ {showNews && ( +
+ + {hasUnreadNews && ( + + )} +
+ )} + + {isSignedIn ? ( + + + + + + Account Settings + Log out + + + ) : ( + + )} +
+
+
+ ); +} diff --git a/apps/frontend/src/components/InfoModal.tsx b/apps/frontend/src/components/InfoModal.tsx new file mode 100644 index 00000000..63ac4dc8 --- /dev/null +++ b/apps/frontend/src/components/InfoModal.tsx @@ -0,0 +1,51 @@ +import { X } from 'lucide-react'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from './ui/dialog'; + +interface InfoModalProps { + open: boolean; + onClose: () => void; + type: 'what' | 'private' | 'local' | null; +} + +const infoContent = { + what: { + title: 'What is GitRay?', + description: + 'GitRay is a powerful Git repository analytics tool that helps you understand your codebase better. It analyzes commit patterns, file distributions, contributor activity, and provides actionable insights to improve your development workflow. Simply paste a GitHub repository URL to get started.', + }, + private: { + title: 'Analyze a Private Repository', + description: + "To analyze private repositories, you'll need to provide a GitHub Personal Access Token. Go to Settings → Connections and add your token. GitRay securely uses this token to fetch repository data without storing your credentials. Your token is encrypted and only used for analysis purposes.", + }, + local: { + title: 'Analyze on a Local Server', + description: + 'GitRay can be self-hosted on your local server for enhanced privacy and control. Clone the GitRay repository, configure your environment variables, and run the Docker container. This allows you to analyze private repositories without sharing data externally. Check our documentation for setup instructions.', + }, +}; + +export function InfoModal({ open, onClose, type }: InfoModalProps) { + if (!type) return null; + + const content = infoContent[type]; + + return ( + + + + {content.title} + + {content.description} + + + + + ); +} diff --git a/apps/frontend/src/components/LandingPage.tsx b/apps/frontend/src/components/LandingPage.tsx new file mode 100644 index 00000000..41288076 --- /dev/null +++ b/apps/frontend/src/components/LandingPage.tsx @@ -0,0 +1,121 @@ +import { useState } from 'react'; +import { ChevronDown, ArrowRight } from 'lucide-react'; +import { Button } from './ui/button'; +import { Input } from './ui/input'; +import { Label } from './ui/label'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from './ui/select'; + +interface LandingPageProps { + onAnalyze: (url: string, mode: string) => void; + onInfoClick: (type: 'what' | 'private' | 'local') => void; +} + +export function LandingPage({ onAnalyze, onInfoClick }: LandingPageProps) { + const [url, setUrl] = useState(''); + const [mode, setMode] = useState('main'); + + const handleAnalyze = () => { + if (url.trim()) { + onAnalyze(url, mode); + } + }; + + return ( +
+
+ {/* Hero Wordmark */} +
+

+ GitRay +

+

+ Powerful analytics for your Git repositories. Understand your + codebase like never before. +

+
+ + {/* Input Section */} +
+
+ + setUrl(e.target.value)} + className="h-12 md:h-14 text-base md:text-lg border-2 focus:border-primary transition-colors" + onKeyDown={(e) => { + if (e.key === 'Enter') { + handleAnalyze(); + } + }} + /> +
+ +
+ + +
+ + +
+ + {/* Helper Chips */} +
+ + + +
+
+
+ ); +} diff --git a/apps/frontend/src/components/LoadingSpinner.tsx b/apps/frontend/src/components/LoadingSpinner.tsx new file mode 100644 index 00000000..38e6df0e --- /dev/null +++ b/apps/frontend/src/components/LoadingSpinner.tsx @@ -0,0 +1,19 @@ +import { Loader2 } from 'lucide-react'; + +interface LoadingSpinnerProps { + message?: string; +} + +export function LoadingSpinner({ + message = 'Loading...', +}: LoadingSpinnerProps) { + return ( +
+
+
+ +
+

{message}

+
+ ); +} diff --git a/apps/frontend/src/components/NewsDrawer.tsx b/apps/frontend/src/components/NewsDrawer.tsx new file mode 100644 index 00000000..f387450d --- /dev/null +++ b/apps/frontend/src/components/NewsDrawer.tsx @@ -0,0 +1,91 @@ +import { ExternalLink } from 'lucide-react'; +import { Button } from './ui/button'; +import { Sheet, SheetContent, SheetHeader, SheetTitle } from './ui/sheet'; + +interface NewsDrawerProps { + open: boolean; + onClose: () => void; +} + +const newsItems = [ + { + version: 'v2.0', + title: 'Major Update: AI Insights & Premium Features', + description: + 'Introducing AI-powered project analysis, weekly summaries, and comprehensive premium features including multi-language support (8 languages available).', + date: 'Just now', + }, + { + version: 'v2.0', + title: 'New: Advanced Analytics Tab', + description: + 'Access Code Churn Analysis, File Type Distribution, Graph View Timeline with playback, and Git Diff viewer all in one place.', + date: 'Just now', + }, + { + version: 'v2.0', + title: 'Enhanced: Contribution Ranking', + description: + 'See detailed contributor leaderboards with commit counts, code changes, and achievement badges on the Overview tab.', + date: 'Just now', + }, + { + version: 'v1.9', + title: 'Private repo tokens', + description: + 'You can now add tokens to Connections to analyze private repositories securely.', + date: '2 days ago', + }, + { + version: 'v1.8', + title: 'New: File Distribution chart', + description: + "Visualize your repository's file types and language distribution with our new chart.", + date: '1 week ago', + }, +]; + +export function NewsDrawer({ open, onClose }: NewsDrawerProps) { + return ( + + + + What's New + + +
+ {newsItems.map((item, index) => ( +
+
+
+
+ + {item.version} + +
+

{item.title}

+
+
+

+ {item.description} +

+

{item.date}

+
+ ))} + + +
+
+
+ ); +} diff --git a/apps/frontend/src/components/PremiumFeatures.tsx b/apps/frontend/src/components/PremiumFeatures.tsx new file mode 100644 index 00000000..f89ebb77 --- /dev/null +++ b/apps/frontend/src/components/PremiumFeatures.tsx @@ -0,0 +1,412 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from './ui/card'; +import { Badge } from './ui/badge'; +import { Button } from './ui/button'; +import { + Lock, + Play, + Download, + ZoomIn, + Layers, + Users, + MessageSquare, + Trophy, + FileType, + Smartphone, + Monitor, + Shield, + Rocket, +} from 'lucide-react'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'; + +const premiumFeatures = [ + { + category: 'Visualizations', + icon: Play, + features: [ + { + name: 'Time-lapse Animation (Gource)', + description: + 'Watch your project evolution with animated commit history visualization', + icon: Play, + badge: 'Premium', + }, + { + name: 'Export Visualizations', + description: + 'Export charts, graphs, and reports in PNG, SVG, or PDF formats', + icon: Download, + badge: 'Premium', + }, + { + name: 'Advanced Zoom & Pan', + description: + 'Interactive navigation with smooth zooming and panning controls', + icon: ZoomIn, + badge: 'Premium', + }, + ], + }, + { + category: 'Analysis Tools', + icon: Layers, + features: [ + { + name: 'UML Diagram Generation', + description: + 'Automatically generate UML diagrams from your codebase using PlantUML', + icon: FileType, + badge: 'Premium', + }, + { + name: 'Project Efficiency Analysis', + description: + 'Get insights on how to complete projects faster and more efficiently', + icon: Rocket, + badge: 'Premium', + }, + { + name: 'Security Insights', + description: + 'Advanced vulnerability detection and security recommendations', + icon: Shield, + badge: 'Premium', + }, + ], + }, + { + category: 'Multi-Project Management', + icon: Layers, + features: [ + { + name: 'Manage Multiple Repositories', + description: + 'Analyze and track multiple projects simultaneously with unified dashboard', + icon: Layers, + badge: 'Team', + }, + { + name: 'Team Collaboration', + description: + 'Share insights, add team members, and collaborate with built-in chat', + icon: Users, + badge: 'Team', + }, + { + name: 'Team Chat Rooms', + description: + 'Real-time communication with push notifications and email alerts', + icon: MessageSquare, + badge: 'Team', + }, + { + name: 'Gamification System', + description: + 'Track levels, ranks, and achievements to motivate your team', + icon: Trophy, + badge: 'Team', + }, + ], + }, + { + category: 'Desktop & Mobile', + icon: Monitor, + features: [ + { + name: 'Desktop Application', + description: + 'Download GitRay as a standalone executable with offline AI capabilities', + icon: Monitor, + badge: 'Enterprise', + }, + { + name: 'Progressive Web App (PWA)', + description: + 'Install GitRay on Android devices with native app experience', + icon: Smartphone, + badge: 'Premium', + }, + ], + }, +]; + +const pricingPlans = [ + { + name: 'Free', + price: '$0', + period: 'forever', + description: 'Perfect for individuals and small projects', + features: [ + 'Up to 3 repositories', + 'Basic analytics & visualizations', + '7-day data retention', + 'Community support', + ], + cta: 'Current Plan', + highlighted: false, + }, + { + name: 'Premium', + price: '$15', + period: 'per month', + description: 'Advanced features for serious developers', + features: [ + 'Unlimited repositories', + 'All visualizations & exports', + '30-day data retention', + 'AI-powered insights', + 'Priority support', + 'Zoom & Pan controls', + ], + cta: 'Upgrade to Premium', + highlighted: true, + }, + { + name: 'Team', + price: '$49', + period: 'per month', + description: 'Collaborate with your entire team', + features: [ + 'Everything in Premium', + 'Multi-project management', + 'Team collaboration tools', + 'Real-time team chat', + 'Gamification system', + '90-day data retention', + 'Up to 10 team members', + ], + cta: 'Start Team Trial', + highlighted: false, + }, + { + name: 'Enterprise', + price: 'Custom', + period: 'contact us', + description: 'For large organizations with specific needs', + features: [ + 'Everything in Team', + 'Unlimited team members', + 'Desktop application', + 'Offline AI capabilities', + 'Custom integrations', + 'Dedicated support', + 'SLA guarantees', + 'On-premise deployment', + ], + cta: 'Contact Sales', + highlighted: false, + }, +]; + +export function PremiumFeatures() { + return ( +
+ + + Premium Features + Plans & Pricing + + + + {premiumFeatures.map((category, categoryIndex) => { + const CategoryIcon = category.icon; + return ( + + + + + {category.category} + + + Unlock powerful tools to supercharge your workflow + + + +
+ {category.features.map((feature, featureIndex) => { + const FeatureIcon = feature.icon; + return ( +
+
+
+
+
+ +
+ + {feature.badge} + +
+
+

+ {feature.name} +

+

+ {feature.description} +

+
+ +
+
+ ); + })} +
+ + + ); + })} + + + + +
+

Unlock All Premium Features

+

+ Get access to advanced visualizations, AI insights, team + collaboration tools, and much more with a Premium + subscription. +

+
+
+ + +
+

+ 14-day free trial · No credit card required +

+
+
+ + + +
+ {pricingPlans.map((plan, index) => ( + + {plan.highlighted && ( +
+ Most Popular +
+ )} + + {plan.name} +
+ {plan.price} + + {plan.price !== 'Custom' && `/${plan.period}`} + +
+ {plan.description} +
+ +
    + {plan.features.map((feature, featureIndex) => ( +
  • +
    +
    +
    + {feature} +
  • + ))} +
+ +
+
+ ))} +
+ + + + Compare All Plans + + Choose the plan that best fits your needs + + + +
+ + + + + {pricingPlans.map((plan, index) => ( + + ))} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature + {plan.name} +
RepositoriesUp to 3UnlimitedUnlimitedUnlimited
Data Retention7 days30 days90 daysUnlimited
AI Insights-✓ + Offline
Team Collaboration--
Desktop App---
+
+
+
+
+ +
+ ); +} diff --git a/apps/frontend/src/components/SettingsDrawer.tsx b/apps/frontend/src/components/SettingsDrawer.tsx new file mode 100644 index 00000000..468d3b78 --- /dev/null +++ b/apps/frontend/src/components/SettingsDrawer.tsx @@ -0,0 +1,184 @@ +import { X } from 'lucide-react'; +import { Button } from './ui/button'; +import { Label } from './ui/label'; +import { Input } from './ui/input'; +import { RadioGroup, RadioGroupItem } from './ui/radio-group'; +import { Switch } from './ui/switch'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'; +import { Sheet, SheetContent, SheetHeader, SheetTitle } from './ui/sheet'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from './ui/select'; +import { useState } from 'react'; + +interface SettingsDrawerProps { + open: boolean; + onClose: () => void; + theme: 'light' | 'dark' | 'system'; + onThemeChange: (theme: 'light' | 'dark' | 'system') => void; +} + +export function SettingsDrawer({ + open, + onClose, + theme, + onThemeChange, +}: SettingsDrawerProps) { + const [language, setLanguage] = useState('english'); + + return ( + + + + Settings + + + + + General + Appearance + Account + Connections + + + +
+

General Settings

+
+
+ + +

+ Choose your preferred display language +

+
+
+
+ +

+ Start analysis automatically when pasting a URL +

+
+ +
+
+
+ +

+ Get notified when analysis completes +

+
+ +
+
+
+ +

+ Allow exporting visualizations and reports +

+
+ +
+
+
+
+ + +
+

Theme

+ +
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+

Account Information

+
+
+ + +
+
+ + +
+ +
+
+
+ + +
+

API Connections

+
+
+ + +

+ Required for private repositories +

+
+
+ + +

+ For enhanced AI-powered insights +

+
+ +
+
+
+
+
+
+ ); +} diff --git a/apps/frontend/src/components/figma/ImageWithFallback.tsx b/apps/frontend/src/components/figma/ImageWithFallback.tsx new file mode 100644 index 00000000..0b119580 --- /dev/null +++ b/apps/frontend/src/components/figma/ImageWithFallback.tsx @@ -0,0 +1,41 @@ +import React, { useState } from 'react'; + +const ERROR_IMG_SRC = + 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODgiIGhlaWdodD0iODgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBvcGFjaXR5PSIuMyIgZmlsbD0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIzLjciPjxyZWN0IHg9IjE2IiB5PSIxNiIgd2lkdGg9IjU2IiBoZWlnaHQ9IjU2IiByeD0iNiIvPjxwYXRoIGQ9Im0xNiA1OCAxNi0xOCAzMiAzMiIvPjxjaXJjbGUgY3g9IjUzIiBjeT0iMzUiIHI9IjciLz48L3N2Zz4KCg=='; + +export function ImageWithFallback( + props: React.ImgHTMLAttributes +) { + const [didError, setDidError] = useState(false); + + const handleError = () => { + setDidError(true); + }; + + const { src, alt, style, className, ...rest } = props; + + return didError ? ( +
+
+ Error loading image +
+
+ ) : ( + {alt} + ); +} diff --git a/apps/frontend/src/components/ui/accordion.tsx b/apps/frontend/src/components/ui/accordion.tsx new file mode 100644 index 00000000..40fbdd5e --- /dev/null +++ b/apps/frontend/src/components/ui/accordion.tsx @@ -0,0 +1,66 @@ +'use client'; + +import * as React from 'react'; +import * as AccordionPrimitive from '@radix-ui/react-accordion@1.2.3'; +import { ChevronDownIcon } from 'lucide-react@0.487.0'; + +import { cn } from './utils'; + +function Accordion({ + ...props +}: React.ComponentProps) { + return ; +} + +function AccordionItem({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AccordionTrigger({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + svg]:rotate-180', + className + )} + {...props} + > + {children} + + + + ); +} + +function AccordionContent({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + +
{children}
+
+ ); +} + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; diff --git a/apps/frontend/src/components/ui/alert-dialog.tsx b/apps/frontend/src/components/ui/alert-dialog.tsx new file mode 100644 index 00000000..ac60e64e --- /dev/null +++ b/apps/frontend/src/components/ui/alert-dialog.tsx @@ -0,0 +1,157 @@ +'use client'; + +import * as React from 'react'; +import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog@1.1.6'; + +import { cn } from './utils'; +import { buttonVariants } from './button'; + +function AlertDialog({ + ...props +}: React.ComponentProps) { + return ; +} + +function AlertDialogTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogPortal({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + + + + ); +} + +function AlertDialogHeader({ + className, + ...props +}: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertDialogFooter({ + className, + ...props +}: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertDialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogAction({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogCancel({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +}; diff --git a/apps/frontend/src/components/ui/alert.tsx b/apps/frontend/src/components/ui/alert.tsx new file mode 100644 index 00000000..f9dc4c2f --- /dev/null +++ b/apps/frontend/src/components/ui/alert.tsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority@0.7.1'; + +import { cn } from './utils'; + +const alertVariants = cva( + 'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current', + { + variants: { + variant: { + default: 'bg-card text-card-foreground', + destructive: + 'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90', + }, + }, + defaultVariants: { + variant: 'default', + }, + } +); + +function Alert({ + className, + variant, + ...props +}: React.ComponentProps<'div'> & VariantProps) { + return ( +
+ ); +} + +function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertDescription({ + className, + ...props +}: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +export { Alert, AlertTitle, AlertDescription }; diff --git a/apps/frontend/src/components/ui/aspect-ratio.tsx b/apps/frontend/src/components/ui/aspect-ratio.tsx new file mode 100644 index 00000000..02fc1a3a --- /dev/null +++ b/apps/frontend/src/components/ui/aspect-ratio.tsx @@ -0,0 +1,11 @@ +'use client'; + +import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio@1.1.2'; + +function AspectRatio({ + ...props +}: React.ComponentProps) { + return ; +} + +export { AspectRatio }; diff --git a/apps/frontend/src/components/ui/avatar.tsx b/apps/frontend/src/components/ui/avatar.tsx new file mode 100644 index 00000000..b0d2ff0d --- /dev/null +++ b/apps/frontend/src/components/ui/avatar.tsx @@ -0,0 +1,53 @@ +'use client'; + +import * as React from 'react'; +import * as AvatarPrimitive from '@radix-ui/react-avatar@1.1.3'; + +import { cn } from './utils'; + +function Avatar({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AvatarImage({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AvatarFallback({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +export { Avatar, AvatarImage, AvatarFallback }; diff --git a/apps/frontend/src/components/ui/badge.tsx b/apps/frontend/src/components/ui/badge.tsx new file mode 100644 index 00000000..be656267 --- /dev/null +++ b/apps/frontend/src/components/ui/badge.tsx @@ -0,0 +1,46 @@ +import * as React from 'react'; +import { Slot } from '@radix-ui/react-slot@1.1.2'; +import { cva, type VariantProps } from 'class-variance-authority@0.7.1'; + +import { cn } from './utils'; + +const badgeVariants = cva( + 'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden', + { + variants: { + variant: { + default: + 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90', + secondary: + 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90', + destructive: + 'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', + outline: + 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground', + }, + }, + defaultVariants: { + variant: 'default', + }, + } +); + +function Badge({ + className, + variant, + asChild = false, + ...props +}: React.ComponentProps<'span'> & + VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot : 'span'; + + return ( + + ); +} + +export { Badge, badgeVariants }; diff --git a/apps/frontend/src/components/ui/breadcrumb.tsx b/apps/frontend/src/components/ui/breadcrumb.tsx new file mode 100644 index 00000000..c93d8efd --- /dev/null +++ b/apps/frontend/src/components/ui/breadcrumb.tsx @@ -0,0 +1,109 @@ +import * as React from 'react'; +import { Slot } from '@radix-ui/react-slot@1.1.2'; +import { ChevronRight, MoreHorizontal } from 'lucide-react@0.487.0'; + +import { cn } from './utils'; + +function Breadcrumb({ ...props }: React.ComponentProps<'nav'>) { + return