From d97b0c7ffcc0f688de7c58ea52b43c728d651e4e Mon Sep 17 00:00:00 2001 From: ashish200729 Date: Sat, 6 Jun 2026 17:21:29 +0530 Subject: [PATCH] Fix CI backend tests and ship frontend UI overhaul Replace the brittle test/**/*.test.js glob (fails on Linux Node 20 CI) with a cross-platform test runner script. Includes dashboard layout, portfolio template redesign, unified theming, and navbar polish. --- backend/package.json | 2 +- backend/scripts/run-tests.mjs | 19 + frontend/index.html | 6 +- frontend/public/favicon.svg | 4 +- frontend/public/manifest.json | 4 +- frontend/public/og-image.svg | 46 +- frontend/src/App.jsx | 158 +-- frontend/src/components/AsyncState.jsx | 35 + frontend/src/components/DashboardLayout.jsx | 99 ++ frontend/src/components/DashboardSidebar.jsx | 209 +++ frontend/src/components/DashboardSkeleton.jsx | 29 + frontend/src/components/IconTile.jsx | 27 + frontend/src/components/MobileTabBar.jsx | 29 + frontend/src/components/Navbar.jsx | 431 +++--- frontend/src/components/PageHeader.jsx | 22 + frontend/src/components/ProfileCard.jsx | 63 +- frontend/src/components/ScrollToTop.jsx | 23 + frontend/src/components/SectionHeading.jsx | 9 + frontend/src/components/ThemeToggle.jsx | 37 +- frontend/src/components/UploadZone.jsx | 37 +- frontend/src/context/ToastContext.jsx | 211 +-- frontend/src/index.css | 319 +++-- frontend/src/main.jsx | 20 +- frontend/src/pages/Analytics.jsx | 275 +--- frontend/src/pages/Dashboard.jsx | 667 +++------ frontend/src/pages/Landing.jsx | 398 ++---- frontend/src/pages/Onboarding.jsx | 107 +- frontend/src/pages/Portfolio.jsx | 1236 +---------------- frontend/src/pages/Premium.jsx | 162 +-- frontend/src/pages/ProfileEditor.jsx | 113 +- frontend/src/pages/ResumeUpload.jsx | 84 +- frontend/src/pages/Settings.jsx | 358 ++--- frontend/src/pages/UsernameSelection.jsx | 23 +- frontend/src/portfolio/PortfolioTemplate.jsx | 121 ++ frontend/src/portfolio/buildSections.js | 100 ++ .../src/portfolio/components/ErrorState.jsx | 27 + frontend/src/portfolio/components/Footer.jsx | 124 ++ .../src/portfolio/components/LoadingState.jsx | 15 + .../src/portfolio/components/ProfileAside.jsx | 142 ++ .../portfolio/components/SectionContent.jsx | 446 ++++++ .../src/portfolio/components/SectionNav.jsx | 30 + frontend/src/portfolio/components/TopBar.jsx | 32 + frontend/src/portfolio/portfolio.css | 149 ++ frontend/src/portfolio/theme.js | 103 ++ frontend/src/utils/clerkAppearance.js | 117 ++ frontend/tailwind.config.js | 88 +- 46 files changed, 3336 insertions(+), 3420 deletions(-) create mode 100644 backend/scripts/run-tests.mjs create mode 100644 frontend/src/components/AsyncState.jsx create mode 100644 frontend/src/components/DashboardLayout.jsx create mode 100644 frontend/src/components/DashboardSidebar.jsx create mode 100644 frontend/src/components/DashboardSkeleton.jsx create mode 100644 frontend/src/components/IconTile.jsx create mode 100644 frontend/src/components/MobileTabBar.jsx create mode 100644 frontend/src/components/PageHeader.jsx create mode 100644 frontend/src/components/ScrollToTop.jsx create mode 100644 frontend/src/components/SectionHeading.jsx create mode 100644 frontend/src/portfolio/PortfolioTemplate.jsx create mode 100644 frontend/src/portfolio/buildSections.js create mode 100644 frontend/src/portfolio/components/ErrorState.jsx create mode 100644 frontend/src/portfolio/components/Footer.jsx create mode 100644 frontend/src/portfolio/components/LoadingState.jsx create mode 100644 frontend/src/portfolio/components/ProfileAside.jsx create mode 100644 frontend/src/portfolio/components/SectionContent.jsx create mode 100644 frontend/src/portfolio/components/SectionNav.jsx create mode 100644 frontend/src/portfolio/components/TopBar.jsx create mode 100644 frontend/src/portfolio/portfolio.css create mode 100644 frontend/src/portfolio/theme.js create mode 100644 frontend/src/utils/clerkAppearance.js diff --git a/backend/package.json b/backend/package.json index a6329ba..4b454d2 100644 --- a/backend/package.json +++ b/backend/package.json @@ -7,7 +7,7 @@ "scripts": { "dev": "node --watch src/index.js", "start": "node src/index.js", - "test": "node --test test/**/*.test.js" + "test": "node scripts/run-tests.mjs" }, "dependencies": { "@clerk/express": "^1.0.0", diff --git a/backend/scripts/run-tests.mjs b/backend/scripts/run-tests.mjs new file mode 100644 index 0000000..013fecc --- /dev/null +++ b/backend/scripts/run-tests.mjs @@ -0,0 +1,19 @@ +import { readdirSync } from 'node:fs' +import { spawnSync } from 'node:child_process' +import { join, dirname } from 'node:path' +import { fileURLToPath } from 'node:url' + +const root = join(dirname(fileURLToPath(import.meta.url)), '..') +const testDir = join(root, 'test') +const files = readdirSync(testDir) + .filter((name) => name.endsWith('.test.js')) + .map((name) => join(testDir, name)) + .sort() + +if (files.length === 0) { + console.error('No test files found in backend/test/') + process.exit(1) +} + +const result = spawnSync(process.execPath, ['--test', ...files], { stdio: 'inherit' }) +process.exit(result.status ?? 1) \ No newline at end of file diff --git a/frontend/index.html b/frontend/index.html index 9706096..5bb059c 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -24,8 +24,8 @@ - - + + @@ -137,7 +137,7 @@ diff --git a/frontend/public/favicon.svg b/frontend/public/favicon.svg index 9301c7d..d359530 100644 --- a/frontend/public/favicon.svg +++ b/frontend/public/favicon.svg @@ -1,8 +1,8 @@ - - + + diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json index e214538..96eea35 100644 --- a/frontend/public/manifest.json +++ b/frontend/public/manifest.json @@ -4,8 +4,8 @@ "description": "Transform your resume into a stunning, professional portfolio in seconds with AI.", "start_url": "/", "display": "standalone", - "background_color": "#0f0f23", - "theme_color": "#6366f1", + "background_color": "#09090b", + "theme_color": "#5a7a9e", "orientation": "portrait-primary", "scope": "/", "lang": "en", diff --git a/frontend/public/og-image.svg b/frontend/public/og-image.svg index f411fcf..e415920 100644 --- a/frontend/public/og-image.svg +++ b/frontend/public/og-image.svg @@ -1,13 +1,13 @@ - - - + + + - - + + @@ -18,48 +18,38 @@ - - - - - + + + - - + - - P - - Portlify + Portlify - - AI-Powered Resume to Portfolio Builder + AI-Powered Resume to Portfolio Builder - - - ✨ AI Parsing + + ✨ AI Parsing - - ⚡ Instant Portfolio + + ⚡ Instant Portfolio - - 📊 Analytics + + 📊 Analytics - portlify.techycsr.dev - - Transform your resume into a stunning portfolio in seconds + Transform your resume into a stunning portfolio in seconds \ No newline at end of file diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 663820a..5d3ae8d 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -3,6 +3,7 @@ import { SignIn, SignUp } from '@clerk/clerk-react' import { ThemeProvider, useTheme } from './context/ThemeContext' import { ToastProvider } from './context/ToastContext' import Navbar from './components/Navbar' +import ScrollToTop from './components/ScrollToTop' import Landing from './pages/Landing' import UsernameSelection from './pages/UsernameSelection' import Onboarding from './pages/Onboarding' @@ -14,106 +15,8 @@ import Analytics from './pages/Analytics' import Premium from './pages/Premium' import Portfolio from './pages/Portfolio' import ProtectedRoute from './components/ProtectedRoute' - -// Clerk appearance config based on theme -const getClerkAppearance = (theme) => ({ - baseTheme: theme === 'dark' ? undefined : undefined, - variables: { - colorPrimary: '#6366f1', - colorBackground: theme === 'dark' ? '#1e1e2a' : '#ffffff', - colorText: theme === 'dark' ? '#ffffff' : '#0f172a', - colorTextSecondary: theme === 'dark' ? '#a0a0b0' : '#475569', - colorInputBackground: theme === 'dark' ? '#1a1a25' : '#f1f5f9', - colorInputText: theme === 'dark' ? '#ffffff' : '#0f172a', - colorNeutral: theme === 'dark' ? '#a0a0b0' : '#475569', - borderRadius: '12px', - fontFamily: 'Inter, system-ui, sans-serif' - }, - elements: { - rootBox: { - boxShadow: theme === 'dark' - ? '0 25px 50px -12px rgba(0, 0, 0, 0.5)' - : '0 25px 50px -12px rgba(0, 0, 0, 0.15)' - }, - card: { - backgroundColor: theme === 'dark' ? '#1e1e2a' : '#ffffff', - border: theme === 'dark' ? '1px solid rgba(255,255,255,0.08)' : '1px solid rgba(0,0,0,0.08)', - boxShadow: 'none' - }, - headerTitle: { - color: theme === 'dark' ? '#ffffff' : '#0f172a' - }, - headerSubtitle: { - color: theme === 'dark' ? '#a0a0b0' : '#475569' - }, - socialButtonsBlockButton: { - backgroundColor: theme === 'dark' ? '#12121a' : '#f8fafc', - border: theme === 'dark' ? '1px solid rgba(255,255,255,0.1)' : '1px solid rgba(0,0,0,0.1)', - color: theme === 'dark' ? '#ffffff' : '#0f172a', - '&:hover': { - backgroundColor: theme === 'dark' ? '#1a1a25' : '#f1f5f9' - } - }, - formFieldLabel: { - color: theme === 'dark' ? '#a0a0b0' : '#475569' - }, - formFieldInput: { - backgroundColor: theme === 'dark' ? '#12121a' : '#f8fafc', - borderColor: theme === 'dark' ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)', - color: theme === 'dark' ? '#ffffff' : '#0f172a', - '&:focus': { - borderColor: '#6366f1', - boxShadow: '0 0 0 3px rgba(99, 102, 241, 0.2)' - } - }, - formButtonPrimary: { - background: 'linear-gradient(135deg, #6366f1, #a855f7)', - '&:hover': { - background: 'linear-gradient(135deg, #4f46e5, #9333ea)' - } - }, - footerActionLink: { - color: '#6366f1' - }, - identityPreviewText: { - color: theme === 'dark' ? '#ffffff' : '#0f172a' - }, - identityPreviewEditButton: { - color: '#6366f1' - }, - formFieldHintText: { - color: theme === 'dark' ? '#6b6b7b' : '#94a3b8' - }, - dividerLine: { - backgroundColor: theme === 'dark' ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)' - }, - dividerText: { - color: theme === 'dark' ? '#6b6b7b' : '#94a3b8' - }, - userButtonPopoverCard: { - backgroundColor: theme === 'dark' ? '#1e1e2a' : '#ffffff', - border: theme === 'dark' ? '1px solid rgba(255,255,255,0.08)' : '1px solid rgba(0,0,0,0.08)' - }, - userButtonPopoverActionButton: { - color: theme === 'dark' ? '#ffffff' : '#0f172a', - '&:hover': { - backgroundColor: theme === 'dark' ? '#12121a' : '#f1f5f9' - } - }, - userButtonPopoverActionButtonText: { - color: theme === 'dark' ? '#ffffff' : '#0f172a' - }, - userButtonPopoverActionButtonIcon: { - color: theme === 'dark' ? '#a0a0b0' : '#475569' - }, - userPreviewMainIdentifier: { - color: theme === 'dark' ? '#ffffff' : '#0f172a' - }, - userPreviewSecondaryIdentifier: { - color: theme === 'dark' ? '#a0a0b0' : '#475569' - } - } -}) +import DashboardLayout from './components/DashboardLayout' +import { getClerkAppearance } from './utils/clerkAppearance' // Layout wrapper that conditionally shows navbar function AppLayout({ children }) { @@ -133,12 +36,14 @@ function AppLayout({ children }) { return ( <> - {/* Background orbs */} -
-
-
+ {/* Background orbs — clipped so they never cause horizontal scroll */} +