-
Notifications
You must be signed in to change notification settings - Fork 139
Enhance Dashboard UX with Skeletons, Empty States, and Backend Dependency Alignmen #270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Enhance Dashboard UX with Skeletons, Empty States, and Backend Dependency Alignmen #270
Conversation
📝 WalkthroughWalkthroughAdds a new backend Changes
Sequence Diagram(s)sequenceDiagram
participant Browser as Browser (DashboardPage)
participant UI as UI Components (Skeleton / EmptyState)
participant API as Backend API
Browser->>API: Request dashboard data (on mount)
API-->>Browser: Returns data or empty result
alt while fetching
Browser->>UI: Render Skeleton placeholders
else data received
Browser->>UI: Render populated metric cards / lists
else no data
Browser->>UI: Render EmptyState with CTA
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (1 warning, 2 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🤖 Fix all issues with AI Agents
In @Backend/app/schemas/schema.py:
- Around line 6-15: Change the LoginResponse.email type to use
pydantic.types.EmailStr to match UserCreate: import EmailStr from pydantic (or
pydantic.types) and replace the email: str annotation in the LoginResponse class
with email: EmailStr so login responses get the same email-format validation as
UserCreate.
In @Frontend/src/pages/DashboardPage.tsx:
- Around line 34-41: Replace the artificial setTimeout loader in the useEffect
with an actual async fetch: inside the existing useEffect that currently sets
isLoading via setTimeout, create and call an async function (e.g.,
fetchDashboardData) that sets setIsLoading(true), performs fetch calls to your
dashboard endpoints (e.g., '/api/dashboard/metrics' or other APIs), parses
responses, updates relevant state (replace the simulated loading state with real
data state), and in both success and catch blocks call setIsLoading(false);
ensure you clear or ignore results if the component unmounts (use an abort
controller or mounted flag) and keep references to useEffect, isLoading, and
setIsLoading so the change is localized.
- Around line 241-249: The onAction handler in the EmptyState inside TabsContent
is still a console.log placeholder; replace it with real navigation: import and
use React Router's useNavigate (or your app's router hook), create a navigate =
useNavigate() call in DashboardPage, and change onAction={() =>
console.log(...)} to onAction={() => navigate('/connections' /* or your
connect-accounts route */)} (or call your existing navigateToConnections
function); remove the console.log and ensure the route string matches your
connect social accounts route.
- Around line 226-234: The EmptyState onAction currently logs to console;
replace that with real navigation: import useNavigate from react-router-dom at
the top of the file, call const navigate = useNavigate() in the component, and
change the onAction handler on the EmptyState (value "sponsorships") to () =>
navigate('/profile') (or the app's profile route); ensure you remove the
console.log and use the EmptyState onAction prop to trigger
navigate('/profile').
🧹 Nitpick comments (2)
Frontend/src/components/ui/Skeleton.tsx (1)
10-27: Consider using a className utility for cleaner concatenation.The template literal concatenation on Line 23 works but could be more robust with a utility like
clsxor a customcnhelper to handle edge cases (empty strings, undefined values).🔎 Example using a cn utility
If you have a
cnutility in your project (common in shadcn/ui-based projects):+import { cn } from "@/lib/utils" + const Skeleton: React.FC<SkeletonProps> = ({ className, variant = "rect", ...props }) => { // Base classes for the pulse animation and color const baseClasses = "animate-pulse bg-gray-200 dark:bg-gray-700"; // Shape variants const variantClasses = variant === "circle" ? "rounded-full" : "rounded-md"; return ( <div - className={`${baseClasses} ${variantClasses} ${className}`} + className={cn(baseClasses, variantClasses, className)} {...props} /> ); };Frontend/src/pages/DashboardPage.tsx (1)
213-222: Consider adding loading state forCollaborationsPage.Unlike other sections in the Overview tab (Performance Metrics, Recent Activity, AI-Matched Sponsorships), the Creator Collaborations card renders
CollaborationsPageimmediately without a skeleton placeholder. This creates an inconsistent loading experience.🔎 Suggested improvement
<Card className="col-span-3 bg-white dark:bg-slate-950 border-[hsl(214.3,31.8%,91.4%)] dark:border-slate-800"> <CardHeader> <CardTitle>Creator Collaborations</CardTitle> <CardDescription>Creators with complementary audiences</CardDescription> </CardHeader> <CardContent> - <CollaborationsPage /> + {isLoading ? <Skeleton className="h-40 w-full" /> : <CollaborationsPage />} </CardContent> </Card>
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
Backend/app/schemas/schema.pyFrontend/src/components/ui/EmptyState.tsxFrontend/src/components/ui/Skeleton.tsxFrontend/src/pages/DashboardPage.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
Frontend/src/pages/DashboardPage.tsx (4)
Frontend/src/components/dashboard/performance-metrics.tsx (1)
PerformanceMetrics(36-50)Frontend/src/components/dashboard/recent-activity.tsx (1)
RecentActivity(3-52)Frontend/src/components/dashboard/sponsorship-matches.tsx (1)
SponsorshipMatches(20-83)Frontend/src/pages/Collaborations.tsx (1)
CollaborationsPage(23-251)
🔇 Additional comments (5)
Backend/app/schemas/schema.py (1)
17-23: LGTM!The upgrade to
EmailStradds automatic email validation, preventing invalid email formats from being accepted during user creation.Frontend/src/components/ui/EmptyState.tsx (1)
1-38: LGTM!The
EmptyStatecomponent is well-structured with proper conditional rendering, comprehensive dark mode support, and clean prop typing. The implementation correctly handles optional icon and action button scenarios.Frontend/src/pages/DashboardPage.tsx (3)
44-90: LGTM!The header navigation refactor using an array and
mapis a clean improvement that follows DRY principles. The dark mode support and accessibility labels (sr-only) are properly implemented.
112-171: LGTM!The skeleton loading states properly match the structure of the actual metric cards, preventing layout shift and providing good perceived performance during data loading.
210-210: No action needed.SponsorshipMatchesproperly handles emptycreatorIdthrough early validation checks at lines 26 and 44, preventing unnecessary API calls and displaying a user-friendly message instead.
|
Hi Maintainers, |
|
@Kalpana-chavhan please do the coderabbit ai suggestion fix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @Frontend/src/pages/DashboardPage.tsx:
- Around line 243-252: The EmptyState JSX has a duplicate onAction prop; remove
the redundant onAction={() => console.log("Navigate to profile")} so there is
only a single onAction prop using navigate("/profile") (i.e., keep the onAction
that calls navigate and delete the console.log variant) to eliminate the
dead/duplicate prop on the EmptyState component inside the TabsContent for
"sponsorships".
- Around line 41-56: The effect fetch never stores the API result and has a
spacing typo in the dependency array; add component state (e.g., metrics and
setMetrics) to DashboardPage, update fetchDashboardData to call setMetrics(data)
after parsing the response (and keep setting setIsLoading(false) in finally or
both branches), change the Overview metric cards to read values from the metrics
state instead of hardcoded numbers, and fix the dependency array formatting from
"} , [])" to "}, [])".
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
Backend/app/schemas/schema.pyFrontend/src/pages/DashboardPage.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- Backend/app/schemas/schema.py
🧰 Additional context used
🪛 Biome (2.1.2)
Frontend/src/pages/DashboardPage.tsx
[error] 249-249: This JSX property is assigned multiple times.
This attribute is assigned again here.
(lint/suspicious/noDuplicateJsxProps)
🔇 Additional comments (6)
Frontend/src/pages/DashboardPage.tsx (6)
1-1: LGTM! Clean import additions.The new imports for
useEffect, navigation hooks, icons, and UX components are all properly utilized in the component.Also applies to: 20-21, 27-32
35-37: LGTM! Proper state initialization.The
isLoadingstate andnavigatehook are correctly initialized and used throughout the component.
61-106: LGTM! Excellent header refactoring.The navigation items are now cleanly structured using an array with
.map(), making the code more maintainable. The search input and mode toggle are properly styled with light/dark mode support.
131-187: Well-implemented skeleton loading pattern.The skeleton placeholders correctly mirror the structure of the metric cards, preventing layout shift during loading. The conditional rendering is clean and the skeleton variants (circle for icons) are appropriately used.
Note: Once the data fetching issue (lines 41-56) is resolved, replace the hardcoded values with the actual metrics data.
192-239: LGTM! Consistent loading pattern implementation.The skeleton loading is consistently applied across Performance Metrics, Recent Activity, and AI-Matched Sponsorships sections. The loading states enhance perceived performance while data is being fetched.
254-267: LGTM! Clean empty state implementations.The Collaborations and Analytics tabs are properly structured. The EmptyState component in the Analytics tab provides clear guidance with contextual messaging and an appropriate call-to-action.
Frontend/src/pages/DashboardPage.tsx
Outdated
| useEffect(() => { | ||
| const fetchDashboardData = async () => { | ||
| try { | ||
| setIsLoading(true) | ||
|
|
||
| const response = await fetch('/api/dashboard/metrics') | ||
| const data = await response.json() | ||
|
|
||
| setIsLoading(false) | ||
| } catch (error) { | ||
| console.error('Failed to fetch dashboard data:', error) | ||
| setIsLoading(false) | ||
| } | ||
| } | ||
| fetchDashboardData() | ||
| } , []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fetched data is never stored or used.
The API response (line 47) is assigned to a local variable but never stored in component state. Consequently, the Overview tab always displays hardcoded values (lines 152, 162, 172, 182) regardless of what the backend returns, defeating the purpose of the fetch.
💾 Proposed fix: Store and use the fetched data
Add state to store metrics:
const { logout, user } = useAuth()
const [isLoading, setIsLoading] = useState(true)
+ const [metrics, setMetrics] = useState<any>(null)
const navigate = useNavigate()Update the fetch to store data:
useEffect(() => {
const fetchDashboardData = async () => {
try {
setIsLoading(true)
const response = await fetch('/api/dashboard/metrics')
const data = await response.json()
+ setMetrics(data)
setIsLoading(false)
} catch (error) {
console.error('Failed to fetch dashboard data:', error)
setIsLoading(false)
}
}
fetchDashboardData()
- } , [])
+ }, [])Then use metrics data in the metric cards instead of hardcoded values.
Minor: Fix spacing in dependency array.
Line 56 has an extra space before the comma: } , []) should be }, []).
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In @Frontend/src/pages/DashboardPage.tsx around lines 41 - 56, The effect fetch
never stores the API result and has a spacing typo in the dependency array; add
component state (e.g., metrics and setMetrics) to DashboardPage, update
fetchDashboardData to call setMetrics(data) after parsing the response (and keep
setting setIsLoading(false) in finally or both branches), change the Overview
metric cards to read values from the metrics state instead of hardcoded numbers,
and fix the dependency array formatting from "} , [])" to "}, [])".
|
hello, @Aditya30ag ,the checks are passing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🤖 Fix all issues with AI agents
In @Frontend/src/pages/DashboardPage.tsx:
- Around line 53-56: The catch block in DashboardPage.tsx currently only logs
errors and leaves the UI without feedback; add a component-level error state
(e.g., const [error, setError] = useState<string | null>(null)) and update the
fetch error handler in the try/catch inside the effect or fetch function to call
setError(error?.message ?? String(error)) and setIsLoading(false); clear the
error on a successful fetch (setError(null)). Then render the provided error UI
snippet conditionally in the DashboardPage JSX (e.g., {error && (...)}) so users
see a friendly error message when loading fails.
- Around line 48-52: The fetch in DashboardPage.tsx does not check response.ok
before calling response.json(), so non-2xx responses will crash parsing; update
the async fetch logic (the block that calls fetch('/api/dashboard/metrics'),
then awaits response.json() and calls setMetrics) to first check if response.ok,
handle non-ok by reading error text/json and either throw a descriptive Error or
set an error state, and ensure setIsLoading(false) runs in both success and
error paths (e.g., via finally) so UI correctly stops loading.
- Around line 43-59: The effect fetchDashboardData sets metrics via setMetrics
but the JSX still renders hardcoded values; update the DashboardPage metric
cards to read from the metrics state (e.g., use metrics.totalUsers,
metrics.activeSessions, metrics.revenue, metrics.conversionRate or whatever keys
the API returns) instead of the literal numbers currently rendered, and add safe
fallbacks (e.g., show loading/0/— when metrics is null) so the component uses
the fetched data from metrics set by useEffect/fetchDashboardData.
- Around line 262-268: The DashboardPage EmptyState uses
navigate("/settings/connections") but that route isn't defined in the app
router; either add a matching route in App.tsx (create a route for
"/settings/connections" that renders the appropriate Connections or Integrations
component) or change the navigation target in DashboardPage (the onAction
callback inside the EmptyState) to an existing route such as "/dashboard" or
"/settings" so the navigate call resolves correctly; update references to the
path string in the navigate call and ensure App.tsx exports/handles the same
route name.
- Around line 247-253: The EmptyState component is calling navigate("/profile")
in DashboardPage (onAction={() => navigate("/profile")}) but there is no
/profile route registered in the router; either add a new route for the profile
page in App.tsx (e.g., <Route path="/profile" element={<ProfilePage/>} /> and
implement ProfilePage) or change the navigation target in DashboardPage to an
existing route (for example replace navigate("/profile") with
navigate("/onboarding") or navigate("/dashboard")) so the button points to a
valid route.
🧹 Nitpick comments (2)
Frontend/src/pages/DashboardPage.tsx (2)
38-38: Prefer typed interfaces overany.The
metricsstate usesany, which bypasses TypeScript's type safety.♻️ Suggested improvement
Define a proper interface for the metrics shape:
+interface DashboardMetrics { + totalRevenue: number + revenueChange: number + activeSponsorships: number + collaborations: number + audienceGrowth: number + // ... other fields +} + -const [metrics, setMetrics] = useState<any>(null) +const [metrics, setMetrics] = useState<DashboardMetrics | null>(null)
116-119: Consider adding functionality to "New Campaign" button.The button currently has no
onClickhandler. Should it navigate to a campaign creation page or open a modal?Example implementation
- <Button className="bg-[hsl(262.1,83.3%,57.8%)] text-white hover:bg-[hsl(262.1,73.3%,57.8%)]"> + <Button + className="bg-[hsl(262.1,83.3%,57.8%)] text-white hover:bg-[hsl(262.1,73.3%,57.8%)]" + onClick={() => navigate("/dashboard/campaigns/new")} + > <PlusCircle className="mr-2 h-4 w-4" /> New Campaign </Button>
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Frontend/src/pages/DashboardPage.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-12T20:28:05.017Z
Learnt from: Saahi30
Repo: AOSSIE-Org/InPactAI PR: 98
File: Frontend/src/pages/CollaborationDetails.tsx:519-521
Timestamp: 2025-07-12T20:28:05.017Z
Learning: In frontend-only commits that use mock data, hardcoded progress values and similar placeholder data are acceptable and intentional. These values serve as placeholders for UI development and will be replaced with dynamic calculations once backend integration occurs.
Applied to files:
Frontend/src/pages/DashboardPage.tsx
🧬 Code graph analysis (1)
Frontend/src/pages/DashboardPage.tsx (5)
Frontend/src/context/AuthContext.tsx (1)
useAuth(216-222)Frontend/src/components/dashboard/performance-metrics.tsx (1)
PerformanceMetrics(36-50)Frontend/src/components/dashboard/recent-activity.tsx (1)
RecentActivity(3-52)Frontend/src/components/dashboard/sponsorship-matches.tsx (1)
SponsorshipMatches(20-83)Frontend/src/pages/Collaborations.tsx (1)
CollaborationsPage(23-251)
🔇 Additional comments (6)
Frontend/src/pages/DashboardPage.tsx (6)
1-33: Imports look good.All new imports are properly used throughout the component for data fetching, navigation, loading states, and empty states.
64-110: LGTM! Header with proper dark mode support.The header refactoring to use a mapped array for navigation items is clean and maintainable. Dark mode styling is consistently applied throughout.
123-129: Clean tab structure with dark mode support.The tab layout is well-organized and properly styled for both light and dark modes.
134-146: Well-implemented skeleton loading.The skeleton placeholders effectively mirror the layout of the metric cards, reducing perceived loading time and layout shift.
193-220: Excellent loading state handling.The skeleton implementations for both performance metrics and recent activity provide good visual feedback during data loading.
256-258: LGTM! Proper CollaborationsPage integration.Rendering
CollaborationsPagein its own tab withshowHeader={false}is the correct approach to avoid duplicate headers.
| useEffect(() => { | ||
| const fetchDashboardData = async () => { | ||
| try { | ||
| setIsLoading(true) | ||
|
|
||
| const response = await fetch('/api/dashboard/metrics') | ||
| const data = await response.json() | ||
| setMetrics(data) | ||
|
|
||
| setIsLoading(false) | ||
| } catch (error) { | ||
| console.error('Failed to fetch dashboard data:', error) | ||
| setIsLoading(false) | ||
| } | ||
| } | ||
| fetchDashboardData() | ||
| }, []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Fetched metrics data is never used.
The useEffect fetches data from /api/dashboard/metrics and stores it in the metrics state, but this data is never rendered. Lines 155, 165, 175, and 185 display hardcoded values instead of the fetched data.
🔧 Proposed fix to use fetched metrics
) : (
<>
<Card className="bg-white dark:bg-slate-950 border-[hsl(214.3,31.8%,91.4%)] dark:border-slate-800">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Total Revenue</CardTitle>
<DollarSign className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
- <div className="text-2xl font-bold">$45,231.89</div>
- <p className="text-xs text-green-600 dark:text-green-400 font-medium">+20.1% from last month</p>
+ <div className="text-2xl font-bold">${metrics?.totalRevenue?.toLocaleString() ?? '0'}</div>
+ <p className="text-xs text-green-600 dark:text-green-400 font-medium">
+ {metrics?.revenueChange ? `+${metrics.revenueChange}% from last month` : 'No change data'}
+ </p>
</CardContent>
</Card>Apply similar changes to the other three metric cards.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In @Frontend/src/pages/DashboardPage.tsx around lines 43 - 59, The effect
fetchDashboardData sets metrics via setMetrics but the JSX still renders
hardcoded values; update the DashboardPage metric cards to read from the metrics
state (e.g., use metrics.totalUsers, metrics.activeSessions, metrics.revenue,
metrics.conversionRate or whatever keys the API returns) instead of the literal
numbers currently rendered, and add safe fallbacks (e.g., show loading/0/— when
metrics is null) so the component uses the fetched data from metrics set by
useEffect/fetchDashboardData.
| const response = await fetch('/api/dashboard/metrics') | ||
| const data = await response.json() | ||
| setMetrics(data) | ||
|
|
||
| setIsLoading(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Missing HTTP error handling.
The fetch doesn't check response.ok before calling response.json(). Non-2xx responses will cause the JSON parsing to fail with unclear errors.
🔧 Proposed fix
const response = await fetch('/api/dashboard/metrics')
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`)
+ }
const data = await response.json()
setMetrics(data)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const response = await fetch('/api/dashboard/metrics') | |
| const data = await response.json() | |
| setMetrics(data) | |
| setIsLoading(false) | |
| const response = await fetch('/api/dashboard/metrics') | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`) | |
| } | |
| const data = await response.json() | |
| setMetrics(data) | |
| setIsLoading(false) |
🤖 Prompt for AI Agents
In @Frontend/src/pages/DashboardPage.tsx around lines 48 - 52, The fetch in
DashboardPage.tsx does not check response.ok before calling response.json(), so
non-2xx responses will crash parsing; update the async fetch logic (the block
that calls fetch('/api/dashboard/metrics'), then awaits response.json() and
calls setMetrics) to first check if response.ok, handle non-ok by reading error
text/json and either throw a descriptive Error or set an error state, and ensure
setIsLoading(false) runs in both success and error paths (e.g., via finally) so
UI correctly stops loading.
| } catch (error) { | ||
| console.error('Failed to fetch dashboard data:', error) | ||
| setIsLoading(false) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Major: No user-facing error feedback.
When the fetch fails, the error is only logged to console. Users are left with a perpetually loading state or empty dashboard with no explanation.
💡 Suggested improvement
Consider adding an error state and displaying it to users:
const [isLoading, setIsLoading] = useState(true)
const [metrics, setMetrics] = useState<any>(null)
+ const [error, setError] = useState<string | null>(null)
useEffect(() => {
const fetchDashboardData = async () => {
try {
setIsLoading(true)
+ setError(null)
const response = await fetch('/api/dashboard/metrics')
if (!response.ok) {
throw new Error(`Failed to load dashboard data`)
}
const data = await response.json()
setMetrics(data)
setIsLoading(false)
} catch (error) {
console.error('Failed to fetch dashboard data:', error)
+ setError(error instanceof Error ? error.message : 'An error occurred')
setIsLoading(false)
}
}
fetchDashboardData()
}, [])Then render the error state in your UI:
{error && (
<div className="rounded-lg bg-red-50 dark:bg-red-900/20 p-4 text-red-600 dark:text-red-400">
<p className="font-medium">Error loading dashboard</p>
<p className="text-sm">{error}</p>
</div>
)}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In @Frontend/src/pages/DashboardPage.tsx around lines 53 - 56, The catch block
in DashboardPage.tsx currently only logs errors and leaves the UI without
feedback; add a component-level error state (e.g., const [error, setError] =
useState<string | null>(null)) and update the fetch error handler in the
try/catch inside the effect or fetch function to call setError(error?.message ??
String(error)) and setIsLoading(false); clear the error on a successful fetch
(setError(null)). Then render the provided error UI snippet conditionally in the
DashboardPage JSX (e.g., {error && (...)}) so users see a friendly error message
when loading fails.
| <Card className="col-span-3 bg-white dark:bg-slate-950 border-[hsl(214.3,31.8%,91.4%)] dark:border-slate-800"> | ||
| <CardHeader> | ||
| <CardTitle className="text-[hsl(222.2,84%,4.9%)]">Creator Collaborations</CardTitle> | ||
| <CardDescription className="text-[hsl(215.4,16.3%,46.9%)]">Creators with complementary audiences</CardDescription> | ||
| <CardTitle>Creator Collaborations</CardTitle> | ||
| <CardDescription>Creators with complementary audiences</CardDescription> | ||
| </CardHeader> | ||
| <CardContent> | ||
| <CollaborationsPage /> | ||
| </CardContent> | ||
| </Card> | ||
| </div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Major: CollaborationsPage embedded in Card causes layout issues.
CollaborationsPage is a full-page component with its own layout structure (header, main sections, grid layouts). Embedding it within a Card on line 239 creates nested, conflicting layouts.
Additionally, line 257 already renders CollaborationsPage in a dedicated tab, making this embedded instance redundant.
🔧 Proposed fix
Consider creating a dedicated mini-component for the collaborations overview instead of embedding the full page:
<Card className="col-span-3 bg-white dark:bg-slate-950 border-[hsl(214.3,31.8%,91.4%)] dark:border-slate-800">
<CardHeader>
<CardTitle>Creator Collaborations</CardTitle>
<CardDescription>Creators with complementary audiences</CardDescription>
</CardHeader>
<CardContent>
- <CollaborationsPage />
+ {isLoading ? (
+ <Skeleton className="h-40 w-full" />
+ ) : (
+ <EmptyState
+ icon={Users}
+ title="Explore Collaborations"
+ description="Find and connect with creators in your niche"
+ actionText="View All Collaborations"
+ onAction={() => navigate("/dashboard/collaborations")}
+ />
+ )}
</CardContent>
</Card>Or extract a reusable CollaborationsWidget component that shows a summary without the full page structure.
Committable suggestion skipped: line range outside the PR's diff.
| <EmptyState | ||
| icon={Briefcase} | ||
| title="No active sponsorships found" | ||
| description="Our AI is looking for brands that align with your content. Check back in a few hours or update your profile to speed up the process." | ||
| actionText="Update Profile" | ||
| onAction={() => navigate("/profile")} | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for profile route definitions
rg -n "path.*['\"]/?profile['\"]" --type=tsx --type=ts --type=jsx --type=jsRepository: AOSSIE-Org/InPactAI
Length of output: 90
🏁 Script executed:
#!/bin/bash
# Search for profile route definitions using valid ripgrep types
rg -n "path.*['\"]/?profile['\"]" --type=ts --type=jsRepository: AOSSIE-Org/InPactAI
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Find router/route configuration files
echo "=== Looking for route configuration files ==="
fd -e ts -e js -e tsx -e jsx | grep -i route | head -20
echo -e "\n=== Searching for 'profile' in route-like files ==="
rg -l "profile" --type=ts --type=js | head -20
echo -e "\n=== Checking DashboardPage imports ==="
head -30 Frontend/src/pages/DashboardPage.tsxRepository: AOSSIE-Org/InPactAI
Length of output: 1854
🏁 Script executed:
#!/bin/bash
# Find the main App/router configuration
echo "=== Looking for App.tsx or similar root files ==="
fd -name "App.tsx" -o -name "App.jsx" -o -name "main.tsx" -o -name "main.jsx"
echo -e "\n=== Search for route configuration with 'profile' ==="
rg -n "profile" Frontend/src/pages/DashboardPage.tsx | head -5
echo -e "\n=== Check if there's a routes file ==="
fd -name "*route*" -type f Frontend/src/
echo -e "\n=== Look at App.tsx if it exists ==="
if [ -f "Frontend/src/App.tsx" ]; then
cat -n Frontend/src/App.tsx
fiRepository: AOSSIE-Org/InPactAI
Length of output: 6453
Add the missing /profile route or update the navigation path.
The EmptyState navigates to /profile when users click "Update Profile" (line 252), but this route is not defined in App.tsx. Either add the /profile route to your router configuration or update the navigation to an existing route (e.g., /dashboard or /onboarding).
🤖 Prompt for AI Agents
In @Frontend/src/pages/DashboardPage.tsx around lines 247 - 253, The EmptyState
component is calling navigate("/profile") in DashboardPage (onAction={() =>
navigate("/profile")}) but there is no /profile route registered in the router;
either add a new route for the profile page in App.tsx (e.g., <Route
path="/profile" element={<ProfilePage/>} /> and implement ProfilePage) or change
the navigation target in DashboardPage to an existing route (for example replace
navigate("/profile") with navigate("/onboarding") or navigate("/dashboard")) so
the button points to a valid route.
| <EmptyState | ||
| icon={TrendingUp} | ||
| title="Analytics Data Pending" | ||
| description="We need at least 24 hours of data to generate your first growth report. Keep creating content!" | ||
| actionText="Connect YouTube/Instagram" | ||
| onAction={() => navigate("/settings/connections")} | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for /settings/connections route definitions
rg -n "settings/connections" --type=tsx --type=ts --type=jsx --type=js -i
echo "---"
echo "Searching for common router/route files:"
fd -e ts -e tsx -e js -e jsx | grep -iE "(route|router|routing)" | head -20Repository: AOSSIE-Org/InPactAI
Length of output: 235
🏁 Script executed:
#!/bin/bash
# Search for settings/connections with proper file types
echo "=== Searching for settings/connections route ==="
rg -n "settings/connections" --type typescript --type javascript
echo ""
echo "=== Searching for /settings routes ==="
rg -n "/settings|settings:" --type typescript --type javascript | grep -i "route\|path" | head -20
echo ""
echo "=== Looking for main router/App file ==="
fd "App\.(tsx|ts|jsx|js)$" Frontend/src/
echo ""
echo "=== Checking router configuration files ==="
fd -e ts -e tsx -e js -e jsx Frontend/src | grep -iE "router|route|routing" | head -20Repository: AOSSIE-Org/InPactAI
Length of output: 700
🏁 Script executed:
#!/bin/bash
# Read App.tsx to check router configuration
echo "=== Contents of App.tsx ==="
cat -n "Frontend/src/App.tsx"
echo ""
echo "=== Searching for route definitions (broader pattern) ==="
grep -r "settings\|connections" Frontend/src --include="*.tsx" --include="*.ts" -n | head -30Repository: AOSSIE-Org/InPactAI
Length of output: 5763
Add /settings/connections route or update navigation target.
The EmptyState navigates to /settings/connections on line 267, but this route is not defined in App.tsx. Either create this route in your router configuration or update the navigation to an existing route like /dashboard.
🤖 Prompt for AI Agents
In @Frontend/src/pages/DashboardPage.tsx around lines 262 - 268, The
DashboardPage EmptyState uses navigate("/settings/connections") but that route
isn't defined in the app router; either add a matching route in App.tsx (create
a route for "/settings/connections" that renders the appropriate Connections or
Integrations component) or change the navigation target in DashboardPage (the
onAction callback inside the EmptyState) to an existing route such as
"/dashboard" or "/settings" so the navigate call resolves correctly; update
references to the path string in the navigate call and ensure App.tsx
exports/handles the same route name.
closes #269
Description
This PR significantly enhances the Dashboard user experience by moving away from static "Coming Soon" text to a dynamic, professional interface. The focus was on improving the "perceived performance" of the app—ensuring that even while data is loading or missing, the interface remains polished and guided.
Beyond the UI, I have also synchronized the backend requirements to ensure a smooth "one-click" setup for future contributors, resolving common dependency issues found in the local development environment.
Changes Made
Checklist
Summary by CodeRabbit
New Features
Backend / Auth
UI/UX Improvements
✏️ Tip: You can customize this high-level summary in your review settings.