Skip to content

fix(dashboard): add loading skeleton to VendorsCard to prevent empty-state flash - #256

Draft
dccakes wants to merge 2 commits into
mainfrom
claude/sharp-feynman-3q5r71
Draft

dccakes wants to merge 2 commits into
mainfrom
claude/sharp-feynman-3q5r71

Conversation

@dccakes

@dccakes dccakes commented Aug 15, 2026

Copy link
Copy Markdown
Owner

📝 TLDR

Add a loading skeleton to VendorsCard on the dashboard so users don't see a false "No vendors added yet" empty state while vendor data is being fetched.

📝 Description

The VendorsCard component on the planning dashboard fetched vendor data client-side via api.vendor.getAll.useQuery({}). Before this fix, the component used vendors?.length ?? 0 to compute vendorCount, which evaluated to 0 while vendors was still undefined (i.e., the initial network request was in-flight). This caused the card to immediately flash the empty-state message ("No vendors added yet") and the "Add your first vendor →" CTA for every user on every page load, even users with many vendors already tracked.

This Change

  • Added an early-return guard: when vendors === undefined (data still loading), the card now renders animated skeleton placeholders matching the shape of the populated card — a large number skeleton + label skeleton, and three stat-column skeletons below.
  • Removed all optional chaining (?.) and nullish-coalescing fallbacks from the stat calculations (selected, inProgress, inReview) since they now only run after the undefined guard, where TypeScript narrows vendors to VendorWithQuotes[].
  • Added import { Skeleton } from '~/components/ui/skeleton' — the existing skeleton component used throughout the app.

Jira Ticket(s): N/A (daily automated improvement)


Recommendations Reviewed

# Recommendation Priority Effort Type Action
1 VendorsCard shows false empty-state flash while data loads High Small Bug Fix ✅ Selected
2 BudgetCard has same loading anti-pattern (budgetOverview?.totalBudget ?? 0) High Small Bug Fix Documented — follow-up
3 Font tokens --font-serif (Merriweather) and --font-mono (Ubuntu Mono) are declared in CSS but the fonts are never loaded, so font-serif and font-mono Tailwind classes fall back to browser defaults Medium Medium Bug Fix Documented
4 Legacy shadcn Toaster coexists with Sonner (covered by existing PR #250) Low Small Cleanup Already tracked
5 Dashboard TasksCard and MilestonesCard have no loading state at all Medium Small UX Future recommendation

Selected Improvement

VendorsCard loading skeleton — preventing the false empty-state flash on the dashboard.

Why This Was Selected

  • Highest user-visible impact per line of code changed: every user with vendors sees a flash of "No vendors added yet" on every dashboard load.
  • Small, self-contained change with zero risk surface: adds a conditional early-return and a new import; no API, schema, or routing changes.
  • Follows existing patterns exactly — Skeleton from ~/components/ui/skeleton is already used in dozens of loading states across the app (e.g., src/app/(authenicated)/vendors/loading.tsx).
  • No open PR covers this today.

Changes Made

Added a vendors === undefined guard at the top of VendorsCard that returns a skeleton card matching the populated card's layout:

┌─────────────────────────────────────┐
│ Vendors                    ◐        │
│                                     │
│  [██] [████████████████████]        │  ← count + label skeletons
│  ┌──────┬──────┬──────────────┐     │
│  │[███] │[███] │     [███]    │     │  ← three stat column skeletons
│  │[████]│[████]│    [█████]   │     │
│  └──────┴──────┴──────────────┘     │
└─────────────────────────────────────┘

After the guard, the existing empty-state and populated-state branches run on confirmed loaded data.

Files Changed

File Change
src/components/dashboard/planning-overview.tsx Added Skeleton import; added vendors === undefined loading state to VendorsCard; removed optional chaining from narrowed stat calculations

🧪 Testing

  • Added/updated tests
  • Manually reviewed code for correctness
  • Verified Skeleton import path matches component at ~/components/ui/skeleton
  • Verified TypeScript narrowing is correct (vendors === undefined → early return; subsequent code has vendors: VendorWithQuotes[])
  • Verified skeleton structure matches populated card layout

🧪 How to test as a user

  1. Open the dashboard on a slow network (or throttle to 3G in DevTools).
  2. Before: the Vendors card immediately shows "No vendors added yet" for ~300–800ms even if you have vendors.
  3. After: the Vendors card shows animated skeleton placeholders while loading, then transitions to your vendor count and stats.

📚 Documentation

  • N/A — no documentation changes required.

🎨 Style and code quality

  • Code follows existing component patterns in planning-overview.tsx
  • No biome installed in this environment — reviewed manually; change is minimal and pattern-matched

📦 Dependencies

  • No new dependencies. ~/components/ui/skeleton is already in the project.

Future Recommendations

  1. BudgetCard loading skeleton (High / Small): BudgetCard has the same budgetOverview?.totalBudget ?? 0 pattern — it shows $0 and "of $0 budget used" while data loads. Same fix applies.
  2. TasksCard / MilestonesCard loading states (Medium / Small): These cards render nothing meaningful during load. Adding skeletons would round out the dashboard loading experience.
  3. Font token mismatch (Medium / Medium): --font-serif: Merriweather and --font-mono: Ubuntu Mono are CSS token declarations but neither font is loaded in the project. Classes using font-serif and font-mono silently fall back to browser defaults. The fix requires either adding next/font imports for these fonts or updating the tokens to reference fonts that are actually loaded.

GitHub Issues Created or Proposed

No new GitHub issues created. The BudgetCard and font-token issues are noted here as follow-up recommendations for the next daily run.


Generated by Claude Code

@vercel

vercel Bot commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
scv Error Error Aug 15, 2026 10:31am

…eton addition

The two vendor empty-state tests relied on data: undefined triggering the
empty state. Now that undefined renders a skeleton, explicitly set data: []
to reach the empty-state branch.
@github-actions

Copy link
Copy Markdown
Contributor

Jest Test Coverage

Coverage Summary

Lines Statements Branches Functions
Coverage: 81%
81.73% (35155/43013) 82.9% (3730/4499) 68.11% (1038/1524)

This branch had an error being deployed

1 failed deployment
Preview — d87c7e9c Deployed Aug 15, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant