Commit Graph

7 Commits

Author SHA1 Message Date
Arnas Donauskas
eb8d0b3ac6
Merge pull request #44 from ArnasDon/fix/dashboard-activity-feed-pagination
fix(dashboard): paginate recent activity feed with a size picker
2026-04-17 22:39:18 +03:00
Arnas Donauskas
96debd193b
fix(dashboard): paginate recent activity feed with a size picker
With real data the feed showed 20 rows by default and filled most of
the viewport. Switched to a 5-row default with an inline size picker
(5 / 10 / 20 / 50) so users choose how much history is visible.

- Dashboard page bumps the fetch from 20 → 50 so every size option is
  already in memory. Switching sizes is a pure client-side slice, no
  round trip.
- ActivityFeed owns the pageSize state, renders "Showing N of M"
  plus a button group in the footer. The smallest option is always
  enabled; larger options unlock only once we have enough rows to
  meaningfully reveal more (e.g. "10" enables once loaded > 5).
- Existing "View all" header link left alone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 22:35:42 +03:00
Arnas Donauskas
2954123d9b
fix(dashboard): pipeline card stretches to match the chart row height
With grid items-stretch (the default) the two cards in the charts
row try to share the tallest sibling's height — but the Pipeline
Value card was rendering at its natural (shorter) height because
neither its col-wrapper nor its inner section had h-full. So the
line chart's taller content drove the row but the pipeline card
hung at the top with trailing whitespace.

Added h-full on both col wrappers and flex h-full flex-col on
each inner section so they actually fill the row. The existing
flex-1 wrapper inside PipelineDonut now has a defined height to
stretch against, so the empty state (and the populated donut +
legend) span the card cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 22:29:54 +03:00
Arnas Donauskas
ed669424b6
feat(dashboard): replace placeholder with real analytics
Rewrites the dashboard page as a data-driven analytics surface using
existing Supabase tables only — no schema changes, no other pages
touched.

Widgets (all render independent skeletons while their data fetches,
and show a shared empty state when there's not enough data to be
useful):

- Metric cards (Active Conversations, New Contacts Today, Open Deals
  Value, Messages Sent Today) with up/down/no-change delta indicator.
- Quick actions row (New Contact / Deal / Broadcast / Automation).
- Conversations Over Time: SVG line chart, 7/30/90-day tabs, per-day
  hover crosshair + tooltip. Cached per range so tab switches are
  instant.
- Pipeline Value: SVG donut with per-stage arc segments, total in the
  center, legend with deal count + value.
- Average First Response Time: SVG bar chart by weekday with a
  configurable dashed target line and this-week / last-week summary.
- Activity feed: latest 20 items merged across messages, contacts,
  deals, broadcasts, and automation logs — click-through deep-links
  where applicable.

Deviations from spec, noted up-front:
- Strictly dark theme — spec's #f9fafb alternating rows translate to
  slate-900 / slate-900/40 stripes.
- Kept Inter (tabular-nums, bold 28px) for metric values instead of
  Space Grotesk to avoid touching root layout.
- Quick actions link to the relevant list pages (/contacts, etc.)
  rather than auto-opening their create modals — that would require
  modifying those pages.

All aggregation is client-side via RLS-scoped queries. If a tenant's
dataset outgrows a few thousand messages per range window, the
response-time and line-chart queries should migrate to SQL RPCs —
noted as follow-up, not shipped here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 22:16:00 +03:00
Arnas Donauskas
03c53905c1
fix(dashboard): open the clicked conversation when deep-linking from dashboard
Clicking a row in the dashboard's "Recent Conversations" routed to
/inbox with no hint about which conversation to open, so the user
landed on the empty center panel and had to find the thread again.

- Dashboard now routes to /inbox?c=<conversation_id> for per-row clicks.
  "View all" still goes to plain /inbox.
- Inbox page reads ?c=<id> and auto-selects the matching conversation
  in handleConversationsLoaded (event handler, not an effect, so
  react-hooks/set-state-in-effect stays happy). A ref guards against
  resnapping the selection on later realtime list refreshes.
- Inbox also now replaces the URL with ?c=<id> when the user picks a
  conversation, so a page refresh / shared link lands on the same
  thread.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 21:11:05 +03:00
Arnas Donauskas
a4c966334a
fix: remove /dashboard prefix from nav links and redirects
Next.js route groups like (dashboard) don't appear in URLs, so the
sidebar, header, and dashboard page were linking to /dashboard/inbox,
/dashboard/contacts, etc. which don't exist and returned 404.

Fixed paths in:
- src/components/layout/sidebar.tsx (nav hrefs)
- src/components/layout/header.tsx (page title map)
- src/app/(dashboard)/dashboard/page.tsx (router.push calls)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 19:29:34 +03:00
Arnas Donauskas
658d070811
Initial scaffold: WhatsApp CRM with Next.js + Supabase
Complete WhatsApp CRM application built with Next.js 14 (App Router),
Supabase (PostgreSQL + Auth + Realtime), and shadcn/ui.

Features:
- Auth: Login, signup, forgot password with Supabase Auth
- Dashboard: Analytics overview with stats, recent activity
- Inbox: Real-time WhatsApp conversations with message threading
- Contacts: CRUD with tags, custom fields, notes, CSV import
- Broadcasts: 4-step wizard with audience selection, template sending
- Pipelines: Kanban board with deal management
- Settings: WhatsApp API config, templates, tags
- WhatsApp API: Webhook (verify + receive), send, broadcast, media proxy
- Database: 16 tables with RLS policies, indexes, realtime subscriptions
- Dark theme throughout with emerald accents

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 18:17:31 +03:00